From owner-svn-src-all@FreeBSD.ORG Wed Mar 19 23:58:08 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id DCAA7CC7; Wed, 19 Mar 2014 23:58:08 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id C4DB2FCA; Wed, 19 Mar 2014 23:58:08 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s2JNw8ZA008232; Wed, 19 Mar 2014 23:58:08 GMT (envelope-from delphij@svn.freebsd.org) Received: (from delphij@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s2JNw6FR008216; Wed, 19 Mar 2014 23:58:06 GMT (envelope-from delphij@svn.freebsd.org) Message-Id: <201403192358.s2JNw6FR008216@svn.freebsd.org> From: Xin LI Date: Wed, 19 Mar 2014 23:58:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r263398 - in stable: 8/cddl/contrib/opensolaris/cmd/zdb 8/cddl/contrib/opensolaris/cmd/zhack 8/cddl/contrib/opensolaris/cmd/zpool 8/sys/boot/zfs 8/sys/cddl/boot/zfs 8/sys/cddl/contrib/o... X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 19 Mar 2014 23:58:08 -0000 Author: delphij Date: Wed Mar 19 23:58:05 2014 New Revision: 263398 URL: http://svnweb.freebsd.org/changeset/base/263398 Log: MFC r260150: MFV r259170: 4370 avoid transmitting holes during zfs send 4371 DMU code clean up illumos/illumos-gate@43466aae47bfcd2ad9bf501faec8e75c08095e4f NOTE: Make sure the boot code is updated if a zpool upgrade is done on boot zpool. Modified: stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb.c stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb_il.c stable/9/cddl/contrib/opensolaris/cmd/zhack/zhack.c stable/9/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 stable/9/lib/libprocstat/zfs/Makefile stable/9/sys/boot/zfs/zfsimpl.c stable/9/sys/cddl/boot/zfs/zfsimpl.h stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev.h stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfeature.h stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_cache.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_disk.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfeature.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Directory Properties: stable/9/cddl/contrib/opensolaris/ (props changed) stable/9/cddl/contrib/opensolaris/cmd/zpool/ (props changed) stable/9/lib/libprocstat/ (props changed) stable/9/sys/ (props changed) stable/9/sys/boot/ (props changed) stable/9/sys/cddl/contrib/opensolaris/ (props changed) Changes in other areas also in this revision: Modified: stable/8/cddl/contrib/opensolaris/cmd/zdb/zdb.c stable/8/cddl/contrib/opensolaris/cmd/zdb/zdb_il.c stable/8/cddl/contrib/opensolaris/cmd/zhack/zhack.c stable/8/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 stable/8/sys/boot/zfs/zfsimpl.c stable/8/sys/cddl/boot/zfs/zfsimpl.h stable/8/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c stable/8/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dbuf.h stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/dmu.h stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa.h stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/spa_impl.h stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/vdev.h stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sys/zfeature.h stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_cache.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_disk.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfeature.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c stable/8/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c Directory Properties: stable/8/cddl/contrib/opensolaris/ (props changed) stable/8/cddl/contrib/opensolaris/cmd/zpool/ (props changed) stable/8/sys/ (props changed) stable/8/sys/boot/ (props changed) stable/8/sys/cddl/ (props changed) stable/8/sys/cddl/contrib/opensolaris/ (props changed) Modified: stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb.c ============================================================================== --- stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb.c Wed Mar 19 23:55:03 2014 (r263397) +++ stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb.c Wed Mar 19 23:58:05 2014 (r263398) @@ -764,7 +764,7 @@ dump_dde(const ddt_t *ddt, const ddt_ent if (ddp->ddp_phys_birth == 0) continue; ddt_bp_create(ddt->ddt_checksum, ddk, ddp, &blk); - sprintf_blkptr(blkbuf, &blk); + snprintf_blkptr(blkbuf, sizeof (blkbuf), &blk); (void) printf("index %llx refcnt %llu %s %s\n", (u_longlong_t)index, (u_longlong_t)ddp->ddp_refcnt, types[p], blkbuf); @@ -1024,31 +1024,39 @@ blkid2offset(const dnode_phys_t *dnp, co } static void -sprintf_blkptr_compact(char *blkbuf, const blkptr_t *bp) +snprintf_blkptr_compact(char *blkbuf, size_t buflen, const blkptr_t *bp) { const dva_t *dva = bp->blk_dva; int ndvas = dump_opt['d'] > 5 ? BP_GET_NDVAS(bp) : 1; if (dump_opt['b'] >= 6) { - sprintf_blkptr(blkbuf, bp); + snprintf_blkptr(blkbuf, buflen, bp); return; } blkbuf[0] = '\0'; for (int i = 0; i < ndvas; i++) - (void) sprintf(blkbuf + strlen(blkbuf), "%llu:%llx:%llx ", + (void) snprintf(blkbuf + strlen(blkbuf), + buflen - strlen(blkbuf), "%llu:%llx:%llx ", (u_longlong_t)DVA_GET_VDEV(&dva[i]), (u_longlong_t)DVA_GET_OFFSET(&dva[i]), (u_longlong_t)DVA_GET_ASIZE(&dva[i])); - (void) sprintf(blkbuf + strlen(blkbuf), - "%llxL/%llxP F=%llu B=%llu/%llu", - (u_longlong_t)BP_GET_LSIZE(bp), - (u_longlong_t)BP_GET_PSIZE(bp), - (u_longlong_t)bp->blk_fill, - (u_longlong_t)bp->blk_birth, - (u_longlong_t)BP_PHYSICAL_BIRTH(bp)); + if (BP_IS_HOLE(bp)) { + (void) snprintf(blkbuf + strlen(blkbuf), + buflen - strlen(blkbuf), "B=%llu", + (u_longlong_t)bp->blk_birth); + } else { + (void) snprintf(blkbuf + strlen(blkbuf), + buflen - strlen(blkbuf), + "%llxL/%llxP F=%llu B=%llu/%llu", + (u_longlong_t)BP_GET_LSIZE(bp), + (u_longlong_t)BP_GET_PSIZE(bp), + (u_longlong_t)bp->blk_fill, + (u_longlong_t)bp->blk_birth, + (u_longlong_t)BP_PHYSICAL_BIRTH(bp)); + } } static void @@ -1073,7 +1081,7 @@ print_indirect(blkptr_t *bp, const zbook } } - sprintf_blkptr_compact(blkbuf, bp); + snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp); (void) printf("%s\n", blkbuf); } @@ -1088,7 +1096,7 @@ visit_indirect(spa_t *spa, const dnode_p print_indirect(bp, zb, dnp); - if (BP_GET_LEVEL(bp) > 0) { + if (BP_GET_LEVEL(bp) > 0 && !BP_IS_HOLE(bp)) { uint32_t flags = ARC_WAIT; int i; blkptr_t *cbp; @@ -1213,7 +1221,7 @@ dump_dsl_dataset(objset_t *os, uint64_t 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); + snprintf_blkptr(blkbuf, sizeof (blkbuf), &ds->ds_bp); (void) printf("\t\tdir_obj = %llu\n", (u_longlong_t)ds->ds_dir_obj); @@ -1258,7 +1266,7 @@ dump_bptree_cb(void *arg, const blkptr_t char blkbuf[BP_SPRINTF_LEN]; if (bp->blk_birth != 0) { - sprintf_blkptr(blkbuf, bp); + snprintf_blkptr(blkbuf, sizeof (blkbuf), bp); (void) printf("\t%s\n", blkbuf); } return (0); @@ -1296,7 +1304,7 @@ dump_bpobj_cb(void *arg, const blkptr_t char blkbuf[BP_SPRINTF_LEN]; ASSERT(bp->blk_birth != 0); - sprintf_blkptr_compact(blkbuf, bp); + snprintf_blkptr_compact(blkbuf, sizeof (blkbuf), bp); (void) printf("\t%s\n", blkbuf); return (0); } @@ -1795,8 +1803,9 @@ dump_dir(objset_t *os) zdb_nicenum(refdbytes, numbuf); if (verbosity >= 4) { - (void) sprintf(blkbuf, ", rootbp "); - (void) sprintf_blkptr(blkbuf + strlen(blkbuf), os->os_rootbp); + (void) snprintf(blkbuf, sizeof (blkbuf), ", rootbp "); + (void) snprintf_blkptr(blkbuf + strlen(blkbuf), + sizeof (blkbuf) - strlen(blkbuf), os->os_rootbp); } else { blkbuf[0] = '\0'; } @@ -1826,7 +1835,7 @@ dump_dir(objset_t *os) if (verbosity < 2) return; - if (os->os_rootbp->blk_birth == 0) + if (BP_IS_HOLE(os->os_rootbp)) return; dump_object(os, 0, verbosity, &print_header); @@ -1867,7 +1876,7 @@ dump_uberblock(uberblock_t *ub, const ch (u_longlong_t)ub->ub_timestamp, asctime(localtime(×tamp))); if (dump_opt['u'] >= 3) { char blkbuf[BP_SPRINTF_LEN]; - sprintf_blkptr(blkbuf, &ub->ub_rootbp); + snprintf_blkptr(blkbuf, sizeof (blkbuf), &ub->ub_rootbp); (void) printf("\trootbp = %s\n", blkbuf); } (void) printf(footer ? footer : ""); @@ -2181,7 +2190,7 @@ zdb_blkptr_done(zio_t *zio) zcb->zcb_errors[ioerr]++; if (dump_opt['b'] >= 2) - sprintf_blkptr(blkbuf, bp); + snprintf_blkptr(blkbuf, sizeof (blkbuf), bp); else blkbuf[0] = '\0'; @@ -2204,11 +2213,22 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog const zbookmark_t *zb, const dnode_phys_t *dnp, void *arg) { zdb_cb_t *zcb = arg; - char blkbuf[BP_SPRINTF_LEN]; dmu_object_type_t type; boolean_t is_metadata; - if (bp == NULL) + if (dump_opt['b'] >= 5 && bp->blk_birth > 0) { + char blkbuf[BP_SPRINTF_LEN]; + snprintf_blkptr(blkbuf, sizeof (blkbuf), bp); + (void) printf("objset %llu object %llu " + "level %lld offset 0x%llx %s\n", + (u_longlong_t)zb->zb_objset, + (u_longlong_t)zb->zb_object, + (longlong_t)zb->zb_level, + (u_longlong_t)blkid2offset(dnp, bp, zb), + blkbuf); + } + + if (BP_IS_HOLE(bp)) return (0); type = BP_GET_TYPE(bp); @@ -2239,17 +2259,6 @@ zdb_blkptr_cb(spa_t *spa, zilog_t *zilog zcb->zcb_readfails = 0; - if (dump_opt['b'] >= 5) { - sprintf_blkptr(blkbuf, bp); - (void) printf("objset %llu object %llu " - "level %lld offset 0x%llx %s\n", - (u_longlong_t)zb->zb_objset, - (u_longlong_t)zb->zb_object, - (longlong_t)zb->zb_level, - (u_longlong_t)blkid2offset(dnp, bp, zb), - blkbuf); - } - if (dump_opt['b'] < 5 && isatty(STDERR_FILENO) && gethrtime() > zcb->zcb_lastprint + NANOSEC) { uint64_t now = gethrtime(); @@ -2406,7 +2415,7 @@ count_block_cb(void *arg, const blkptr_t if (dump_opt['b'] >= 5) { char blkbuf[BP_SPRINTF_LEN]; - sprintf_blkptr(blkbuf, bp); + snprintf_blkptr(blkbuf, sizeof (blkbuf), bp); (void) printf("[%s] %s\n", "deferred free", blkbuf); } @@ -2640,7 +2649,7 @@ zdb_ddt_add_cb(spa_t *spa, zilog_t *zilo avl_index_t where; zdb_ddt_entry_t *zdde, zdde_search; - if (bp == NULL) + if (BP_IS_HOLE(bp)) return (0); if (dump_opt['S'] > 1 && zb->zb_level == ZB_ROOT_LEVEL) { @@ -2807,7 +2816,7 @@ zdb_print_blkptr(blkptr_t *bp, int flags if (flags & ZDB_FLAG_BSWAP) byteswap_uint64_array((void *)bp, sizeof (blkptr_t)); - sprintf_blkptr(blkbuf, bp); + snprintf_blkptr(blkbuf, sizeof (blkbuf), bp); (void) printf("%s\n", blkbuf); } Modified: stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb_il.c ============================================================================== --- stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb_il.c Wed Mar 19 23:55:03 2014 (r263397) +++ stable/9/cddl/contrib/opensolaris/cmd/zdb/zdb_il.c Wed Mar 19 23:58:05 2014 (r263398) @@ -24,6 +24,10 @@ */ /* + * Copyright (c) 2013 by Delphix. All rights reserved. + */ + +/* * Print intent log header and statistics. */ @@ -47,7 +51,7 @@ print_log_bp(const blkptr_t *bp, const c { char blkbuf[BP_SPRINTF_LEN]; - sprintf_blkptr(blkbuf, bp); + snprintf_blkptr(blkbuf, sizeof (blkbuf), bp); (void) printf("%s%s\n", prefix, blkbuf); } @@ -132,6 +136,7 @@ zil_prt_rec_write(zilog_t *zilog, int tx if (lr->lr_common.lrc_reclen == sizeof (lr_write_t)) { (void) printf("%shas blkptr, %s\n", prefix, + !BP_IS_HOLE(bp) && bp->blk_birth >= spa_first_txg(zilog->zl_spa) ? "will claim" : "won't claim"); print_log_bp(bp, prefix); @@ -139,8 +144,6 @@ zil_prt_rec_write(zilog_t *zilog, int tx if (BP_IS_HOLE(bp)) { (void) printf("\t\t\tLSIZE 0x%llx\n", (u_longlong_t)BP_GET_LSIZE(bp)); - } - if (bp->blk_birth == 0) { bzero(buf, sizeof (buf)); (void) printf("%s\n", prefix); return; @@ -313,7 +316,8 @@ print_log_block(zilog_t *zilog, blkptr_t if (verbose >= 5) { (void) strcpy(blkbuf, ", "); - sprintf_blkptr(blkbuf + strlen(blkbuf), bp); + snprintf_blkptr(blkbuf + strlen(blkbuf), + sizeof (blkbuf) - strlen(blkbuf), bp); } else { blkbuf[0] = '\0'; } @@ -361,7 +365,7 @@ dump_intent_log(zilog_t *zilog) int verbose = MAX(dump_opt['d'], dump_opt['i']); int i; - if (zh->zh_log.blk_birth == 0 || verbose < 1) + if (BP_IS_HOLE(&zh->zh_log) || verbose < 1) return; (void) printf("\n ZIL header: claim_txg %llu, " Modified: stable/9/cddl/contrib/opensolaris/cmd/zhack/zhack.c ============================================================================== --- stable/9/cddl/contrib/opensolaris/cmd/zhack/zhack.c Wed Mar 19 23:55:03 2014 (r263397) +++ stable/9/cddl/contrib/opensolaris/cmd/zhack/zhack.c Wed Mar 19 23:58:05 2014 (r263398) @@ -277,6 +277,9 @@ zhack_do_feature_stat(int argc, char **a dump_obj(os, spa->spa_feat_for_read_obj, "for_read"); dump_obj(os, spa->spa_feat_for_write_obj, "for_write"); dump_obj(os, spa->spa_feat_desc_obj, "descriptions"); + if (spa_feature_is_active(spa, SPA_FEATURE_ENABLED_TXG)) { + dump_obj(os, spa->spa_feat_enabled_txg_obj, "enabled_txg"); + } dump_mos(spa); spa_close(spa, FTAG); @@ -313,7 +316,9 @@ zhack_do_feature_enable(int argc, char * feature.fi_uname = "zhack"; feature.fi_mos = B_FALSE; feature.fi_can_readonly = B_FALSE; + feature.fi_activate_on_enable = B_FALSE; feature.fi_depends = nodeps; + feature.fi_feature = SPA_FEATURE_NONE; optind = 1; while ((c = getopt(argc, argv, "rmd:")) != -1) { @@ -371,7 +376,7 @@ feature_incr_sync(void *arg, dmu_tx_t *t zfeature_info_t *feature = arg; uint64_t refcount; - VERIFY0(feature_get_refcount(spa, feature, &refcount)); + VERIFY0(feature_get_refcount_from_disk(spa, feature, &refcount)); feature_sync(spa, feature, refcount + 1, tx); spa_history_log_internal(spa, "zhack feature incr", tx, "name=%s", feature->fi_guid); @@ -384,7 +389,7 @@ feature_decr_sync(void *arg, dmu_tx_t *t zfeature_info_t *feature = arg; uint64_t refcount; - VERIFY0(feature_get_refcount(spa, feature, &refcount)); + VERIFY0(feature_get_refcount_from_disk(spa, feature, &refcount)); feature_sync(spa, feature, refcount - 1, tx); spa_history_log_internal(spa, "zhack feature decr", tx, "name=%s", feature->fi_guid); @@ -411,6 +416,7 @@ zhack_do_feature_ref(int argc, char **ar feature.fi_mos = B_FALSE; feature.fi_desc = NULL; feature.fi_depends = nodeps; + feature.fi_feature = SPA_FEATURE_NONE; optind = 1; while ((c = getopt(argc, argv, "md")) != -1) { @@ -459,8 +465,8 @@ zhack_do_feature_ref(int argc, char **ar if (decr) { uint64_t count; - if (feature_get_refcount(spa, &feature, &count) == 0 && - count != 0) { + if (feature_get_refcount_from_disk(spa, &feature, + &count) == 0 && count != 0) { fatal(spa, FTAG, "feature refcount already 0: %s", feature.fi_guid); } Modified: stable/9/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 ============================================================================== --- stable/9/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 Wed Mar 19 23:55:03 2014 (r263397) +++ stable/9/cddl/contrib/opensolaris/cmd/zpool/zpool-features.7 Wed Mar 19 23:58:05 2014 (r263398) @@ -23,7 +23,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 08, 2013 +.Dd December 31, 2013 .Dt ZPOOL-FEATURES 7 .Os .Sh NAME @@ -286,6 +286,76 @@ and will be returned to the .Sy enabled state when all datasets that use this feature are destroyed. +.It Sy enabled_txg +.Bl -column "READ\-ONLY COMPATIBLE" "com.delphix:enabled_txg" +.It GUID Ta com.delphix:enabled_txg +.It READ\-ONLY COMPATIBLE Ta yes +.It DEPENDENCIES Ta none +.El +.Pp +Once this feature is enabled ZFS records the transaction group number +in which new features are enabled. This has no user-visible impact, +but other features may depend on this feature. +.Pp +This feature becomes +.Sy active +as soon as it is enabled and will +never return to being +.Sy enabled . +.It Sy hole_birth +.Bl -column "READ\-ONLY COMPATIBLE" "com.delphix:hole_birth" +.It GUID Ta com.delphix:hole_birth +.It READ\-ONLY COMPATIBLE Ta no +.It DEPENDENCIES Ta enabled_txg +.El +.Pp +This feature improves performance of incremental sends +.Pq Dq zfs send -i +and receives for objects with many holes. +The most common case of +hole-filled objects is zvols. +.Pp +An incremental send stream from snapshot +.Sy A +to snapshot +.Sy B +contains information about every block that changed between +.Sy A +and +.Sy B . +Blocks which did not change between those snapshots can be +identified and omitted from the stream using a piece of metadata called +the 'block birth time', but birth times are not recorded for holes +.Pq blocks filled only with zeroes . +Since holes created after +.Sy A +cannot be +distinguished from holes created before +.Sy A , +information about every +hole in the entire filesystem or zvol is included in the send stream. +.Pp +For workloads where holes are rare this is not a problem. +However, when +incrementally replicating filesystems or zvols with many holes +.Pq for example a zvol formatted with another filesystem +a lot of time will +be spent sending and receiving unnecessary information about holes that +already exist on the receiving side. +.Pp +Once the +.Sy hole_birth +feature has been enabled the block birth times +of all new holes will be recorded. +Incremental sends between snapshots +created after this feature is enabled will use this new metadata to avoid +sending information about holes that already exist on the receiving side. +.Pp +This feature becomes +.Sy active +as soon as it is enabled and will +never return to being +.Sy enabled . .El .Sh SEE ALSO .Xr zpool 8 Modified: stable/9/lib/libprocstat/zfs/Makefile ============================================================================== --- stable/9/lib/libprocstat/zfs/Makefile Wed Mar 19 23:55:03 2014 (r263397) +++ stable/9/lib/libprocstat/zfs/Makefile Wed Mar 19 23:58:05 2014 (r263398) @@ -10,6 +10,7 @@ CFLAGS+= -I${.CURDIR}/../../../sys/cddl/ CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/include CFLAGS+= -I${.CURDIR}/../../../cddl/compat/opensolaris/lib/libumem CFLAGS+= -I${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libzpool/common +CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/common/zfs CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/fs/zfs CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common CFLAGS+= -I${.CURDIR}/../../../sys/cddl/contrib/opensolaris/uts/common/sys Modified: stable/9/sys/boot/zfs/zfsimpl.c ============================================================================== --- stable/9/sys/boot/zfs/zfsimpl.c Wed Mar 19 23:55:03 2014 (r263397) +++ stable/9/sys/boot/zfs/zfsimpl.c Wed Mar 19 23:58:05 2014 (r263398) @@ -53,6 +53,9 @@ static vdev_list_t zfs_vdevs; * List of ZFS features supported for read */ static const char *features_for_read[] = { + "org.illumos:lz4_compress", + "com.delphix:hole_birth", + "com.delphix:extensible_dataset", NULL }; Modified: stable/9/sys/cddl/boot/zfs/zfsimpl.h ============================================================================== --- stable/9/sys/cddl/boot/zfs/zfsimpl.h Wed Mar 19 23:55:03 2014 (r263397) +++ stable/9/sys/cddl/boot/zfs/zfsimpl.h Wed Mar 19 23:58:05 2014 (r263398) @@ -222,9 +222,10 @@ typedef struct blkptr { * Macros to get and set fields in a bp or DVA. */ #define DVA_GET_ASIZE(dva) \ - BF64_GET_SB((dva)->dva_word[0], 0, 24, SPA_MINBLOCKSHIFT, 0) + BF64_GET_SB((dva)->dva_word[0], 0, SPA_ASIZEBITS, SPA_MINBLOCKSHIFT, 0) #define DVA_SET_ASIZE(dva, x) \ - BF64_SET_SB((dva)->dva_word[0], 0, 24, SPA_MINBLOCKSHIFT, 0, x) + BF64_SET_SB((dva)->dva_word[0], 0, SPA_ASIZEBITS, \ + SPA_MINBLOCKSHIFT, 0, x) #define DVA_GET_GRID(dva) BF64_GET((dva)->dva_word[0], 24, 8) #define DVA_SET_GRID(dva, x) BF64_SET((dva)->dva_word[0], 24, 8, x) @@ -242,14 +243,14 @@ typedef struct blkptr { #define BP_GET_LSIZE(bp) \ (BP_IS_HOLE(bp) ? 0 : \ - BF64_GET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1)) + BF64_GET_SB((bp)->blk_prop, 0, SPA_LSIZEBITS, SPA_MINBLOCKSHIFT, 1)) #define BP_SET_LSIZE(bp, x) \ - BF64_SET_SB((bp)->blk_prop, 0, 16, SPA_MINBLOCKSHIFT, 1, x) + BF64_SET_SB((bp)->blk_prop, 0, SPA_LSIZEBITS, SPA_MINBLOCKSHIFT, 1, x) #define BP_GET_PSIZE(bp) \ - BF64_GET_SB((bp)->blk_prop, 16, 16, SPA_MINBLOCKSHIFT, 1) + BF64_GET_SB((bp)->blk_prop, 16, SPA_LSIZEBITS, SPA_MINBLOCKSHIFT, 1) #define BP_SET_PSIZE(bp, x) \ - BF64_SET_SB((bp)->blk_prop, 16, 16, SPA_MINBLOCKSHIFT, 1, x) + BF64_SET_SB((bp)->blk_prop, 16, SPA_LSIZEBITS, SPA_MINBLOCKSHIFT, 1, x) #define BP_GET_COMPRESS(bp) BF64_GET((bp)->blk_prop, 32, 8) #define BP_SET_COMPRESS(bp, x) BF64_SET((bp)->blk_prop, 32, 8, x) @@ -266,7 +267,7 @@ typedef struct blkptr { #define BP_GET_DEDUP(bp) BF64_GET((bp)->blk_prop, 62, 1) #define BP_SET_DEDUP(bp, x) BF64_SET((bp)->blk_prop, 62, 1, x) -#define BP_GET_BYTEORDER(bp) (0 - BF64_GET((bp)->blk_prop, 63, 1)) +#define BP_GET_BYTEORDER(bp) BF64_GET((bp)->blk_prop, 63, 1) #define BP_SET_BYTEORDER(bp, x) BF64_SET((bp)->blk_prop, 63, 1, x) #define BP_PHYSICAL_BIRTH(bp) \ @@ -285,11 +286,6 @@ typedef struct blkptr { !!DVA_GET_ASIZE(&(bp)->blk_dva[1]) + \ !!DVA_GET_ASIZE(&(bp)->blk_dva[2])) -#define BP_COUNT_GANG(bp) \ - (DVA_GET_GANG(&(bp)->blk_dva[0]) + \ - DVA_GET_GANG(&(bp)->blk_dva[1]) + \ - DVA_GET_GANG(&(bp)->blk_dva[2])) - #define DVA_EQUAL(dva1, dva2) \ ((dva1)->dva_word[1] == (dva2)->dva_word[1] && \ (dva1)->dva_word[0] == (dva2)->dva_word[0]) @@ -313,7 +309,9 @@ typedef struct blkptr { #define BP_IDENTITY(bp) (&(bp)->blk_dva[0]) #define BP_IS_GANG(bp) DVA_GET_GANG(BP_IDENTITY(bp)) -#define BP_IS_HOLE(bp) ((bp)->blk_birth == 0) +#define DVA_IS_EMPTY(dva) ((dva)->dva_word[0] == 0ULL && \ + (dva)->dva_word[1] == 0ULL) +#define BP_IS_HOLE(bp) DVA_IS_EMPTY(BP_IDENTITY(bp)) #define BP_IS_OLDER(bp, txg) (!BP_IS_HOLE(bp) && (bp)->blk_birth < (txg)) #define BP_ZERO(bp) \ Modified: stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c ============================================================================== --- stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c Wed Mar 19 23:55:03 2014 (r263397) +++ stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.c Wed Mar 19 23:58:05 2014 (r263398) @@ -114,10 +114,21 @@ zfeature_lookup_name(const char *name, s return (ENOENT); } +boolean_t +zfeature_depends_on(spa_feature_t fid, spa_feature_t check) { + zfeature_info_t *feature = &spa_feature_table[fid]; + + for (int i = 0; feature->fi_depends[i] != SPA_FEATURE_NONE; i++) { + if (feature->fi_depends[i] == check) + return (B_TRUE); + } + return (B_FALSE); +} + static void zfeature_register(spa_feature_t fid, const char *guid, const char *name, const char *desc, boolean_t readonly, boolean_t mos, - const spa_feature_t *deps) + boolean_t activate_on_enable, const spa_feature_t *deps) { zfeature_info_t *feature = &spa_feature_table[fid]; static spa_feature_t nodeps[] = { SPA_FEATURE_NONE }; @@ -137,6 +148,7 @@ zfeature_register(spa_feature_t fid, con feature->fi_desc = desc; feature->fi_can_readonly = readonly; feature->fi_mos = mos; + feature->fi_activate_on_enable = activate_on_enable; feature->fi_depends = deps; } @@ -145,21 +157,43 @@ zpool_feature_init(void) { zfeature_register(SPA_FEATURE_ASYNC_DESTROY, "com.delphix:async_destroy", "async_destroy", - "Destroy filesystems asynchronously.", B_TRUE, B_FALSE, NULL); + "Destroy filesystems asynchronously.", B_TRUE, B_FALSE, + B_FALSE, NULL); + zfeature_register(SPA_FEATURE_EMPTY_BPOBJ, "com.delphix:empty_bpobj", "empty_bpobj", - "Snapshots use less space.", B_TRUE, B_FALSE, NULL); + "Snapshots use less space.", B_TRUE, B_FALSE, + B_FALSE, NULL); + zfeature_register(SPA_FEATURE_LZ4_COMPRESS, "org.illumos:lz4_compress", "lz4_compress", - "LZ4 compression algorithm support.", B_FALSE, B_FALSE, NULL); + "LZ4 compression algorithm support.", B_FALSE, B_FALSE, + B_FALSE, NULL); + zfeature_register(SPA_FEATURE_MULTI_VDEV_CRASH_DUMP, "com.joyent:multi_vdev_crash_dump", "multi_vdev_crash_dump", - "Crash dumps to multiple vdev pools.", B_FALSE, B_FALSE, NULL); + "Crash dumps to multiple vdev pools.", B_FALSE, B_FALSE, + B_FALSE, NULL); + zfeature_register(SPA_FEATURE_SPACEMAP_HISTOGRAM, "com.delphix:spacemap_histogram", "spacemap_histogram", - "Spacemaps maintain space histograms.", B_TRUE, B_FALSE, NULL); + "Spacemaps maintain space histograms.", B_TRUE, B_FALSE, + B_FALSE, NULL); + + zfeature_register(SPA_FEATURE_ENABLED_TXG, + "com.delphix:enabled_txg", "enabled_txg", + "Record txg at which a feature is enabled", B_TRUE, B_FALSE, + B_FALSE, NULL); + + static spa_feature_t hole_birth_deps[] = { SPA_FEATURE_ENABLED_TXG, + SPA_FEATURE_NONE }; + zfeature_register(SPA_FEATURE_HOLE_BIRTH, + "com.delphix:hole_birth", "hole_birth", + "Retain hole birth txg for more precise zfs send", + B_FALSE, B_TRUE, B_TRUE, hole_birth_deps); + zfeature_register(SPA_FEATURE_EXTENSIBLE_DATASET, "com.delphix:extensible_dataset", "extensible_dataset", "Enhanced dataset functionality, used by other features.", - B_FALSE, B_FALSE, NULL); + B_FALSE, B_FALSE, B_FALSE, NULL); } Modified: stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h ============================================================================== --- stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h Wed Mar 19 23:55:03 2014 (r263397) +++ stable/9/sys/cddl/contrib/opensolaris/common/zfs/zfeature_common.h Wed Mar 19 23:58:05 2014 (r263398) @@ -44,10 +44,14 @@ typedef enum spa_feature { SPA_FEATURE_LZ4_COMPRESS, SPA_FEATURE_MULTI_VDEV_CRASH_DUMP, SPA_FEATURE_SPACEMAP_HISTOGRAM, + SPA_FEATURE_ENABLED_TXG, + SPA_FEATURE_HOLE_BIRTH, SPA_FEATURE_EXTENSIBLE_DATASET, SPA_FEATURES } spa_feature_t; +#define SPA_FEATURE_DISABLED (-1ULL) + typedef struct zfeature_info { spa_feature_t fi_feature; const char *fi_uname; /* User-facing feature name */ @@ -55,6 +59,8 @@ typedef struct zfeature_info { const char *fi_desc; /* Feature description */ boolean_t fi_can_readonly; /* Can open pool readonly w/o support? */ boolean_t fi_mos; /* Is the feature necessary to read the MOS? */ + /* Activate this feature at the same time it is enabled */ + boolean_t fi_activate_on_enable; /* array of dependencies, terminated by SPA_FEATURE_NONE */ const spa_feature_t *fi_depends; } zfeature_info_t; @@ -69,6 +75,7 @@ extern boolean_t zfeature_is_valid_guid( extern boolean_t zfeature_is_supported(const char *); extern int zfeature_lookup_name(const char *name, spa_feature_t *res); +extern boolean_t zfeature_depends_on(spa_feature_t fid, spa_feature_t check); extern void zpool_feature_init(void); Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c ============================================================================== --- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c Wed Mar 19 23:55:03 2014 (r263397) +++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c Wed Mar 19 23:58:05 2014 (r263398) @@ -845,7 +845,7 @@ buf_hash(uint64_t spa, const dva_t *dva, #define BUF_EMPTY(buf) \ ((buf)->b_dva.dva_word[0] == 0 && \ (buf)->b_dva.dva_word[1] == 0 && \ - (buf)->b_birth == 0) + (buf)->b_cksum0 == 0) #define BUF_EQUAL(spa, dva, birth, buf) \ ((buf)->b_dva.dva_word[0] == (dva)->dva_word[0]) && \ @@ -3767,9 +3767,13 @@ arc_write_done(zio_t *zio) ASSERT(hdr->b_acb == NULL); if (zio->io_error == 0) { - hdr->b_dva = *BP_IDENTITY(zio->io_bp); - hdr->b_birth = BP_PHYSICAL_BIRTH(zio->io_bp); - hdr->b_cksum0 = zio->io_bp->blk_cksum.zc_word[0]; + if (BP_IS_HOLE(zio->io_bp)) { + buf_discard_identity(hdr); + } else { + hdr->b_dva = *BP_IDENTITY(zio->io_bp); + hdr->b_birth = BP_PHYSICAL_BIRTH(zio->io_bp); + hdr->b_cksum0 = zio->io_bp->blk_cksum.zc_word[0]; + } } else { ASSERT(BUF_EMPTY(hdr)); } Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c ============================================================================== --- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c Wed Mar 19 23:55:03 2014 (r263397) +++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c Wed Mar 19 23:58:05 2014 (r263398) @@ -20,7 +20,7 @@ */ /* - * Copyright (c) 2012 by Delphix. All rights reserved. + * Copyright (c) 2013 by Delphix. All rights reserved. */ #include @@ -141,7 +141,7 @@ bptree_visit_cb(spa_t *spa, zilog_t *zil int err; struct bptree_args *ba = arg; - if (bp == NULL) + if (BP_IS_HOLE(bp)) return (0); err = ba->ba_func(ba->ba_arg, bp, ba->ba_tx); Modified: stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c ============================================================================== --- stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c Wed Mar 19 23:55:03 2014 (r263397) +++ stable/9/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c Wed Mar 19 23:58:05 2014 (r263398) @@ -455,10 +455,9 @@ dbuf_loan_arcbuf(dmu_buf_impl_t *db) mutex_enter(&db->db_mtx); if (arc_released(db->db_buf) || refcount_count(&db->db_holds) > 1) { int blksz = db->db.db_size; - spa_t *spa; + spa_t *spa = db->db_objset->os_spa; mutex_exit(&db->db_mtx); - DB_GET_SPA(&spa, db); abuf = arc_loan_buf(spa, blksz); bcopy(db->db.db_data, abuf->b_data, blksz); } else { @@ -519,7 +518,6 @@ static void dbuf_read_impl(dmu_buf_impl_t *db, zio_t *zio, uint32_t *flags) { dnode_t *dn; - spa_t *spa; zbookmark_t zb; uint32_t aflags = ARC_NOWAIT; @@ -559,9 +557,9 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t BP_IS_HOLE(db->db_blkptr)))) { arc_buf_contents_t type = DBUF_GET_BUFC_TYPE(db); - dbuf_set_data(db, arc_buf_alloc(dn->dn_objset->os_spa, - db->db.db_size, db, type)); DB_DNODE_EXIT(db); + dbuf_set_data(db, arc_buf_alloc(db->db_objset->os_spa, + db->db.db_size, db, type)); bzero(db->db.db_data, db->db.db_size); db->db_state = DB_CACHED; *flags |= DB_RF_CACHED; @@ -569,7 +567,6 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t return; } - spa = dn->dn_objset->os_spa; DB_DNODE_EXIT(db); db->db_state = DB_READ; @@ -586,7 +583,7 @@ dbuf_read_impl(dmu_buf_impl_t *db, zio_t dbuf_add_ref(db, NULL); - (void) arc_read(zio, spa, db->db_blkptr, + (void) arc_read(zio, db->db_objset->os_spa, db->db_blkptr, dbuf_read_done, db, ZIO_PRIORITY_SYNC_READ, (*flags & DB_RF_CANFAIL) ? ZIO_FLAG_CANFAIL : ZIO_FLAG_MUSTSUCCEED, &aflags, &zb); @@ -598,8 +595,8 @@ int dbuf_read(dmu_buf_impl_t *db, zio_t *zio, uint32_t flags) { int err = 0; - int havepzio = (zio != NULL); - int prefetch; + boolean_t havepzio = (zio != NULL); + boolean_t prefetch; dnode_t *dn; /* @@ -694,11 +691,10 @@ dbuf_noread(dmu_buf_impl_t *db) cv_wait(&db->db_changed, &db->db_mtx); if (db->db_state == DB_UNCACHED) { arc_buf_contents_t type = DBUF_GET_BUFC_TYPE(db); - spa_t *spa; + spa_t *spa = db->db_objset->os_spa; ASSERT(db->db_buf == NULL); ASSERT(db->db.db_data == NULL); - DB_GET_SPA(&spa, db); dbuf_set_data(db, arc_buf_alloc(spa, db->db.db_size, db, type)); db->db_state = DB_FILL; } else if (db->db_state == DB_NOFILL) { @@ -753,9 +749,8 @@ dbuf_fix_old_data(dmu_buf_impl_t *db, ui } else if (refcount_count(&db->db_holds) > db->db_dirtycnt) { int size = db->db.db_size; arc_buf_contents_t type = DBUF_GET_BUFC_TYPE(db); - spa_t *spa; + spa_t *spa = db->db_objset->os_spa; - DB_GET_SPA(&spa, db); dr->dt.dl.dr_data = arc_buf_alloc(spa, size, db, type); bcopy(db->db.db_data, dr->dt.dl.dr_data->b_data, size); } else { @@ -781,12 +776,9 @@ dbuf_unoverride(dbuf_dirty_record_t *dr) ASSERT(db->db_data_pending != dr); /* free this block */ - if (!BP_IS_HOLE(bp) && !dr->dt.dl.dr_nopwrite) { - spa_t *spa; + if (!BP_IS_HOLE(bp) && !dr->dt.dl.dr_nopwrite) + zio_free(db->db_objset->os_spa, txg, bp); - DB_GET_SPA(&spa, db); - zio_free(spa, txg, bp); - } dr->dt.dl.dr_override_state = DR_NOT_OVERRIDDEN; dr->dt.dl.dr_nopwrite = B_FALSE; @@ -804,9 +796,7 @@ dbuf_unoverride(dbuf_dirty_record_t *dr) /* * Evict (if its unreferenced) or clear (if its referenced) any level-0 * data blocks in the free range, so that any future readers will find - * empty blocks. Also, if we happen across any level-1 dbufs in the - * range that have not already been marked dirty, mark them dirty so - * they stay in memory. + * empty blocks. * * This is a no-op if the dataset is in the middle of an incremental * receive; see comment below for details. @@ -816,14 +806,9 @@ dbuf_free_range(dnode_t *dn, uint64_t st { dmu_buf_impl_t *db, *db_next; uint64_t txg = tx->tx_txg; - int epbs = dn->dn_indblkshift - SPA_BLKPTRSHIFT; - uint64_t first_l1 = start >> epbs; - uint64_t last_l1 = end >> epbs; - if (end > dn->dn_maxblkid && (end != DMU_SPILL_BLKID)) { + if (end > dn->dn_maxblkid && (end != DMU_SPILL_BLKID)) end = dn->dn_maxblkid; - last_l1 = end >> epbs; - } dprintf_dnode(dn, "start=%llu end=%llu\n", start, end); mutex_enter(&dn->dn_dbufs_mtx); @@ -846,23 +831,8 @@ dbuf_free_range(dnode_t *dn, uint64_t st db_next = list_next(&dn->dn_dbufs, db); ASSERT(db->db_blkid != DMU_BONUS_BLKID); - if (db->db_level == 1 && - db->db_blkid >= first_l1 && db->db_blkid <= last_l1) { - mutex_enter(&db->db_mtx); - if (db->db_last_dirty && - db->db_last_dirty->dr_txg < txg) { - dbuf_add_ref(db, FTAG); - mutex_exit(&db->db_mtx); - dbuf_will_dirty(db, tx); - dbuf_rele(db, FTAG); - } else { - mutex_exit(&db->db_mtx); - } - } - if (db->db_level != 0) continue; - dprintf_dbuf(db, "found buf %s\n", ""); if (db->db_blkid < start || db->db_blkid > end) continue; @@ -939,24 +909,29 @@ dbuf_block_freeable(dmu_buf_impl_t *db) * We don't need any locking to protect db_blkptr: * If it's syncing, then db_last_dirty will be set * so we'll ignore db_blkptr. + * + * This logic ensures that only block births for + * filled blocks are considered. */ ASSERT(MUTEX_HELD(&db->db_mtx)); - if (db->db_last_dirty) + if (db->db_last_dirty && (db->db_blkptr == NULL || + !BP_IS_HOLE(db->db_blkptr))) { birth_txg = db->db_last_dirty->dr_txg; - else if (db->db_blkptr) + } else if (db->db_blkptr != NULL && !BP_IS_HOLE(db->db_blkptr)) { birth_txg = db->db_blkptr->blk_birth; + } /* - * If we don't exist or are in a snapshot, we can't be freed. + * If this block don't exist or is in a snapshot, it can't be freed. * Don't pass the bp to dsl_dataset_block_freeable() since we * are holding the db_mtx lock and might deadlock if we are * prefetching a dedup-ed block. */ - if (birth_txg) + if (birth_txg != 0) return (ds == NULL || dsl_dataset_block_freeable(ds, NULL, birth_txg)); else - return (FALSE); + return (B_FALSE); } void @@ -976,7 +951,7 @@ dbuf_new_size(dmu_buf_impl_t *db, int si ASSERT(RW_WRITE_HELD(&dn->dn_struct_rwlock)); /* - * This call to dbuf_will_dirty() with the dn_struct_rwlock held + * This call to dmu_buf_will_dirty() with the dn_struct_rwlock held * is OK, because there can be no other references to the db * when we are changing its size, so no concurrent DB_FILL can * be happening. @@ -985,7 +960,7 @@ dbuf_new_size(dmu_buf_impl_t *db, int si * XXX we should be doing a dbuf_read, checking the return * value and returning that up to our callers */ - dbuf_will_dirty(db, tx); + dmu_buf_will_dirty(&db->db, tx); /* create the data buffer for the new block */ buf = arc_buf_alloc(dn->dn_objset->os_spa, size, db, type); @@ -1015,9 +990,8 @@ dbuf_new_size(dmu_buf_impl_t *db, int si void dbuf_release_bp(dmu_buf_impl_t *db) { - objset_t *os; + objset_t *os = db->db_objset; - DB_GET_OBJSET(&os, db); ASSERT(dsl_pool_sync_context(dmu_objset_pool(os))); ASSERT(arc_released(os->os_phys_buf) || list_link_active(&os->os_dsl_dataset->ds_synced_link)); @@ -1391,10 +1365,10 @@ dbuf_undirty(dmu_buf_impl_t *db, dmu_tx_ return (B_FALSE); } -#pragma weak dmu_buf_will_dirty = dbuf_will_dirty void -dbuf_will_dirty(dmu_buf_impl_t *db, dmu_tx_t *tx) +dmu_buf_will_dirty(dmu_buf_t *db_fake, dmu_tx_t *tx) { + dmu_buf_impl_t *db = (dmu_buf_impl_t *)db_fake; int rf = DB_RF_MUST_SUCCEED | DB_RF_NOPREFETCH; ASSERT(tx->tx_txg != 0); @@ -1517,7 +1491,7 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, a db->db_state = DB_FILL; mutex_exit(&db->db_mtx); (void) dbuf_dirty(db, tx); - dbuf_fill_done(db, tx); + dmu_buf_fill_done(&db->db, tx); } /* @@ -2022,7 +1996,6 @@ dbuf_add_ref(dmu_buf_impl_t *db, void *t * Without that, the dbuf_rele() could lead to a dnode_rele() followed by the * dnode's parent dbuf evicting its dnode handles. */ -#pragma weak dmu_buf_rele = dbuf_rele void dbuf_rele(dmu_buf_impl_t *db, void *tag) { @@ -2030,6 +2003,12 @@ dbuf_rele(dmu_buf_impl_t *db, void *tag) dbuf_rele_and_unlock(db, tag); } +void +dmu_buf_rele(dmu_buf_t *db, void *tag) +{ + dbuf_rele((dmu_buf_impl_t *)db, tag); +} + /* * dbuf_rele() for an already-locked dbuf. This is necessary to allow * db_dirtycnt and db_holds to be updated atomically. @@ -2480,18 +2459,14 @@ dbuf_write_ready(zio_t *zio, arc_buf_t * dnode_diduse_space(dn, delta - zio->io_prev_space_delta); zio->io_prev_space_delta = delta; - if (BP_IS_HOLE(bp)) { - ASSERT(bp->blk_fill == 0); - DB_DNODE_EXIT(db); - return; + if (bp->blk_birth != 0) { + ASSERT((db->db_blkid != DMU_SPILL_BLKID && + BP_GET_TYPE(bp) == dn->dn_type) || + (db->db_blkid == DMU_SPILL_BLKID && + BP_GET_TYPE(bp) == dn->dn_bonustype)); + ASSERT(BP_GET_LEVEL(bp) == db->db_level); } - ASSERT((db->db_blkid != DMU_SPILL_BLKID && - BP_GET_TYPE(bp) == dn->dn_type) || - (db->db_blkid == DMU_SPILL_BLKID && - BP_GET_TYPE(bp) == dn->dn_bonustype)); - ASSERT(BP_GET_LEVEL(bp) == db->db_level); - mutex_enter(&db->db_mtx); #ifdef ZFS_DEBUG @@ -2517,7 +2492,11 @@ dbuf_write_ready(zio_t *zio, arc_buf_t * fill++; } } else { - fill = 1; + if (BP_IS_HOLE(bp)) { + fill = 0; + } else { + fill = 1; + } } } else { blkptr_t *ibp = db->db.db_data; @@ -2572,9 +2551,10 @@ static void dbuf_write_done(zio_t *zio, arc_buf_t *buf, void *vdb) { dmu_buf_impl_t *db = vdb; - blkptr_t *bp = zio->io_bp; blkptr_t *bp_orig = &zio->io_bp_orig; - uint64_t txg = zio->io_txg; + blkptr_t *bp = db->db_blkptr; + objset_t *os = db->db_objset; + dmu_tx_t *tx = os->os_synctx; dbuf_dirty_record_t **drp, *dr; ASSERT0(zio->io_error); @@ -2587,14 +2567,7 @@ dbuf_write_done(zio_t *zio, arc_buf_t *b if (zio->io_flags & (ZIO_FLAG_IO_REWRITE | ZIO_FLAG_NOPWRITE)) { ASSERT(BP_EQUAL(bp, bp_orig)); } else { - objset_t *os; - dsl_dataset_t *ds; - dmu_tx_t *tx; - - DB_GET_OBJSET(&os, db); - ds = os->os_dsl_dataset; - tx = os->os_synctx; - + dsl_dataset_t *ds = os->os_dsl_dataset; (void) dsl_dataset_block_kill(ds, bp_orig, tx, B_TRUE); dsl_dataset_block_born(ds, bp, tx); } @@ -2607,7 +2580,6 @@ dbuf_write_done(zio_t *zio, arc_buf_t *b *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***