static void dsl_bookmark_create_sync(void *arg, dmu_tx_t *tx) { dsl_bookmark_create_arg_t *dbca = arg; dsl_pool_t *dp = dmu_tx_pool(tx); objset_t *mos = dp->dp_meta_objset; nvpair_t *pair; ASSERT(spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_BOOKMARKS)); for (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; char *shortname; VERIFY0(dsl_dataset_hold(dp, fnvpair_value_string(pair), FTAG, &snapds)); VERIFY0(dsl_bookmark_hold_ds(dp, nvpair_name(pair), &bmark_fs, FTAG, &shortname)); if (bmark_fs->ds_bookmarks == 0) { bmark_fs->ds_bookmarks = zap_create_norm(mos, U8_TEXTPREP_TOUPPER, DMU_OTN_ZAP_METADATA, DMU_OT_NONE, 0, tx); spa_feature_incr(dp->dp_spa, SPA_FEATURE_BOOKMARKS, tx); dsl_dataset_zapify(bmark_fs, tx); VERIFY0(zap_add(mos, bmark_fs->ds_object, DS_FIELD_BOOKMARK_NAMES, sizeof (bmark_fs->ds_bookmarks), 1, &bmark_fs->ds_bookmarks, tx)); } bmark_phys.zbm_guid = dsl_dataset_phys(snapds)->ds_guid; bmark_phys.zbm_creation_txg = dsl_dataset_phys(snapds)->ds_creation_txg; bmark_phys.zbm_creation_time = dsl_dataset_phys(snapds)->ds_creation_time; VERIFY0(zap_add(mos, bmark_fs->ds_bookmarks, shortname, sizeof (uint64_t), sizeof (zfs_bookmark_phys_t) / sizeof (uint64_t), &bmark_phys, tx)); spa_history_log_internal_ds(bmark_fs, "bookmark", tx, "name=%s creation_txg=%llu target_snap=%llu", shortname, (longlong_t)bmark_phys.zbm_creation_txg, (longlong_t)snapds->ds_object); dsl_dataset_rele(bmark_fs, FTAG); dsl_dataset_rele(snapds, FTAG); } }
static void dsl_bookmark_create_sync(void *arg, dmu_tx_t *tx) { dsl_bookmark_create_arg_t *dbca = arg; dsl_pool_t *dp = dmu_tx_pool(tx); objset_t *mos = dp->dp_meta_objset; nvpair_t *pair; ASSERT(spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_BOOKMARKS)); for (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 = { 0 }; char *shortname; uint32_t bmark_len = BOOKMARK_PHYS_SIZE_V1; VERIFY0(dsl_dataset_hold(dp, fnvpair_value_string(pair), FTAG, &snapds)); VERIFY0(dsl_bookmark_hold_ds(dp, nvpair_name(pair), &bmark_fs, FTAG, &shortname)); if (bmark_fs->ds_bookmarks == 0) { bmark_fs->ds_bookmarks = zap_create_norm(mos, U8_TEXTPREP_TOUPPER, DMU_OTN_ZAP_METADATA, DMU_OT_NONE, 0, tx); spa_feature_incr(dp->dp_spa, SPA_FEATURE_BOOKMARKS, tx); dsl_dataset_zapify(bmark_fs, tx); VERIFY0(zap_add(mos, bmark_fs->ds_object, DS_FIELD_BOOKMARK_NAMES, sizeof (bmark_fs->ds_bookmarks), 1, &bmark_fs->ds_bookmarks, tx)); } bmark_phys.zbm_guid = dsl_dataset_phys(snapds)->ds_guid; bmark_phys.zbm_creation_txg = dsl_dataset_phys(snapds)->ds_creation_txg; bmark_phys.zbm_creation_time = dsl_dataset_phys(snapds)->ds_creation_time; /* * If the dataset is encrypted create a larger bookmark to * accommodate the IVset guid. The IVset guid was added * after the encryption feature to prevent a problem with * raw sends. If we encounter an encrypted dataset without * an IVset guid we fall back to a normal bookmark. */ if (snapds->ds_dir->dd_crypto_obj != 0 && spa_feature_is_enabled(dp->dp_spa, SPA_FEATURE_BOOKMARK_V2)) { int err = zap_lookup(mos, snapds->ds_object, DS_FIELD_IVSET_GUID, sizeof (uint64_t), 1, &bmark_phys.zbm_ivset_guid); if (err == 0) { bmark_len = BOOKMARK_PHYS_SIZE_V2; spa_feature_incr(dp->dp_spa, SPA_FEATURE_BOOKMARK_V2, tx); } } VERIFY0(zap_add(mos, bmark_fs->ds_bookmarks, shortname, sizeof (uint64_t), 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", shortname, (longlong_t)bmark_phys.zbm_creation_txg, (longlong_t)snapds->ds_object); dsl_dataset_rele(bmark_fs, FTAG); dsl_dataset_rele(snapds, FTAG); } }