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>
This commit is contained in:
@@ -494,6 +494,49 @@ nfsd4_probe_callback(struct nfs4_client *clp)
|
|||||||
do_probe_callback(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.
|
* called with dp->dl_count inc'ed.
|
||||||
*/
|
*/
|
||||||
@@ -507,32 +550,13 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
|
|||||||
.rpc_argp = dp,
|
.rpc_argp = dp,
|
||||||
.rpc_cred = clp->cl_cb_conn.cb_cred
|
.rpc_cred = clp->cl_cb_conn.cb_cred
|
||||||
};
|
};
|
||||||
int status = 0;
|
int status;
|
||||||
|
|
||||||
dp->dl_retries = 1;
|
dp->dl_retries = 1;
|
||||||
status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
|
status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT,
|
||||||
while (dp->dl_retries--) {
|
&nfsd4_cb_recall_ops, dp);
|
||||||
switch (status) {
|
if (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);
|
|
||||||
}
|
|
||||||
out_put_cred:
|
|
||||||
/*
|
|
||||||
* Success or failure, now we're either waiting for lease expiration
|
|
||||||
* or deleg_return.
|
|
||||||
*/
|
|
||||||
put_nfs4_client(clp);
|
put_nfs4_client(clp);
|
||||||
nfs4_put_delegation(dp);
|
nfs4_put_delegation(dp);
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2059,19 +2059,6 @@ nfs4_file_downgrade(struct file *filp, unsigned int share_access)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Recall a delegation
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
do_recall(void *__dp)
|
|
||||||
{
|
|
||||||
struct nfs4_delegation *dp = __dp;
|
|
||||||
|
|
||||||
dp->dl_file->fi_had_conflict = true;
|
|
||||||
nfsd4_cb_recall(dp);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Spawn a thread to perform a recall on the delegation represented
|
* Spawn a thread to perform a recall on the delegation represented
|
||||||
* by the lease (file_lock)
|
* by the lease (file_lock)
|
||||||
@@ -2083,8 +2070,7 @@ do_recall(void *__dp)
|
|||||||
static
|
static
|
||||||
void nfsd_break_deleg_cb(struct file_lock *fl)
|
void nfsd_break_deleg_cb(struct file_lock *fl)
|
||||||
{
|
{
|
||||||
struct nfs4_delegation *dp= (struct nfs4_delegation *)fl->fl_owner;
|
struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner;
|
||||||
struct task_struct *t;
|
|
||||||
|
|
||||||
dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl);
|
dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl);
|
||||||
if (!dp)
|
if (!dp)
|
||||||
@@ -2112,16 +2098,8 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
|
|||||||
*/
|
*/
|
||||||
fl->fl_break_time = 0;
|
fl->fl_break_time = 0;
|
||||||
|
|
||||||
t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall");
|
dp->dl_file->fi_had_conflict = true;
|
||||||
if (IS_ERR(t)) {
|
nfsd4_cb_recall(dp);
|
||||||
struct nfs4_client *clp = dp->dl_client;
|
|
||||||
|
|
||||||
printk(KERN_INFO "NFSD: Callback thread failed for "
|
|
||||||
"for client (clientid %08x/%08x)\n",
|
|
||||||
clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
|
|
||||||
put_nfs4_client(dp->dl_client);
|
|
||||||
nfs4_put_delegation(dp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user