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>
这个提交包含在:
Olga Kornievskaia
2018-08-13 15:33:01 -04:00
提交者 Anna Schumaker
父节点 6b8d84e2f1
当前提交 e4648aa4f9
修改 5 个文件,包含 41 行新增5 行删除

查看文件

@@ -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(&copy->stateid, &res->write_res.stateid, NFS4_STATEID_SIZE);
init_completion(&copy->completion);
copy->parent_state = ctx->state;
list_add_tail(&copy->copies, &server->ss_copies);
spin_unlock(&server->nfs_client->cl_lock);
@@ -172,15 +174,20 @@ static int handle_async_copy(struct nfs42_copy_res *res,
list_del_init(&copy->copies);
spin_unlock(&server->nfs_client->cl_lock);
if (status == -ERESTARTSYS) {
nfs42_do_offload_cancel_async(dst, &copy->stateid);
kfree(copy);
return status;
goto out_cancel;
} else if (copy->flags) {
status = -EAGAIN;
goto out_cancel;
}
out:
res->write_res.count = copy->count;
memcpy(&res->write_res.verifier, &copy->verf, sizeof(copy->verf));
status = -copy->error;
kfree(copy);
return status;
out_cancel:
nfs42_do_offload_cancel_async(dst, &copy->stateid);
kfree(copy);
return status;
}
@@ -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)