diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-05-11 18:00:51 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-05-11 22:52:13 -0400 |
commit | a75b9df9d3bfc3cd1083974c045ae31ce5f3434f (patch) | |
tree | 039cc65774c895d704f23a2c89b7f1bcd736e0b9 /fs/nfs/nfs4filelayout.c | |
parent | 2887fe45522843149ccf72e01f43813be4fb36c5 (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/nfs4filelayout.c')
-rw-r--r-- | fs/nfs/nfs4filelayout.c | 25 |
1 files changed, 14 insertions, 11 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 7841ea603c91..be79dc9f386d 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
@@ -418,7 +418,8 @@ static int | |||
418 | filelayout_check_layout(struct pnfs_layout_hdr *lo, | 418 | filelayout_check_layout(struct pnfs_layout_hdr *lo, |
419 | struct nfs4_filelayout_segment *fl, | 419 | struct nfs4_filelayout_segment *fl, |
420 | struct nfs4_layoutget_res *lgr, | 420 | struct nfs4_layoutget_res *lgr, |
421 | struct nfs4_deviceid *id) | 421 | struct nfs4_deviceid *id, |
422 | gfp_t gfp_flags) | ||
422 | { | 423 | { |
423 | struct nfs4_file_layout_dsaddr *dsaddr; | 424 | struct nfs4_file_layout_dsaddr *dsaddr; |
424 | int status = -EINVAL; | 425 | int status = -EINVAL; |
@@ -441,7 +442,7 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, | |||
441 | /* find and reference the deviceid */ | 442 | /* find and reference the deviceid */ |
442 | dsaddr = nfs4_fl_find_get_deviceid(id); | 443 | dsaddr = nfs4_fl_find_get_deviceid(id); |
443 | if (dsaddr == NULL) { | 444 | if (dsaddr == NULL) { |
444 | dsaddr = get_device_info(lo->plh_inode, id); | 445 | dsaddr = get_device_info(lo->plh_inode, id, gfp_flags); |
445 | if (dsaddr == NULL) | 446 | if (dsaddr == NULL) |
446 | goto out; | 447 | goto out; |
447 | } | 448 | } |
@@ -502,7 +503,8 @@ static int | |||
502 | filelayout_decode_layout(struct pnfs_layout_hdr *flo, | 503 | filelayout_decode_layout(struct pnfs_layout_hdr *flo, |
503 | struct nfs4_filelayout_segment *fl, | 504 | struct nfs4_filelayout_segment *fl, |
504 | struct nfs4_layoutget_res *lgr, | 505 | struct nfs4_layoutget_res *lgr, |
505 | struct nfs4_deviceid *id) | 506 | struct nfs4_deviceid *id, |
507 | gfp_t gfp_flags) | ||
506 | { | 508 | { |
507 | struct xdr_stream stream; | 509 | struct xdr_stream stream; |
508 | struct xdr_buf buf = { | 510 | struct xdr_buf buf = { |
@@ -518,7 +520,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, | |||
518 | 520 | ||
519 | dprintk("%s: set_layout_map Begin\n", __func__); | 521 | dprintk("%s: set_layout_map Begin\n", __func__); |
520 | 522 | ||
521 | scratch = alloc_page(GFP_KERNEL); | 523 | scratch = alloc_page(gfp_flags); |
522 | if (!scratch) | 524 | if (!scratch) |
523 | return -ENOMEM; | 525 | return -ENOMEM; |
524 | 526 | ||
@@ -556,13 +558,13 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, | |||
556 | goto out_err; | 558 | goto out_err; |
557 | 559 | ||
558 | fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), | 560 | fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), |
559 | GFP_KERNEL); | 561 | gfp_flags); |
560 | if (!fl->fh_array) | 562 | if (!fl->fh_array) |
561 | goto out_err; | 563 | goto out_err; |
562 | 564 | ||
563 | for (i = 0; i < fl->num_fh; i++) { | 565 | for (i = 0; i < fl->num_fh; i++) { |
564 | /* Do we want to use a mempool here? */ | 566 | /* Do we want to use a mempool here? */ |
565 | fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), GFP_KERNEL); | 567 | fl->fh_array[i] = kmalloc(sizeof(struct nfs_fh), gfp_flags); |
566 | if (!fl->fh_array[i]) | 568 | if (!fl->fh_array[i]) |
567 | goto out_err_free; | 569 | goto out_err_free; |
568 | 570 | ||
@@ -607,19 +609,20 @@ filelayout_free_lseg(struct pnfs_layout_segment *lseg) | |||
607 | 609 | ||
608 | static struct pnfs_layout_segment * | 610 | static struct pnfs_layout_segment * |
609 | filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, | 611 | filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, |
610 | struct nfs4_layoutget_res *lgr) | 612 | struct nfs4_layoutget_res *lgr, |
613 | gfp_t gfp_flags) | ||
611 | { | 614 | { |
612 | struct nfs4_filelayout_segment *fl; | 615 | struct nfs4_filelayout_segment *fl; |
613 | int rc; | 616 | int rc; |
614 | struct nfs4_deviceid id; | 617 | struct nfs4_deviceid id; |
615 | 618 | ||
616 | dprintk("--> %s\n", __func__); | 619 | dprintk("--> %s\n", __func__); |
617 | fl = kzalloc(sizeof(*fl), GFP_KERNEL); | 620 | fl = kzalloc(sizeof(*fl), gfp_flags); |
618 | if (!fl) | 621 | if (!fl) |
619 | return NULL; | 622 | return NULL; |
620 | 623 | ||
621 | rc = filelayout_decode_layout(layoutid, fl, lgr, &id); | 624 | rc = filelayout_decode_layout(layoutid, fl, lgr, &id, gfp_flags); |
622 | if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id)) { | 625 | if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id, gfp_flags)) { |
623 | _filelayout_free_lseg(fl); | 626 | _filelayout_free_lseg(fl); |
624 | return NULL; | 627 | return NULL; |
625 | } | 628 | } |
@@ -635,7 +638,7 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, | |||
635 | int size = (fl->stripe_type == STRIPE_SPARSE) ? | 638 | int size = (fl->stripe_type == STRIPE_SPARSE) ? |
636 | fl->dsaddr->ds_num : fl->dsaddr->stripe_count; | 639 | fl->dsaddr->ds_num : fl->dsaddr->stripe_count; |
637 | 640 | ||
638 | fl->commit_buckets = kcalloc(size, sizeof(struct list_head), GFP_KERNEL); | 641 | fl->commit_buckets = kcalloc(size, sizeof(struct list_head), gfp_flags); |
639 | if (!fl->commit_buckets) { | 642 | if (!fl->commit_buckets) { |
640 | filelayout_free_lseg(&fl->generic_hdr); | 643 | filelayout_free_lseg(&fl->generic_hdr); |
641 | return NULL; | 644 | return NULL; |