diff options
Diffstat (limited to 'fs/nfs/filelayout/filelayout.c')
-rw-r--r-- | fs/nfs/filelayout/filelayout.c | 151 |
1 files changed, 96 insertions, 55 deletions
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index 44347f4bdc15..acd30baca461 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c | |||
@@ -202,10 +202,10 @@ static int filelayout_async_handle_error(struct rpc_task *task, | |||
202 | task->tk_status); | 202 | task->tk_status); |
203 | nfs4_mark_deviceid_unavailable(devid); | 203 | nfs4_mark_deviceid_unavailable(devid); |
204 | pnfs_error_mark_layout_for_return(inode, lseg); | 204 | pnfs_error_mark_layout_for_return(inode, lseg); |
205 | pnfs_set_lo_fail(lseg); | ||
206 | rpc_wake_up(&tbl->slot_tbl_waitq); | 205 | rpc_wake_up(&tbl->slot_tbl_waitq); |
207 | /* fall through */ | 206 | /* fall through */ |
208 | default: | 207 | default: |
208 | pnfs_set_lo_fail(lseg); | ||
209 | reset: | 209 | reset: |
210 | dprintk("%s Retry through MDS. Error %d\n", __func__, | 210 | dprintk("%s Retry through MDS. Error %d\n", __func__, |
211 | task->tk_status); | 211 | task->tk_status); |
@@ -560,6 +560,50 @@ filelayout_write_pagelist(struct nfs_pgio_header *hdr, int sync) | |||
560 | return PNFS_ATTEMPTED; | 560 | return PNFS_ATTEMPTED; |
561 | } | 561 | } |
562 | 562 | ||
563 | static int | ||
564 | filelayout_check_deviceid(struct pnfs_layout_hdr *lo, | ||
565 | struct nfs4_filelayout_segment *fl, | ||
566 | gfp_t gfp_flags) | ||
567 | { | ||
568 | struct nfs4_deviceid_node *d; | ||
569 | struct nfs4_file_layout_dsaddr *dsaddr; | ||
570 | int status = -EINVAL; | ||
571 | |||
572 | /* find and reference the deviceid */ | ||
573 | d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid, | ||
574 | lo->plh_lc_cred, gfp_flags); | ||
575 | if (d == NULL) | ||
576 | goto out; | ||
577 | |||
578 | dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node); | ||
579 | /* Found deviceid is unavailable */ | ||
580 | if (filelayout_test_devid_unavailable(&dsaddr->id_node)) | ||
581 | goto out_put; | ||
582 | |||
583 | fl->dsaddr = dsaddr; | ||
584 | |||
585 | if (fl->first_stripe_index >= dsaddr->stripe_count) { | ||
586 | dprintk("%s Bad first_stripe_index %u\n", | ||
587 | __func__, fl->first_stripe_index); | ||
588 | goto out_put; | ||
589 | } | ||
590 | |||
591 | if ((fl->stripe_type == STRIPE_SPARSE && | ||
592 | fl->num_fh > 1 && fl->num_fh != dsaddr->ds_num) || | ||
593 | (fl->stripe_type == STRIPE_DENSE && | ||
594 | fl->num_fh != dsaddr->stripe_count)) { | ||
595 | dprintk("%s num_fh %u not valid for given packing\n", | ||
596 | __func__, fl->num_fh); | ||
597 | goto out_put; | ||
598 | } | ||
599 | status = 0; | ||
600 | out: | ||
601 | return status; | ||
602 | out_put: | ||
603 | nfs4_fl_put_deviceid(dsaddr); | ||
604 | goto out; | ||
605 | } | ||
606 | |||
563 | /* | 607 | /* |
564 | * filelayout_check_layout() | 608 | * filelayout_check_layout() |
565 | * | 609 | * |
@@ -572,11 +616,8 @@ static int | |||
572 | filelayout_check_layout(struct pnfs_layout_hdr *lo, | 616 | filelayout_check_layout(struct pnfs_layout_hdr *lo, |
573 | struct nfs4_filelayout_segment *fl, | 617 | struct nfs4_filelayout_segment *fl, |
574 | struct nfs4_layoutget_res *lgr, | 618 | struct nfs4_layoutget_res *lgr, |
575 | struct nfs4_deviceid *id, | ||
576 | gfp_t gfp_flags) | 619 | gfp_t gfp_flags) |
577 | { | 620 | { |
578 | struct nfs4_deviceid_node *d; | ||
579 | struct nfs4_file_layout_dsaddr *dsaddr; | ||
580 | int status = -EINVAL; | 621 | int status = -EINVAL; |
581 | 622 | ||
582 | dprintk("--> %s\n", __func__); | 623 | dprintk("--> %s\n", __func__); |
@@ -601,41 +642,10 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, | |||
601 | goto out; | 642 | goto out; |
602 | } | 643 | } |
603 | 644 | ||
604 | /* find and reference the deviceid */ | ||
605 | d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), id, | ||
606 | lo->plh_lc_cred, gfp_flags); | ||
607 | if (d == NULL) | ||
608 | goto out; | ||
609 | |||
610 | dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node); | ||
611 | /* Found deviceid is unavailable */ | ||
612 | if (filelayout_test_devid_unavailable(&dsaddr->id_node)) | ||
613 | goto out_put; | ||
614 | |||
615 | fl->dsaddr = dsaddr; | ||
616 | |||
617 | if (fl->first_stripe_index >= dsaddr->stripe_count) { | ||
618 | dprintk("%s Bad first_stripe_index %u\n", | ||
619 | __func__, fl->first_stripe_index); | ||
620 | goto out_put; | ||
621 | } | ||
622 | |||
623 | if ((fl->stripe_type == STRIPE_SPARSE && | ||
624 | fl->num_fh > 1 && fl->num_fh != dsaddr->ds_num) || | ||
625 | (fl->stripe_type == STRIPE_DENSE && | ||
626 | fl->num_fh != dsaddr->stripe_count)) { | ||
627 | dprintk("%s num_fh %u not valid for given packing\n", | ||
628 | __func__, fl->num_fh); | ||
629 | goto out_put; | ||
630 | } | ||
631 | |||
632 | status = 0; | 645 | status = 0; |
633 | out: | 646 | out: |
634 | dprintk("--> %s returns %d\n", __func__, status); | 647 | dprintk("--> %s returns %d\n", __func__, status); |
635 | return status; | 648 | return status; |
636 | out_put: | ||
637 | nfs4_fl_put_deviceid(dsaddr); | ||
638 | goto out; | ||
639 | } | 649 | } |
640 | 650 | ||
641 | static void _filelayout_free_lseg(struct nfs4_filelayout_segment *fl) | 651 | static void _filelayout_free_lseg(struct nfs4_filelayout_segment *fl) |
@@ -657,7 +667,6 @@ static int | |||
657 | filelayout_decode_layout(struct pnfs_layout_hdr *flo, | 667 | filelayout_decode_layout(struct pnfs_layout_hdr *flo, |
658 | struct nfs4_filelayout_segment *fl, | 668 | struct nfs4_filelayout_segment *fl, |
659 | struct nfs4_layoutget_res *lgr, | 669 | struct nfs4_layoutget_res *lgr, |
660 | struct nfs4_deviceid *id, | ||
661 | gfp_t gfp_flags) | 670 | gfp_t gfp_flags) |
662 | { | 671 | { |
663 | struct xdr_stream stream; | 672 | struct xdr_stream stream; |
@@ -682,9 +691,9 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, | |||
682 | if (unlikely(!p)) | 691 | if (unlikely(!p)) |
683 | goto out_err; | 692 | goto out_err; |
684 | 693 | ||
685 | memcpy(id, p, sizeof(*id)); | 694 | memcpy(&fl->deviceid, p, sizeof(fl->deviceid)); |
686 | p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); | 695 | p += XDR_QUADLEN(NFS4_DEVICEID4_SIZE); |
687 | nfs4_print_deviceid(id); | 696 | nfs4_print_deviceid(&fl->deviceid); |
688 | 697 | ||
689 | nfl_util = be32_to_cpup(p++); | 698 | nfl_util = be32_to_cpup(p++); |
690 | if (nfl_util & NFL4_UFLG_COMMIT_THRU_MDS) | 699 | if (nfl_util & NFL4_UFLG_COMMIT_THRU_MDS) |
@@ -831,15 +840,14 @@ filelayout_alloc_lseg(struct pnfs_layout_hdr *layoutid, | |||
831 | { | 840 | { |
832 | struct nfs4_filelayout_segment *fl; | 841 | struct nfs4_filelayout_segment *fl; |
833 | int rc; | 842 | int rc; |
834 | struct nfs4_deviceid id; | ||
835 | 843 | ||
836 | dprintk("--> %s\n", __func__); | 844 | dprintk("--> %s\n", __func__); |
837 | fl = kzalloc(sizeof(*fl), gfp_flags); | 845 | fl = kzalloc(sizeof(*fl), gfp_flags); |
838 | if (!fl) | 846 | if (!fl) |
839 | return NULL; | 847 | return NULL; |
840 | 848 | ||
841 | rc = filelayout_decode_layout(layoutid, fl, lgr, &id, gfp_flags); | 849 | rc = filelayout_decode_layout(layoutid, fl, lgr, gfp_flags); |
842 | if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, &id, gfp_flags)) { | 850 | if (rc != 0 || filelayout_check_layout(layoutid, fl, lgr, gfp_flags)) { |
843 | _filelayout_free_lseg(fl); | 851 | _filelayout_free_lseg(fl); |
844 | return NULL; | 852 | return NULL; |
845 | } | 853 | } |
@@ -888,18 +896,51 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, | |||
888 | return min(stripe_unit - (unsigned int)stripe_offset, size); | 896 | return min(stripe_unit - (unsigned int)stripe_offset, size); |
889 | } | 897 | } |
890 | 898 | ||
899 | static struct pnfs_layout_segment * | ||
900 | fl_pnfs_update_layout(struct inode *ino, | ||
901 | struct nfs_open_context *ctx, | ||
902 | loff_t pos, | ||
903 | u64 count, | ||
904 | enum pnfs_iomode iomode, | ||
905 | bool strict_iomode, | ||
906 | gfp_t gfp_flags) | ||
907 | { | ||
908 | struct pnfs_layout_segment *lseg = NULL; | ||
909 | struct pnfs_layout_hdr *lo; | ||
910 | struct nfs4_filelayout_segment *fl; | ||
911 | int status; | ||
912 | |||
913 | lseg = pnfs_update_layout(ino, ctx, pos, count, iomode, strict_iomode, | ||
914 | gfp_flags); | ||
915 | if (!lseg) | ||
916 | lseg = ERR_PTR(-ENOMEM); | ||
917 | if (IS_ERR(lseg)) | ||
918 | goto out; | ||
919 | |||
920 | lo = NFS_I(ino)->layout; | ||
921 | fl = FILELAYOUT_LSEG(lseg); | ||
922 | |||
923 | status = filelayout_check_deviceid(lo, fl, gfp_flags); | ||
924 | if (status) | ||
925 | lseg = ERR_PTR(status); | ||
926 | out: | ||
927 | if (IS_ERR(lseg)) | ||
928 | pnfs_put_lseg(lseg); | ||
929 | return lseg; | ||
930 | } | ||
931 | |||
891 | static void | 932 | static void |
892 | filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, | 933 | filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, |
893 | struct nfs_page *req) | 934 | struct nfs_page *req) |
894 | { | 935 | { |
895 | if (!pgio->pg_lseg) { | 936 | if (!pgio->pg_lseg) { |
896 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 937 | pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode, |
897 | req->wb_context, | 938 | req->wb_context, |
898 | 0, | 939 | 0, |
899 | NFS4_MAX_UINT64, | 940 | NFS4_MAX_UINT64, |
900 | IOMODE_READ, | 941 | IOMODE_READ, |
901 | false, | 942 | false, |
902 | GFP_KERNEL); | 943 | GFP_KERNEL); |
903 | if (IS_ERR(pgio->pg_lseg)) { | 944 | if (IS_ERR(pgio->pg_lseg)) { |
904 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | 945 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); |
905 | pgio->pg_lseg = NULL; | 946 | pgio->pg_lseg = NULL; |
@@ -919,13 +960,13 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, | |||
919 | int status; | 960 | int status; |
920 | 961 | ||
921 | if (!pgio->pg_lseg) { | 962 | if (!pgio->pg_lseg) { |
922 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 963 | pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode, |
923 | req->wb_context, | 964 | req->wb_context, |
924 | 0, | 965 | 0, |
925 | NFS4_MAX_UINT64, | 966 | NFS4_MAX_UINT64, |
926 | IOMODE_RW, | 967 | IOMODE_RW, |
927 | false, | 968 | false, |
928 | GFP_NOFS); | 969 | GFP_NOFS); |
929 | if (IS_ERR(pgio->pg_lseg)) { | 970 | if (IS_ERR(pgio->pg_lseg)) { |
930 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | 971 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); |
931 | pgio->pg_lseg = NULL; | 972 | pgio->pg_lseg = NULL; |