Skip to content

Commit ed603bc

Browse files
committed
sunrpc: Replace the rq_pages array with dynamically-allocated memory
As a step towards making NFSD's maximum rsize and wsize variable at run-time, replace the fixed-size rq_vec[] array in struct svc_rqst with a chunk of dynamically-allocated memory. On a system with 8-byte pointers and 4KB pages, pahole reports that the rq_pages[] array is 2080 bytes. This patch replaces that with a single 8-byte pointer field. Reviewed-by: Jeff Layton <[email protected]> Reviewed-by: NeilBrown <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent 1a58791 commit ed603bc

File tree

4 files changed

+21
-25
lines changed

4 files changed

+21
-25
lines changed

include/linux/sunrpc/svc.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ struct svc_rqst {
205205
struct xdr_stream rq_res_stream;
206206
struct page *rq_scratch_page;
207207
struct xdr_buf rq_res;
208-
struct page *rq_pages[RPCSVC_MAXPAGES + 1];
208+
unsigned long rq_maxpages; /* num of entries in rq_pages */
209+
struct page * *rq_pages;
209210
struct page * *rq_respages; /* points into rq_pages */
210211
struct page * *rq_next_page; /* next reply page to use */
211212
struct page * *rq_page_end; /* one past the last page */

net/sunrpc/svc.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -636,20 +636,22 @@ svc_destroy(struct svc_serv **servp)
636636
EXPORT_SYMBOL_GPL(svc_destroy);
637637

638638
static bool
639-
svc_init_buffer(struct svc_rqst *rqstp, unsigned int size, int node)
639+
svc_init_buffer(struct svc_rqst *rqstp, const struct svc_serv *serv, int node)
640640
{
641-
unsigned long pages, ret;
641+
unsigned long ret;
642642

643-
pages = size / PAGE_SIZE + 1; /* extra page as we hold both request and reply.
644-
* We assume one is at most one page
645-
*/
646-
WARN_ON_ONCE(pages > RPCSVC_MAXPAGES);
647-
if (pages > RPCSVC_MAXPAGES)
648-
pages = RPCSVC_MAXPAGES;
643+
rqstp->rq_maxpages = svc_serv_maxpages(serv);
649644

650-
ret = alloc_pages_bulk_node(GFP_KERNEL, node, pages,
645+
/* rq_pages' last entry is NULL for historical reasons. */
646+
rqstp->rq_pages = kcalloc_node(rqstp->rq_maxpages + 1,
647+
sizeof(struct page *),
648+
GFP_KERNEL, node);
649+
if (!rqstp->rq_pages)
650+
return false;
651+
652+
ret = alloc_pages_bulk_node(GFP_KERNEL, node, rqstp->rq_maxpages,
651653
rqstp->rq_pages);
652-
return ret == pages;
654+
return ret == rqstp->rq_maxpages;
653655
}
654656

655657
/*
@@ -658,11 +660,12 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size, int node)
658660
static void
659661
svc_release_buffer(struct svc_rqst *rqstp)
660662
{
661-
unsigned int i;
663+
unsigned long i;
662664

663-
for (i = 0; i < ARRAY_SIZE(rqstp->rq_pages); i++)
665+
for (i = 0; i < rqstp->rq_maxpages; i++)
664666
if (rqstp->rq_pages[i])
665667
put_page(rqstp->rq_pages[i]);
668+
kfree(rqstp->rq_pages);
666669
}
667670

668671
static void
@@ -704,7 +707,7 @@ svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node)
704707
if (!rqstp->rq_resp)
705708
goto out_enomem;
706709

707-
if (!svc_init_buffer(rqstp, serv->sv_max_mesg, node))
710+
if (!svc_init_buffer(rqstp, serv, node))
708711
goto out_enomem;
709712

710713
rqstp->rq_err = -EAGAIN; /* No error yet */
@@ -896,7 +899,7 @@ EXPORT_SYMBOL_GPL(svc_set_num_threads);
896899
bool svc_rqst_replace_page(struct svc_rqst *rqstp, struct page *page)
897900
{
898901
struct page **begin = rqstp->rq_pages;
899-
struct page **end = &rqstp->rq_pages[RPCSVC_MAXPAGES];
902+
struct page **end = &rqstp->rq_pages[rqstp->rq_maxpages];
900903

901904
if (unlikely(rqstp->rq_next_page < begin || rqstp->rq_next_page > end)) {
902905
trace_svc_replace_page_err(rqstp);

net/sunrpc/svc_xprt.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -652,18 +652,10 @@ static void svc_check_conn_limits(struct svc_serv *serv)
652652

653653
static bool svc_alloc_arg(struct svc_rqst *rqstp)
654654
{
655-
struct svc_serv *serv = rqstp->rq_server;
656655
struct xdr_buf *arg = &rqstp->rq_arg;
657656
unsigned long pages, filled, ret;
658657

659-
pages = (serv->sv_max_mesg + 2 * PAGE_SIZE) >> PAGE_SHIFT;
660-
if (pages > RPCSVC_MAXPAGES) {
661-
pr_warn_once("svc: warning: pages=%lu > RPCSVC_MAXPAGES=%lu\n",
662-
pages, RPCSVC_MAXPAGES);
663-
/* use as many pages as possible */
664-
pages = RPCSVC_MAXPAGES;
665-
}
666-
658+
pages = rqstp->rq_maxpages;
667659
for (filled = 0; filled < pages; filled = ret) {
668660
ret = alloc_pages_bulk(GFP_KERNEL, pages, rqstp->rq_pages);
669661
if (ret > filled)

net/sunrpc/xprtrdma/svc_rdma_rw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ static int svc_rdma_build_read_segment(struct svc_rqst *rqstp,
765765
}
766766
len -= seg_len;
767767

768-
if (len && ((head->rc_curpage + 1) > ARRAY_SIZE(rqstp->rq_pages)))
768+
if (len && ((head->rc_curpage + 1) > rqstp->rq_maxpages))
769769
goto out_overrun;
770770
}
771771

0 commit comments

Comments
 (0)