aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c57
-rw-r--r--fs/nfs/pnfs.c39
-rw-r--r--fs/nfs/pnfs.h2
3 files changed, 58 insertions, 40 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index a99a8d948721..6a78d49da5c1 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -6223,11 +6223,58 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata)
6223 dprintk("<-- %s\n", __func__); 6223 dprintk("<-- %s\n", __func__);
6224} 6224}
6225 6225
6226static size_t max_response_pages(struct nfs_server *server)
6227{
6228 u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
6229 return nfs_page_array_len(0, max_resp_sz);
6230}
6231
6232static void nfs4_free_pages(struct page **pages, size_t size)
6233{
6234 int i;
6235
6236 if (!pages)
6237 return;
6238
6239 for (i = 0; i < size; i++) {
6240 if (!pages[i])
6241 break;
6242 __free_page(pages[i]);
6243 }
6244 kfree(pages);
6245}
6246
6247static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags)
6248{
6249 struct page **pages;
6250 int i;
6251
6252 pages = kcalloc(size, sizeof(struct page *), gfp_flags);
6253 if (!pages) {
6254 dprintk("%s: can't alloc array of %zu pages\n", __func__, size);
6255 return NULL;
6256 }
6257
6258 for (i = 0; i < size; i++) {
6259 pages[i] = alloc_page(gfp_flags);
6260 if (!pages[i]) {
6261 dprintk("%s: failed to allocate page\n", __func__);
6262 nfs4_free_pages(pages, size);
6263 return NULL;
6264 }
6265 }
6266
6267 return pages;
6268}
6269
6226static void nfs4_layoutget_release(void *calldata) 6270static void nfs4_layoutget_release(void *calldata)
6227{ 6271{
6228 struct nfs4_layoutget *lgp = calldata; 6272 struct nfs4_layoutget *lgp = calldata;
6273 struct nfs_server *server = NFS_SERVER(lgp->args.inode);
6274 size_t max_pages = max_response_pages(server);
6229 6275
6230 dprintk("--> %s\n", __func__); 6276 dprintk("--> %s\n", __func__);
6277 nfs4_free_pages(lgp->args.layout.pages, max_pages);
6231 put_nfs_open_context(lgp->args.ctx); 6278 put_nfs_open_context(lgp->args.ctx);
6232 kfree(calldata); 6279 kfree(calldata);
6233 dprintk("<-- %s\n", __func__); 6280 dprintk("<-- %s\n", __func__);
@@ -6239,9 +6286,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = {
6239 .rpc_release = nfs4_layoutget_release, 6286 .rpc_release = nfs4_layoutget_release,
6240}; 6287};
6241 6288
6242int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) 6289int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags)
6243{ 6290{
6244 struct nfs_server *server = NFS_SERVER(lgp->args.inode); 6291 struct nfs_server *server = NFS_SERVER(lgp->args.inode);
6292 size_t max_pages = max_response_pages(server);
6245 struct rpc_task *task; 6293 struct rpc_task *task;
6246 struct rpc_message msg = { 6294 struct rpc_message msg = {
6247 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], 6295 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET],
@@ -6259,6 +6307,13 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp)
6259 6307
6260 dprintk("--> %s\n", __func__); 6308 dprintk("--> %s\n", __func__);
6261 6309
6310 lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags);
6311 if (!lgp->args.layout.pages) {
6312 nfs4_layoutget_release(lgp);
6313 return -ENOMEM;
6314 }
6315 lgp->args.layout.pglen = max_pages * PAGE_SIZE;
6316
6262 lgp->res.layoutp = &lgp->args.layout; 6317 lgp->res.layoutp = &lgp->args.layout;
6263 lgp->res.seq_res.sr_slot = NULL; 6318 lgp->res.seq_res.sr_slot = NULL;
6264 nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); 6319 nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 76875bfcf19c..2e00feacd4be 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -583,9 +583,6 @@ send_layoutget(struct pnfs_layout_hdr *lo,
583 struct nfs_server *server = NFS_SERVER(ino); 583 struct nfs_server *server = NFS_SERVER(ino);
584 struct nfs4_layoutget *lgp; 584 struct nfs4_layoutget *lgp;
585 struct pnfs_layout_segment *lseg = NULL; 585 struct pnfs_layout_segment *lseg = NULL;
586 struct page **pages = NULL;
587 int i;
588 u32 max_resp_sz, max_pages;
589 586
590 dprintk("--> %s\n", __func__); 587 dprintk("--> %s\n", __func__);
591 588
@@ -594,20 +591,6 @@ send_layoutget(struct pnfs_layout_hdr *lo,
594 if (lgp == NULL) 591 if (lgp == NULL)
595 return NULL; 592 return NULL;
596 593
597 /* allocate pages for xdr post processing */
598 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
599 max_pages = nfs_page_array_len(0, max_resp_sz);
600
601 pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags);
602 if (!pages)
603 goto out_err_free;
604
605 for (i = 0; i < max_pages; i++) {
606 pages[i] = alloc_page(gfp_flags);
607 if (!pages[i])
608 goto out_err_free;
609 }
610
611 lgp->args.minlength = PAGE_CACHE_SIZE; 594 lgp->args.minlength = PAGE_CACHE_SIZE;
612 if (lgp->args.minlength > range->length) 595 if (lgp->args.minlength > range->length)
613 lgp->args.minlength = range->length; 596 lgp->args.minlength = range->length;
@@ -616,39 +599,19 @@ send_layoutget(struct pnfs_layout_hdr *lo,
616 lgp->args.type = server->pnfs_curr_ld->id; 599 lgp->args.type = server->pnfs_curr_ld->id;
617 lgp->args.inode = ino; 600 lgp->args.inode = ino;
618 lgp->args.ctx = get_nfs_open_context(ctx); 601 lgp->args.ctx = get_nfs_open_context(ctx);
619 lgp->args.layout.pages = pages;
620 lgp->args.layout.pglen = max_pages * PAGE_SIZE;
621 lgp->lsegpp = &lseg; 602 lgp->lsegpp = &lseg;
622 lgp->gfp_flags = gfp_flags; 603 lgp->gfp_flags = gfp_flags;
623 604
624 /* Synchronously retrieve layout information from server and 605 /* Synchronously retrieve layout information from server and
625 * store in lseg. 606 * store in lseg.
626 */ 607 */
627 nfs4_proc_layoutget(lgp); 608 nfs4_proc_layoutget(lgp, gfp_flags);
628 if (!lseg) { 609 if (!lseg) {
629 /* remember that LAYOUTGET failed and suspend trying */ 610 /* remember that LAYOUTGET failed and suspend trying */
630 set_bit(lo_fail_bit(range->iomode), &lo->plh_flags); 611 set_bit(lo_fail_bit(range->iomode), &lo->plh_flags);
631 } 612 }
632 613
633 /* free xdr pages */
634 for (i = 0; i < max_pages; i++)
635 __free_page(pages[i]);
636 kfree(pages);
637
638 return lseg; 614 return lseg;
639
640out_err_free:
641 /* free any allocated xdr pages, lgp as it's not used */
642 if (pages) {
643 for (i = 0; i < max_pages; i++) {
644 if (!pages[i])
645 break;
646 __free_page(pages[i]);
647 }
648 kfree(pages);
649 }
650 kfree(lgp);
651 return NULL;
652} 615}
653 616
654/* 617/*
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 2c6c80503ba4..5ea019e80b4c 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -172,7 +172,7 @@ extern int nfs4_proc_getdevicelist(struct nfs_server *server,
172 struct pnfs_devicelist *devlist); 172 struct pnfs_devicelist *devlist);
173extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, 173extern int nfs4_proc_getdeviceinfo(struct nfs_server *server,
174 struct pnfs_device *dev); 174 struct pnfs_device *dev);
175extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp); 175extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags);
176extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); 176extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp);
177 177
178/* pnfs.c */ 178/* pnfs.c */