Print this page
2619 asynchronous destruction of ZFS file systems
2747 SPA versioning with zfs feature flags
Reviewed by: Matt Ahrens <mahrens@delphix.com>
Reviewed by: George Wilson <gwilson@delphix.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Reviewed by: Dan Kruchinin <dan.kruchinin@gmail.com>
Approved by: Dan McDonald <danmcd@nexenta.com>

@@ -16,12 +16,14 @@
  * fields enclosed by brackets "[]" replaced with your own identifying
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #include <stdio.h>
 #include <stdio_ext.h>
 #include <stdlib.h>

@@ -52,20 +54,22 @@
 #include <sys/zio_checksum.h>
 #include <sys/zio_compress.h>
 #include <sys/zfs_fuid.h>
 #include <sys/arc.h>
 #include <sys/ddt.h>
+#include <sys/zfeature.h>
 #undef ZFS_MAXNAMELEN
 #undef verify
 #include <libzfs.h>
 
 #define ZDB_COMPRESS_NAME(idx) ((idx) < ZIO_COMPRESS_FUNCTIONS ? \
     zio_compress_table[(idx)].ci_name : "UNKNOWN")
 #define ZDB_CHECKSUM_NAME(idx) ((idx) < ZIO_CHECKSUM_FUNCTIONS ? \
     zio_checksum_table[(idx)].ci_name : "UNKNOWN")
 #define ZDB_OT_NAME(idx) ((idx) < DMU_OT_NUMTYPES ? \
-    dmu_ot[(idx)].ot_name : "UNKNOWN")
+    dmu_ot[(idx)].ot_name : DMU_OT_IS_VALID(idx) ? \
+    dmu_ot_byteswap[DMU_OT_BYTESWAP(idx)].ob_name : "UNKNOWN")
 #define ZDB_OT_TYPE(idx) ((idx) < DMU_OT_NUMTYPES ? (idx) : DMU_OT_NUMTYPES)
 
 #ifndef lint
 extern int zfs_recover;
 #else

@@ -1086,11 +1090,11 @@
         if (ds == NULL)
                 return;
 
         ASSERT(size == sizeof (*ds));
         crtime = ds->ds_creation_time;
-        zdb_nicenum(ds->ds_used_bytes, used);
+        zdb_nicenum(ds->ds_referenced_bytes, used);
         zdb_nicenum(ds->ds_compressed_bytes, compressed);
         zdb_nicenum(ds->ds_uncompressed_bytes, uncompressed);
         zdb_nicenum(ds->ds_unique_bytes, unique);
         sprintf_blkptr(blkbuf, &ds->ds_bp);
 

@@ -1130,10 +1134,48 @@
         (void) printf("\t\tbp = %s\n", blkbuf);
 }
 
 /* ARGSUSED */
 static int
