Add snapshots_changed as property

Make dd_snap_cmtime property persistent across mount and unmount
operations by storing in ZAP and restore the value from ZAP on hold
into dd_snap_cmtime instead of updating it.

Expose dd_snap_cmtime as 'snapshots_changed' property that provides a
mechanism to quickly determine whether snapshot list for dataset has
changed without having to mount a dataset or iterate the snapshot list.

It specifies the time at which a snapshot for a dataset was last
created or deleted. This allows us to be more efficient how often we
query snapshots.

Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Umer Saleem <usaleem@ixsystems.com>
Closes #13635
This commit is contained in:
Umer Saleem
2022-08-03 04:45:30 +05:00
committed by GitHub
parent 5ad44a0ce9
commit 9681de4657
14 changed files with 203 additions and 9 deletions
+5
View File
@@ -734,6 +734,11 @@ zfs_prop_init(void)
NULL, PROP_READONLY, ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK,
"<date>", "CREATION", B_FALSE, B_TRUE, B_TRUE, NULL, sfeatures);
zprop_register_impl(ZFS_PROP_SNAPSHOTS_CHANGED, "snapshots_changed",
PROP_TYPE_NUMBER, 0, NULL, PROP_READONLY, ZFS_TYPE_FILESYSTEM |
ZFS_TYPE_VOLUME, "<date>", "SNAPSHOTS_CHANGED", B_FALSE, B_TRUE,
B_TRUE, NULL, sfeatures);
zfs_mod_list_supported_free(sfeatures);
}
+4 -2
View File
@@ -534,7 +534,7 @@ dsl_dataset_snap_remove(dsl_dataset_t *ds, const char *name, dmu_tx_t *tx,
matchtype_t mt = 0;
int err;
dsl_dir_snap_cmtime_update(ds->ds_dir);
dsl_dir_snap_cmtime_update(ds->ds_dir, tx);
if (dsl_dataset_phys(ds)->ds_flags & DS_FLAG_CI_DATASET)
mt = MT_NORMALIZE;
@@ -1865,7 +1865,7 @@ dsl_dataset_snapshot_sync_impl(dsl_dataset_t *ds, const char *snapname,
dsl_scan_ds_snapshotted(ds, tx);
dsl_dir_snap_cmtime_update(ds->ds_dir);
dsl_dir_snap_cmtime_update(ds->ds_dir, tx);
spa_history_log_internal_ds(ds->ds_prev, "snapshot", tx, " ");
}
@@ -2809,6 +2809,8 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
dsl_get_userrefs(ds));
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_DEFER_DESTROY,
dsl_get_defer_destroy(ds));
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_SNAPSHOTS_CHANGED,
dsl_dir_snap_cmtime(ds->ds_dir).tv_sec);
dsl_dataset_crypt_stats(ds, nv);
if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) {
+14 -3
View File
@@ -207,8 +207,6 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj,
}
}
dsl_dir_snap_cmtime_update(dd);
if (dsl_dir_phys(dd)->dd_parent_obj) {
err = dsl_dir_hold_obj(dp,
dsl_dir_phys(dd)->dd_parent_obj, NULL, dd,
@@ -270,6 +268,14 @@ dsl_dir_hold_obj(dsl_pool_t *dp, uint64_t ddobj,
}
}
inode_timespec_t t = {0};
zap_lookup(dd->dd_pool->dp_meta_objset,
dsl_dir_phys(dd)->dd_props_zapobj,
zfs_prop_to_name(ZFS_PROP_SNAPSHOTS_CHANGED),
sizeof (uint64_t),
sizeof (inode_timespec_t) / sizeof (uint64_t), &t);
dd->dd_snap_cmtime = t;
dmu_buf_init_user(&dd->dd_dbu, NULL, dsl_dir_evict_async,
&dd->dd_dbuf);
winner = dmu_buf_set_user_ie(dbuf, &dd->dd_dbu);
@@ -2243,13 +2249,18 @@ dsl_dir_snap_cmtime(dsl_dir_t *dd)
}
void
dsl_dir_snap_cmtime_update(dsl_dir_t *dd)
dsl_dir_snap_cmtime_update(dsl_dir_t *dd, dmu_tx_t *tx)
{
inode_timespec_t t;
objset_t *mos = dd->dd_pool->dp_meta_objset;
uint64_t zapobj = dsl_dir_phys(dd)->dd_props_zapobj;
const char *prop_name = zfs_prop_to_name(ZFS_PROP_SNAPSHOTS_CHANGED);
gethrestime(&t);
mutex_enter(&dd->dd_lock);
dd->dd_snap_cmtime = t;
VERIFY0(zap_update(mos, zapobj, prop_name, sizeof (uint64_t),
sizeof (inode_timespec_t) / sizeof (uint64_t), &t, tx));
mutex_exit(&dd->dd_lock);
}
+4
View File
@@ -403,6 +403,10 @@ get_special_prop(lua_State *state, dsl_dataset_t *ds, const char *dsname,
break;
}
case ZFS_PROP_SNAPSHOTS_CHANGED:
numval = dsl_dir_snap_cmtime(ds->ds_dir).tv_sec;
break;
default:
/* Did not match these props, check in the dsl_dir */
error = get_dsl_dir_prop(ds, zfs_prop, &numval);