Skip to content

Commit 36e9976

Browse files
committed
Add snapshots_changed_nsecs dataset property (#17998)
Signed-off-by: Wolfgang Hoschek <wolfgang.hoschek@mac.com>
1 parent 9fdb854 commit 36e9976

8 files changed

Lines changed: 86 additions & 10 deletions

File tree

include/sys/fs/zfs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ typedef enum {
193193
ZFS_PROP_REDACTED,
194194
ZFS_PROP_REDACT_SNAPS,
195195
ZFS_PROP_SNAPSHOTS_CHANGED,
196+
ZFS_PROP_SNAPSHOTS_CHANGED_NSECS,
196197
ZFS_PROP_PREFETCH,
197198
ZFS_PROP_VOLTHREADING,
198199
ZFS_PROP_DIRECT,

lib/libzfs/libzfs.abi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2451,6 +2451,7 @@
24512451
<enumerator name='ZFS_PROP_DEFAULTGROUPOBJQUOTA' value='104'/>
24522452
<enumerator name='ZFS_PROP_DEFAULTPROJECTOBJQUOTA' value='105'/>
24532453
<enumerator name='ZFS_NUM_PROPS' value='106'/>
2454+
<enumerator name='ZFS_PROP_SNAPSHOTS_CHANGED_NSECS' value='107'/>
24542455
</enum-decl>
24552456
<typedef-decl name='zfs_prop_t' type-id='4b000d60' id='58603c44'/>
24562457
<enum-decl name='zprop_source_t' naming-typedef-id='a2256d42' id='5903f80e'>

lib/libzfs/libzfs_dataset.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3001,6 +3001,13 @@ zfs_prop_get(zfs_handle_t *zhp, zfs_prop_t prop, char *propbuf, size_t proplen,
30013001
zcp_check(zhp, prop, val, NULL);
30023002
break;
30033003

3004+
case ZFS_PROP_SNAPSHOTS_CHANGED_NSECS:
3005+
if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
3006+
return (-1);
3007+
(void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
3008+
zcp_check(zhp, prop, val, NULL);
3009+
break;
3010+
30043011
default:
30053012
switch (zfs_prop_get_type(prop)) {
30063013
case PROP_TYPE_NUMBER:

man/man7/zfsprops.7

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,19 @@ This allows us to be more efficient how often we query snapshots.
535535
The property is persistent across mount and unmount operations only if the
536536
.Sy extensible_dataset
537537
feature is enabled.
538+
.It Sy snapshots_changed_nsecs
539+
Specifies the nanosecond component of the time at which a snapshot for a
540+
dataset was last created or deleted, corresponding to
541+
.Sy snapshots_changed .
542+
The value is in the range 0 to 999999999.
543+
It is only meaningful when
544+
.Sy snapshots_changed
545+
is not
546+
.Ql - .
547+
The full timestamp in nanoseconds since the Unix epoch can be reconstructed as
548+
.Sy snapshots_changed
549+
multiplied by 1000000000 plus
550+
.Sy snapshots_changed_nsecs .
538551
.It Sy volblocksize
539552
For volumes, specifies the block size of the volume.
540553
The

module/zcommon/zfs_prop.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,12 @@ zfs_prop_init(void)
796796
ZFS_TYPE_VOLUME, "<date>", "SNAPSHOTS_CHANGED", B_FALSE, B_TRUE,
797797
B_TRUE, NULL, sfeatures);
798798

799+
zprop_register_impl(ZFS_PROP_SNAPSHOTS_CHANGED_NSECS,
800+
"snapshots_changed_nsecs", PROP_TYPE_NUMBER, 0, NULL,
801+
PROP_READONLY, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "<nsec>",
802+
"SNAPSHOTS_CHANGED_NSECS", B_FALSE, B_FALSE, B_TRUE, NULL,
803+
sfeatures);
804+
799805
zprop_register_index(ZFS_PROP_LONGNAME, "longname", 0, PROP_INHERIT,
800806
ZFS_TYPE_FILESYSTEM, "on | off", "LONGNAME", boolean_table,
801807
sfeatures);

module/zfs/dsl_dataset.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2855,8 +2855,13 @@ dsl_dataset_stats(dsl_dataset_t *ds, nvlist_t *nv)
28552855
dsl_get_userrefs(ds));
28562856
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_DEFER_DESTROY,
28572857
dsl_get_defer_destroy(ds));
2858+
inode_timespec_t snap_cmtime = dsl_dir_snap_cmtime(ds->ds_dir);
28582859
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_SNAPSHOTS_CHANGED,
2859-
dsl_dir_snap_cmtime(ds->ds_dir).tv_sec);
2860+
snap_cmtime.tv_sec);
2861+
if (snap_cmtime.tv_sec != 0) {
2862+
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_SNAPSHOTS_CHANGED_NSECS,
2863+
snap_cmtime.tv_nsec);
2864+
}
28602865
dsl_dataset_crypt_stats(ds, nv);
28612866

