mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-10 07:10:27 +00:00
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: c5967721e106 ("NFSD: handle GETATTR conflict with write delegation") Signed-off-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
a078a7dc0e
commit
bf92e5008b
@ -5914,6 +5914,28 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
nfs4_delegation_stat(struct nfs4_delegation *dp, struct svc_fh *currentfh,
|
||||
struct kstat *stat)
|
||||
{
|
||||
struct nfsd_file *nf = find_rw_file(dp->dl_stid.sc_file);
|
||||
struct path path;
|
||||
int rc;
|
||||
|
||||
if (!nf)
|
||||
return false;
|
||||
|
||||
path.mnt = currentfh->fh_export->ex_path.mnt;
|
||||
path.dentry = file_dentry(nf->nf_file);
|
||||
|
||||
rc = vfs_getattr(&path, stat,
|
||||
(STATX_SIZE | STATX_CTIME | STATX_CHANGE_COOKIE),
|
||||
AT_STATX_SYNC_AS_STAT);
|
||||
|
||||
nfsd_file_put(nf);
|
||||
return rc == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* The Linux NFS server does not offer write delegations to NFSv4.0
|
||||
* 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,
|
||||
int cb_up;
|
||||
int status = 0;
|
||||
struct kstat stat;
|
||||
struct path path;
|
||||
|
||||
cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
|
||||
open->op_recall = false;
|
||||
@ -5985,20 +6006,16 @@ nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
|
||||
memcpy(&open->op_delegate_stateid, &dp->dl_stid.sc_stateid, sizeof(dp->dl_stid.sc_stateid));
|
||||
|
||||
if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) {
|
||||
open->op_delegate_type = NFS4_OPEN_DELEGATE_WRITE;
|
||||
trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid);
|
||||
path.mnt = currentfh->fh_export->ex_path.mnt;
|
||||
path.dentry = currentfh->fh_dentry;
|
||||
if (vfs_getattr(&path, &stat,
|
||||
(STATX_SIZE | STATX_CTIME | STATX_CHANGE_COOKIE),
|
||||
AT_STATX_SYNC_AS_STAT)) {
|
||||
if (!nfs4_delegation_stat(dp, currentfh, &stat)) {
|
||||
nfs4_put_stid(&dp->dl_stid);
|
||||
destroy_delegation(dp);
|
||||
goto out_no_deleg;
|
||||
}
|
||||
open->op_delegate_type = NFS4_OPEN_DELEGATE_WRITE;
|
||||
dp->dl_cb_fattr.ncf_cur_fsize = stat.size;
|
||||
dp->dl_cb_fattr.ncf_initial_cinfo =
|
||||
nfsd4_change_attribute(&stat, d_inode(currentfh->fh_dentry));
|
||||
trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid);
|
||||
} else {
|
||||
open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
|
||||
trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid);
|
||||
|
Loading…
x
Reference in New Issue
Block a user