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