diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-07-21 12:44:15 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-07-24 16:16:39 -0400 |
commit | e5fd1904b8422615a2a286777e2b7c881ad53e73 (patch) | |
tree | c487abdf11e5502658827c2973a845f9be021607 /fs/nfs/pnfs.c | |
parent | 793b7fe55858dca1f5bd3e42185b541a9eddc144 (diff) |
pNFS: Ensure layoutreturn acts as a completion for layout callbacks
When we return NFS_OK to the CB_LAYOUTRECALL, we are required to
send a layoutreturn that "completes" that layout recall request, using
the correct stateid.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 85c3e7b47ddb..878dc4b7085a 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -883,12 +883,28 @@ pnfs_clear_layoutreturn_info(struct pnfs_layout_hdr *lo) | |||
883 | } | 883 | } |
884 | 884 | ||
885 | static bool | 885 | static bool |
886 | pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo) | 886 | pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo, |
887 | nfs4_stateid *stateid, | ||
888 | enum pnfs_iomode *iomode) | ||
887 | { | 889 | { |
888 | if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) | 890 | if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) |
889 | return false; | 891 | return false; |
890 | pnfs_get_layout_hdr(lo); | 892 | pnfs_get_layout_hdr(lo); |
891 | pnfs_clear_layoutreturn_info(lo); | 893 | if (test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags)) { |
894 | if (stateid != NULL) { | ||
895 | nfs4_stateid_copy(stateid, &lo->plh_stateid); | ||
896 | if (lo->plh_return_seq != 0) | ||
897 | stateid->seqid = cpu_to_be32(lo->plh_return_seq); | ||
898 | } | ||
899 | if (iomode != NULL) | ||
900 | *iomode = lo->plh_return_iomode; | ||
901 | pnfs_clear_layoutreturn_info(lo); | ||
902 | return true; | ||
903 | } | ||
904 | if (stateid != NULL) | ||
905 | nfs4_stateid_copy(stateid, &lo->plh_stateid); | ||
906 | if (iomode != NULL) | ||
907 | *iomode = IOMODE_ANY; | ||
892 | return true; | 908 | return true; |
893 | } | 909 | } |
894 | 910 | ||
@@ -956,10 +972,7 @@ static void pnfs_layoutreturn_before_put_layout_hdr(struct pnfs_layout_hdr *lo) | |||
956 | enum pnfs_iomode iomode; | 972 | enum pnfs_iomode iomode; |
957 | bool send; | 973 | bool send; |
958 | 974 | ||
959 | nfs4_stateid_copy(&stateid, &lo->plh_stateid); | 975 | send = pnfs_prepare_layoutreturn(lo, &stateid, &iomode); |
960 | stateid.seqid = cpu_to_be32(lo->plh_return_seq); | ||
961 | iomode = lo->plh_return_iomode; | ||
962 | send = pnfs_prepare_layoutreturn(lo); | ||
963 | spin_unlock(&inode->i_lock); | 976 | spin_unlock(&inode->i_lock); |
964 | if (send) { | 977 | if (send) { |
965 | /* Send an async layoutreturn so we dont deadlock */ | 978 | /* Send an async layoutreturn so we dont deadlock */ |
@@ -996,7 +1009,6 @@ _pnfs_return_layout(struct inode *ino) | |||
996 | dprintk("NFS: %s no layout to return\n", __func__); | 1009 | dprintk("NFS: %s no layout to return\n", __func__); |
997 | goto out; | 1010 | goto out; |
998 | } | 1011 | } |
999 | nfs4_stateid_copy(&stateid, &nfsi->layout->plh_stateid); | ||
1000 | /* Reference matched in nfs4_layoutreturn_release */ | 1012 | /* Reference matched in nfs4_layoutreturn_release */ |
1001 | pnfs_get_layout_hdr(lo); | 1013 | pnfs_get_layout_hdr(lo); |
1002 | empty = list_empty(&lo->plh_segs); | 1014 | empty = list_empty(&lo->plh_segs); |
@@ -1020,7 +1032,7 @@ _pnfs_return_layout(struct inode *ino) | |||
1020 | } | 1032 | } |
1021 | 1033 | ||
1022 | set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); | 1034 | set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); |
1023 | send = pnfs_prepare_layoutreturn(lo); | 1035 | send = pnfs_prepare_layoutreturn(lo, &stateid, NULL); |
1024 | spin_unlock(&ino->i_lock); | 1036 | spin_unlock(&ino->i_lock); |
1025 | pnfs_free_lseg_list(&tmp_list); | 1037 | pnfs_free_lseg_list(&tmp_list); |
1026 | if (send) | 1038 | if (send) |
@@ -1087,11 +1099,10 @@ bool pnfs_roc(struct inode *ino) | |||
1087 | goto out_noroc; | 1099 | goto out_noroc; |
1088 | } | 1100 | } |
1089 | 1101 | ||
1090 | nfs4_stateid_copy(&stateid, &lo->plh_stateid); | ||
1091 | /* always send layoutreturn if being marked so */ | 1102 | /* always send layoutreturn if being marked so */ |
1092 | if (test_and_clear_bit(NFS_LAYOUT_RETURN_REQUESTED, | 1103 | if (test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags)) |
1093 | &lo->plh_flags)) | 1104 | layoutreturn = pnfs_prepare_layoutreturn(lo, |
1094 | layoutreturn = pnfs_prepare_layoutreturn(lo); | 1105 | &stateid, NULL); |
1095 | 1106 | ||
1096 | list_for_each_entry_safe(lseg, tmp, &lo->plh_segs, pls_list) | 1107 | list_for_each_entry_safe(lseg, tmp, &lo->plh_segs, pls_list) |
1097 | /* If we are sending layoutreturn, invalidate all valid lsegs */ | 1108 | /* If we are sending layoutreturn, invalidate all valid lsegs */ |
@@ -1874,10 +1885,9 @@ void pnfs_error_mark_layout_for_return(struct inode *inode, | |||
1874 | if (!pnfs_mark_matching_lsegs_return(lo, &free_me, | 1885 | if (!pnfs_mark_matching_lsegs_return(lo, &free_me, |
1875 | &range, lseg->pls_seq)) { | 1886 | &range, lseg->pls_seq)) { |
1876 | nfs4_stateid stateid; | 1887 | nfs4_stateid stateid; |
1877 | enum pnfs_iomode iomode = lo->plh_return_iomode; | 1888 | enum pnfs_iomode iomode; |
1878 | 1889 | ||
1879 | nfs4_stateid_copy(&stateid, &lo->plh_stateid); | 1890 | return_now = pnfs_prepare_layoutreturn(lo, &stateid, &iomode); |
1880 | return_now = pnfs_prepare_layoutreturn(lo); | ||
1881 | spin_unlock(&inode->i_lock); | 1891 | spin_unlock(&inode->i_lock); |
1882 | if (return_now) | 1892 | if (return_now) |
1883 | pnfs_send_layoutreturn(lo, &stateid, iomode, false); | 1893 | pnfs_send_layoutreturn(lo, &stateid, iomode, false); |