NFS recover from destination server reboot for copies
Subsystems (2)
PATCH 9/11 NFS recover from destination server reboot for copies
Mark the destination state to indicate a server-side copy is happening. On detecting a reboot and recovering open state check if any state is engaged in a server-side copy, if so, find the copy and mark it and then signal the waiting thread. Upon wakeup, if copy was marked then propage EAGAIN to the nfsd_copy_file_range and restart the copy from scratch.
Signed-off-by Olga Kornievskaia <[email protected]>
--- fs/nfs/nfs42proc.c | 16 +++++++++++++--- fs/nfs/nfs4_fs.h | 3 +++ fs/nfs/nfs4file.c | 9 +++++++-- fs/nfs/nfs4state.c | 16 ++++++++++++++++ include/linux/nfs_fs.h | 2 ++ 5 files changed, 41 insertions(+), 5 deletions(-)
fs/nfs/nfs42proc.c +13 -3
@@ -140,6 +140,7 @@ static int handle_async_copy(struct nfs42_copy_res *res,struct nfs4_copy_state *copy;int status =NFS4_OK ;bool found_pending = false; +struct nfs_open_context *ctx =nfs_file_open_context (dst);spin_lock (&server->nfs_client->cl_lock); list_for_each_entry(copy, &server->nfs_client->pending_cb_stateids,
@@ -163,6 +164,7 @@ static int handle_async_copy(struct nfs42_copy_res *res, }memcpy (©->stateid, &res->write_res.stateid,NFS4_STATEID_SIZE );init_completion (©->completion); + copy->parent_state = ctx->state;list_add_tail (©->copies, &server->ss_copies);spin_unlock (&server->nfs_client->cl_lock);
@@ -172,9 +174,10 @@ static int handle_async_copy(struct nfs42_copy_res *res,list_del_init (©->copies);spin_unlock (&server->nfs_client->cl_lock);if (status == -ERESTARTSYS ) { -nfs42_do_offload_cancel_async (dst, ©->stateid); -kfree (copy); -return status; + goto out_cancel; + }else if (copy->flags) { + status = -EAGAIN ; + goto out_cancel; } out: res->write_res.count = copy->count;
@@ -183,6 +186,10 @@ static int handle_async_copy(struct nfs42_copy_res *res,kfree (copy);return status; +out_cancel: +nfs42_do_offload_cancel_async (dst, ©->stateid); +kfree (copy); +return status; } static ssize_t _nfs42_proc_copy(struct file *src,
@@ -230,6 +237,9 @@ static ssize_t _nfs42_proc_copy(struct file *src,if (!res->commit_res.verf)return -ENOMEM ; } +set_bit (NFS_CLNT_DST_SSC_COPY_STATE , + &dst_lock->open_context->state->flags); + status =nfs4_call_sync (server->client, server, &msg, &args->seq_args, &res->seq_res,0 );if (status == -ENOTSUPP )
fs/nfs/nfs4_fs.h +3 -0
@@ -163,6 +163,9 @@ enum {NFS_STATE_RECOVERY_FAILED ,/* OPEN stateid state recovery failed */ NFS_STATE_MAY_NOTIFY_LOCK ,/* server may CB_NOTIFY_LOCK */ 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*/ +#endif /* CONFIG_NFS_V4_2 */ }; struct nfs4_state {
fs/nfs/nfs4file.c +7 -2
@@ -133,10 +133,15 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, size_t count, unsigned int flags) { + ssize_t ret; +if (file_inode (file_in) ==file_inode (file_out))return -EINVAL ; - -return nfs42_proc_copy (file_in, pos_in, file_out, pos_out, count); +retry: + ret =nfs42_proc_copy (file_in, pos_in, file_out, pos_out, count); +if (ret == -EAGAIN ) + goto retry; +return ret; }static loff_t nfs4_file_llseek (struct file *filep,loff_t offset,int whence)
fs/nfs/nfs4state.c +16 -0
@@ -1588,6 +1588,22 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs }clear_bit (NFS_STATE_RECLAIM_NOGRACE , &state->flags); +#ifdef CONFIG_NFS_V4_2 +if (test_bit (NFS_CLNT_DST_SSC_COPY_STATE , &state->flags)) { +struct nfs4_copy_state *copy; + +spin_lock (&sp->so_server->nfs_client->cl_lock); +list_for_each_entry (copy, &sp->so_server->ss_copies, copies) { +if (memcmp (&state->stateid.other, ©->parent_state->stateid.other,NFS4_STATEID_SIZE )) +continue ; + copy->flags =1 ; +complete (©->completion); +printk ("AGLO: server rebooted waking up the copy\n" ); +break ; + } +spin_unlock (&sp->so_server->nfs_client->cl_lock); + } +#endif /* CONFIG_NFS_V4_2 */ nfs4_put_open_state (state);spin_lock (&sp->so_lock); goto restart;
include/linux/nfs_fs.h +2 -0
@@ -192,6 +192,8 @@ struct nfs4_copy_state {uint64_t count;struct nfs_writeverf verf;int error; +int flags; +struct nfs4_state *parent_state; };/*
Signature · 1 line
1.8.3.1