]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
nfsd: update mtime/ctime on CLONE in presense of delegated attributes
authorOlga Kornievskaia <okorniev@redhat.com>
Fri, 10 Apr 2026 16:09:19 +0000 (12:09 -0400)
committerChuck Lever <chuck.lever@oracle.com>
Sun, 10 May 2026 16:39:48 +0000 (12:39 -0400)
When delegated attributes are given on open, the file is opened with
NOCMTIME and modifying operations do not update mtime/ctime as to not get
out-of-sync with the client's delegated view. However, for CLONE operation,
the server should update its view of mtime/ctime and reflect that in any
GETATTR queries.

Fixes: e5e9b24ab8fa ("nfsd: freeze c/mtime updates with outstanding WRITE_ATTRS delegation")
Cc: stable@vger.kernel.org
Signed-off-by: Olga Kornievskaia <okorniev@redhat.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/state.h

index 2797da8cc9501fe46fce8ce4841876558df89e31..5de8f37df78a299ef81e6671049431a186bcb43a 100644 (file)
@@ -1413,6 +1413,9 @@ nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                        dst, clone->cl_dst_pos, clone->cl_count,
                        EX_ISSYNC(cstate->current_fh.fh_export));
 
+       if (!status && (READ_ONCE(dst->nf_file->f_mode) & FMODE_NOCMTIME) != 0)
+               nfsd_update_cmtime_attr(dst->nf_file, 0);
+
        nfsd_file_put(dst);
        nfsd_file_put(src);
 out:
index a9f7bd491b8cd3a1e3fc0bf416f6d05b22d0b1ac..3cd8b3b59de4655c66f2a10827458ea12e5a62fe 100644 (file)
@@ -1221,10 +1221,6 @@ static void put_deleg_file(struct nfs4_file *fp)
 
 static void nfsd4_finalize_deleg_timestamps(struct nfs4_delegation *dp, struct file *f)
 {
-       struct iattr ia = { .ia_valid = ATTR_ATIME | ATTR_CTIME | ATTR_MTIME | ATTR_DELEG };
-       struct inode *inode = file_inode(f);
-       int ret;
-
        /* don't do anything if FMODE_NOCMTIME isn't set */
        if ((READ_ONCE(f->f_mode) & FMODE_NOCMTIME) == 0)
                return;
@@ -1242,17 +1238,7 @@ static void nfsd4_finalize_deleg_timestamps(struct nfs4_delegation *dp, struct f
                return;
 
        /* Stamp everything to "now" */
-       inode_lock(inode);
-       ret = notify_change(&nop_mnt_idmap, f->f_path.dentry, &ia, NULL);
-       inode_unlock(inode);
-       if (ret) {
-               struct inode *inode = file_inode(f);
-
-               pr_notice_ratelimited("nfsd: Unable to update timestamps on inode %02x:%02x:%lu: %d\n",
-                                       MAJOR(inode->i_sb->s_dev),
-                                       MINOR(inode->i_sb->s_dev),
-                                       inode->i_ino, ret);
-       }
+       nfsd_update_cmtime_attr(f, ATTR_ATIME);
 }
 
 static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp)
@@ -9563,3 +9549,31 @@ out_delegees:
        put_nfs4_file(fp);
        return ERR_PTR(status);
 }
+
+/**
+ * nfsd_update_cmtime_attr - update file's delegated ctime/mtime,
+ *                           and optionally other attributes (ie ATTR_ATIME).
+ * @f: pointer to an opened file
+ * @flags: any additional flags that should be updated
+ *
+ * Given upon opening a file delegated attributes were issues, update
+ * @f attributes to current times.
+ */
+void nfsd_update_cmtime_attr(struct file *f, unsigned int flags)
+{
+       int ret;
+       struct inode *inode = file_inode(f);
+       struct iattr attr = {
+               .ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_DELEG | flags,
+       };
+
+       inode_lock(inode);
+       ret = notify_change(&nop_mnt_idmap, f->f_path.dentry, &attr, NULL);
+       inode_unlock(inode);
+       if (ret)
+               pr_notice_ratelimited("nfsd: Unable to update timestamps on "
+                                     "inode %02x:%02x:%lu: %d\n",
+                                     MAJOR(inode->i_sb->s_dev),
+                                     MINOR(inode->i_sb->s_dev),
+                                     inode->i_ino, ret);
+}
index 953675eba5c36654937262ca8199d4b975723899..c5ccea64c2817f3e252e6d9be8657b7fe5a3f345 100644 (file)
@@ -843,6 +843,7 @@ extern void nfsd4_shutdown_copy(struct nfs4_client *clp);
 void nfsd4_put_client(struct nfs4_client *clp);
 void nfsd4_async_copy_reaper(struct nfsd_net *nn);
 bool nfsd4_has_active_async_copies(struct nfs4_client *clp);
+void nfsd_update_cmtime_attr(struct file *f, unsigned int flags);
 extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(struct xdr_netobj name,
                                struct xdr_netobj princhash, struct nfsd_net *nn);
 extern bool nfs4_has_reclaimed_state(struct xdr_netobj name, struct nfsd_net *nn);