summaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfsfh.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@kernel.org>2022-10-05 06:26:41 -0400
committerJeff Layton <jlayton@kernel.org>2023-01-26 07:00:06 -0500
commit3139b1d79588f65977b3543149df01063dc3d323 (patch)
tree36b2431a643e75416527526864d6d0d77f1eab28 /fs/nfsd/nfsfh.c
parentf6102994338c950f55233643c90f334305996758 (diff)
downloadlinux-3139b1d79588f65977b3543149df01063dc3d323.tar.gz
linux-3139b1d79588f65977b3543149df01063dc3d323.tar.bz2
linux-3139b1d79588f65977b3543149df01063dc3d323.zip
nfsd: move nfsd4_change_attribute to nfsfh.c
This is a pretty big function for inlining. Move it to being non-inlined. Acked-by: Chuck Lever <chuck.lever@oracle.com> Reviewed-by: NeilBrown <neilb@suse.de> Signed-off-by: Jeff Layton <jlayton@kernel.org>
Diffstat (limited to 'fs/nfsd/nfsfh.c')
-rw-r--r--fs/nfsd/nfsfh.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
index 8c52b6c9d31a..ac89e25e7733 100644
--- a/fs/nfsd/nfsfh.c
+++ b/fs/nfsd/nfsfh.c
@@ -748,3 +748,30 @@ enum fsid_source fsid_source(const struct svc_fh *fhp)
return FSIDSOURCE_UUID;
return FSIDSOURCE_DEV;
}
+
+/*
+ * We could use i_version alone as the change attribute. However,
+ * i_version can go backwards after a reboot. On its own that doesn't
+ * necessarily cause a problem, but if i_version goes backwards and then
+ * is incremented again it could reuse a value that was previously used
+ * before boot, and a client who queried the two values might
+ * incorrectly assume nothing changed.
+ *
+ * By using both ctime and the i_version counter we guarantee that as
+ * long as time doesn't go backwards we never reuse an old value.
+ */
+u64 nfsd4_change_attribute(struct kstat *stat, struct inode *inode)
+{
+ if (inode->i_sb->s_export_op->fetch_iversion)
+ return inode->i_sb->s_export_op->fetch_iversion(inode);
+ else if (IS_I_VERSION(inode)) {
+ u64 chattr;
+
+ chattr = stat->ctime.tv_sec;
+ chattr <<= 30;
+ chattr += stat->ctime.tv_nsec;
+ chattr += inode_query_iversion(inode);
+ return chattr;
+ } else
+ return time_to_chattr(&stat->ctime);
+}