NFS: skip recovery of copy open on dest server

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>
This commit is contained in:
Olga Kornievskaia 2019-10-08 16:34:36 -04:00 committed by Olga Kornievskaia
parent ec4b092508
commit 0b9018b9ca
3 changed files with 16 additions and 0 deletions

View File

@ -168,6 +168,7 @@ enum {
NFS_STATE_CHANGE_WAIT, /* A state changing operation is outstanding */ NFS_STATE_CHANGE_WAIT, /* A state changing operation is outstanding */
#ifdef CONFIG_NFS_V4_2 #ifdef CONFIG_NFS_V4_2
NFS_CLNT_DST_SSC_COPY_STATE, /* dst server open state on client*/ 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 */ #endif /* CONFIG_NFS_V4_2 */
}; };

View File

@ -352,6 +352,7 @@ nfs42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh,
if (ctx->state == NULL) if (ctx->state == NULL)
goto out_stateowner; goto out_stateowner;
set_bit(NFS_SRV_SSC_COPY_STATE, &ctx->state->flags);
set_bit(NFS_OPEN_STATE, &ctx->state->flags); set_bit(NFS_OPEN_STATE, &ctx->state->flags);
memcpy(&ctx->state->open_stateid.other, &stateid->other, memcpy(&ctx->state->open_stateid.other, &stateid->other,
NFS4_STATEID_OTHER_SIZE); NFS4_STATEID_OTHER_SIZE);

View File

@ -1609,6 +1609,9 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs
struct nfs4_state *state; struct nfs4_state *state;
unsigned int loop = 0; unsigned int loop = 0;
int status = 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 /* Note: we rely on the sp->so_states list being ordered
* so that we always reclaim open(O_RDWR) and/or open(O_WRITE) * so that we always reclaim open(O_RDWR) and/or open(O_WRITE)
@ -1628,6 +1631,13 @@ restart:
continue; continue;
if (state->state == 0) if (state->state == 0)
continue; 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); refcount_inc(&state->count);
spin_unlock(&sp->so_lock); spin_unlock(&sp->so_lock);
status = __nfs4_reclaim_open_state(sp, state, ops); status = __nfs4_reclaim_open_state(sp, state, ops);
@ -1682,6 +1692,10 @@ restart:
} }
raw_write_seqcount_end(&sp->so_reclaim_seqcount); raw_write_seqcount_end(&sp->so_reclaim_seqcount);
spin_unlock(&sp->so_lock); spin_unlock(&sp->so_lock);
#ifdef CONFIG_NFS_V4_2
if (found_ssc_copy_state)
return -EIO;
#endif /* CONFIG_NFS_V4_2 */
return 0; return 0;
out_err: out_err:
nfs4_put_open_state(state); nfs4_put_open_state(state);