Merge tag 'nfsd-5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 8 Sep 2021 22:55:42 +0000 (15:55 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 8 Sep 2021 22:55:42 +0000 (15:55 -0700)
Pull nfsd fixes from Chuck Lever:

 - Restore performance on memory-starved servers

* tag 'nfsd-5.15-1' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux:
  SUNRPC: improve error response to over-size gss credential
  SUNRPC: don't pause on incomplete allocation

net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/cache.c
net/sunrpc/svc_xprt.c

index 9de41e7..3e776e3 100644 (file)
@@ -194,6 +194,8 @@ static void rsi_request(struct cache_detail *cd,
        qword_addhex(bpp, blen, rsii->in_handle.data, rsii->in_handle.len);
        qword_addhex(bpp, blen, rsii->in_token.data, rsii->in_token.len);
        (*bpp)[-1] = '\n';
+       WARN_ONCE(*blen < 0,
+                 "RPCSEC/GSS credential too large - please use gssproxy\n");
 }
 
 static int rsi_parse(struct cache_detail *cd,
index 1a2c1c4..5964180 100644 (file)
@@ -803,7 +803,7 @@ static int cache_request(struct cache_detail *detail,
 
        detail->cache_request(detail, crq->item, &bp, &len);
        if (len < 0)
-               return -EAGAIN;
+               return -E2BIG;
        return PAGE_SIZE - len;
 }
 
index e1153cb..6316bd2 100644 (file)
@@ -663,7 +663,7 @@ static int svc_alloc_arg(struct svc_rqst *rqstp)
 {
        struct svc_serv *serv = rqstp->rq_server;
        struct xdr_buf *arg = &rqstp->rq_arg;
-       unsigned long pages, filled;
+       unsigned long pages, filled, ret;
 
        pagevec_init(&rqstp->rq_pvec);
 
@@ -675,11 +675,12 @@ static int svc_alloc_arg(struct svc_rqst *rqstp)
                pages = RPCSVC_MAXPAGES;
        }
 
-       for (;;) {
-               filled = alloc_pages_bulk_array(GFP_KERNEL, pages,
-                                               rqstp->rq_pages);
-               if (filled == pages)
-                       break;
+       for (filled = 0; filled < pages; filled = ret) {
+               ret = alloc_pages_bulk_array(GFP_KERNEL, pages,
+                                            rqstp->rq_pages);
+               if (ret > filled)
+                       /* Made progress, don't sleep yet */
+                       continue;
 
                set_current_state(TASK_INTERRUPTIBLE);
                if (signalled() || kthread_should_stop()) {