28622867
if (dsl_dataset_phys(ds)->ds_prev_snap_obj != 0) {

module/zfs/zcp_get.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,10 @@ get_special_prop(lua_State *state, dsl_dataset_t *ds, const char *dsname,
434434
numval = dsl_dir_snap_cmtime(ds->ds_dir).tv_sec;
435435
break;
436436

437+
case ZFS_PROP_SNAPSHOTS_CHANGED_NSECS:
438+
numval = dsl_dir_snap_cmtime(ds->ds_dir).tv_nsec;
439+
break;
440+
437441
default:
438442
/* Did not match these props, check in the dsl_dir */
439443
error = get_dsl_dir_prop(ds, zfs_prop, &numval);

tests/zfs-tests/tests/functional/snapshot/snapshot_018_pos.ksh

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,22 @@
3030

3131
#
3232
# DESCRIPTION:
33-
# Verify the functionality of snapshots_changed property
33+
# Verify the functionality of snapshots_changed and snapshots_changed_nsecs properties.
3434
#
3535
# STRATEGY:
3636
# 1. Create a pool
37-
# 2. Verify snapshots_changed property is NULL
37+
# 2. Verify snapshots_changed and snapshots_changed_nsecs properties are NULL
3838
# 3. Create a filesystem
39-
# 4. Verify snapshots_changed property is NULL
39+
# 4. Verify snapshots_changed and snapshots_changed_nsecs properties are NULL
4040
# 5. Create snapshots for all filesystems
41-
# 6. Verify snapshots_changed property shows correct time
41+
# 6. Verify snapshots_changed property shows correct time and snapshots_changed_nsecs is a valid nanosecond value
4242
# 7. Unmount all filesystems
4343
# 8. Create a snapshot while unmounted
44-
# 9. Verify snapshots_changed
44+
# 9. Verify snapshots_changed and snapshots_changed_nsecs
4545
# 10. Mount the filsystems
46-
# 11. Verify snapshots_changed
46+
# 11. Verify snapshots_changed and snapshots_changed_nsecs
4747
# 12. Destroy the snapshots
48-
# 13. Verify snapshots_changed
48+
# 13. Verify snapshots_changed and snapshots_changed_nsecs
4949
#
5050

5151
function cleanup
@@ -55,7 +55,7 @@ function cleanup
5555

5656
verify_runnable "both"
5757

58-
log_assert "Verify snapshots_changed property"
58+
log_assert "Verify snapshots_changed and snapshots_changed_nsecs properties"
5959

6060
log_onexit cleanup
6161

@@ -67,62 +67,101 @@ snapdir=".zfs/snapshot"
6767
# Create filesystems and check snapshots_changed is NULL
6868
create_pool $TESTPOOL $DISKS
6969
snap_changed_testpool=$(zfs get -H -o value -p snapshots_changed $TESTPOOL)
70+
snap_changed_nsecs_testpool=$(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL)
7071
log_must eval "[[ $snap_changed_testpool == - ]]"
72+
log_must eval "[[ $snap_changed_nsecs_testpool == - ]]"
73+
list_changed_testpool=$(zfs list -H -p -o snapshots_changed $TESTPOOL)
74+
list_changed_nsecs_testpool=$(zfs list -H -p -o snapshots_changed_nsecs $TESTPOOL)
75+
log_must eval "[[ $list_changed_testpool == - ]]"
76+
log_must eval "[[ $list_changed_nsecs_testpool == - ]]"
7177
tpool_snapdir=$(get_prop mountpoint $TESTPOOL)/$snapdir
7278
log_must eval "[[ $(stat_mtime $tpool_snapdir) == 0 ]]"
7379

7480
log_must zfs create $TESTPOOL/$TESTFS
7581
snap_changed_testfs=$(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS)
82+
snap_changed_nsecs_testfs=$(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL/$TESTFS)
7683
log_must eval "[[ $snap_changed_testfs == - ]]"
84+
log_must eval "[[ $snap_changed_nsecs_testfs == - ]]"
85+
list_changed_testfs=$(zfs list -H -p -o snapshots_changed $TESTPOOL/$TESTFS)
86+
list_changed_nsecs_testfs=$(zfs list -H -p -o snapshots_changed_nsecs $TESTPOOL/$TESTFS)
87+
log_must eval "[[ $list_changed_testfs == - ]]"
88+
log_must eval "[[ $list_changed_nsecs_testfs == - ]]"
7789
tfs_snapdir=$(get_prop mountpoint $TESTPOOL/$TESTFS)/$snapdir
7890
log_must eval "[[ $(stat_mtime $tfs_snapdir) == 0 ]]"
7991

8092
# Create snapshots for filesystems and check snapshots_changed reports correct time
8193
curr_time=$(date '+%s')
8294
log_must zfs snapshot $snap_testpool
8395
snap_changed_testpool=$(zfs get -H -o value -p snapshots_changed $TESTPOOL)
96+
snap_changed_nsecs_testpool=$(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL)
8497
log_must eval "[[ $snap_changed_testpool -ge $curr_time ]]"
98+
log_must eval "[[ $snap_changed_nsecs_testpool -ge 0 ]]"
99+
log_must eval "[[ $snap_changed_nsecs_testpool -lt 1000000000 ]]"
100+
list_changed_testpool=$(zfs list -H -p -o snapshots_changed $TESTPOOL)
101+
list_changed_nsecs_testpool=$(zfs list -H -p -o snapshots_changed_nsecs $TESTPOOL)
102+
log_must eval "[[ $list_changed_testpool == $snap_changed_testpool ]]"
103+
log_must eval "[[ $list_changed_nsecs_testpool == $snap_changed_nsecs_testpool ]]"
85104
log_must eval "[[ $(stat_mtime $tpool_snapdir) == $snap_changed_testpool ]]"
86105

87106
curr_time=$(date '+%s')
88107
log_must zfs snapshot $snap_testfsv1
89108
snap_changed_testfs=$(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS)
109+
snap_changed_nsecs_testfs=$(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL/$TESTFS)
90110
log_must eval "[[ $snap_changed_testfs -ge $curr_time ]]"
111+
log_must eval "[[ $snap_changed_nsecs_testfs -ge 0 ]]"
112+
log_must eval "[[ $snap_changed_nsecs_testfs -lt 1000000000 ]]"
113+
list_changed_testfs=$(zfs list -H -p -o snapshots_changed $TESTPOOL/$TESTFS)
114+
list_changed_nsecs_testfs=$(zfs list -H -p -o snapshots_changed_nsecs $TESTPOOL/$TESTFS)
115+
log_must eval "[[ $list_changed_testfs == $snap_changed_testfs ]]"
116+
log_must eval "[[ $list_changed_nsecs_testfs == $snap_changed_nsecs_testfs ]]"
91117
log_must eval "[[ $(stat_mtime $tfs_snapdir) == $snap_changed_testfs ]]"
92118

93119
# Unmount the filesystems and check snapshots_changed has correct value after unmount
94120
log_must zfs unmount $TESTPOOL/$TESTFS
95121
log_must eval "[[ $(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS) == $snap_changed_testfs ]]"
122+
log_must eval "[[ $(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL/$TESTFS) == $snap_changed_nsecs_testfs ]]"
96123

97124
# Create snapshot while unmounted
98125
curr_time=$(date '+%s')
99126
log_must zfs snapshot $snap_testfsv2
100127
snap_changed_testfs=$(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS)
128+
snap_changed_nsecs_testfs=$(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL/$TESTFS)
101129
log_must eval "[[ $snap_changed_testfs -ge $curr_time ]]"
130+
log_must eval "[[ $snap_changed_nsecs_testfs -ge 0 ]]"
131+
log_must eval "[[ $snap_changed_nsecs_testfs -lt 1000000000 ]]"
102132

103133
log_must zfs unmount $TESTPOOL
104134
log_must eval "[[ $(zfs get -H -o value -p snapshots_changed $TESTPOOL) == $snap_changed_testpool ]]"
135+
log_must eval "[[ $(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL) == $snap_changed_nsecs_testpool ]]"
105136

106137
# Mount back the filesystems and check snapshots_changed still has correct value
107138
log_must zfs mount $TESTPOOL
108139
log_must eval "[[ $(zfs get -H -o value -p snapshots_changed $TESTPOOL) == $snap_changed_testpool ]]"
140+
log_must eval "[[ $(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL) == $snap_changed_nsecs_testpool ]]"
109141
log_must eval "[[ $(stat_mtime $tpool_snapdir) == $snap_changed_testpool ]]"
110142

111143
log_must zfs mount $TESTPOOL/$TESTFS
112144
log_must eval "[[ $(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS) == $snap_changed_testfs ]]"
145+
log_must eval "[[ $(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL/$TESTFS) == $snap_changed_nsecs_testfs ]]"
113146
log_must eval "[[ $(stat_mtime $tfs_snapdir) == $snap_changed_testfs ]]"
114147

115148
# Destroy the snapshots and check snapshots_changed shows correct time
116149
curr_time=$(date '+%s')
117150
log_must zfs destroy $snap_testfsv1
118151
snap_changed_testfs=$(zfs get -H -o value -p snapshots_changed $TESTPOOL/$TESTFS)
152+
snap_changed_nsecs_testfs=$(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL/$TESTFS)
119153
log_must eval "[[ $snap_changed_testfs -ge $curr_time ]]"
154+
log_must eval "[[ $snap_changed_nsecs_testfs -ge 0 ]]"
155+
log_must eval "[[ $snap_changed_nsecs_testfs -lt 1000000000 ]]"
120156
log_must eval "[[ $(stat_mtime $tfs_snapdir) == $snap_changed_testfs ]]"
121157

122158
curr_time=$(date '+%s')
123159
log_must zfs destroy $snap_testpool
124160
snap_changed_testpool=$(zfs get -H -o value -p snapshots_changed $TESTPOOL)
161+
snap_changed_nsecs_testpool=$(zfs get -H -o value -p snapshots_changed_nsecs $TESTPOOL)
125162
log_must eval "[[ $snap_changed_testpool -ge $curr_time ]]"
163+
log_must eval "[[ $snap_changed_nsecs_testpool -ge 0 ]]"
164+
log_must eval "[[ $snap_changed_nsecs_testpool -lt 1000000000 ]]"
126165
log_must eval "[[ $(stat_mtime $tpool_snapdir) == $snap_changed_testpool ]]"
127166

128-
log_pass "snapshots_changed property behaves correctly"
167+
log_pass "snapshots_changed and snapshots_changed_nsecs properties behave correctly"

0 commit comments

Comments
 (0)