NFS: skip recovery of copy open on dest server
authorOlga Kornievskaia <kolga@netapp.com>
Tue, 8 Oct 2019 20:34:36 +0000 (16:34 -0400)
committerOlga Kornievskaia <olga.kornievskaia@gmail.com>
Wed, 9 Oct 2019 16:05:56 +0000 (12:05 -0400)
Mark the open created for the source file on the destination
server. Then if this open is going thru a recovery, then fail
the recovery as we don't need to be recoving a "fake" open.
We need to fail the ongoing READs and vfs_copy_file_range().

Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
fs/nfs/nfs4_fs.h
fs/nfs/nfs4file.c
fs/nfs/nfs4state.c

index 5f27942..814674f 100644 (file)
@@ -168,6 +168,7 @@ enum {
        NFS_STATE_CHANGE_WAIT,          /* A state changing operation is outstanding */
 #ifdef CONFIG_NFS_V4_2
        NFS_CLNT_DST_SSC_COPY_STATE,    /* dst server open state on client*/
+       NFS_SRV_SSC_COPY_STATE,         /* ssc state on the dst server */
 #endif /* CONFIG_NFS_V4_2 */
 };
 
index 1898262..a932fc9 100644 (file)
@@ -352,6 +352,7 @@ nfs42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh,
        if (ctx->state == NULL)
                goto out_stateowner;
 
+       set_bit(NFS_SRV_SSC_COPY_STATE, &ctx->state->flags);
        set_bit(NFS_OPEN_STATE, &ctx->state->flags);
        memcpy(&ctx->state->open_stateid.other, &stateid->other,
               NFS4_STATEID_OTHER_SIZE);
index 0c6d53d..c45b300 100644 (file)
@@ -1609,6 +1609,9 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
        struct nfs4_state *state;
        unsigned int loop = 0;
        int status = 0;
+#ifdef CONFIG_NFS_V4_2
+       bool found_ssc_copy_state = false;
+#endif /* CONFIG_NFS_V4_2 */
 
        /* Note: we rely on the sp->so_states list being ordered 
         * so that we always reclaim open(O_RDWR) and/or open(O_WRITE)
@@ -1628,6 +1631,13 @@ restart:
                        continue;
                if (state->state == 0)
                        continue;
+#ifdef CONFIG_NFS_V4_2
+               if (test_bit(NFS_SRV_SSC_COPY_STATE, &state->flags)) {
+                       nfs4_state_mark_recovery_failed(state, -EIO);
+                       found_ssc_copy_state = true;
+                       continue;
+               }
+#endif /* CONFIG_NFS_V4_2 */
                refcount_inc(&state->count);
                spin_unlock(&sp->so_lock);
                status = __nfs4_reclaim_open_state(sp, state, ops);
@@ -1682,6 +1692,10 @@ restart:
        }
        raw_write_seqcount_end(&sp->so_reclaim_seqcount);
        spin_unlock(&sp->so_lock);
+#ifdef CONFIG_NFS_V4_2
+       if (found_ssc_copy_state)
+               return -EIO;
+#endif /* CONFIG_NFS_V4_2 */
        return 0;
 out_err:
        nfs4_put_open_state(state);