diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 88c347957da5..205ee8cc6fa2 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); @@ -9130,25 +9135,25 @@ nfsd4_get_writestateid(struct nfsd4_compound_state *cstate, } /** - * set_cb_time - vet and set the timespec for a cb_getattr update - * @cb: timestamp from the CB_GETATTR response + * nfsd4_vet_deleg_time - vet and set the timespec for a delegated timestamp update + * @req: timestamp from the client * @orig: original timestamp in the inode * @now: current time * - * Given a timestamp in a CB_GETATTR response, check it against the + * Given a timestamp from the client response, check it against the * current timestamp in the inode and the current time. Returns true * if the inode's timestamp needs to be updated, and false otherwise. - * @cb may also be changed if the timestamp needs to be clamped. + * @req may also be changed if the timestamp needs to be clamped. */ -static bool set_cb_time(struct timespec64 *cb, const struct timespec64 *orig, - const struct timespec64 *now) +bool nfsd4_vet_deleg_time(struct timespec64 *req, const struct timespec64 *orig, + const struct timespec64 *now) { /* * "When the time presented is before the original time, then the * update is ignored." Also no need to update if there is no change. */ - if (timespec64_compare(cb, orig) <= 0) + if (timespec64_compare(req, orig) <= 0) return false; /* @@ -9156,10 +9161,8 @@ static bool set_cb_time(struct timespec64 *cb, const struct timespec64 *orig, * clamp the new time to the current time, or it may * return NFS4ERR_DELAY to the client, allowing it to retry." */ - if (timespec64_compare(cb, now) > 0) { - /* clamp it */ - *cb = *now; - } + if (timespec64_compare(req, now) > 0) + *req = *now; return true; } @@ -9167,28 +9170,27 @@ static bool set_cb_time(struct timespec64 *cb, const struct timespec64 *orig, static int cb_getattr_update_times(struct dentry *dentry, struct nfs4_delegation *dp) { struct inode *inode = d_inode(dentry); - struct timespec64 now = current_time(inode); struct nfs4_cb_fattr *ncf = &dp->dl_cb_fattr; struct iattr attrs = { }; int ret; if (deleg_attrs_deleg(dp->dl_type)) { - struct timespec64 atime = inode_get_atime(inode); - struct timespec64 mtime = inode_get_mtime(inode); + struct timespec64 now = current_time(inode); attrs.ia_atime = ncf->ncf_cb_atime; attrs.ia_mtime = ncf->ncf_cb_mtime; - if (set_cb_time(&attrs.ia_atime, &atime, &now)) + if (nfsd4_vet_deleg_time(&attrs.ia_atime, &dp->dl_atime, &now)) attrs.ia_valid |= ATTR_ATIME | ATTR_ATIME_SET; - if (set_cb_time(&attrs.ia_mtime, &mtime, &now)) { - attrs.ia_valid |= ATTR_CTIME | ATTR_MTIME | ATTR_MTIME_SET; + if (nfsd4_vet_deleg_time(&attrs.ia_mtime, &dp->dl_mtime, &now)) { + attrs.ia_valid |= ATTR_MTIME | ATTR_MTIME_SET; attrs.ia_ctime = attrs.ia_mtime; + if (nfsd4_vet_deleg_time(&attrs.ia_ctime, &dp->dl_ctime, &now)) + attrs.ia_valid |= ATTR_CTIME | ATTR_CTIME_SET; } } else { attrs.ia_valid |= ATTR_MTIME | ATTR_CTIME; - attrs.ia_mtime = attrs.ia_ctime = now; } if (!attrs.ia_valid) |