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 <[email protected]>
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 <[email protected]>
---
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++];
/*