1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Print intent log header and statistics. 31 */ 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <ctype.h> 36 #include <sys/zfs_context.h> 37 #include <sys/spa.h> 38 #include <sys/dmu.h> 39 #include <sys/stat.h> 40 #include <sys/resource.h> 41 #include <sys/zil.h> 42 #include <sys/zil_impl.h> 43 44 extern uint8_t dump_opt[256]; 45 46 static void 47 print_log_bp(blkptr_t *bp, const char *prefix) 48 { 49 char blkbuf[200]; 50 51 sprintf_blkptr(blkbuf, bp); 52 (void) printf("%s%s\n", prefix, blkbuf); 53 } 54 55 /* ARGSUSED */ 56 static void 57 zil_prt_rec_create(zilog_t *zilog, int txtype, lr_create_t *lr) 58 { 59 time_t crtime = lr->lr_crtime[0]; 60 char *name = (char *)(lr + 1); 61 char *link = name + strlen(name) + 1; 62 63 if (txtype == TX_SYMLINK) 64 (void) printf("\t\t\t%s -> %s\n", name, link); 65 else 66 (void) printf("\t\t\t%s\n", name); 67 68 (void) printf("\t\t\t%s", ctime(&crtime)); 69 (void) printf("\t\t\tdoid %llu, foid %llu, mode %llo\n", 70 (u_longlong_t)lr->lr_doid, (u_longlong_t)lr->lr_foid, 71 (longlong_t)lr->lr_mode); 72 (void) printf("\t\t\tuid %llu, gid %llu, gen %llu, rdev 0x%llx\n", 73 (u_longlong_t)lr->lr_uid, (u_longlong_t)lr->lr_gid, 74 (u_longlong_t)lr->lr_gen, (u_longlong_t)lr->lr_rdev); 75 } 76 77 /* ARGSUSED */ 78 static void 79 zil_prt_rec_remove(zilog_t *zilog, int txtype, lr_remove_t *lr) 80 { 81 (void) printf("\t\t\tdoid %llu, name %s\n", 82 (u_longlong_t)lr->lr_doid, (char *)(lr + 1)); 83 } 84 85 /* ARGSUSED */ 86 static void 87 zil_prt_rec_link(zilog_t *zilog, int txtype, lr_link_t *lr) 88 { 89 (void) printf("\t\t\tdoid %llu, link_obj %llu, name %s\n", 90 (u_longlong_t)lr->lr_doid, (u_longlong_t)lr->lr_link_obj, 91 (char *)(lr + 1)); 92 } 93 94 /* ARGSUSED */ 95 static void 96 zil_prt_rec_rename(zilog_t *zilog, int txtype, lr_rename_t *lr) 97 { 98 char *snm = (char *)(lr + 1); 99 char *tnm = snm + strlen(snm) + 1; 100 101 (void) printf("\t\t\tsdoid %llu, tdoid %llu\n", 102 (u_longlong_t)lr->lr_sdoid, (u_longlong_t)lr->lr_tdoid); 103 (void) printf("\t\t\tsrc %s tgt %s\n", snm, tnm); 104 } 105 106 /* ARGSUSED */ 107 static void 108 zil_prt_rec_write(zilog_t *zilog, int txtype, lr_write_t *lr) 109 { 110 char *data, *dlimit; 111 blkptr_t *bp = &lr->lr_blkptr; 112 char buf[SPA_MAXBLOCKSIZE]; 113 int verbose = MAX(dump_opt['d'], dump_opt['i']); 114 int error; 115 116 (void) printf("\t\t\tfoid %llu, offset 0x%llx," 117 " length 0x%llx, blkoff 0x%llx\n", 118 (u_longlong_t)lr->lr_foid, (longlong_t)lr->lr_offset, 119 (u_longlong_t)lr->lr_length, (u_longlong_t)lr->lr_blkoff); 120 121 if (verbose < 5) 122 return; 123 124 if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) { 125 (void) printf("\t\t\thas blkptr, %s\n", 126 bp->blk_birth >= spa_first_txg(zilog->zl_spa) ? 127 "will claim" : "won't claim"); 128 print_log_bp(bp, "\t\t\t"); 129 if (bp->blk_birth == 0) { 130 bzero(buf, sizeof (buf)); 131 } else { 132 error = zio_wait(zio_read(NULL, zilog->zl_spa, 133 bp, buf, BP_GET_LSIZE(bp), NULL, NULL, 134 ZIO_PRIORITY_SYNC_READ, ZIO_FLAG_CANFAIL)); 135 if (error) 136 return; 137 } 138 data = buf + lr->lr_blkoff; 139 } else { 140 data = (char *)(lr + 1); 141 } 142 143 dlimit = data + MIN(lr->lr_length, 144 (verbose < 6 ? 20 : SPA_MAXBLOCKSIZE)); 145 146 (void) printf("\t\t\t"); 147 while (data < dlimit) { 148 if (isprint(*data)) 149 (void) printf("%c ", *data); 150 else 151 (void) printf("%2X", *data); 152 data++; 153 } 154 (void) printf("\n"); 155 } 156 157 /* ARGSUSED */ 158 static void 159 zil_prt_rec_truncate(zilog_t *zilog, int txtype, lr_truncate_t *lr) 160 { 161 (void) printf("\t\t\tfoid %llu, offset 0x%llx, length 0x%llx\n", 162 (u_longlong_t)lr->lr_foid, (longlong_t)lr->lr_offset, 163 (u_longlong_t)lr->lr_length); 164 } 165 166 /* ARGSUSED */ 167 static void 168 zil_prt_rec_setattr(zilog_t *zilog, int txtype, lr_setattr_t *lr) 169 { 170 time_t atime = (time_t)lr->lr_atime[0]; 171 time_t mtime = (time_t)lr->lr_mtime[0]; 172 173 (void) printf("\t\t\tfoid %llu, mask 0x%llx\n", 174 (u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_mask); 175 176 if (lr->lr_mask & AT_MODE) { 177 (void) printf("\t\t\tAT_MODE %llo\n", 178 (longlong_t)lr->lr_mode); 179 } 180 181 if (lr->lr_mask & AT_UID) { 182 (void) printf("\t\t\tAT_UID %llu\n", 183 (u_longlong_t)lr->lr_uid); 184 } 185 186 if (lr->lr_mask & AT_GID) { 187 (void) printf("\t\t\tAT_GID %llu\n", 188 (u_longlong_t)lr->lr_gid); 189 } 190 191 if (lr->lr_mask & AT_SIZE) { 192 (void) printf("\t\t\tAT_SIZE %llu\n", 193 (u_longlong_t)lr->lr_size); 194 } 195 196 if (lr->lr_mask & AT_ATIME) { 197 (void) printf("\t\t\tAT_ATIME %llu.%09llu %s", 198 (u_longlong_t)lr->lr_atime[0], 199 (u_longlong_t)lr->lr_atime[1], 200 ctime(&atime)); 201 } 202 203 if (lr->lr_mask & AT_MTIME) { 204 (void) printf("\t\t\tAT_MTIME %llu.%09llu %s", 205 (u_longlong_t)lr->lr_mtime[0], 206 (u_longlong_t)lr->lr_mtime[1], 207 ctime(&mtime)); 208 } 209 } 210 211 /* ARGSUSED */ 212 static void 213 zil_prt_rec_acl(zilog_t *zilog, int txtype, lr_acl_t *lr) 214 { 215 (void) printf("\t\t\tfoid %llu, aclcnt %llu\n", 216 (u_longlong_t)lr->lr_foid, (u_longlong_t)lr->lr_aclcnt); 217 } 218 219 typedef void (*zil_prt_rec_func_t)(); 220 typedef struct zil_rec_info { 221 zil_prt_rec_func_t zri_print; 222 char *zri_name; 223 uint64_t zri_count; 224 } zil_rec_info_t; 225 226 static zil_rec_info_t zil_rec_info[TX_MAX_TYPE] = { 227 { NULL, "Total " }, 228 { zil_prt_rec_create, "TX_CREATE " }, 229 { zil_prt_rec_create, "TX_MKDIR " }, 230 { zil_prt_rec_create, "TX_MKXATTR " }, 231 { zil_prt_rec_create, "TX_SYMLINK " }, 232 { zil_prt_rec_remove, "TX_REMOVE " }, 233 { zil_prt_rec_remove, "TX_RMDIR " }, 234 { zil_prt_rec_link, "TX_LINK " }, 235 { zil_prt_rec_rename, "TX_RENAME " }, 236 { zil_prt_rec_write, "TX_WRITE " }, 237 { zil_prt_rec_truncate, "TX_TRUNCATE" }, 238 { zil_prt_rec_setattr, "TX_SETATTR " }, 239 { zil_prt_rec_acl, "TX_ACL " }, 240 }; 241 242 /* ARGSUSED */ 243 static void 244 print_log_record(zilog_t *zilog, lr_t *lr, void *arg, uint64_t first_txg) 245 { 246 int txtype; 247 int verbose = MAX(dump_opt['d'], dump_opt['i']); 248 249 txtype = lr->lrc_txtype; 250 251 ASSERT(txtype != 0 && (uint_t)txtype < TX_MAX_TYPE); 252 ASSERT(lr->lrc_txg); 253 254 (void) printf("\t\t%s len %6llu, txg %llu, seq %llu\n", 255 zil_rec_info[txtype].zri_name, 256 (u_longlong_t)lr->lrc_reclen, 257 (u_longlong_t)lr->lrc_txg, 258 (u_longlong_t)lr->lrc_seq); 259 260 if (txtype && verbose >= 3) 261 zil_rec_info[txtype].zri_print(zilog, txtype, lr); 262 263 zil_rec_info[txtype].zri_count++; 264 zil_rec_info[0].zri_count++; 265 } 266 267 /* ARGSUSED */ 268 static void 269 print_log_block(zilog_t *zilog, blkptr_t *bp, void *arg, uint64_t first_txg) 270 { 271 char blkbuf[200]; 272 int verbose = MAX(dump_opt['d'], dump_opt['i']); 273 274 if (verbose <= 3) 275 return; 276 277 if (verbose >= 5) { 278 (void) strcpy(blkbuf, ", "); 279 sprintf_blkptr(blkbuf + strlen(blkbuf), bp); 280 } else { 281 blkbuf[0] = '\0'; 282 } 283 284 (void) printf("\tBlock seqno %llu, %s%s\n", 285 (u_longlong_t)bp->blk_cksum.zc_word[3], 286 bp->blk_birth >= first_txg ? "will claim" : "won't claim", blkbuf); 287 } 288 289 static void 290 print_log_stats(int verbose) 291 { 292 int i, w, p10; 293 294 if (verbose > 3) 295 (void) printf("\n"); 296 297 if (zil_rec_info[0].zri_count == 0) 298 return; 299 300 for (w = 1, p10 = 10; zil_rec_info[0].zri_count >= p10; p10 *= 10) 301 w++; 302 303 for (i = 0; i < TX_MAX_TYPE; i++) 304 if (zil_rec_info[i].zri_count || verbose >= 3) 305 (void) printf("\t\t%s %*llu\n", 306 zil_rec_info[i].zri_name, w, 307 (u_longlong_t)zil_rec_info[i].zri_count); 308 (void) printf("\n"); 309 } 310 311 /* ARGSUSED */ 312 void 313 dump_intent_log(zilog_t *zilog) 314 { 315 zil_header_t *zh = zilog->zl_header; 316 int verbose = MAX(dump_opt['d'], dump_opt['i']); 317 int i; 318 319 if (zh->zh_log.blk_birth == 0 || verbose < 2) 320 return; 321 322 (void) printf("\n ZIL header: claim_txg %llu, seq %llu\n", 323 (u_longlong_t)zh->zh_claim_txg, (u_longlong_t)zh->zh_replay_seq); 324 325 if (verbose >= 4) 326 print_log_bp(&zh->zh_log, "\n\tfirst block: "); 327 328 for (i = 0; i < TX_MAX_TYPE; i++) 329 zil_rec_info[i].zri_count = 0; 330 331 if (verbose >= 2) { 332 (void) printf("\n"); 333 zil_parse(zilog, print_log_block, print_log_record, NULL, 334 spa_first_txg(zilog->zl_spa)); 335 print_log_stats(verbose); 336 } 337 } 338