aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/module/os/linux/zfs/zpl_inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/module/os/linux/zfs/zpl_inode.c')
-rw-r--r--sys/contrib/openzfs/module/os/linux/zfs/zpl_inode.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/sys/contrib/openzfs/module/os/linux/zfs/zpl_inode.c b/sys/contrib/openzfs/module/os/linux/zfs/zpl_inode.c
index f97662d052c7..e4e15c824f4b 100644
--- a/sys/contrib/openzfs/module/os/linux/zfs/zpl_inode.c
+++ b/sys/contrib/openzfs/module/os/linux/zfs/zpl_inode.c
@@ -506,6 +506,32 @@ zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,
}
#endif
+#ifdef STATX_CHANGE_COOKIE
+ if (request_mask & STATX_CHANGE_COOKIE) {
+ /*
+ * knfsd uses the STATX_CHANGE_COOKIE to surface to clients
+ * change_info4 data, which is used to implement NFS client
+ * name caching (see RFC 8881 Section 10.8). This number
+ * should always increase with changes and should not be
+ * reused. We cannot simply present ctime here because
+ * ZFS uses a coarse timer to set them, which may cause
+ * clients to fail to detect changes and invalidate cache.
+ *
+ * ZFS always increments znode z_seq number, but this is
+ * uint_t and so we mask in ctime to upper bits.
+ *
+ * STATX_ATTR_CHANGE_MONOTONIC is advertised
+ * to prevent knfsd from generating the change cookie
+ * based on ctime. C.f. nfsd4_change_attribute in
+ * fs/nfsd/nfsfh.c.
+ */
+ stat->change_cookie =
+ ((u64)stat->ctime.tv_sec << 32) | zp->z_seq;
+ stat->attributes |= STATX_ATTR_CHANGE_MONOTONIC;
+ stat->result_mask |= STATX_CHANGE_COOKIE;
+ }
+#endif
+
#ifdef STATX_DIOALIGN
if (request_mask & STATX_DIOALIGN) {
uint64_t align;