aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/nfs4state.c')
-rw-r--r--fs/nfs/nfs4state.c32
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
992static bool nfs4_copy_lock_stateid(nfs4_stateid *dst, struct nfs4_state *state, 992static 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
1021static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state) 1025static 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 */
1035void nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state, 1045int 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);
1055out:
1056 return ret;
1043} 1057}
1044 1058
1045struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask) 1059struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask)