diff --git a/include/sys/dsl_bookmark.h b/include/sys/dsl_bookmark.h index e477bb231c..3cdad74414 100644 --- a/include/sys/dsl_bookmark.h +++ b/include/sys/dsl_bookmark.h @@ -36,8 +36,25 @@ typedef struct zfs_bookmark_phys { uint64_t zbm_guid; /* guid of bookmarked dataset */ uint64_t zbm_creation_txg; /* birth transaction group */ uint64_t zbm_creation_time; /* bookmark creation time */ + + /* the following fields are reserved for redacted send / recv */ + uint64_t zbm_redaction_obj; /* redaction list object */ + uint64_t zbm_flags; /* ZBM_FLAG_* */ + uint64_t zbm_referenced_bytes_refd; + uint64_t zbm_compressed_bytes_refd; + uint64_t zbm_uncompressed_bytes_refd; + uint64_t zbm_referenced_freed_before_next_snap; + uint64_t zbm_compressed_freed_before_next_snap; + uint64_t zbm_uncompressed_freed_before_next_snap; + + /* fields used for raw sends */ + uint64_t zbm_ivset_guid; } zfs_bookmark_phys_t; + +#define BOOKMARK_PHYS_SIZE_V1 (3 * sizeof (uint64_t)) +#define BOOKMARK_PHYS_SIZE_V2 (12 * sizeof (uint64_t)) + int dsl_bookmark_create(nvlist_t *, nvlist_t *); int dsl_get_bookmarks(const char *, nvlist_t *, nvlist_t *); int dsl_get_bookmarks_impl(dsl_dataset_t *, nvlist_t *, nvlist_t *); diff --git a/include/zfeature_common.h b/include/zfeature_common.h index 089a7e29d1..4e75fe71e3 100644 --- a/include/zfeature_common.h +++ b/include/zfeature_common.h @@ -66,6 +66,7 @@ typedef enum spa_feature { SPA_FEATURE_SPACEMAP_V2, SPA_FEATURE_ALLOCATION_CLASSES, SPA_FEATURE_RESILVER_DEFER, + SPA_FEATURE_BOOKMARK_V2, SPA_FEATURES } spa_feature_t; diff --git a/man/man5/zpool-features.5 b/man/man5/zpool-features.5 index 4769c4eac3..919fb673da 100644 --- a/man/man5/zpool-features.5 +++ b/man/man5/zpool-features.5 @@ -702,6 +702,27 @@ files. .RE +.sp +.ne 2 +.na +\fB\fBbookmark_v2\fR\fR +.ad +.RS 4n +.TS +l l . +GUID com.datto:bookmark_v2 +READ\-ONLY COMPATIBLE no +DEPENDENCIES extensible_dataset +.TE + +This feature enables the creation and management of larger bookmarks which are +needed for other features in ZFS. + +This feature becomes \fBactive\fR when a v2 bookmark is created and will be +returned to the \fBenabled\fR state when all v2 bookmarks are destroyed. + +.RE + .sp .ne 2 .na diff --git a/module/zcommon/zfeature_common.c b/module/zcommon/zfeature_common.c index 80f4a05628..74ff2b6570 100644 --- a/module/zcommon/zfeature_common.c +++ b/module/zcommon/zfeature_common.c @@ -439,6 +439,17 @@ zpool_feature_init(void) ZFEATURE_TYPE_BOOLEAN, userobj_accounting_deps); } + { + static const spa_feature_t bookmark_v2_deps[] = { + SPA_FEATURE_EXTENSIBLE_DATASET, + SPA_FEATURE_NONE + }; + zfeature_register(SPA_FEATURE_BOOKMARK_V2, + "com.datto:bookmark_v2", "bookmark_v2", + "Support for larger bookmarks", + 0, ZFEATURE_TYPE_BOOLEAN, bookmark_v2_deps); + } + { static const spa_feature_t encryption_deps[] = { SPA_FEATURE_EXTENSIBLE_DATASET, diff --git a/module/zfs/dsl_bookmark.c b/module/zfs/dsl_bookmark.c index 0a58115341..08e8355414 100644 --- a/module/zfs/dsl_bookmark.c +++ b/module/zfs/dsl_bookmark.c @@ -70,6 +70,12 @@ dsl_dataset_bmark_lookup(dsl_dataset_t *ds, const char *shortname, if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET) mt = MT_NORMALIZE; + /* + * Zero out the bookmark in case the one stored on disk + * is in an older, shorter format. + */ + bzero(bmark_phys, sizeof (*bmark_phys)); + err = zap_lookup_norm(mos, bmark_zapobj, shortname, sizeof (uint64_t), sizeof (*bmark_phys) / sizeof (uint64_t), bmark_phys, mt, NULL, 0, NULL); @@ -188,8 +194,9 @@ dsl_bookmark_create_sync(void *arg, dmu_tx_t *tx) for (nvpair_t *pair = nvlist_next_nvpair(dbca->dbca_bmarks, NULL); pair != NULL; pair = nvlist_next_nvpair(dbca->dbca_bmarks, pair)) { dsl_dataset_t *snapds, *bmark_fs; - zfs_bookmark_phys_t bmark_phys; + zfs_bookmark_phys_t bmark_phys = { 0 }; char *shortname; + uint32_t bmark_len = BOOKMARK_PHYS_SIZE_V1; VERIFY0(dsl_dataset_hold(dp, fnvpair_value_string(pair), FTAG, &snapds)); @@ -216,8 +223,7 @@ dsl_bookmark_create_sync(void *arg, dmu_tx_t *tx) VERIFY0(zap_add(mos, bmark_fs->ds_bookmarks, shortname, sizeof (uint64_t), - sizeof (zfs_bookmark_phys_t) / sizeof (uint64_t), - &bmark_phys, tx)); + bmark_len / sizeof (uint64_t), &bmark_phys, tx)); spa_history_log_internal_ds(bmark_fs, "bookmark", tx, "name=%s creation_txg=%llu target_snap=%llu",