Commit 0078117c authored by J. Bruce Fields's avatar J. Bruce Fields

nfsd: return RESOURCE not GARBAGE_ARGS on too many ops

A client that sends more than a hundred ops in a single compound
currently gets an rpc-level GARBAGE_ARGS error.

It would be more helpful to return NFS4ERR_RESOURCE, since that gives
the client a better idea how to recover (for example by splitting up the
compound into smaller compounds).

This is all a bit academic since we've never actually seen a reason for
clients to send such long compounds, but we may as well fix it.

While we're there, just use NFSD4_MAX_OPS_PER_COMPOUND == 16, the
constant we already use in the 4.1 case, instead of hard-coding 100.
Chances anyone actually uses even 16 ops per compound are small enough
that I think there's a neglible risk or any regression.

This fixes pynfs test COMP6.
Reported-by: default avatar"Lu, Xinyu" <luxy.fnst@cn.fujitsu.com>
Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 25020720
...@@ -1703,6 +1703,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) ...@@ -1703,6 +1703,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
status = nfserr_minor_vers_mismatch; status = nfserr_minor_vers_mismatch;
if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0) if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0)
goto out; goto out;
status = nfserr_resource;
if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
goto out;
status = nfs41_check_op_ordering(args); status = nfs41_check_op_ordering(args);
if (status) { if (status) {
......
...@@ -1918,8 +1918,13 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) ...@@ -1918,8 +1918,13 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
if (argp->taglen > NFSD4_MAX_TAGLEN) if (argp->taglen > NFSD4_MAX_TAGLEN)
goto xdr_error; goto xdr_error;
if (argp->opcnt > 100) /*
goto xdr_error; * NFS4ERR_RESOURCE is a more helpful error than GARBAGE_ARGS
* here, so we return success at the xdr level so that
* nfsd4_proc can handle this is an NFS-level error.
*/
if (argp->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
return 0;
if (argp->opcnt > ARRAY_SIZE(argp->iops)) { if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL); argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment