Commit 48aab160 authored by Chuck Lever's avatar Chuck Lever
Browse files

NFSD: Remove the cap on number of operations per NFSv4 COMPOUND



This limit has always been a sanity check; in nearly all cases a
large COMPOUND is a sign of a malfunctioning client. The only real
limit on COMPOUND size and complexity is the size of NFSD's send
and receive buffers.

However, there are a few cases where a large COMPOUND is sane. For
example, when a client implementation wants to walk down a long file
pathname in a single round trip.

A small risk is that now a client can construct a COMPOUND request
that can keep a single nfsd thread busy for quite some time.

Suggested-by: default avatarJeff Layton <jlayton@kernel.org>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent a2d61427
Loading
Loading
Loading
Loading
+2 −12
Original line number Diff line number Diff line
@@ -2842,20 +2842,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 +2922,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp)
			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);
+0 −1
Original line number Diff line number Diff line
@@ -3865,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);
+1 −3
Original line number Diff line number Diff line
@@ -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));
+0 −3
Original line number Diff line number Diff line
@@ -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;
+0 −1
Original line number Diff line number Diff line
@@ -870,7 +870,6 @@ struct nfsd4_compoundargs {
	char *				tag;
	u32				taglen;
	u32				minorversion;
	u32				client_opcnt;
	u32				opcnt;
	bool				splice_ok;
	struct nfsd4_op			*ops;