diff options
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 8c1309d852a6..29c0ca7fc347 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -634,14 +634,16 @@ _pnfs_return_layout(struct inode *ino) | |||
634 | 634 | ||
635 | spin_lock(&ino->i_lock); | 635 | spin_lock(&ino->i_lock); |
636 | lo = nfsi->layout; | 636 | lo = nfsi->layout; |
637 | if (!lo || !mark_matching_lsegs_invalid(lo, &tmp_list, NULL)) { | 637 | if (!lo) { |
638 | spin_unlock(&ino->i_lock); | 638 | spin_unlock(&ino->i_lock); |
639 | dprintk("%s: no layout segments to return\n", __func__); | 639 | dprintk("%s: no layout to return\n", __func__); |
640 | goto out; | 640 | return status; |
641 | } | 641 | } |
642 | stateid = nfsi->layout->plh_stateid; | 642 | stateid = nfsi->layout->plh_stateid; |
643 | /* Reference matched in nfs4_layoutreturn_release */ | 643 | /* Reference matched in nfs4_layoutreturn_release */ |
644 | get_layout_hdr(lo); | 644 | get_layout_hdr(lo); |
645 | mark_matching_lsegs_invalid(lo, &tmp_list, NULL); | ||
646 | lo->plh_block_lgets++; | ||
645 | spin_unlock(&ino->i_lock); | 647 | spin_unlock(&ino->i_lock); |
646 | pnfs_free_lseg_list(&tmp_list); | 648 | pnfs_free_lseg_list(&tmp_list); |
647 | 649 | ||
@@ -650,6 +652,9 @@ _pnfs_return_layout(struct inode *ino) | |||
650 | lrp = kzalloc(sizeof(*lrp), GFP_KERNEL); | 652 | lrp = kzalloc(sizeof(*lrp), GFP_KERNEL); |
651 | if (unlikely(lrp == NULL)) { | 653 | if (unlikely(lrp == NULL)) { |
652 | status = -ENOMEM; | 654 | status = -ENOMEM; |
655 | set_bit(NFS_LAYOUT_RW_FAILED, &lo->plh_flags); | ||
656 | set_bit(NFS_LAYOUT_RO_FAILED, &lo->plh_flags); | ||
657 | put_layout_hdr(lo); | ||
653 | goto out; | 658 | goto out; |
654 | } | 659 | } |
655 | 660 | ||
@@ -887,7 +892,7 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, | |||
887 | ret = get_lseg(lseg); | 892 | ret = get_lseg(lseg); |
888 | break; | 893 | break; |
889 | } | 894 | } |
890 | if (cmp_layout(range, &lseg->pls_range) > 0) | 895 | if (lseg->pls_range.offset > range->offset) |
891 | break; | 896 | break; |
892 | } | 897 | } |
893 | 898 | ||
@@ -1059,23 +1064,36 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, | |||
1059 | gfp_flags = GFP_NOFS; | 1064 | gfp_flags = GFP_NOFS; |
1060 | } | 1065 | } |
1061 | 1066 | ||
1062 | if (pgio->pg_count == prev->wb_bytes) { | 1067 | if (pgio->pg_lseg == NULL) { |
1068 | if (pgio->pg_count != prev->wb_bytes) | ||
1069 | return true; | ||
1063 | /* This is first coelesce call for a series of nfs_pages */ | 1070 | /* This is first coelesce call for a series of nfs_pages */ |
1064 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 1071 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
1065 | prev->wb_context, | 1072 | prev->wb_context, |
1066 | req_offset(req), | 1073 | req_offset(prev), |
1067 | pgio->pg_count, | 1074 | pgio->pg_count, |
1068 | access_type, | 1075 | access_type, |
1069 | gfp_flags); | 1076 | gfp_flags); |
1070 | return true; | 1077 | if (pgio->pg_lseg == NULL) |
1078 | return true; | ||
1071 | } | 1079 | } |
1072 | 1080 | ||
1073 | if (pgio->pg_lseg && | 1081 | /* |
1074 | req_offset(req) > end_offset(pgio->pg_lseg->pls_range.offset, | 1082 | * Test if a nfs_page is fully contained in the pnfs_layout_range. |
1075 | pgio->pg_lseg->pls_range.length)) | 1083 | * Note that this test makes several assumptions: |
1076 | return false; | 1084 | * - that the previous nfs_page in the struct nfs_pageio_descriptor |
1077 | 1085 | * is known to lie within the range. | |
1078 | return true; | 1086 | * - that the nfs_page being tested is known to be contiguous with the |
1087 | * previous nfs_page. | ||
1088 | * - Layout ranges are page aligned, so we only have to test the | ||
1089 | * start offset of the request. | ||
1090 | * | ||
1091 | * Please also note that 'end_offset' is actually the offset of the | ||
1092 | * first byte that lies outside the pnfs_layout_range. FIXME? | ||
1093 | * | ||
1094 | */ | ||
1095 | return req_offset(req) < end_offset(pgio->pg_lseg->pls_range.offset, | ||
1096 | pgio->pg_lseg->pls_range.length); | ||
1079 | } | 1097 | } |
1080 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); | 1098 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); |
1081 | 1099 | ||