aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2011-05-11 18:00:51 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-05-11 22:52:13 -0400
commita75b9df9d3bfc3cd1083974c045ae31ce5f3434f (patch)
tree039cc65774c895d704f23a2c89b7f1bcd736e0b9 /fs/nfs/pnfs.c
parent2887fe45522843149ccf72e01f43813be4fb36c5 (diff)
NFSv4.1: Ensure that layoutget uses the correct gfp modes
Currently, writebacks may end up recursing back into the filesystem due to GFP_KERNEL direct reclaims in the pnfs subsystem. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r--fs/nfs/pnfs.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 65455f58b109..f57f5281a520 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -467,7 +467,8 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
467static struct pnfs_layout_segment * 467static struct pnfs_layout_segment *
468send_layoutget(struct pnfs_layout_hdr *lo, 468send_layoutget(struct pnfs_layout_hdr *lo,
469 struct nfs_open_context *ctx, 469 struct nfs_open_context *ctx,
470 u32 iomode) 470 u32 iomode,
471 gfp_t gfp_flags)
471{ 472{
472 struct inode *ino = lo->plh_inode; 473 struct inode *ino = lo->plh_inode;
473 struct nfs_server *server = NFS_SERVER(ino); 474 struct nfs_server *server = NFS_SERVER(ino);
@@ -480,7 +481,7 @@ send_layoutget(struct pnfs_layout_hdr *lo,
480 dprintk("--> %s\n", __func__); 481 dprintk("--> %s\n", __func__);
481 482
482 BUG_ON(ctx == NULL); 483 BUG_ON(ctx == NULL);
483 lgp = kzalloc(sizeof(*lgp), GFP_KERNEL); 484 lgp = kzalloc(sizeof(*lgp), gfp_flags);
484 if (lgp == NULL) 485 if (lgp == NULL)
485 return NULL; 486 return NULL;
486 487
@@ -488,12 +489,12 @@ send_layoutget(struct pnfs_layout_hdr *lo,
488 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; 489 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz;
489 max_pages = max_resp_sz >> PAGE_SHIFT; 490 max_pages = max_resp_sz >> PAGE_SHIFT;
490 491
491 pages = kzalloc(max_pages * sizeof(struct page *), GFP_KERNEL); 492 pages = kzalloc(max_pages * sizeof(struct page *), gfp_flags);
492 if (!pages) 493 if (!pages)
493 goto out_err_free; 494 goto out_err_free;
494 495
495 for (i = 0; i < max_pages; i++) { 496 for (i = 0; i < max_pages; i++) {
496 pages[i] = alloc_page(GFP_KERNEL); 497 pages[i] = alloc_page(gfp_flags);
497 if (!pages[i]) 498 if (!pages[i])
498 goto out_err_free; 499 goto out_err_free;
499 } 500 }
@@ -509,6 +510,7 @@ send_layoutget(struct pnfs_layout_hdr *lo,
509 lgp->args.layout.pages = pages; 510 lgp->args.layout.pages = pages;
510 lgp->args.layout.pglen = max_pages * PAGE_SIZE; 511 lgp->args.layout.pglen = max_pages * PAGE_SIZE;
511 lgp->lsegpp = &lseg; 512 lgp->lsegpp = &lseg;
513 lgp->gfp_flags = gfp_flags;
512 514
513 /* Synchronously retrieve layout information from server and 515 /* Synchronously retrieve layout information from server and
514 * store in lseg. 516 * store in lseg.
@@ -666,11 +668,11 @@ pnfs_insert_layout(struct pnfs_layout_hdr *lo,
666} 668}
667 669
668static struct pnfs_layout_hdr * 670static struct pnfs_layout_hdr *
669alloc_init_layout_hdr(struct inode *ino) 671alloc_init_layout_hdr(struct inode *ino, gfp_t gfp_flags)
670{ 672{
671 struct pnfs_layout_hdr *lo; 673 struct pnfs_layout_hdr *lo;
672 674
673 lo = kzalloc(sizeof(struct pnfs_layout_hdr), GFP_KERNEL); 675 lo = kzalloc(sizeof(struct pnfs_layout_hdr), gfp_flags);
674 if (!lo) 676 if (!lo)
675 return NULL; 677 return NULL;
676 atomic_set(&lo->plh_refcount, 1); 678 atomic_set(&lo->plh_refcount, 1);
@@ -682,7 +684,7 @@ alloc_init_layout_hdr(struct inode *ino)
682} 684}
683 685
684static struct pnfs_layout_hdr * 686static struct pnfs_layout_hdr *
685pnfs_find_alloc_layout(struct inode *ino) 687pnfs_find_alloc_layout(struct inode *ino, gfp_t gfp_flags)
686{ 688{
687 struct nfs_inode *nfsi = NFS_I(ino); 689 struct nfs_inode *nfsi = NFS_I(ino);
688 struct pnfs_layout_hdr *new = NULL; 690 struct pnfs_layout_hdr *new = NULL;
@@ -697,7 +699,7 @@ pnfs_find_alloc_layout(struct inode *ino)
697 return nfsi->layout; 699 return nfsi->layout;
698 } 700 }
699 spin_unlock(&ino->i_lock); 701 spin_unlock(&ino->i_lock);
700 new = alloc_init_layout_hdr(ino); 702 new = alloc_init_layout_hdr(ino, gfp_flags);
701 spin_lock(&ino->i_lock); 703 spin_lock(&ino->i_lock);
702 704
703 if (likely(nfsi->layout == NULL)) /* Won the race? */ 705 if (likely(nfsi->layout == NULL)) /* Won the race? */
@@ -757,7 +759,8 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, u32 iomode)
757struct pnfs_layout_segment * 759struct pnfs_layout_segment *
758pnfs_update_layout(struct inode *ino, 760pnfs_update_layout(struct inode *ino,
759 struct nfs_open_context *ctx, 761 struct nfs_open_context *ctx,
760 enum pnfs_iomode iomode) 762 enum pnfs_iomode iomode,
763 gfp_t gfp_flags)
761{ 764{
762 struct nfs_inode *nfsi = NFS_I(ino); 765 struct nfs_inode *nfsi = NFS_I(ino);
763 struct nfs_client *clp = NFS_SERVER(ino)->nfs_client; 766 struct nfs_client *clp = NFS_SERVER(ino)->nfs_client;
@@ -768,7 +771,7 @@ pnfs_update_layout(struct inode *ino,
768 if (!pnfs_enabled_sb(NFS_SERVER(ino))) 771 if (!pnfs_enabled_sb(NFS_SERVER(ino)))
769 return NULL; 772 return NULL;
770 spin_lock(&ino->i_lock); 773 spin_lock(&ino->i_lock);
771 lo = pnfs_find_alloc_layout(ino); 774 lo = pnfs_find_alloc_layout(ino, gfp_flags);
772 if (lo == NULL) { 775 if (lo == NULL) {
773 dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__); 776 dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__);
774 goto out_unlock; 777 goto out_unlock;
@@ -808,7 +811,7 @@ pnfs_update_layout(struct inode *ino,
808 spin_unlock(&clp->cl_lock); 811 spin_unlock(&clp->cl_lock);
809 } 812 }
810 813
811 lseg = send_layoutget(lo, ctx, iomode); 814 lseg = send_layoutget(lo, ctx, iomode, gfp_flags);
812 if (!lseg && first) { 815 if (!lseg && first) {
813 spin_lock(&clp->cl_lock); 816 spin_lock(&clp->cl_lock);
814 list_del_init(&lo->plh_layouts); 817 list_del_init(&lo->plh_layouts);
@@ -847,7 +850,7 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
847 goto out; 850 goto out;
848 } 851 }
849 /* Inject layout blob into I/O device driver */ 852 /* Inject layout blob into I/O device driver */
850 lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res); 853 lseg = NFS_SERVER(ino)->pnfs_curr_ld->alloc_lseg(lo, res, lgp->gfp_flags);
851 if (!lseg || IS_ERR(lseg)) { 854 if (!lseg || IS_ERR(lseg)) {
852 if (!lseg) 855 if (!lseg)
853 status = -ENOMEM; 856 status = -ENOMEM;
@@ -900,7 +903,8 @@ static int pnfs_read_pg_test(struct nfs_pageio_descriptor *pgio,
900 /* This is first coelesce call for a series of nfs_pages */ 903 /* This is first coelesce call for a series of nfs_pages */
901 pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, 904 pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
902 prev->wb_context, 905 prev->wb_context,
903 IOMODE_READ); 906 IOMODE_READ,
907 GFP_KERNEL);
904 } 908 }
905 return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req); 909 return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req);
906} 910}
@@ -922,7 +926,8 @@ static int pnfs_write_pg_test(struct nfs_pageio_descriptor *pgio,
922 /* This is first coelesce call for a series of nfs_pages */ 926 /* This is first coelesce call for a series of nfs_pages */
923 pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, 927 pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
924 prev->wb_context, 928 prev->wb_context,
925 IOMODE_RW); 929 IOMODE_RW,
930 GFP_NOFS);
926 } 931 }
927 return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req); 932 return NFS_SERVER(pgio->pg_inode)->pnfs_curr_ld->pg_test(pgio, prev, req);
928} 933}