aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@citi.umich.edu>2009-05-01 22:36:55 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-05-03 15:08:56 -0400
commit63e4863fabc6e165a6ca813051305be58966da45 (patch)
treee84b927ca00ce91c8a3a4e93b7f61a0fea315e00 /fs/nfsd
parent3aea09dc9106407d8bc18e593fbffda9ad632844 (diff)
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')
-rw-r--r--fs/nfsd/nfs4callback.c74
-rw-r--r--fs/nfsd/nfs4state.c28
2 files changed, 52 insertions, 50 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)
494 do_probe_callback(clp); 494 do_probe_callback(clp);
495} 495}
496 496
497static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata)
498{
499 struct nfs4_delegation *dp = calldata;
500 struct nfs4_client *clp = dp->dl_client;
501
502 switch (task->tk_status) {
503 case -EIO:
504 /* Network partition? */
505 atomic_set(&clp->cl_cb_conn.cb_set, 0);
506 warn_no_callback_path(clp, task->tk_status);
507 case -EBADHANDLE:
508 case -NFS4ERR_BAD_STATEID:
509 /* Race: client probably got cb_recall
510 * before open reply granting delegation */
511 break;
512 default:
513 /* success, or error we can't handle */
514 return;
515 }
516 if (dp->dl_retries--) {
517 rpc_delay(task, 2*HZ);
518 task->tk_status = 0;
519 rpc_restart_call(task);
520 } else {
521 atomic_set(&clp->cl_cb_conn.cb_set, 0);
522 warn_no_callback_path(clp, task->tk_status);
523 }
524}
525
526static void nfsd4_cb_recall_release(void *calldata)
527{
528 struct nfs4_delegation *dp = calldata;
529 struct nfs4_client *clp = dp->dl_client;
530
531 nfs4_put_delegation(dp);
532 put_nfs4_client(clp);
533}
534
535static const struct rpc_call_ops nfsd4_cb_recall_ops = {
536 .rpc_call_done = nfsd4_cb_recall_done,
537 .rpc_release = nfsd4_cb_recall_release,
538};
539
497/* 540/*
498 * called with dp->dl_count inc'ed. 541 * called with dp->dl_count inc'ed.
499 */ 542 */
@@ -507,32 +550,13 @@ nfsd4_cb_recall(struct nfs4_delegation *dp)
507 .rpc_argp = dp, 550 .rpc_argp = dp,
508 .rpc_cred = clp->cl_cb_conn.cb_cred 551 .rpc_cred = clp->cl_cb_conn.cb_cred
509 }; 552 };
510 int status = 0; 553 int status;
511 554
512 dp->dl_retries = 1; 555 dp->dl_retries = 1;
513 status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT); 556 status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT,
514 while (dp->dl_retries--) { 557 &nfsd4_cb_recall_ops, dp);
515 switch (status) { 558 if (status) {
516 case -EIO: 559 put_nfs4_client(clp);
517 /* Network partition? */ 560 nfs4_put_delegation(dp);
518 atomic_set(&clp->cl_cb_conn.cb_set, 0);
519 case -EBADHANDLE:
520 case -NFS4ERR_BAD_STATEID:
521 /* Race: client probably got cb_recall
522 * before open reply granting delegation */
523 break;
524 default:
525 goto out_put_cred;
526 }
527 ssleep(2);
528 status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
529 } 561 }
530out_put_cred:
531 /*
532 * Success or failure, now we're either waiting for lease expiration
533 * or deleg_return.
534 */
535 put_nfs4_client(clp);
536 nfs4_put_delegation(dp);
537 return;
538} 562}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index cbb16e191d5b..a4bdf2589b41 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2060,19 +2060,6 @@ nfs4_file_downgrade(struct file *filp, unsigned int share_access)
2060} 2060}
2061 2061
2062/* 2062/*
2063 * Recall a delegation
2064 */
2065static int
2066do_recall(void *__dp)
2067{
2068 struct nfs4_delegation *dp = __dp;
2069
2070 dp->dl_file->fi_had_conflict = true;
2071 nfsd4_cb_recall(dp);
2072 return 0;
2073}
2074
2075/*
2076 * Spawn a thread to perform a recall on the delegation represented 2063 * Spawn a thread to perform a recall on the delegation represented
2077 * by the lease (file_lock) 2064 * by the lease (file_lock)
2078 * 2065 *
@@ -2083,8 +2070,7 @@ do_recall(void *__dp)
2083static 2070static
2084void nfsd_break_deleg_cb(struct file_lock *fl) 2071void nfsd_break_deleg_cb(struct file_lock *fl)
2085{ 2072{
2086 struct nfs4_delegation *dp= (struct nfs4_delegation *)fl->fl_owner; 2073 struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner;
2087 struct task_struct *t;
2088 2074
2089 dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl); 2075 dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl);
2090 if (!dp) 2076 if (!dp)
@@ -2112,16 +2098,8 @@ void nfsd_break_deleg_cb(struct file_lock *fl)
2112 */ 2098 */
2113 fl->fl_break_time = 0; 2099 fl->fl_break_time = 0;
2114 2100
2115 t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall"); 2101 dp->dl_file->fi_had_conflict = true;
2116 if (IS_ERR(t)) { 2102 nfsd4_cb_recall(dp);
2117 struct nfs4_client *clp = dp->dl_client;
2118
2119 printk(KERN_INFO "NFSD: Callback thread failed for "
2120 "for client (clientid %08x/%08x)\n",
2121 clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
2122 put_nfs4_client(dp->dl_client);
2123 nfs4_put_delegation(dp);
2124 }
2125} 2103}
2126 2104
2127/* 2105/*