+dump_bptree_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
+{
+        char blkbuf[BP_SPRINTF_LEN];
+
+        if (bp->blk_birth != 0) {
+                sprintf_blkptr(blkbuf, bp);
+                (void) printf("\t%s\n", blkbuf);
+        }
+        return (0);
+}
+
+static void
+dump_bptree(objset_t *os, uint64_t obj, char *name)
+{
+        char bytes[32];
+        bptree_phys_t *bt;
+        dmu_buf_t *db;
+
+        if (dump_opt['d'] < 3)
+                return;
+
+        VERIFY3U(0, ==, dmu_bonus_hold(os, obj, FTAG, &db));
+        bt = db->db_data;
+        zdb_nicenum(bt->bt_bytes, bytes);
+        (void) printf("\n    %s: %llu datasets, %s\n",
+            name, (unsigned long long)(bt->bt_end - bt->bt_begin), bytes);
+        dmu_buf_rele(db, FTAG);
+
+        if (dump_opt['d'] < 5)
+                return;
+
+        (void) printf("\n");
+
+        (void) bptree_iterate(os, obj, B_FALSE, dump_bptree_cb, NULL, NULL);
+}
+
+/* ARGSUSED */
+static int
 dump_bpobj_cb(void *arg, const blkptr_t *bp, dmu_tx_t *tx)
 {
         char blkbuf[BP_SPRINTF_LEN];
 
         ASSERT(bp->blk_birth != 0);

@@ -1881,15 +1923,17 @@
 /*
  * Extended object types to report deferred frees and dedup auto-ditto blocks.
  */
 #define ZDB_OT_DEFERRED (DMU_OT_NUMTYPES + 0)
 #define ZDB_OT_DITTO    (DMU_OT_NUMTYPES + 1)
-#define ZDB_OT_TOTAL    (DMU_OT_NUMTYPES + 2)
+#define ZDB_OT_OTHER    (DMU_OT_NUMTYPES + 2)
+#define ZDB_OT_TOTAL    (DMU_OT_NUMTYPES + 3)
 
 static char *zdb_ot_extname[] = {
         "deferred free",
         "dedup ditto",
+        "other",
         "Total",
 };
 
 #define ZB_TOTAL        DN_MAX_LEVELS
 

@@ -1966,13 +2010,14 @@
         if (bp == NULL)
                 return (0);
 
         type = BP_GET_TYPE(bp);
 
-        zdb_count_block(zcb, zilog, bp, type);
+        zdb_count_block(zcb, zilog, bp,
+            (type & DMU_OT_NEWTYPE) ? ZDB_OT_OTHER : type);
 
-        is_metadata = (BP_GET_LEVEL(bp) != 0 || dmu_ot[type].ot_metadata);
+        is_metadata = (BP_GET_LEVEL(bp) != 0 || DMU_OT_IS_METADATA(type));
 
         if (dump_opt['c'] > 1 || (dump_opt['c'] && is_metadata)) {
                 int ioerr;
                 size_t size = BP_GET_PSIZE(bp);
                 void *data = malloc(size);

@@ -2193,10 +2238,16 @@
          */
         (void) bpobj_iterate_nofree(&spa->spa_deferred_bpobj,
             count_block_cb, &zcb, NULL);
         (void) bpobj_iterate_nofree(&spa->spa_dsl_pool->dp_free_bpobj,
             count_block_cb, &zcb, NULL);
+        if (spa_feature_is_active(spa,
+            &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
+                VERIFY3U(0, ==, bptree_iterate(spa->spa_meta_objset,
+                    spa->spa_dsl_pool->dp_bptree_obj, B_FALSE, count_block_cb,
+                    &zcb, NULL));
+        }
 
         if (dump_opt['c'] > 1)
                 flags |= TRAVERSE_PREFETCH_DATA;
 
         zcb.zcb_haderrors |= traverse_pool(spa, 0, flags, zdb_blkptr_cb, &zcb);

@@ -2369,11 +2420,11 @@
                     (u_longlong_t)bp->blk_fill,
                     avl_numnodes(t));
         }
 
         if (BP_IS_HOLE(bp) || BP_GET_CHECKSUM(bp) == ZIO_CHECKSUM_OFF ||
-            BP_GET_LEVEL(bp) > 0 || dmu_ot[BP_GET_TYPE(bp)].ot_metadata)
+            BP_GET_LEVEL(bp) > 0 || DMU_OT_IS_METADATA(BP_GET_TYPE(bp)))
                 return (0);
 
         ddt_key_fill(&zdde_search.zdde_key, bp);
 
         zdde = avl_find(t, &zdde_search, &where);

@@ -2474,12 +2525,19 @@
                 dump_dir(dp->dp_meta_objset);
                 if (dump_opt['d'] >= 3) {
                         dump_bpobj(&spa->spa_deferred_bpobj, "Deferred frees");
                         if (spa_version(spa) >= SPA_VERSION_DEADLISTS) {
                                 dump_bpobj(&spa->spa_dsl_pool->dp_free_bpobj,
-                                    "Pool frees");
+                                    "Pool snapshot frees");
                         }
+
+                        if (spa_feature_is_active(spa,
+                            &spa_feature_table[SPA_FEATURE_ASYNC_DESTROY])) {
+                                dump_bptree(spa->spa_meta_objset,
+                                    spa->spa_dsl_pool->dp_bptree_obj,
+                                    "Pool dataset frees");
+                        }
                         dump_dtl(spa->spa_root_vdev, 0);
                 }
                 (void) dmu_objset_find(spa_name(spa), dump_one_dir,
                     NULL, DS_FIND_SNAPSHOTS | DS_FIND_CHILDREN);
         }