diff options
author | Olga Kornievskaia <kolga@netapp.com> | 2018-08-13 15:33:01 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2018-08-13 17:04:23 -0400 |
commit | e4648aa4f98a87cf0a83f73a5864cede073053a0 (patch) | |
tree | c6e48236e743a8be03bf7062d33e98d8e550aecb /fs/nfs/nfs42proc.c | |
parent | 6b8d84e2f1299a5876ed812b137c49686cc85c7c (diff) |
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 <kolga@netapp.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs/nfs/nfs42proc.c')
-rw-r--r-- | fs/nfs/nfs42proc.c | 16 |
1 files changed, 13 insertions, 3 deletions
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c index d158526d1044..ac5b784a1de0 100644 --- a/fs/nfs/nfs42proc.c +++ b/fs/nfs/nfs42proc.c @@ -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 @@ out: kfree(copy); return status; +out_cancel: + nfs42_do_offload_cancel_async(dst, ©->stateid); + kfree(copy); + return status; } static int process_copy_commit(struct file *dst, loff_t pos_dst, @@ -254,6 +261,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) |