diff options
Diffstat (limited to 'fs/nfs/filelayout/filelayout.c')
-rw-r--r-- | fs/nfs/filelayout/filelayout.c | 138 |
1 files changed, 91 insertions, 47 deletions
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index cad74c1c79ff..367f8eb19bfa 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c | |||
@@ -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 | * |
@@ -574,8 +618,6 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, | |||
574 | struct nfs4_layoutget_res *lgr, | 618 | struct nfs4_layoutget_res *lgr, |
575 | gfp_t gfp_flags) | 619 | gfp_t gfp_flags) |
576 | { | 620 | { |
577 | struct nfs4_deviceid_node *d; | ||
578 | struct nfs4_file_layout_dsaddr *dsaddr; | ||
579 | int status = -EINVAL; | 621 | int status = -EINVAL; |
580 | 622 | ||
581 | dprintk("--> %s\n", __func__); | 623 | dprintk("--> %s\n", __func__); |
@@ -600,41 +642,10 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo, | |||
600 | goto out; | 642 | goto out; |
601 | } | 643 | } |
602 | 644 | ||
603 | /* find and reference the deviceid */ | ||
604 | d = nfs4_find_get_deviceid(NFS_SERVER(lo->plh_inode), &fl->deviceid, | ||
605 | lo->plh_lc_cred, gfp_flags); | ||
606 | if (d == NULL) | ||
607 | goto out; | ||
608 | |||
609 | dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node); | ||
610 | /* Found deviceid is unavailable */ | ||
611 | if (filelayout_test_devid_unavailable(&dsaddr->id_node)) | ||
612 | goto out_put; | ||
613 | |||
614 | fl->dsaddr = dsaddr; | ||
615 | |||
616 | if (fl->first_stripe_index >= dsaddr->stripe_count) { | ||
617 | dprintk("%s Bad first_stripe_index %u\n", | ||
618 | __func__, fl->first_stripe_index); | ||
619 | goto out_put; | ||
620 | } | ||
621 | |||
622 | if ((fl->stripe_type == STRIPE_SPARSE && | ||
623 | fl->num_fh > 1 && fl->num_fh != dsaddr->ds_num) || | ||
624 | (fl->stripe_type == STRIPE_DENSE && | ||
625 | fl->num_fh != dsaddr->stripe_count)) { | ||
626 | dprintk("%s num_fh %u not valid for given packing\n", | ||
627 | __func__, fl->num_fh); | ||
628 | goto out_put; | ||
629 | } | ||
630 | |||
631 | status = 0; | 645 | status = 0; |
632 | out: | 646 | out: |
633 | dprintk("--> %s returns %d\n", __func__, status); | 647 | dprintk("--> %s returns %d\n", __func__, status); |
634 | return status; | 648 | return status; |
635 | out_put: | ||
636 | nfs4_fl_put_deviceid(dsaddr); | ||
637 | goto out; | ||
638 | } | 649 | } |
639 | 650 | ||
640 | static void _filelayout_free_lseg(struct nfs4_filelayout_segment *fl) | 651 | static void _filelayout_free_lseg(struct nfs4_filelayout_segment *fl) |
@@ -885,18 +896,51 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, | |||
885 | return min(stripe_unit - (unsigned int)stripe_offset, size); | 896 | return min(stripe_unit - (unsigned int)stripe_offset, size); |
886 | } | 897 | } |
887 | 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 | |||
888 | static void | 932 | static void |
889 | filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, | 933 | filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio, |
890 | struct nfs_page *req) | 934 | struct nfs_page *req) |
891 | { | 935 | { |
892 | if (!pgio->pg_lseg) { | 936 | if (!pgio->pg_lseg) { |
893 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 937 | pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode, |
894 | req->wb_context, | 938 | req->wb_context, |
895 | 0, | 939 | 0, |
896 | NFS4_MAX_UINT64, | 940 | NFS4_MAX_UINT64, |
897 | IOMODE_READ, | 941 | IOMODE_READ, |
898 | false, | 942 | false, |
899 | GFP_KERNEL); | 943 | GFP_KERNEL); |
900 | if (IS_ERR(pgio->pg_lseg)) { | 944 | if (IS_ERR(pgio->pg_lseg)) { |
901 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | 945 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); |
902 | pgio->pg_lseg = NULL; | 946 | pgio->pg_lseg = NULL; |
@@ -916,13 +960,13 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio, | |||
916 | int status; | 960 | int status; |
917 | 961 | ||
918 | if (!pgio->pg_lseg) { | 962 | if (!pgio->pg_lseg) { |
919 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 963 | pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode, |
920 | req->wb_context, | 964 | req->wb_context, |
921 | 0, | 965 | 0, |
922 | NFS4_MAX_UINT64, | 966 | NFS4_MAX_UINT64, |
923 | IOMODE_RW, | 967 | IOMODE_RW, |
924 | false, | 968 | false, |
925 | GFP_NOFS); | 969 | GFP_NOFS); |
926 | if (IS_ERR(pgio->pg_lseg)) { | 970 | if (IS_ERR(pgio->pg_lseg)) { |
927 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); | 971 | pgio->pg_error = PTR_ERR(pgio->pg_lseg); |
928 | pgio->pg_lseg = NULL; | 972 | pgio->pg_lseg = NULL; |