Merge tag 'nfs-for-4.19-2' of git://git.linux-nfs.org/projects/anna/linux-nfs
[muen/linux.git] / fs / nfs / nfs4proc.c
index 34830f6457ea252a2b56b9ef379b6ca3551f4f46..8220a168282e054164cb5b3bb8534f76be89faa7 100644 (file)
@@ -1637,6 +1637,14 @@ static void nfs_state_set_delegation(struct nfs4_state *state,
        write_sequnlock(&state->seqlock);
 }
 
+static void nfs_state_clear_delegation(struct nfs4_state *state)
+{
+       write_seqlock(&state->seqlock);
+       nfs4_stateid_copy(&state->stateid, &state->open_stateid);
+       clear_bit(NFS_DELEGATED_STATE, &state->flags);
+       write_sequnlock(&state->seqlock);
+}
+
 static int update_open_stateid(struct nfs4_state *state,
                const nfs4_stateid *open_stateid,
                const nfs4_stateid *delegation,
@@ -2145,10 +2153,7 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx,
        if (IS_ERR(opendata))
                return PTR_ERR(opendata);
        nfs4_stateid_copy(&opendata->o_arg.u.delegation, stateid);
-       write_seqlock(&state->seqlock);
-       nfs4_stateid_copy(&state->stateid, &state->open_stateid);
-       write_sequnlock(&state->seqlock);
-       clear_bit(NFS_DELEGATED_STATE, &state->flags);
+       nfs_state_clear_delegation(state);
        switch (type & (FMODE_READ|FMODE_WRITE)) {
        case FMODE_READ|FMODE_WRITE:
        case FMODE_WRITE:
@@ -2601,10 +2606,7 @@ static void nfs_finish_clear_delegation_stateid(struct nfs4_state *state,
                const nfs4_stateid *stateid)
 {
        nfs_remove_bad_delegation(state->inode, stateid);
-       write_seqlock(&state->seqlock);
-       nfs4_stateid_copy(&state->stateid, &state->open_stateid);
-       write_sequnlock(&state->seqlock);
-       clear_bit(NFS_DELEGATED_STATE, &state->flags);
+       nfs_state_clear_delegation(state);
 }
 
 static void nfs40_clear_delegation_stateid(struct nfs4_state *state)
@@ -2672,15 +2674,20 @@ static void nfs41_check_delegation_stateid(struct nfs4_state *state)
        delegation = rcu_dereference(NFS_I(state->inode)->delegation);
        if (delegation == NULL) {
                rcu_read_unlock();
+               nfs_state_clear_delegation(state);
                return;
        }
 
        nfs4_stateid_copy(&stateid, &delegation->stateid);
-       if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags) ||
-               !test_and_clear_bit(NFS_DELEGATION_TEST_EXPIRED,
-                       &delegation->flags)) {
+       if (test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) {
+               rcu_read_unlock();
+               nfs_state_clear_delegation(state);
+               return;
+       }
+
+       if (!test_and_clear_bit(NFS_DELEGATION_TEST_EXPIRED,
+                               &delegation->flags)) {
                rcu_read_unlock();
-               nfs_finish_clear_delegation_stateid(state, &stateid);
                return;
        }