summaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4_fs.h
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-11-14 11:19:55 -0500
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2016-11-18 13:35:58 -0500
commit3e7dfb1659c2888fc0152ec2b02a5e932397bb0a (patch)
tree301cbdf7e52009221b137a1d028a1b916d38e167 /fs/nfs/nfs4_fs.h
parent23ea44c2150d14b97518435a65cc74111804fbeb (diff)
downloadlinux-3e7dfb1659c2888fc0152ec2b02a5e932397bb0a.tar.gz
linux-3e7dfb1659c2888fc0152ec2b02a5e932397bb0a.tar.bz2
linux-3e7dfb1659c2888fc0152ec2b02a5e932397bb0a.zip
NFSv4: Fix CLOSE races with OPEN
If the reply to a successful CLOSE call races with an OPEN to the same file, we can end up scribbling over the stateid that represents the new open state. The race looks like: Client Server ====== ====== CLOSE stateid A on file "foo" CLOSE stateid A, return stateid C OPEN file "foo" OPEN "foo", return stateid B Receive reply to OPEN Reset open state for "foo" Associate stateid B to "foo" Receive CLOSE for A Reset open state for "foo" Replace stateid B with C The fix is to examine the argument of the CLOSE, and check for a match with the current stateid "other" field. If the two do not match, then the above race occurred, and we should just ignore the CLOSE. Reported-by: Benjamin Coddington <bcodding@redhat.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs/nfs/nfs4_fs.h')
-rw-r--r--fs/nfs/nfs4_fs.h7
1 files changed, 7 insertions, 0 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 9b3a82abab07..1452177c822d 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -542,6 +542,13 @@ static inline bool nfs4_valid_open_stateid(const struct nfs4_state *state)
return test_bit(NFS_STATE_RECOVERY_FAILED, &state->flags) == 0;
}
+static inline bool nfs4_state_match_open_stateid_other(const struct nfs4_state *state,
+ const nfs4_stateid *stateid)
+{
+ return test_bit(NFS_OPEN_STATE, &state->flags) &&
+ nfs4_stateid_match_other(&state->open_stateid, stateid);
+}
+
#else
#define nfs4_close_state(a, b) do { } while (0)