diff options
author | Olga Kornievskaia <kolga@netapp.com> | 2018-07-09 21:13:31 +0200 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2018-08-09 18:56:39 +0200 |
commit | 62164f317972fcd36590578888f33a1994dda519 (patch) | |
tree | 24608dd5c9a8cd89f5bb16325e21b44d7064acb3 /fs/nfs/callback_proc.c | |
parent | NFS COPY xdr handle async reply (diff) | |
download | linux-62164f317972fcd36590578888f33a1994dda519.tar.xz linux-62164f317972fcd36590578888f33a1994dda519.zip |
NFS add support for asynchronous COPY
Change xdr to always send COPY asynchronously.
Keep the list copies send in a list under a server structure.
Once copy is sent, it waits on a completion structure that will
be signalled by the callback thread that receives CB_OFFLOAD.
If CB_OFFLOAD returned an error and even if it returned partial
bytes, ignore them (as we can't commit without a verifier to
match) and return an error.
Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs/nfs/callback_proc.c')
-rw-r--r-- | fs/nfs/callback_proc.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c index d6f45bd176a9..acdda259912e 100644 --- a/fs/nfs/callback_proc.c +++ b/fs/nfs/callback_proc.c @@ -662,9 +662,45 @@ __be32 nfs4_callback_notify_lock(void *argp, void *resp, } #endif /* CONFIG_NFS_V4_1 */ #ifdef CONFIG_NFS_V4_2 -__be32 nfs4_callback_offload(void *args, void *dummy, +static void nfs4_copy_cb_args(struct nfs4_copy_state *cp_state, + struct cb_offloadargs *args) +{ + cp_state->count = args->wr_count; + cp_state->error = args->error; + if (!args->error) { + cp_state->verf.committed = args->wr_writeverf.committed; + memcpy(&cp_state->verf.verifier.data[0], + &args->wr_writeverf.verifier.data[0], + NFS4_VERIFIER_SIZE); + } +} + +__be32 nfs4_callback_offload(void *data, void *dummy, struct cb_process_state *cps) { + struct cb_offloadargs *args = data; + struct nfs_server *server; + struct nfs4_copy_state *copy; + + rcu_read_lock(); + list_for_each_entry_rcu(server, &cps->clp->cl_superblocks, + client_link) { + spin_lock(&server->nfs_client->cl_lock); + list_for_each_entry(copy, &server->ss_copies, copies) { + if (memcmp(args->coa_stateid.other, + copy->stateid.other, + sizeof(args->coa_stateid.other))) + continue; + nfs4_copy_cb_args(copy, args); + complete(©->completion); + spin_unlock(&server->nfs_client->cl_lock); + goto out; + } + spin_unlock(&server->nfs_client->cl_lock); + } +out: + rcu_read_unlock(); + return 0; } #endif /* CONFIG_NFS_V4_2 */ |