NFSD: Refactor nfsd_setattr()
[ Upstream commit c0aa1913db57219e91a0a8832363cbafb3a9cf8f ] Move code that will be retried (in a subsequent patch) into a helper function. Reviewed-by: Jeff Layton <jlayton@kernel.org> [ cel: backported to 5.10.y, prior to idmapped mounts ] 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
95dce2279c
commit
f326970df1
@@ -356,8 +356,61 @@ out_nfserrno:
|
|||||||
return nfserrno(host_err);
|
return nfserrno(host_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static int __nfsd_setattr(struct dentry *dentry, struct iattr *iap)
|
||||||
* Set various file attributes. After this call fhp needs an fh_put.
|
{
|
||||||
|
int host_err;
|
||||||
|
|
||||||
|
if (iap->ia_valid & ATTR_SIZE) {
|
||||||
|
/*
|
||||||
|
* RFC5661, Section 18.30.4:
|
||||||
|
* Changing the size of a file with SETATTR indirectly
|
||||||
|
* changes the time_modify and change attributes.
|
||||||
|
*
|
||||||
|
* (and similar for the older RFCs)
|
||||||
|
*/
|
||||||
|
struct iattr size_attr = {
|
||||||
|
.ia_valid = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME,
|
||||||
|
.ia_size = iap->ia_size,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (iap->ia_size < 0)
|
||||||
|
return -EFBIG;
|
||||||
|
|
||||||
|
host_err = notify_change(dentry, &size_attr, NULL);
|
||||||
|
if (host_err)
|
||||||
|
return host_err;
|
||||||
|
iap->ia_valid &= ~ATTR_SIZE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Avoid the additional setattr call below if the only other
|
||||||
|
* attribute that the client sends is the mtime, as we update
|
||||||
|
* it as part of the size change above.
|
||||||
|
*/
|
||||||
|
if ((iap->ia_valid & ~ATTR_MTIME) == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!iap->ia_valid)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
iap->ia_valid |= ATTR_CTIME;
|
||||||
|
return notify_change(dentry, iap, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nfsd_setattr - Set various file attributes.
|
||||||
|
* @rqstp: controlling RPC transaction
|
||||||
|
* @fhp: filehandle of target
|
||||||
|
* @attr: attributes to set
|
||||||
|
* @check_guard: set to 1 if guardtime is a valid timestamp
|
||||||
|
* @guardtime: do not act if ctime.tv_sec does not match this timestamp
|
||||||
|
*
|
||||||
|
* This call may adjust the contents of @attr (in particular, this
|
||||||
|
* call may change the bits in the na_iattr.ia_valid field).
|
||||||
|
*
|
||||||
|
* Returns nfs_ok on success, otherwise an NFS status code is
|
||||||
|
* returned. Caller must release @fhp by calling fh_put in either
|
||||||
|
* case.
|
||||||
*/
|
*/
|
||||||
__be32
|
__be32
|
||||||
nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||||
@@ -370,7 +423,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
|||||||
int accmode = NFSD_MAY_SATTR;
|
int accmode = NFSD_MAY_SATTR;
|
||||||
umode_t ftype = 0;
|
umode_t ftype = 0;
|
||||||
__be32 err;
|
__be32 err;
|
||||||
int host_err = 0;
|
int host_err;
|
||||||
bool get_write_count;
|
bool get_write_count;
|
||||||
bool size_change = (iap->ia_valid & ATTR_SIZE);
|
bool size_change = (iap->ia_valid & ATTR_SIZE);
|
||||||
|
|
||||||
@@ -427,43 +480,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
inode_lock(inode);
|
inode_lock(inode);
|
||||||
if (size_change) {
|
host_err = __nfsd_setattr(dentry, iap);
|
||||||
/*
|
|
||||||
* RFC5661, Section 18.30.4:
|
|
||||||
* Changing the size of a file with SETATTR indirectly
|
|
||||||
* changes the time_modify and change attributes.
|
|
||||||
*
|
|
||||||
* (and similar for the older RFCs)
|
|
||||||
*/
|
|
||||||
struct iattr size_attr = {
|
|
||||||
.ia_valid = ATTR_SIZE | ATTR_CTIME | ATTR_MTIME,
|
|
||||||
.ia_size = iap->ia_size,
|
|
||||||
};
|
|
||||||
|
|
||||||
host_err = -EFBIG;
|
|
||||||
if (iap->ia_size < 0)
|
|
||||||
goto out_unlock;
|
|
||||||
|
|
||||||
host_err = notify_change(dentry, &size_attr, NULL);
|
|
||||||
if (host_err)
|
|
||||||
goto out_unlock;
|
|
||||||
iap->ia_valid &= ~ATTR_SIZE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Avoid the additional setattr call below if the only other
|
|
||||||
* attribute that the client sends is the mtime, as we update
|
|
||||||
* it as part of the size change above.
|
|
||||||
*/
|
|
||||||
if ((iap->ia_valid & ~ATTR_MTIME) == 0)
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iap->ia_valid) {
|
|
||||||
iap->ia_valid |= ATTR_CTIME;
|
|
||||||
host_err = notify_change(dentry, iap, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
out_unlock:
|
|
||||||
if (attr->na_seclabel && attr->na_seclabel->len)
|
if (attr->na_seclabel && attr->na_seclabel->len)
|
||||||
attr->na_labelerr = security_inode_setsecctx(dentry,
|
attr->na_labelerr = security_inode_setsecctx(dentry,
|
||||||
attr->na_seclabel->data, attr->na_seclabel->len);
|
attr->na_seclabel->data, attr->na_seclabel->len);
|
||||||
|
Reference in New Issue
Block a user