mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 04:21:09 -04:00
SUNRPC: Optimize rq_respages allocation in svc_alloc_arg
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>
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user