As Trond points out [1], the "original time" mentioned in RFC 9754
refers to the timestamps on the files at the time that the delegation
was granted, and not the current timestamp of the file on the server.

Store the current timestamps for the file in the nfs4_delegation when
granting one. Add STATX_ATIME and STATX_MTIME to the request mask in
nfs4_delegation_stat(). When granting OPEN_DELEGATE_READ_ATTRS_DELEG, do
a nfs4_delegation_stat() and save the correct atime. If the stat() fails
for any reason, fall back to granting a normal read deleg.

[1]: 
https://lore.kernel.org/linux-nfs/47a4e40310e797f21b5137e847b06bb203d99e66.ca...@kernel.org/

Fixes: 7e13f4f8d27d ("nfsd: handle delegated timestamps in SETATTR")
Signed-off-by: Jeff Layton <jlay...@kernel.org>
---
 fs/nfsd/nfs4state.c | 11 ++++++++---
 fs/nfsd/state.h     |  5 +++++
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 
77eea2ad93cc07939f045fc4b983b1ac00d068b8..8737b721daf3433bab46065e751175a4dcdd1c89
 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -6157,7 +6157,8 @@ nfs4_delegation_stat(struct nfs4_delegation *dp, struct 
svc_fh *currentfh,
        path.dentry = file_dentry(nf->nf_file);
 
        rc = vfs_getattr(&path, stat,
-                        (STATX_MODE | STATX_SIZE | STATX_CTIME | 
STATX_CHANGE_COOKIE),
+                        STATX_MODE | STATX_SIZE | STATX_ATIME |
+                        STATX_MTIME | STATX_CTIME | STATX_CHANGE_COOKIE,
                         AT_STATX_SYNC_AS_STAT);
 
        nfsd_file_put(nf);
@@ -6274,10 +6275,14 @@ nfs4_open_delegation(struct svc_rqst *rqstp, struct 
nfsd4_open *open,
                                                    OPEN_DELEGATE_WRITE;
                dp->dl_cb_fattr.ncf_cur_fsize = stat.size;
                dp->dl_cb_fattr.ncf_initial_cinfo = 
nfsd4_change_attribute(&stat);
+               dp->dl_atime = stat.atime;
+               dp->dl_ctime = stat.ctime;
+               dp->dl_mtime = stat.mtime;
                trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid);
        } else {
-               open->op_delegate_type = deleg_ts ? 
OPEN_DELEGATE_READ_ATTRS_DELEG :
-                                                   OPEN_DELEGATE_READ;
+               open->op_delegate_type = deleg_ts && nfs4_delegation_stat(dp, 
currentfh, &stat) ?
+                                        OPEN_DELEGATE_READ_ATTRS_DELEG : 
OPEN_DELEGATE_READ;
+               dp->dl_atime = stat.atime;
                trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid);
        }
        nfs4_put_stid(&dp->dl_stid);
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 
8adc2550129e67a4e6646395fa2811e1c2acb98e..ce7c0d129ba338e1269ed163266e1ee192cd02c5
 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -224,6 +224,11 @@ struct nfs4_delegation {
 
        /* for CB_GETATTR */
        struct nfs4_cb_fattr    dl_cb_fattr;
+
+       /* For delegated timestamps */
+       struct timespec64       dl_atime;
+       struct timespec64       dl_mtime;
+       struct timespec64       dl_ctime;
 };
 
 static inline bool deleg_is_read(u32 dl_type)

-- 
2.50.1


Reply via email to