mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
nfsd: fix initial getattr on write delegation
[ Upstream commitbf92e5008b] 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:c5967721e1("NFSD: handle GETATTR conflict with write delegation") Signed-off-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
f7f6e7fe13
commit
dfbe943b75
@@ -5912,6 +5912,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
|
||||
@@ -5947,7 +5969,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;
|
||||
@@ -5983,20 +6004,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);
|
||||
|
||||
Reference in New Issue
Block a user