If an NFS server returns RESOURCE on the first operation in an NFSv4 COMPOUND, there's no way for a client to make forward progress. Instead, make the server process as many operations in a large COMPOUND as it can before returning NFS4ERR_RESOURCE on the first operation it did not process. Suggested-by: Bruce Fields <bfields@xxxxxxxxxxxx> Link: https://bugzilla.kernel.org/show_bug.cgi?id=216383 Fixes: 0078117c6d91 ("nfsd: return RESOURCE not GARBAGE_ARGS on too many ops") Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> --- fs/nfsd/nfs4proc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) Hi- Request for comments, compile-tested only. diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index a72ab97f77ef..094cf4520931 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -2633,9 +2633,6 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) status = nfserr_minor_vers_mismatch; if (nfsd_minorversion(nn, args->minorversion, NFSD_TEST) <= 0) goto out; - status = nfserr_resource; - if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND) - goto out; status = nfs41_check_op_ordering(args); if (status) { @@ -2650,6 +2647,11 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) trace_nfsd_compound(rqstp, args->opcnt); while (!status && resp->opcnt < args->opcnt) { + if (unlikely(resp->opcnt > NFSD_MAX_OPS_PER_COMPOUND)) { + status = nfserr_resource; + break; + } + op = &args->ops[resp->opcnt++]; /*