diff options
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r-- | fs/nfs/nfs4state.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 8db102c7add6..4e95bd72f480 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -989,13 +989,14 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl) | |||
989 | return 0; | 989 | return 0; |
990 | } | 990 | } |
991 | 991 | ||
992 | static bool nfs4_copy_lock_stateid(nfs4_stateid *dst, struct nfs4_state *state, | 992 | static int nfs4_copy_lock_stateid(nfs4_stateid *dst, |
993 | struct nfs4_state *state, | ||
993 | const struct nfs_lockowner *lockowner) | 994 | const struct nfs_lockowner *lockowner) |
994 | { | 995 | { |
995 | struct nfs4_lock_state *lsp; | 996 | struct nfs4_lock_state *lsp; |
996 | fl_owner_t fl_owner; | 997 | fl_owner_t fl_owner; |
997 | pid_t fl_pid; | 998 | pid_t fl_pid; |
998 | bool ret = false; | 999 | int ret = -ENOENT; |
999 | 1000 | ||
1000 | 1001 | ||
1001 | if (lockowner == NULL) | 1002 | if (lockowner == NULL) |
@@ -1010,7 +1011,10 @@ static bool nfs4_copy_lock_stateid(nfs4_stateid *dst, struct nfs4_state *state, | |||
1010 | lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE); | 1011 | lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE); |
1011 | if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) { | 1012 | if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) { |
1012 | nfs4_stateid_copy(dst, &lsp->ls_stateid); | 1013 | nfs4_stateid_copy(dst, &lsp->ls_stateid); |
1013 | ret = true; | 1014 | ret = 0; |
1015 | smp_rmb(); | ||
1016 | if (!list_empty(&lsp->ls_seqid.list)) | ||
1017 | ret = -EWOULDBLOCK; | ||
1014 | } | 1018 | } |
1015 | spin_unlock(&state->state_lock); | 1019 | spin_unlock(&state->state_lock); |
1016 | nfs4_put_lock_state(lsp); | 1020 | nfs4_put_lock_state(lsp); |
@@ -1018,28 +1022,38 @@ out: | |||
1018 | return ret; | 1022 | return ret; |
1019 | } | 1023 | } |
1020 | 1024 | ||
1021 | static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) | 1025 | static int nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) |
1022 | { | 1026 | { |
1027 | int ret; | ||
1023 | int seq; | 1028 | int seq; |
1024 | 1029 | ||
1025 | do { | 1030 | do { |
1026 | seq = read_seqbegin(&state->seqlock); | 1031 | seq = read_seqbegin(&state->seqlock); |
1027 | nfs4_stateid_copy(dst, &state->stateid); | 1032 | nfs4_stateid_copy(dst, &state->stateid); |
1033 | ret = 0; | ||
1034 | smp_rmb(); | ||
1035 | if (!list_empty(&state->owner->so_seqid.list)) | ||
1036 | ret = -EWOULDBLOCK; | ||
1028 | } while (read_seqretry(&state->seqlock, seq)); | 1037 | } while (read_seqretry(&state->seqlock, seq)); |
1038 | return ret; | ||
1029 | } | 1039 | } |
1030 | 1040 | ||
1031 | /* | 1041 | /* |
1032 | * Byte-range lock aware utility to initialize the stateid of read/write | 1042 | * Byte-range lock aware utility to initialize the stateid of read/write |
1033 | * requests. | 1043 | * requests. |
1034 | */ | 1044 | */ |
1035 | void nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state, | 1045 | int nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state, |
1036 | fmode_t fmode, const struct nfs_lockowner *lockowner) | 1046 | fmode_t fmode, const struct nfs_lockowner *lockowner) |
1037 | { | 1047 | { |
1048 | int ret = 0; | ||
1038 | if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) | 1049 | if (nfs4_copy_delegation_stateid(dst, state->inode, fmode)) |
1039 | return; | 1050 | goto out; |
1040 | if (nfs4_copy_lock_stateid(dst, state, lockowner)) | 1051 | ret = nfs4_copy_lock_stateid(dst, state, lockowner); |
1041 | return; | 1052 | if (ret != -ENOENT) |
1042 | nfs4_copy_open_stateid(dst, state); | 1053 | goto out; |
1054 | ret = nfs4_copy_open_stateid(dst, state); | ||
1055 | out: | ||
1056 | return ret; | ||
1043 | } | 1057 | } |
1044 | 1058 | ||
1045 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask) | 1059 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask) |