]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
NFSD: Remove the cap on number of operations per NFSv4 COMPOUND
authorChuck Lever <chuck.lever@oracle.com>
Tue, 10 Jun 2025 16:05:09 +0000 (12:05 -0400)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 14 Jul 2025 16:46:41 +0000 (12:46 -0400)
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: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsd.h
fs/nfsd/xdr4.h

index f13abbb13b388d223165b1168dc2c07eafb259cb..f4edf222e00e6c56067c47e4c864f0b2df790527 100644 (file)
@@ -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 @@ 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);
index f46d0814d20643d45760104420cadb0cd1352ba2..88c347957da5b8f352be63f84f207d2225f81cb9 100644 (file)
@@ -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);
index 3afcdbed6e1465929ec7da67593243a8bf97b3f4..ea91bad4eee2cdcee6fd8f1d93c5f155dcd38172 100644 (file)
@@ -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));
index 570065285e67f8101fa7483df36c75ba7eebac34..54a96042f5ac6f277a859174be9cd1163e02e10d 100644 (file)
@@ -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;
index aa2a356da7843a18910d101b359f62de6b29ee52..a23bc56051caf5d61788f1aaef078cba0cb7e0cb 100644 (file)
@@ -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;