mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
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 <jlayton@kernel.org> Reviewed-by: NeilBrown <neil@brown.name> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
1a58791292
commit
ed603bcf4f
4 changed files with 21 additions and 25 deletions
|
@ -205,7 +205,8 @@ struct svc_rqst {
|
||||||
struct xdr_stream rq_res_stream;
|
struct xdr_stream rq_res_stream;
|
||||||
struct page *rq_scratch_page;
|
struct page *rq_scratch_page;
|
||||||
struct xdr_buf rq_res;
|
struct xdr_buf rq_res;
|
||||||
struct page *rq_pages[RPCSVC_MAXPAGES + 1];
|
unsigned long rq_maxpages; /* num of entries in rq_pages */
|
||||||
|
struct page * *rq_pages;
|
||||||
struct page * *rq_respages; /* points into rq_pages */
|
struct page * *rq_respages; /* points into rq_pages */
|
||||||
struct page * *rq_next_page; /* next reply page to use */
|
struct page * *rq_next_page; /* next reply page to use */
|
||||||
struct page * *rq_page_end; /* one past the last page */
|
struct page * *rq_page_end; /* one past the last page */
|
||||||
|
|
|
@ -636,20 +636,22 @@ svc_destroy(struct svc_serv **servp)
|
||||||
EXPORT_SYMBOL_GPL(svc_destroy);
|
EXPORT_SYMBOL_GPL(svc_destroy);
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
svc_init_buffer(struct svc_rqst *rqstp, unsigned int size, int node)
|
svc_init_buffer(struct svc_rqst *rqstp, const struct svc_serv *serv, int node)
|
||||||
{
|
{
|
||||||
unsigned long pages, ret;
|
unsigned long ret;
|
||||||
|
|
||||||
pages = size / PAGE_SIZE + 1; /* extra page as we hold both request and reply.
|
rqstp->rq_maxpages = svc_serv_maxpages(serv);
|
||||||
* We assume one is at most one page
|
|
||||||
*/
|
|
||||||
WARN_ON_ONCE(pages > RPCSVC_MAXPAGES);
|
|
||||||
if (pages > RPCSVC_MAXPAGES)
|
|
||||||
pages = RPCSVC_MAXPAGES;
|
|
||||||
|
|
||||||
ret = alloc_pages_bulk_node(GFP_KERNEL, node, pages,
|
/* rq_pages' last entry is NULL for historical reasons. */
|
||||||
|
rqstp->rq_pages = kcalloc_node(rqstp->rq_maxpages + 1,
|
||||||
|
sizeof(struct page *),
|
||||||
|
GFP_KERNEL, node);
|
||||||
|
if (!rqstp->rq_pages)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
ret = alloc_pages_bulk_node(GFP_KERNEL, node, rqstp->rq_maxpages,
|
||||||
rqstp->rq_pages);
|
rqstp->rq_pages);
|
||||||
return ret == pages;
|
return ret == rqstp->rq_maxpages;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -658,11 +660,12 @@ svc_init_buffer(struct svc_rqst *rqstp, unsigned int size, int node)
|
||||||
static void
|
static void
|
||||||
svc_release_buffer(struct svc_rqst *rqstp)
|
svc_release_buffer(struct svc_rqst *rqstp)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned long i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(rqstp->rq_pages); i++)
|
for (i = 0; i < rqstp->rq_maxpages; i++)
|
||||||
if (rqstp->rq_pages[i])
|
if (rqstp->rq_pages[i])
|
||||||
put_page(rqstp->rq_pages[i]);
|
put_page(rqstp->rq_pages[i]);
|
||||||
|
kfree(rqstp->rq_pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -704,7 +707,7 @@ svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node)
|
||||||
if (!rqstp->rq_resp)
|
if (!rqstp->rq_resp)
|
||||||
goto out_enomem;
|
goto out_enomem;
|
||||||
|
|
||||||
if (!svc_init_buffer(rqstp, serv->sv_max_mesg, node))
|
if (!svc_init_buffer(rqstp, serv, node))
|
||||||
goto out_enomem;
|
goto out_enomem;
|
||||||
|
|
||||||
rqstp->rq_err = -EAGAIN; /* No error yet */
|
rqstp->rq_err = -EAGAIN; /* No error yet */
|
||||||
|
@ -896,7 +899,7 @@ EXPORT_SYMBOL_GPL(svc_set_num_threads);
|
||||||
bool svc_rqst_replace_page(struct svc_rqst *rqstp, struct page *page)
|
bool svc_rqst_replace_page(struct svc_rqst *rqstp, struct page *page)
|
||||||
{
|
{
|
||||||
struct page **begin = rqstp->rq_pages;
|
struct page **begin = rqstp->rq_pages;
|
||||||
struct page **end = &rqstp->rq_pages[RPCSVC_MAXPAGES];
|
struct page **end = &rqstp->rq_pages[rqstp->rq_maxpages];
|
||||||
|
|
||||||
if (unlikely(rqstp->rq_next_page < begin || rqstp->rq_next_page > end)) {
|
if (unlikely(rqstp->rq_next_page < begin || rqstp->rq_next_page > end)) {
|
||||||
trace_svc_replace_page_err(rqstp);
|
trace_svc_replace_page_err(rqstp);
|
||||||
|
|
|
@ -652,18 +652,10 @@ static void svc_check_conn_limits(struct svc_serv *serv)
|
||||||
|
|
||||||
static bool svc_alloc_arg(struct svc_rqst *rqstp)
|
static bool svc_alloc_arg(struct svc_rqst *rqstp)
|
||||||
{
|
{
|
||||||
struct svc_serv *serv = rqstp->rq_server;
|
|
||||||
struct xdr_buf *arg = &rqstp->rq_arg;
|
struct xdr_buf *arg = &rqstp->rq_arg;
|
||||||
unsigned long pages, filled, ret;
|
unsigned long pages, filled, ret;
|
||||||
|
|
||||||
pages = (serv->sv_max_mesg + 2 * PAGE_SIZE) >> PAGE_SHIFT;
|
pages = rqstp->rq_maxpages;
|
||||||
if (pages > RPCSVC_MAXPAGES) {
|
|
||||||
pr_warn_once("svc: warning: pages=%lu > RPCSVC_MAXPAGES=%lu\n",
|
|
||||||
pages, RPCSVC_MAXPAGES);
|
|
||||||
/* use as many pages as possible */
|
|
||||||
pages = RPCSVC_MAXPAGES;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (filled = 0; filled < pages; filled = ret) {
|
for (filled = 0; filled < pages; filled = ret) {
|
||||||
ret = alloc_pages_bulk(GFP_KERNEL, pages, rqstp->rq_pages);
|
ret = alloc_pages_bulk(GFP_KERNEL, pages, rqstp->rq_pages);
|
||||||
if (ret > filled)
|
if (ret > filled)
|
||||||
|
|
|
@ -765,7 +765,7 @@ static int svc_rdma_build_read_segment(struct svc_rqst *rqstp,
|
||||||
}
|
}
|
||||||
len -= seg_len;
|
len -= seg_len;
|
||||||
|
|
||||||
if (len && ((head->rc_curpage + 1) > ARRAY_SIZE(rqstp->rq_pages)))
|
if (len && ((head->rc_curpage + 1) > rqstp->rq_maxpages))
|
||||||
goto out_overrun;
|
goto out_overrun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue