Skip to content

Commit bf92e50

Browse files
jtlaytonchucklever
authored andcommitted
nfsd: fix initial getattr on write delegation
At this point in compound processing, currentfh refers to the parent of the file, not the file itself. Get the correct dentry from the delegation stateid instead. Fixes: c596772 ("NFSD: handle GETATTR conflict with write delegation") Signed-off-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent a078a7d commit bf92e50

File tree

1 file changed

+25
-8
lines changed

1 file changed

+25
-8
lines changed

fs/nfsd/nfs4state.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5914,6 +5914,28 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
59145914
}
59155915
}
59165916

5917+
static bool
5918+
nfs4_delegation_stat(struct nfs4_delegation *dp, struct svc_fh *currentfh,
5919+
struct kstat *stat)
5920+
{
5921+
struct nfsd_file *nf = find_rw_file(dp->dl_stid.sc_file);
5922+
struct path path;
5923+
int rc;
5924+
5925+
if (!nf)
5926+
return false;
5927+
5928+
path.mnt = currentfh->fh_export->ex_path.mnt;
5929+
path.dentry = file_dentry(nf->nf_file);
5930+
5931+
rc = vfs_getattr(&path, stat,
5932+
(STATX_SIZE | STATX_CTIME | STATX_CHANGE_COOKIE),
5933+
AT_STATX_SYNC_AS_STAT);
5934+
5935+
nfsd_file_put(nf);
5936+
return rc == 0;
5937+
}
5938+
59175939
/*
59185940
* The Linux NFS server does not offer write delegations to NFSv4.0
59195941
* clients in order to avoid conflicts between write delegations and
@@ -5949,7 +5971,6 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
59495971
int cb_up;
59505972
int status = 0;
59515973
struct kstat stat;
5952-
struct path path;
59535974

59545975
cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
59555976
open->op_recall = false;
@@ -5985,20 +6006,16 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
59856006
memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid));
59866007

59876008
if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) {
5988-
open->op_delegate_type = NFS4_OPEN_DELEGATE_WRITE;
5989-
trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid);
5990-
path.mnt = currentfh->fh_export->ex_path.mnt;
5991-
path.dentry = currentfh->fh_dentry;
5992-
if (vfs_getattr(&path, &stat,
5993-
(STATX_SIZE | STATX_CTIME | STATX_CHANGE_COOKIE),
5994-
AT_STATX_SYNC_AS_STAT)) {
6009+
if (!nfs4_delegation_stat(dp, currentfh, &stat)) {
59956010
nfs4_put_stid(&dp->dl_stid);
59966011
destroy_delegation(dp);
59976012
goto out_no_deleg;
59986013
}
6014+
open->op_delegate_type = NFS4_OPEN_DELEGATE_WRITE;
59996015
dp->dl_cb_fattr.ncf_cur_fsize = stat.size;
60006016
dp->dl_cb_fattr.ncf_initial_cinfo =
60016017
nfsd4_change_attribute(&stat, d_inode(currentfh->fh_dentry));
6018+
trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid);
60026019
} else {
60036020
open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
60046021
trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid);

0 commit comments

Comments
 (0)