diff options
author | J. Bruce Fields <bfields@citi.umich.edu> | 2009-05-02 04:36:55 +0200 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-05-03 21:08:56 +0200 |
commit | 63e4863fabc6e165a6ca813051305be58966da45 (patch) | |
tree | e84b927ca00ce91c8a3a4e93b7f61a0fea315e00 /fs/nfsd/nfs4callback.c | |
parent | nfsd4: track recall retries in nfs4_delegation (diff) | |
download | linux-63e4863fabc6e165a6ca813051305be58966da45.tar.xz linux-63e4863fabc6e165a6ca813051305be58966da45.zip |
nfsd4: make recall callback an asynchronous rpc
As with the probe, this removes the need for another kthread.
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs/nfsd/nfs4callback.c')
-rw-r--r-- | fs/nfsd/nfs4callback.c | 74 |
1 files changed, 49 insertions, 25 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index b88b207d75d9..f4fab69a8c30 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -494,6 +494,49 @@ nfsd4_probe_callback(struct nfs4_client *clp) do_probe_callback(clp); } +static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) +{ + struct nfs4_delegation *dp = calldata; + struct nfs4_client *clp = dp->dl_client; + + switch (task->tk_status) { + case -EIO: + /* Network partition? */ + atomic_set(&clp->cl_cb_conn.cb_set, 0); + warn_no_callback_path(clp, task->tk_status); + case -EBADHANDLE: + case -NFS4ERR_BAD_STATEID: + /* Race: client probably got cb_recall + * before open reply granting delegation */ + break; + default: + /* success, or error we can't handle */ + return; + } + if (dp->dl_retries--) { + rpc_delay(task, 2*HZ); + task->tk_status = 0; + rpc_restart_call(task); + } else { + atomic_set(&clp->cl_cb_conn.cb_set, 0); + warn_no_callback_path(clp, task->tk_status); + } +} + +static void nfsd4_cb_recall_release(void *calldata) +{ + struct nfs4_delegation *dp = calldata; + struct nfs4_client *clp = dp->dl_client; + + nfs4_put_delegation(dp); + put_nfs4_client(clp); +} + +static const struct rpc_call_ops nfsd4_cb_recall_ops = { + .rpc_call_done = nfsd4_cb_recall_done, + .rpc_release = nfsd4_cb_recall_release, +}; + /* * called with dp->dl_count inc'ed. */ @@ -507,32 +550,13 @@ nfsd4_cb_recall(struct nfs4_delegation *dp) .rpc_argp = dp, .rpc_cred = clp->cl_cb_conn.cb_cred }; - int status = 0; + int status; dp->dl_retries = 1; - status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT); - while (dp->dl_retries--) { - switch (status) { - case -EIO: - /* Network partition? */ - atomic_set(&clp->cl_cb_conn.cb_set, 0); - case -EBADHANDLE: - case -NFS4ERR_BAD_STATEID: - /* Race: client probably got cb_recall - * before open reply granting delegation */ - break; - default: - goto out_put_cred; - } - ssleep(2); - status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT); + status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT, + &nfsd4_cb_recall_ops, dp); + if (status) { + put_nfs4_client(clp); + nfs4_put_delegation(dp); } -out_put_cred: - /* - * Success or failure, now we're either waiting for lease expiration - * or deleg_return. - */ - put_nfs4_client(clp); - nfs4_put_delegation(dp); - return; } |