mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge tag 'nfsd-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
Pull nfsd updates from Chuck Lever: "NFSD is finally able to offer write delegations to clients that open files with O_WRONLY, thanks to patches from Dai Ngo. We're expecting this to accelerate a few interesting corner cases. The cap on the number of operations per NFSv4 COMPOUND has been lifted. Now, clients that send COMPOUNDs containing dozens of operations (for example, a long stream of LOOKUP operations to walk a pathname in a single round trip) will no longer be rejected. This release re-enables the ability for NFSD to perform NFSv4.2 COPY operations asynchronously. This feature has been disabled to mitigate the risk of denial-of-service when too many such requests arrive. Many thanks to the contributors, reviewers, testers, and bug reporters who participated during the v6.17 development cycle" * tag 'nfsd-6.17' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: (32 commits) nfsd: Drop dprintk in blocklayout xdr functions sunrpc: make svc_tcp_sendmsg() take a signed sentp pointer sunrpc: rearrange struct svc_rqst for fewer cachelines sunrpc: return better error in svcauth_gss_accept() on alloc failure sunrpc: reset rq_accept_statp when starting a new RPC sunrpc: remove SVC_SYSERR sunrpc: fix handling of unknown auth status codes NFSD: Simplify struct knfsd_fh NFSD: Access a knfsd_fh's fsid by pointer Revert "NFSD: Force all NFSv4.2 COPY requests to be synchronous" NFSD: Avoid multiple -Wflex-array-member-not-at-end warnings NFSD: Use vfs_iocb_iter_write() NFSD: Use vfs_iocb_iter_read() NFSD: Clean up kdoc for nfsd_open_local_fh() NFSD: Clean up kdoc for nfsd_file_put_local() NFSD: Remove definition for trace_nfsd_ctl_maxconn NFSD: Remove definition for trace_nfsd_file_gc_recent NFSD: Remove definitions for unused trace_nfsd_file_lru trace points NFSD: Remove definition for trace_nfsd_file_unhash_and_queue nfsd: Use correct error code when decoding extents ...
This commit is contained in:
+12
-8
@@ -178,11 +178,13 @@ nfsd4_block_proc_layoutcommit(struct inode *inode,
|
||||
{
|
||||
struct iomap *iomaps;
|
||||
int nr_iomaps;
|
||||
__be32 nfserr;
|
||||
|
||||
nr_iomaps = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout,
|
||||
lcp->lc_up_len, &iomaps, i_blocksize(inode));
|
||||
if (nr_iomaps < 0)
|
||||
return nfserrno(nr_iomaps);
|
||||
nfserr = nfsd4_block_decode_layoutupdate(lcp->lc_up_layout,
|
||||
lcp->lc_up_len, &iomaps, &nr_iomaps,
|
||||
i_blocksize(inode));
|
||||
if (nfserr != nfs_ok)
|
||||
return nfserr;
|
||||
|
||||
return nfsd4_block_commit_blocks(inode, lcp, iomaps, nr_iomaps);
|
||||
}
|
||||
@@ -316,11 +318,13 @@ nfsd4_scsi_proc_layoutcommit(struct inode *inode,
|
||||
{
|
||||
struct iomap *iomaps;
|
||||
int nr_iomaps;
|
||||
__be32 nfserr;
|
||||
|
||||
nr_iomaps = nfsd4_scsi_decode_layoutupdate(lcp->lc_up_layout,
|
||||
lcp->lc_up_len, &iomaps, i_blocksize(inode));
|
||||
if (nr_iomaps < 0)
|
||||
return nfserrno(nr_iomaps);
|
||||
nfserr = nfsd4_scsi_decode_layoutupdate(lcp->lc_up_layout,
|
||||
lcp->lc_up_len, &iomaps, &nr_iomaps,
|
||||
i_blocksize(inode));
|
||||
if (nfserr != nfs_ok)
|
||||
return nfserr;
|
||||
|
||||
return nfsd4_block_commit_blocks(inode, lcp, iomaps, nr_iomaps);
|
||||
}
|
||||
|
||||
+63
-48
@@ -112,35 +112,46 @@ nfsd4_block_encode_getdeviceinfo(struct xdr_stream *xdr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
/**
|
||||
* nfsd4_block_decode_layoutupdate - decode the block layout extent array
|
||||
* @p: pointer to the xdr data
|
||||
* @len: number of bytes to decode
|
||||
* @iomapp: pointer to store the decoded extent array
|
||||
* @nr_iomapsp: pointer to store the number of extents
|
||||
* @block_size: alignment of extent offset and length
|
||||
*
|
||||
* This function decodes the opaque field of the layoutupdate4 structure
|
||||
* in a layoutcommit request for the block layout driver. The field is
|
||||
* actually an array of extents sent by the client. It also checks that
|
||||
* the file offset, storage offset and length of each extent are aligned
|
||||
* by @block_size.
|
||||
*
|
||||
* Return values:
|
||||
* %nfs_ok: Successful decoding, @iomapp and @nr_iomapsp are valid
|
||||
* %nfserr_bad_xdr: The encoded array in @p is invalid
|
||||
* %nfserr_inval: An unaligned extent found
|
||||
* %nfserr_delay: Failed to allocate memory for @iomapp
|
||||
*/
|
||||
__be32
|
||||
nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
|
||||
u32 block_size)
|
||||
int *nr_iomapsp, u32 block_size)
|
||||
{
|
||||
struct iomap *iomaps;
|
||||
u32 nr_iomaps, i;
|
||||
|
||||
if (len < sizeof(u32)) {
|
||||
dprintk("%s: extent array too small: %u\n", __func__, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (len < sizeof(u32))
|
||||
return nfserr_bad_xdr;
|
||||
len -= sizeof(u32);
|
||||
if (len % PNFS_BLOCK_EXTENT_SIZE) {
|
||||
dprintk("%s: extent array invalid: %u\n", __func__, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (len % PNFS_BLOCK_EXTENT_SIZE)
|
||||
return nfserr_bad_xdr;
|
||||
|
||||
nr_iomaps = be32_to_cpup(p++);
|
||||
if (nr_iomaps != len / PNFS_BLOCK_EXTENT_SIZE) {
|
||||
dprintk("%s: extent array size mismatch: %u/%u\n",
|
||||
__func__, len, nr_iomaps);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (nr_iomaps != len / PNFS_BLOCK_EXTENT_SIZE)
|
||||
return nfserr_bad_xdr;
|
||||
|
||||
iomaps = kcalloc(nr_iomaps, sizeof(*iomaps), GFP_KERNEL);
|
||||
if (!iomaps) {
|
||||
dprintk("%s: failed to allocate extent array\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (!iomaps)
|
||||
return nfserr_delay;
|
||||
|
||||
for (i = 0; i < nr_iomaps; i++) {
|
||||
struct pnfs_block_extent bex;
|
||||
@@ -150,26 +161,18 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
|
||||
|
||||
p = xdr_decode_hyper(p, &bex.foff);
|
||||
if (bex.foff & (block_size - 1)) {
|
||||
dprintk("%s: unaligned offset 0x%llx\n",
|
||||
__func__, bex.foff);
|
||||
goto fail;
|
||||
}
|
||||
p = xdr_decode_hyper(p, &bex.len);
|
||||
if (bex.len & (block_size - 1)) {
|
||||
dprintk("%s: unaligned length 0x%llx\n",
|
||||
__func__, bex.foff);
|
||||
goto fail;
|
||||
}
|
||||
p = xdr_decode_hyper(p, &bex.soff);
|
||||
if (bex.soff & (block_size - 1)) {
|
||||
dprintk("%s: unaligned disk offset 0x%llx\n",
|
||||
__func__, bex.soff);
|
||||
goto fail;
|
||||
}
|
||||
bex.es = be32_to_cpup(p++);
|
||||
if (bex.es != PNFS_BLOCK_READWRITE_DATA) {
|
||||
dprintk("%s: incorrect extent state %d\n",
|
||||
__func__, bex.es);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -178,59 +181,71 @@ nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
|
||||
}
|
||||
|
||||
*iomapp = iomaps;
|
||||
return nr_iomaps;
|
||||
*nr_iomapsp = nr_iomaps;
|
||||
return nfs_ok;
|
||||
fail:
|
||||
kfree(iomaps);
|
||||
return -EINVAL;
|
||||
return nfserr_inval;
|
||||
}
|
||||
|
||||
int
|
||||
/**
|
||||
* nfsd4_scsi_decode_layoutupdate - decode the scsi layout extent array
|
||||
* @p: pointer to the xdr data
|
||||
* @len: number of bytes to decode
|
||||
* @iomapp: pointer to store the decoded extent array
|
||||
* @nr_iomapsp: pointer to store the number of extents
|
||||
* @block_size: alignment of extent offset and length
|
||||
*
|
||||
* This function decodes the opaque field of the layoutupdate4 structure
|
||||
* in a layoutcommit request for the scsi layout driver. The field is
|
||||
* actually an array of extents sent by the client. It also checks that
|
||||
* the offset and length of each extent are aligned by @block_size.
|
||||
*
|
||||
* Return values:
|
||||
* %nfs_ok: Successful decoding, @iomapp and @nr_iomapsp are valid
|
||||
* %nfserr_bad_xdr: The encoded array in @p is invalid
|
||||
* %nfserr_inval: An unaligned extent found
|
||||
* %nfserr_delay: Failed to allocate memory for @iomapp
|
||||
*/
|
||||
__be32
|
||||
nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
|
||||
u32 block_size)
|
||||
int *nr_iomapsp, u32 block_size)
|
||||
{
|
||||
struct iomap *iomaps;
|
||||
u32 nr_iomaps, expected, i;
|
||||
|
||||
if (len < sizeof(u32)) {
|
||||
dprintk("%s: extent array too small: %u\n", __func__, len);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (len < sizeof(u32))
|
||||
return nfserr_bad_xdr;
|
||||
|
||||
nr_iomaps = be32_to_cpup(p++);
|
||||
expected = sizeof(__be32) + nr_iomaps * PNFS_SCSI_RANGE_SIZE;
|
||||
if (len != expected) {
|
||||
dprintk("%s: extent array size mismatch: %u/%u\n",
|
||||
__func__, len, expected);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (len != expected)
|
||||
return nfserr_bad_xdr;
|
||||
|
||||
iomaps = kcalloc(nr_iomaps, sizeof(*iomaps), GFP_KERNEL);
|
||||
if (!iomaps) {
|
||||
dprintk("%s: failed to allocate extent array\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (!iomaps)
|
||||
return nfserr_delay;
|
||||
|
||||
for (i = 0; i < nr_iomaps; i++) {
|
||||
u64 val;
|
||||
|
||||
p = xdr_decode_hyper(p, &val);
|
||||
if (val & (block_size - 1)) {
|
||||
dprintk("%s: unaligned offset 0x%llx\n", __func__, val);
|
||||
goto fail;
|
||||
}
|
||||
iomaps[i].offset = val;
|
||||
|
||||
p = xdr_decode_hyper(p, &val);
|
||||
if (val & (block_size - 1)) {
|
||||
dprintk("%s: unaligned length 0x%llx\n", __func__, val);
|
||||
goto fail;
|
||||
}
|
||||
iomaps[i].length = val;
|
||||
}
|
||||
|
||||
*iomapp = iomaps;
|
||||
return nr_iomaps;
|
||||
*nr_iomapsp = nr_iomaps;
|
||||
return nfs_ok;
|
||||
fail:
|
||||
kfree(iomaps);
|
||||
return -EINVAL;
|
||||
return nfserr_inval;
|
||||
}
|
||||
|
||||
@@ -54,9 +54,9 @@ __be32 nfsd4_block_encode_getdeviceinfo(struct xdr_stream *xdr,
|
||||
const struct nfsd4_getdeviceinfo *gdp);
|
||||
__be32 nfsd4_block_encode_layoutget(struct xdr_stream *xdr,
|
||||
const struct nfsd4_layoutget *lgp);
|
||||
int nfsd4_block_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
|
||||
u32 block_size);
|
||||
int nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len, struct iomap **iomapp,
|
||||
u32 block_size);
|
||||
__be32 nfsd4_block_decode_layoutupdate(__be32 *p, u32 len,
|
||||
struct iomap **iomapp, int *nr_iomapsp, u32 block_size);
|
||||
__be32 nfsd4_scsi_decode_layoutupdate(__be32 *p, u32 len,
|
||||
struct iomap **iomapp, int *nr_iomapsp, u32 block_size);
|
||||
|
||||
#endif /* _NFSD_BLOCKLAYOUTXDR_H */
|
||||
|
||||
+3
-5
@@ -82,8 +82,7 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
|
||||
int len;
|
||||
struct auth_domain *dom = NULL;
|
||||
int err;
|
||||
int fsidtype;
|
||||
char *ep;
|
||||
u8 fsidtype;
|
||||
struct svc_expkey key;
|
||||
struct svc_expkey *ek = NULL;
|
||||
|
||||
@@ -109,10 +108,9 @@ static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
|
||||
err = -EINVAL;
|
||||
if (qword_get(&mesg, buf, PAGE_SIZE) <= 0)
|
||||
goto out;
|
||||
fsidtype = simple_strtoul(buf, &ep, 10);
|
||||
if (*ep)
|
||||
if (kstrtou8(buf, 10, &fsidtype))
|
||||
goto out;
|
||||
dprintk("found fsidtype %d\n", fsidtype);
|
||||
dprintk("found fsidtype %u\n", fsidtype);
|
||||
if (key_len(fsidtype)==0) /* invalid type */
|
||||
goto out;
|
||||
if ((len=qword_get(&mesg, buf, PAGE_SIZE)) <= 0)
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ struct svc_expkey {
|
||||
struct cache_head h;
|
||||
|
||||
struct auth_domain * ek_client;
|
||||
int ek_fsidtype;
|
||||
u8 ek_fsidtype;
|
||||
u32 ek_fsid[6];
|
||||
|
||||
struct path ek_path;
|
||||
|
||||
+1
-1
@@ -372,7 +372,7 @@ nfsd_file_put(struct nfsd_file *nf)
|
||||
|
||||
/**
|
||||
* nfsd_file_put_local - put nfsd_file reference and arm nfsd_net_put in caller
|
||||
* @nf: nfsd_file of which to put the reference
|
||||
* @pnf: nfsd_file of which to put the reference
|
||||
*
|
||||
* First save the associated net to return to caller, then put
|
||||
* the reference of the nfsd_file.
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@
|
||||
* @rpc_clnt: rpc_clnt that the client established
|
||||
* @cred: cred that the client established
|
||||
* @nfs_fh: filehandle to lookup
|
||||
* @nfp: place to find the nfsd_file, or store it if it was non-NULL
|
||||
* @pnf: place to find the nfsd_file, or store it if it was non-NULL
|
||||
* @fmode: fmode_t to use for open
|
||||
*
|
||||
* This function maps a local fh to a path on a local filesystem.
|
||||
|
||||
+1
-1
@@ -561,7 +561,7 @@ static void nfsd3_init_dirlist_pages(struct svc_rqst *rqstp,
|
||||
buf->pages = rqstp->rq_next_page;
|
||||
rqstp->rq_next_page += (buf->buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
||||
|
||||
xdr_init_encode_pages(xdr, buf, buf->pages, NULL);
|
||||
xdr_init_encode_pages(xdr, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -65,7 +65,7 @@ nfsd4_alloc_devid_map(const struct svc_fh *fhp)
|
||||
return;
|
||||
|
||||
map->fsid_type = fh->fh_fsid_type;
|
||||
memcpy(&map->fsid, fh->fh_fsid, fsid_len);
|
||||
memcpy(&map->fsid, fh_fsid(fh), fsid_len);
|
||||
|
||||
spin_lock(&nfsd_devid_lock);
|
||||
if (fhp->fh_export->ex_devid_map)
|
||||
@@ -75,7 +75,7 @@ nfsd4_alloc_devid_map(const struct svc_fh *fhp)
|
||||
list_for_each_entry(old, &nfsd_devid_hash[i], hash) {
|
||||
if (old->fsid_type != fh->fh_fsid_type)
|
||||
continue;
|
||||
if (memcmp(old->fsid, fh->fh_fsid,
|
||||
if (memcmp(old->fsid, fh_fsid(fh),
|
||||
key_len(old->fsid_type)))
|
||||
continue;
|
||||
|
||||
|
||||
+2
-19
@@ -1917,13 +1917,6 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
struct nfsd42_write_res *result;
|
||||
__be32 status;
|
||||
|
||||
/*
|
||||
* Currently, async COPY is not reliable. Force all COPY
|
||||
* requests to be synchronous to avoid client application
|
||||
* hangs waiting for COPY completion.
|
||||
*/
|
||||
nfsd4_copy_set_sync(copy, true);
|
||||
|
||||
result = ©->cp_res;
|
||||
nfsd_copy_write_verifier((__be32 *)&result->wr_verifier.data, nn);
|
||||
|
||||
@@ -2842,20 +2835,10 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
|
||||
|
||||
rqstp->rq_lease_breaker = (void **)&cstate->clp;
|
||||
|
||||
trace_nfsd_compound(rqstp, args->tag, args->taglen, args->client_opcnt);
|
||||
trace_nfsd_compound(rqstp, args->tag, args->taglen, args->opcnt);
|
||||
while (!status && resp->opcnt < args->opcnt) {
|
||||
op = &args->ops[resp->opcnt++];
|
||||
|
||||
if (unlikely(resp->opcnt == NFSD_MAX_OPS_PER_COMPOUND)) {
|
||||
/* If there are still more operations to process,
|
||||
* stop here and report NFS4ERR_RESOURCE. */
|
||||
if (cstate->minorversion == 0 &&
|
||||
args->client_opcnt > resp->opcnt) {
|
||||
op->status = nfserr_resource;
|
||||
goto encode_op;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The XDR decode routines may have pre-set op->status;
|
||||
* for example, if there is a miscellaneous XDR error
|
||||
@@ -2932,7 +2915,7 @@ encode_op:
|
||||
status = op->status;
|
||||
}
|
||||
|
||||
trace_nfsd_compound_status(args->client_opcnt, resp->opcnt,
|
||||
trace_nfsd_compound_status(args->opcnt, resp->opcnt,
|
||||
status, nfsd4_op_name(op->opnum));
|
||||
|
||||
nfsd4_cstate_clear_replay(cstate);
|
||||
|
||||
+84
-35
@@ -633,18 +633,6 @@ find_readable_file(struct nfs4_file *f)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct nfsd_file *
|
||||
find_rw_file(struct nfs4_file *f)
|
||||
{
|
||||
struct nfsd_file *ret;
|
||||
|
||||
spin_lock(&f->fi_lock);
|
||||
ret = nfsd_file_get(f->fi_fds[O_RDWR]);
|
||||
spin_unlock(&f->fi_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct nfsd_file *
|
||||
find_any_file(struct nfs4_file *f)
|
||||
{
|
||||
@@ -1218,15 +1206,20 @@ nfs4_inc_and_copy_stateid(stateid_t *dst, struct nfs4_stid *stid)
|
||||
|
||||
static void put_deleg_file(struct nfs4_file *fp)
|
||||
{
|
||||
struct nfsd_file *rnf = NULL;
|
||||
struct nfsd_file *nf = NULL;
|
||||
|
||||
spin_lock(&fp->fi_lock);
|
||||
if (--fp->fi_delegees == 0)
|
||||
if (--fp->fi_delegees == 0) {
|
||||
swap(nf, fp->fi_deleg_file);
|
||||
swap(rnf, fp->fi_rdeleg_file);
|
||||
}
|
||||
spin_unlock(&fp->fi_lock);
|
||||
|
||||
if (nf)
|
||||
nfsd_file_put(nf);
|
||||
if (rnf)
|
||||
nfs4_file_put_access(fp, NFS4_SHARE_ACCESS_READ);
|
||||
}
|
||||
|
||||
static void nfs4_unlock_deleg_lease(struct nfs4_delegation *dp)
|
||||
@@ -3872,7 +3865,6 @@ static __be32 check_forechannel_attrs(struct nfsd4_channel_attrs *ca, struct nfs
|
||||
ca->headerpadsz = 0;
|
||||
ca->maxreq_sz = min_t(u32, ca->maxreq_sz, maxrpc);
|
||||
ca->maxresp_sz = min_t(u32, ca->maxresp_sz, maxrpc);
|
||||
ca->maxops = min_t(u32, ca->maxops, NFSD_MAX_OPS_PER_COMPOUND);
|
||||
ca->maxresp_cached = min_t(u32, ca->maxresp_cached,
|
||||
NFSD_SLOT_CACHE_SIZE + NFSD_MIN_HDR_SEQ_SZ);
|
||||
ca->maxreqs = min_t(u32, ca->maxreqs, NFSD_MAX_SLOTS_PER_SESSION);
|
||||
@@ -4697,10 +4689,16 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
|
||||
}
|
||||
status = nfs_ok;
|
||||
if (conf) {
|
||||
old = unconf;
|
||||
unhash_client_locked(old);
|
||||
nfsd4_change_callback(conf, &unconf->cl_cb_conn);
|
||||
} else {
|
||||
if (get_client_locked(conf) == nfs_ok) {
|
||||
old = unconf;
|
||||
unhash_client_locked(old);
|
||||
nfsd4_change_callback(conf, &unconf->cl_cb_conn);
|
||||
} else {
|
||||
conf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!conf) {
|
||||
old = find_confirmed_client_by_name(&unconf->cl_name, nn);
|
||||
if (old) {
|
||||
status = nfserr_clid_inuse;
|
||||
@@ -4717,10 +4715,14 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
|
||||
}
|
||||
trace_nfsd_clid_replaced(&old->cl_clientid);
|
||||
}
|
||||
status = get_client_locked(unconf);
|
||||
if (status != nfs_ok) {
|
||||
old = NULL;
|
||||
goto out;
|
||||
}
|
||||
move_to_confirmed(unconf);
|
||||
conf = unconf;
|
||||
}
|
||||
get_client_locked(conf);
|
||||
spin_unlock(&nn->client_lock);
|
||||
if (conf == unconf)
|
||||
fsnotify_dentry(conf->cl_nfsd_info_dentry, FS_MODIFY);
|
||||
@@ -4750,6 +4752,7 @@ static void nfsd4_file_init(const struct svc_fh *fh, struct nfs4_file *fp)
|
||||
INIT_LIST_HEAD(&fp->fi_clnt_odstate);
|
||||
fh_copy_shallow(&fp->fi_fhandle, &fh->fh_handle);
|
||||
fp->fi_deleg_file = NULL;
|
||||
fp->fi_rdeleg_file = NULL;
|
||||
fp->fi_had_conflict = false;
|
||||
fp->fi_share_deny = 0;
|
||||
memset(fp->fi_fds, 0, sizeof(fp->fi_fds));
|
||||
@@ -6000,14 +6003,19 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
|
||||
* "An OPEN_DELEGATE_WRITE delegation allows the client to handle,
|
||||
* on its own, all opens."
|
||||
*
|
||||
* Furthermore the client can use a write delegation for most READ
|
||||
* operations as well, so we require a O_RDWR file here.
|
||||
* Furthermore, section 9.1.2 says:
|
||||
*
|
||||
* Offer a write delegation in the case of a BOTH open, and ensure
|
||||
* we get the O_RDWR descriptor.
|
||||
* "In the case of READ, the server may perform the corresponding
|
||||
* check on the access mode, or it may choose to allow READ for
|
||||
* OPEN4_SHARE_ACCESS_WRITE, to accommodate clients whose WRITE
|
||||
* implementation may unavoidably do reads (e.g., due to buffer
|
||||
* cache constraints)."
|
||||
*
|
||||
* We choose to offer a write delegation for OPEN with the
|
||||
* OPEN4_SHARE_ACCESS_WRITE access mode to accommodate such clients.
|
||||
*/
|
||||
if ((open->op_share_access & NFS4_SHARE_ACCESS_BOTH) == NFS4_SHARE_ACCESS_BOTH) {
|
||||
nf = find_rw_file(fp);
|
||||
if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) {
|
||||
nf = find_writeable_file(fp);
|
||||
dl_type = deleg_ts ? OPEN_DELEGATE_WRITE_ATTRS_DELEG : OPEN_DELEGATE_WRITE;
|
||||
}
|
||||
|
||||
@@ -6138,7 +6146,7 @@ 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 nfsd_file *nf = find_writeable_file(dp->dl_stid.sc_file);
|
||||
struct path path;
|
||||
int rc;
|
||||
|
||||
@@ -6156,6 +6164,34 @@ nfs4_delegation_stat(struct nfs4_delegation *dp, struct svc_fh *currentfh,
|
||||
return rc == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add NFS4_SHARE_ACCESS_READ to the write delegation granted on OPEN
|
||||
* with NFS4_SHARE_ACCESS_WRITE by allocating separate nfsd_file and
|
||||
* struct file to be used for read with delegation stateid.
|
||||
*
|
||||
*/
|
||||
static bool
|
||||
nfsd4_add_rdaccess_to_wrdeleg(struct svc_rqst *rqstp, struct nfsd4_open *open,
|
||||
struct svc_fh *fh, struct nfs4_ol_stateid *stp)
|
||||
{
|
||||
struct nfs4_file *fp;
|
||||
struct nfsd_file *nf = NULL;
|
||||
|
||||
if ((open->op_share_access & NFS4_SHARE_ACCESS_BOTH) ==
|
||||
NFS4_SHARE_ACCESS_WRITE) {
|
||||
if (nfsd_file_acquire_opened(rqstp, fh, NFSD_MAY_READ, NULL, &nf))
|
||||
return (false);
|
||||
fp = stp->st_stid.sc_file;
|
||||
spin_lock(&fp->fi_lock);
|
||||
__nfs4_file_get_access(fp, NFS4_SHARE_ACCESS_READ);
|
||||
fp = stp->st_stid.sc_file;
|
||||
fp->fi_fds[O_RDONLY] = nf;
|
||||
fp->fi_rdeleg_file = nf;
|
||||
spin_unlock(&fp->fi_lock);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The Linux NFS server does not offer write delegations to NFSv4.0
|
||||
* clients in order to avoid conflicts between write delegations and
|
||||
@@ -6181,8 +6217,9 @@ nfs4_delegation_stat(struct nfs4_delegation *dp, struct svc_fh *currentfh,
|
||||
* open or lock state.
|
||||
*/
|
||||
static void
|
||||
nfs4_open_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
|
||||
struct svc_fh *currentfh)
|
||||
nfs4_open_delegation(struct svc_rqst *rqstp, struct nfsd4_open *open,
|
||||
struct nfs4_ol_stateid *stp, struct svc_fh *currentfh,
|
||||
struct svc_fh *fh)
|
||||
{
|
||||
struct nfs4_openowner *oo = openowner(stp->st_stateowner);
|
||||
bool deleg_ts = nfsd4_want_deleg_timestamps(open);
|
||||
@@ -6227,7 +6264,8 @@ 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) {
|
||||
if (!nfs4_delegation_stat(dp, currentfh, &stat)) {
|
||||
if (!nfsd4_add_rdaccess_to_wrdeleg(rqstp, open, fh, stp) ||
|
||||
!nfs4_delegation_stat(dp, currentfh, &stat)) {
|
||||
nfs4_put_stid(&dp->dl_stid);
|
||||
destroy_delegation(dp);
|
||||
goto out_no_deleg;
|
||||
@@ -6322,6 +6360,20 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
|
||||
status = nfs4_check_deleg(cl, open, &dp);
|
||||
if (status)
|
||||
goto out;
|
||||
if (dp && nfsd4_is_deleg_cur(open) &&
|
||||
(dp->dl_stid.sc_file != fp)) {
|
||||
/*
|
||||
* RFC8881 section 8.2.4 mandates the server to return
|
||||
* NFS4ERR_BAD_STATEID if the selected table entry does
|
||||
* not match the current filehandle. However returning
|
||||
* NFS4ERR_BAD_STATEID in the OPEN can cause the client
|
||||
* to repeatedly retry the operation with the same
|
||||
* stateid, since the stateid itself is valid. To avoid
|
||||
* this situation NFSD returns NFS4ERR_INVAL instead.
|
||||
*/
|
||||
status = nfserr_inval;
|
||||
goto out;
|
||||
}
|
||||
stp = nfsd4_find_and_lock_existing_open(fp, open);
|
||||
} else {
|
||||
open->op_file = NULL;
|
||||
@@ -6383,7 +6435,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
|
||||
* Attempt to hand out a delegation. No error return, because the
|
||||
* OPEN succeeds even if we fail.
|
||||
*/
|
||||
nfs4_open_delegation(open, stp, &resp->cstate.current_fh);
|
||||
nfs4_open_delegation(rqstp, open, stp,
|
||||
&resp->cstate.current_fh, current_fh);
|
||||
|
||||
/*
|
||||
* If there is an existing open stateid, it must be updated and
|
||||
@@ -7076,7 +7129,7 @@ nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
|
||||
return_revoked = true;
|
||||
if (typemask & SC_TYPE_DELEG)
|
||||
/* Always allow REVOKED for DELEG so we can
|
||||
* retturn the appropriate error.
|
||||
* return the appropriate error.
|
||||
*/
|
||||
statusmask |= SC_STATUS_REVOKED;
|
||||
|
||||
@@ -7119,10 +7172,6 @@ nfs4_find_file(struct nfs4_stid *s, int flags)
|
||||
|
||||
switch (s->sc_type) {
|
||||
case SC_TYPE_DELEG:
|
||||
spin_lock(&s->sc_file->fi_lock);
|
||||
ret = nfsd_file_get(s->sc_file->fi_deleg_file);
|
||||
spin_unlock(&s->sc_file->fi_lock);
|
||||
break;
|
||||
case SC_TYPE_OPEN:
|
||||
case SC_TYPE_LOCK:
|
||||
if (flags & RD_STATE)
|
||||
|
||||
+1
-3
@@ -2500,10 +2500,8 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
|
||||
|
||||
if (xdr_stream_decode_u32(argp->xdr, &argp->minorversion) < 0)
|
||||
return false;
|
||||
if (xdr_stream_decode_u32(argp->xdr, &argp->client_opcnt) < 0)
|
||||
if (xdr_stream_decode_u32(argp->xdr, &argp->opcnt) < 0)
|
||||
return false;
|
||||
argp->opcnt = min_t(u32, argp->client_opcnt,
|
||||
NFSD_MAX_OPS_PER_COMPOUND);
|
||||
|
||||
if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
|
||||
argp->ops = vcalloc(argp->opcnt, sizeof(*argp->ops));
|
||||
|
||||
+16
-15
@@ -1436,7 +1436,7 @@ unsigned int nfsd_net_id;
|
||||
|
||||
static int nfsd_genl_rpc_status_compose_msg(struct sk_buff *skb,
|
||||
struct netlink_callback *cb,
|
||||
struct nfsd_genl_rqstp *rqstp)
|
||||
struct nfsd_genl_rqstp *genl_rqstp)
|
||||
{
|
||||
void *hdr;
|
||||
u32 i;
|
||||
@@ -1446,22 +1446,22 @@ static int nfsd_genl_rpc_status_compose_msg(struct sk_buff *skb,
|
||||
if (!hdr)
|
||||
return -ENOBUFS;
|
||||
|
||||
if (nla_put_be32(skb, NFSD_A_RPC_STATUS_XID, rqstp->rq_xid) ||
|
||||
nla_put_u32(skb, NFSD_A_RPC_STATUS_FLAGS, rqstp->rq_flags) ||
|
||||
nla_put_u32(skb, NFSD_A_RPC_STATUS_PROG, rqstp->rq_prog) ||
|
||||
nla_put_u32(skb, NFSD_A_RPC_STATUS_PROC, rqstp->rq_proc) ||
|
||||
nla_put_u8(skb, NFSD_A_RPC_STATUS_VERSION, rqstp->rq_vers) ||
|
||||
if (nla_put_be32(skb, NFSD_A_RPC_STATUS_XID, genl_rqstp->rq_xid) ||
|
||||
nla_put_u32(skb, NFSD_A_RPC_STATUS_FLAGS, genl_rqstp->rq_flags) ||
|
||||
nla_put_u32(skb, NFSD_A_RPC_STATUS_PROG, genl_rqstp->rq_prog) ||
|
||||
nla_put_u32(skb, NFSD_A_RPC_STATUS_PROC, genl_rqstp->rq_proc) ||
|
||||
nla_put_u8(skb, NFSD_A_RPC_STATUS_VERSION, genl_rqstp->rq_vers) ||
|
||||
nla_put_s64(skb, NFSD_A_RPC_STATUS_SERVICE_TIME,
|
||||
ktime_to_us(rqstp->rq_stime),
|
||||
ktime_to_us(genl_rqstp->rq_stime),
|
||||
NFSD_A_RPC_STATUS_PAD))
|
||||
return -ENOBUFS;
|
||||
|
||||
switch (rqstp->rq_saddr.sa_family) {
|
||||
switch (genl_rqstp->rq_saddr.sa_family) {
|
||||
case AF_INET: {
|
||||
const struct sockaddr_in *s_in, *d_in;
|
||||
|
||||
s_in = (const struct sockaddr_in *)&rqstp->rq_saddr;
|
||||
d_in = (const struct sockaddr_in *)&rqstp->rq_daddr;
|
||||
s_in = (const struct sockaddr_in *)&genl_rqstp->rq_saddr;
|
||||
d_in = (const struct sockaddr_in *)&genl_rqstp->rq_daddr;
|
||||
if (nla_put_in_addr(skb, NFSD_A_RPC_STATUS_SADDR4,
|
||||
s_in->sin_addr.s_addr) ||
|
||||
nla_put_in_addr(skb, NFSD_A_RPC_STATUS_DADDR4,
|
||||
@@ -1476,8 +1476,8 @@ static int nfsd_genl_rpc_status_compose_msg(struct sk_buff *skb,
|
||||
case AF_INET6: {
|
||||
const struct sockaddr_in6 *s_in, *d_in;
|
||||
|
||||
s_in = (const struct sockaddr_in6 *)&rqstp->rq_saddr;
|
||||
d_in = (const struct sockaddr_in6 *)&rqstp->rq_daddr;
|
||||
s_in = (const struct sockaddr_in6 *)&genl_rqstp->rq_saddr;
|
||||
d_in = (const struct sockaddr_in6 *)&genl_rqstp->rq_daddr;
|
||||
if (nla_put_in6_addr(skb, NFSD_A_RPC_STATUS_SADDR6,
|
||||
&s_in->sin6_addr) ||
|
||||
nla_put_in6_addr(skb, NFSD_A_RPC_STATUS_DADDR6,
|
||||
@@ -1491,9 +1491,9 @@ static int nfsd_genl_rpc_status_compose_msg(struct sk_buff *skb,
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < rqstp->rq_opcnt; i++)
|
||||
for (i = 0; i < genl_rqstp->rq_opcnt; i++)
|
||||
if (nla_put_u32(skb, NFSD_A_RPC_STATUS_COMPOUND_OPS,
|
||||
rqstp->rq_opnum[i]))
|
||||
genl_rqstp->rq_opnum[i]))
|
||||
return -ENOBUFS;
|
||||
|
||||
genlmsg_end(skb, hdr);
|
||||
@@ -1569,7 +1569,8 @@ int nfsd_nl_rpc_status_get_dumpit(struct sk_buff *skb,
|
||||
int j;
|
||||
|
||||
args = rqstp->rq_argp;
|
||||
genl_rqstp.rq_opcnt = args->opcnt;
|
||||
genl_rqstp.rq_opcnt = min_t(u32, args->opcnt,
|
||||
ARRAY_SIZE(genl_rqstp.rq_opnum));
|
||||
for (j = 0; j < genl_rqstp.rq_opcnt; j++)
|
||||
genl_rqstp.rq_opnum[j] =
|
||||
args->ops[j].opnum;
|
||||
|
||||
+2
-4
@@ -57,9 +57,6 @@ struct readdir_cd {
|
||||
__be32 err; /* 0, nfserr, or nfserr_eof */
|
||||
};
|
||||
|
||||
/* Maximum number of operations per session compound */
|
||||
#define NFSD_MAX_OPS_PER_COMPOUND 50
|
||||
|
||||
struct nfsd_genl_rqstp {
|
||||
struct sockaddr rq_daddr;
|
||||
struct sockaddr rq_saddr;
|
||||
@@ -72,7 +69,7 @@ struct nfsd_genl_rqstp {
|
||||
|
||||
/* NFSv4 compound */
|
||||
u32 rq_opcnt;
|
||||
u32 rq_opnum[NFSD_MAX_OPS_PER_COMPOUND];
|
||||
u32 rq_opnum[16];
|
||||
};
|
||||
|
||||
extern struct svc_program nfsd_programs[];
|
||||
@@ -283,6 +280,7 @@ void nfsd_lockd_shutdown(void);
|
||||
#define nfserr_cb_path_down cpu_to_be32(NFSERR_CB_PATH_DOWN)
|
||||
#define nfserr_locked cpu_to_be32(NFSERR_LOCKED)
|
||||
#define nfserr_wrongsec cpu_to_be32(NFSERR_WRONGSEC)
|
||||
#define nfserr_delay cpu_to_be32(NFS4ERR_DELAY)
|
||||
#define nfserr_badiomode cpu_to_be32(NFS4ERR_BADIOMODE)
|
||||
#define nfserr_badlayout cpu_to_be32(NFS4ERR_BADLAYOUT)
|
||||
#define nfserr_bad_session_digest cpu_to_be32(NFS4ERR_BAD_SESSION_DIGEST)
|
||||
|
||||
+9
-7
@@ -172,6 +172,8 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct net *net,
|
||||
if (len == 0)
|
||||
return error;
|
||||
if (fh->fh_fsid_type == FSID_MAJOR_MINOR) {
|
||||
u32 *fsid = fh_fsid(fh);
|
||||
|
||||
/* deprecated, convert to type 3 */
|
||||
len = key_len(FSID_ENCODE_DEV)/4;
|
||||
fh->fh_fsid_type = FSID_ENCODE_DEV;
|
||||
@@ -181,17 +183,17 @@ static __be32 nfsd_set_fh_dentry(struct svc_rqst *rqstp, struct net *net,
|
||||
* confuses sparse, so we must use __force here to
|
||||
* keep it from complaining.
|
||||
*/
|
||||
fh->fh_fsid[0] = new_encode_dev(MKDEV(ntohl((__force __be32)fh->fh_fsid[0]),
|
||||
ntohl((__force __be32)fh->fh_fsid[1])));
|
||||
fh->fh_fsid[1] = fh->fh_fsid[2];
|
||||
fsid[0] = new_encode_dev(MKDEV(ntohl((__force __be32)fsid[0]),
|
||||
ntohl((__force __be32)fsid[1])));
|
||||
fsid[1] = fsid[2];
|
||||
}
|
||||
data_left -= len;
|
||||
if (data_left < 0)
|
||||
return error;
|
||||
exp = rqst_exp_find(rqstp ? &rqstp->rq_chandle : NULL,
|
||||
net, client, gssclient,
|
||||
fh->fh_fsid_type, fh->fh_fsid);
|
||||
fid = (struct fid *)(fh->fh_fsid + len);
|
||||
fh->fh_fsid_type, fh_fsid(fh));
|
||||
fid = (struct fid *)(fh_fsid(fh) + len);
|
||||
|
||||
error = nfserr_stale;
|
||||
if (IS_ERR(exp)) {
|
||||
@@ -463,7 +465,7 @@ static void _fh_update(struct svc_fh *fhp, struct svc_export *exp,
|
||||
{
|
||||
if (dentry != exp->ex_path.dentry) {
|
||||
struct fid *fid = (struct fid *)
|
||||
(fhp->fh_handle.fh_fsid + fhp->fh_handle.fh_size/4 - 1);
|
||||
(fh_fsid(&fhp->fh_handle) + fhp->fh_handle.fh_size/4 - 1);
|
||||
int maxsize = (fhp->fh_maxsize - fhp->fh_handle.fh_size)/4;
|
||||
int fh_flags = (exp->ex_flags & NFSEXP_NOSUBTREECHECK) ? 0 :
|
||||
EXPORT_FH_CONNECTABLE;
|
||||
@@ -614,7 +616,7 @@ fh_compose(struct svc_fh *fhp, struct svc_export *exp, struct dentry *dentry,
|
||||
fhp->fh_handle.fh_auth_type = 0;
|
||||
|
||||
mk_fsid(fhp->fh_handle.fh_fsid_type,
|
||||
fhp->fh_handle.fh_fsid,
|
||||
fh_fsid(&fhp->fh_handle),
|
||||
ex_dev,
|
||||
d_inode(exp->ex_path.dentry)->i_ino,
|
||||
exp->ex_fsid, exp->ex_uuid);
|
||||
|
||||
+15
-11
@@ -49,18 +49,19 @@ struct knfsd_fh {
|
||||
* Points to the current size while
|
||||
* building a new file handle.
|
||||
*/
|
||||
union {
|
||||
char fh_raw[NFS4_FHSIZE];
|
||||
struct {
|
||||
u8 fh_version; /* == 1 */
|
||||
u8 fh_auth_type; /* deprecated */
|
||||
u8 fh_fsid_type;
|
||||
u8 fh_fileid_type;
|
||||
u32 fh_fsid[]; /* flexible-array member */
|
||||
};
|
||||
};
|
||||
u8 fh_raw[NFS4_FHSIZE];
|
||||
};
|
||||
|
||||
#define fh_version fh_raw[0]
|
||||
#define fh_auth_type fh_raw[1]
|
||||
#define fh_fsid_type fh_raw[2]
|
||||
#define fh_fileid_type fh_raw[3]
|
||||
|
||||
static inline u32 *fh_fsid(const struct knfsd_fh *fh)
|
||||
{
|
||||
return (u32 *)&fh->fh_raw[4];
|
||||
}
|
||||
|
||||
static inline __u32 ino_t_to_u32(ino_t ino)
|
||||
{
|
||||
return (__u32) ino;
|
||||
@@ -260,9 +261,12 @@ static inline bool fh_match(const struct knfsd_fh *fh1,
|
||||
static inline bool fh_fsid_match(const struct knfsd_fh *fh1,
|
||||
const struct knfsd_fh *fh2)
|
||||
{
|
||||
u32 *fsid1 = fh_fsid(fh1);
|
||||
u32 *fsid2 = fh_fsid(fh2);
|
||||
|
||||
if (fh1->fh_fsid_type != fh2->fh_fsid_type)
|
||||
return false;
|
||||
if (memcmp(fh1->fh_fsid, fh2->fh_fsid, key_len(fh1->fh_fsid_type)) != 0)
|
||||
if (memcmp(fsid1, fsid2, key_len(fh1->fh_fsid_type)) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -575,7 +575,7 @@ static void nfsd_init_dirlist_pages(struct svc_rqst *rqstp,
|
||||
buf->pages = rqstp->rq_next_page;
|
||||
rqstp->rq_next_page++;
|
||||
|
||||
xdr_init_encode_pages(xdr, buf, buf->pages, NULL);
|
||||
xdr_init_encode_pages(xdr, buf);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -665,6 +665,7 @@ struct nfs4_file {
|
||||
atomic_t fi_access[2];
|
||||
u32 fi_share_deny;
|
||||
struct nfsd_file *fi_deleg_file;
|
||||
struct nfsd_file *fi_rdeleg_file;
|
||||
int fi_delegees;
|
||||
struct knfsd_fh fi_fhandle;
|
||||
bool fi_had_conflict;
|
||||
|
||||
+2
-25
@@ -344,7 +344,7 @@ TRACE_EVENT(nfsd_exp_find_key,
|
||||
int status),
|
||||
TP_ARGS(key, status),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, fsidtype)
|
||||
__field(u8, fsidtype)
|
||||
__array(u32, fsid, 6)
|
||||
__string(auth_domain, key->ek_client->name)
|
||||
__field(int, status)
|
||||
@@ -367,7 +367,7 @@ TRACE_EVENT(nfsd_expkey_update,
|
||||
TP_PROTO(const struct svc_expkey *key, const char *exp_path),
|
||||
TP_ARGS(key, exp_path),
|
||||
TP_STRUCT__entry(
|
||||
__field(int, fsidtype)
|
||||
__field(u8, fsidtype)
|
||||
__array(u32, fsid, 6)
|
||||
__string(auth_domain, key->ek_client->name)
|
||||
__string(path, exp_path)
|
||||
@@ -1108,7 +1108,6 @@ DEFINE_NFSD_FILE_EVENT(nfsd_file_free);
|
||||
DEFINE_NFSD_FILE_EVENT(nfsd_file_unhash);
|
||||
DEFINE_NFSD_FILE_EVENT(nfsd_file_put);
|
||||
DEFINE_NFSD_FILE_EVENT(nfsd_file_closing);
|
||||
DEFINE_NFSD_FILE_EVENT(nfsd_file_unhash_and_queue);
|
||||
|
||||
TRACE_EVENT(nfsd_file_alloc,
|
||||
TP_PROTO(
|
||||
@@ -1344,9 +1343,7 @@ DEFINE_EVENT(nfsd_file_gc_class, name, \
|
||||
TP_ARGS(nf))
|
||||
|
||||
DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_lru_add);
|
||||
DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_lru_add_disposed);
|
||||
DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_lru_del);
|
||||
DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_lru_del_disposed);
|
||||
DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_in_use);
|
||||
DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_writeback);
|
||||
DEFINE_NFSD_FILE_GC_EVENT(nfsd_file_gc_referenced);
|
||||
@@ -1380,7 +1377,6 @@ DEFINE_EVENT(nfsd_file_lruwalk_class, name, \
|
||||
TP_ARGS(removed, remaining))
|
||||
|
||||
DEFINE_NFSD_FILE_LRUWALK_EVENT(nfsd_file_gc_removed);
|
||||
DEFINE_NFSD_FILE_LRUWALK_EVENT(nfsd_file_gc_recent);
|
||||
DEFINE_NFSD_FILE_LRUWALK_EVENT(nfsd_file_shrinker_removed);
|
||||
|
||||
TRACE_EVENT(nfsd_file_close,
|
||||
@@ -2103,25 +2099,6 @@ TRACE_EVENT(nfsd_ctl_maxblksize,
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(nfsd_ctl_maxconn,
|
||||
TP_PROTO(
|
||||
const struct net *net,
|
||||
int maxconn
|
||||
),
|
||||
TP_ARGS(net, maxconn),
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, netns_ino)
|
||||
__field(int, maxconn)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->netns_ino = net->ns.inum;
|
||||
__entry->maxconn = maxconn;
|
||||
),
|
||||
TP_printk("maxconn=%d",
|
||||
__entry->maxconn
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(nfsd_ctl_time,
|
||||
TP_PROTO(
|
||||
const struct net *net,
|
||||
|
||||
+10
-7
@@ -1086,10 +1086,13 @@ __be32 nfsd_iter_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||
{
|
||||
unsigned long v, total;
|
||||
struct iov_iter iter;
|
||||
loff_t ppos = offset;
|
||||
struct kiocb kiocb;
|
||||
ssize_t host_err;
|
||||
size_t len;
|
||||
|
||||
init_sync_kiocb(&kiocb, file);
|
||||
kiocb.ki_pos = offset;
|
||||
|
||||
v = 0;
|
||||
total = *count;
|
||||
while (total) {
|
||||
@@ -1104,7 +1107,7 @@ __be32 nfsd_iter_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||
|
||||
trace_nfsd_read_vector(rqstp, fhp, offset, *count);
|
||||
iov_iter_bvec(&iter, ITER_DEST, rqstp->rq_bvec, v, *count);
|
||||
host_err = vfs_iter_read(file, &iter, &ppos, 0);
|
||||
host_err = vfs_iocb_iter_read(file, &kiocb, &iter);
|
||||
return nfsd_finish_read(rqstp, fhp, file, offset, count, eof, host_err);
|
||||
}
|
||||
|
||||
@@ -1170,15 +1173,14 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
||||
struct file *file = nf->nf_file;
|
||||
struct super_block *sb = file_inode(file)->i_sb;
|
||||
struct kiocb kiocb;
|
||||
struct svc_export *exp;
|
||||
struct iov_iter iter;
|
||||
errseq_t since;
|
||||
__be32 nfserr;
|
||||
int host_err;
|
||||
loff_t pos = offset;
|
||||
unsigned long exp_op_flags = 0;
|
||||
unsigned int pflags = current->flags;
|
||||
rwf_t flags = 0;
|
||||
bool restore_flags = false;
|
||||
unsigned int nvecs;
|
||||
|
||||
@@ -1204,16 +1206,17 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp,
|
||||
|
||||
if (!EX_ISSYNC(exp))
|
||||
stable = NFS_UNSTABLE;
|
||||
|
||||
init_sync_kiocb(&kiocb, file);
|
||||
kiocb.ki_pos = offset;
|
||||
if (stable && !fhp->fh_use_wgather)
|
||||
flags |= RWF_SYNC;
|
||||
kiocb.ki_flags |= IOCB_DSYNC;
|
||||
|
||||
nvecs = xdr_buf_to_bvec(rqstp->rq_bvec, rqstp->rq_maxpages, payload);
|
||||
iov_iter_bvec(&iter, ITER_SOURCE, rqstp->rq_bvec, nvecs, *cnt);
|
||||
since = READ_ONCE(file->f_wb_err);
|
||||
if (verf)
|
||||
nfsd_copy_write_verifier(verf, nn);
|
||||
host_err = vfs_iter_write(file, &iter, &pos, flags);
|
||||
host_err = vfs_iocb_iter_write(file, &kiocb, &iter);
|
||||
if (host_err < 0) {
|
||||
commit_reset_write_verifier(nn, rqstp, host_err);
|
||||
goto out_nfserr;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user