]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
SUNRPC: Optimize rq_respages allocation in svc_alloc_arg
authorChuck Lever <chuck.lever@oracle.com>
Thu, 26 Feb 2026 14:47:39 +0000 (09:47 -0500)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 30 Mar 2026 01:25:09 +0000 (21:25 -0400)
svc_alloc_arg() invokes alloc_pages_bulk() with the full rq_maxpages
count (~259 for 1MB messages) for the rq_respages array, causing a
full-array scan despite most slots holding valid pages.

svc_rqst_release_pages() NULLs only the range

  [rq_respages, rq_next_page)

after each RPC, so only that range contains NULL entries. Limit the
rq_respages fill in svc_alloc_arg() to that range instead of
scanning the full array.

svc_init_buffer() initializes rq_next_page to span the entire
rq_respages array, so the first svc_alloc_arg() call fills all
slots.

Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
include/linux/sunrpc/svc.h
net/sunrpc/svc.c
net/sunrpc/svc_xprt.c

index c3399cf645241f64249044db9a82516e6104d27d..669c944eaf7fa9b21fc05f0e13037903261d48fe 100644 (file)
@@ -152,6 +152,10 @@ extern u32 svc_max_payload(const struct svc_rqst *rqstp);
  * still in transport use, and set rq_pages_nfree to the count.
  * svc_alloc_arg() refills only that many rq_pages entries.
  *
+ * For rq_respages, svc_rqst_release_pages() NULLs entries in
+ * [rq_respages, rq_next_page) after each RPC. svc_alloc_arg()
+ * refills only that range.
+ *
  * xdr_buf holds responses; the structure fits NFS read responses
  * (header, data pages, optional tail) and enables sharing of
  * client-side routines.
index 6e57e35fa6d6f93ff002076c376d52f91642899e..5e0b5ec2fd52830f9d99912d9ee709b363e143b3 100644 (file)
@@ -656,6 +656,7 @@ svc_init_buffer(struct svc_rqst *rqstp, const struct svc_serv *serv, int node)
        }
 
        rqstp->rq_pages_nfree = rqstp->rq_maxpages;
+       rqstp->rq_next_page = rqstp->rq_respages + rqstp->rq_maxpages;
        return true;
 }
 
index 795b5729525fe56eb6f14f35fee3e265bdde7fcd..b16e710926c1ee3c9cfac4283c341dd358ebb71f 100644 (file)
@@ -686,8 +686,14 @@ static bool svc_alloc_arg(struct svc_rqst *rqstp)
                rqstp->rq_pages_nfree = 0;
        }
 
-       if (!svc_fill_pages(rqstp, rqstp->rq_respages, pages))
+       if (WARN_ON_ONCE(rqstp->rq_next_page < rqstp->rq_respages))
                return false;
+       nfree = rqstp->rq_next_page - rqstp->rq_respages;
+       if (nfree) {
+               if (!svc_fill_pages(rqstp, rqstp->rq_respages, nfree))
+                       return false;
+       }
+
        rqstp->rq_next_page = rqstp->rq_respages;
        rqstp->rq_page_end = &rqstp->rq_respages[pages];
        /* svc_rqst_replace_page() dereferences *rq_next_page even