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
|
* The Linux NFS server does not offer write delegations to NFSv4.0
|
||||||
* clients in order to avoid conflicts between write delegations and
|
* 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 cb_up;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
struct kstat stat;
|
struct kstat stat;
|
||||||
struct path path;
|
|
||||||
|
|
||||||
cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
|
cb_up = nfsd4_cb_channel_good(oo->oo_owner.so_client);
|
||||||
open->op_recall = false;
|
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));
|
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) {
|
if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) {
|
||||||
open->op_delegate_type = NFS4_OPEN_DELEGATE_WRITE;
|
if (!nfs4_delegation_stat(dp, currentfh, &stat)) {
|
||||||
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)) {
|
|
||||||
nfs4_put_stid(&dp->dl_stid);
|
nfs4_put_stid(&dp->dl_stid);
|
||||||
destroy_delegation(dp);
|
destroy_delegation(dp);
|
||||||
goto out_no_deleg;
|
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_cur_fsize = stat.size;
|
||||||
dp->dl_cb_fattr.ncf_initial_cinfo =
|
dp->dl_cb_fattr.ncf_initial_cinfo =
|
||||||
nfsd4_change_attribute(&stat, d_inode(currentfh->fh_dentry));
|
nfsd4_change_attribute(&stat, d_inode(currentfh->fh_dentry));
|
||||||
|
trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid);
|
||||||
} else {
|
} else {
|
||||||
open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
|
open->op_delegate_type = NFS4_OPEN_DELEGATE_READ;
|
||||||
trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid);
|
trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid);
|
||||||
|
|||||||
Reference in New Issue
Block a user