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