forked from luck/tmp_suning_uos_patched
sunrpc: Allocate up to RPCSVC_MAXPAGES per svc_rqst
svcrdma needs 259 pages allocated to receive 1MB NFSv4.0 WRITE requests: - 1 page for the transport header and head iovec - 256 pages for the data payload - 1 page for the trailing GETATTR request (since NFSD XDR decoding does not look for a tail iovec, the GETATTR is stuck at the end of the rqstp->rq_arg.pages list) - 1 page for building the reply xdr_buf But RPCSVC_MAXPAGES is already 259 (on x86_64). The problem is that svc_alloc_arg never allocates that many pages. To address this: 1. The final element of rq_pages always points to NULL. To accommodate up to 259 pages in rq_pages, add an extra element to rq_pages for the array termination sentinel. 2. Adjust the calculation of "pages" to match how RPCSVC_MAXPAGES is calculated, so it can go up to 259. Bruce noted that the calculation assumes sv_max_mesg is a multiple of PAGE_SIZE, which might not always be true. I didn't change this assumption. 3. Change the loop boundaries to allow 259 pages to be allocated. Additional clean-up: WARN_ON_ONCE adds an extra conditional branch, which is basically never taken. And there's no need to dump the stack here because svc_alloc_arg has only one caller. Keeping that NULL "array termination sentinel"; there doesn't appear to be any code that depends on it, only code in nfsd_splice_actor() which needs the 259th element to be initialized to *something*. So it's possible we could just keep the array at 259 elements and drop that final NULL, but we're being conservative for now. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
parent
2d6491a56c
commit
8c6ae4980e
|
@ -246,7 +246,7 @@ struct svc_rqst {
|
|||
size_t rq_xprt_hlen; /* xprt header len */
|
||||
struct xdr_buf rq_arg;
|
||||
struct xdr_buf rq_res;
|
||||
struct page * rq_pages[RPCSVC_MAXPAGES];
|
||||
struct page *rq_pages[RPCSVC_MAXPAGES + 1];
|
||||
struct page * *rq_respages; /* points into rq_pages */
|
||||
struct page * *rq_next_page; /* next reply page to use */
|
||||
struct page * *rq_page_end; /* one past the last page */
|
||||
|
|
|
@ -659,11 +659,13 @@ static int svc_alloc_arg(struct svc_rqst *rqstp)
|
|||
int i;
|
||||
|
||||
/* now allocate needed pages. If we get a failure, sleep briefly */
|
||||
pages = (serv->sv_max_mesg + PAGE_SIZE) / PAGE_SIZE;
|
||||
WARN_ON_ONCE(pages >= RPCSVC_MAXPAGES);
|
||||
if (pages >= RPCSVC_MAXPAGES)
|
||||
pages = (serv->sv_max_mesg + 2 * PAGE_SIZE) >> PAGE_SHIFT;
|
||||
if (pages > RPCSVC_MAXPAGES) {
|
||||
pr_warn_once("svc: warning: pages=%u > RPCSVC_MAXPAGES=%lu\n",
|
||||
pages, RPCSVC_MAXPAGES);
|
||||
/* use as many pages as possible */
|
||||
pages = RPCSVC_MAXPAGES - 1;
|
||||
pages = RPCSVC_MAXPAGES;
|
||||
}
|
||||
for (i = 0; i < pages ; i++)
|
||||
while (rqstp->rq_pages[i] == NULL) {
|
||||
struct page *p = alloc_page(GFP_KERNEL);
|
||||
|
|
Loading…
Reference in New Issue
Block a user