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 *);
SPA_FEATURE_SPACEMAP_V2,
SPA_FEATURE_ALLOCATION_CLASSES,
SPA_FEATURE_RESILVER_DEFER,
+ SPA_FEATURE_BOOKMARK_V2,
SPA_FEATURES
} spa_feature_t;
.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
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,
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);
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));
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",