OSDN Git Service

NFS: nfs_inode_find_state_and_recover() fix stateid matching
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Sat, 26 Oct 2019 14:16:15 +0000 (10:16 -0400)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 4 Nov 2019 02:28:46 +0000 (21:28 -0500)
In nfs_inode_find_state_and_recover() we want to mark for recovery
only those stateids that match or are older than the supplied
stateid parameter.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/delegation.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4state.c

index e3d8055..902baea 100644 (file)
@@ -1207,7 +1207,8 @@ void nfs_inode_find_delegation_state_and_recover(struct inode *inode,
        rcu_read_lock();
        delegation = rcu_dereference(NFS_I(inode)->delegation);
        if (delegation &&
-           nfs4_stateid_match_other(&delegation->stateid, stateid)) {
+           nfs4_stateid_match_or_older(&delegation->stateid, stateid) &&
+           !test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
                nfs_mark_test_expired_delegation(NFS_SERVER(inode), delegation);
                found = true;
        }
index 16b2e5c..40ab554 100644 (file)
@@ -572,6 +572,12 @@ static inline bool nfs4_stateid_is_newer(const nfs4_stateid *s1, const nfs4_stat
        return (s32)(be32_to_cpu(s1->seqid) - be32_to_cpu(s2->seqid)) > 0;
 }
 
+static inline bool nfs4_stateid_match_or_older(const nfs4_stateid *dst, const nfs4_stateid *src)
+{
+       return nfs4_stateid_match_other(dst, src) &&
+               !(src->seqid && nfs4_stateid_is_newer(dst, src));
+}
+
 static inline void nfs4_stateid_seqid_inc(nfs4_stateid *s1)
 {
        u32 seqid = be32_to_cpu(s1->seqid);
index 0c6d53d..a66acb6 100644 (file)
@@ -1407,7 +1407,7 @@ nfs_state_find_lock_state_by_stateid(struct nfs4_state *state,
        list_for_each_entry(pos, &state->lock_states, ls_locks) {
                if (!test_bit(NFS_LOCK_INITIALIZED, &pos->ls_flags))
                        continue;
-               if (nfs4_stateid_match_other(&pos->ls_stateid, stateid))
+               if (nfs4_stateid_match_or_older(&pos->ls_stateid, stateid))
                        return pos;
        }
        return NULL;
@@ -1441,12 +1441,13 @@ void nfs_inode_find_state_and_recover(struct inode *inode,
                state = ctx->state;
                if (state == NULL)
                        continue;
-               if (nfs4_stateid_match_other(&state->stateid, stateid) &&
+               if (nfs4_stateid_match_or_older(&state->stateid, stateid) &&
                    nfs4_state_mark_reclaim_nograce(clp, state)) {
                        found = true;
                        continue;
                }
-               if (nfs4_stateid_match_other(&state->open_stateid, stateid) &&
+               if (test_bit(NFS_OPEN_STATE, &state->flags) &&
+                   nfs4_stateid_match_or_older(&state->open_stateid, stateid) &&
                    nfs4_state_mark_reclaim_nograce(clp, state)) {
                        found = true;
                        continue;