aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@citi.umich.edu>2010-03-03 14:52:55 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2010-04-22 11:34:01 -0400
commitb5a1a81e5c25fb6bb3fdc1812ba69ff6ab638fcf (patch)
treec524a75d111f4060eb985161478362ac18c17169 /fs/nfsd/nfs4state.c
parent3c4ab2aaa90826060b1e8d4036f9bb8325f8759e (diff)
nfsd4: don't sleep in lease-break callback
The NFSv4 server's fl_break callback can sleep (dropping the BKL), in order to allocate a new rpc task to send a recall to the client. As far as I can tell this doesn't cause any races in the current code, but the analysis is difficult. Also, the sleep here may complicate the move away from the BKL. So, just schedule some work to do the job for us instead. The work will later also prove useful for restarting a call after the callback information is changed. Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c34
1 files changed, 16 insertions, 18 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 5051ade30dfb..adc51d10d435 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -198,6 +198,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
198 atomic_set(&dp->dl_count, 1); 198 atomic_set(&dp->dl_count, 1);
199 list_add(&dp->dl_perfile, &fp->fi_delegations); 199 list_add(&dp->dl_perfile, &fp->fi_delegations);
200 list_add(&dp->dl_perclnt, &clp->cl_delegations); 200 list_add(&dp->dl_perclnt, &clp->cl_delegations);
201 INIT_WORK(&dp->dl_recall.cb_work, nfsd4_do_callback_rpc);
201 return dp; 202 return dp;
202} 203}
203 204
@@ -679,21 +680,6 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
679 return clp; 680 return clp;
680} 681}
681 682
682static void
683shutdown_callback_client(struct nfs4_client *clp)
684{
685 struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client;
686
687 if (clnt) {
688 /*
689 * Callback threads take a reference on the client, so there
690 * should be no outstanding callbacks at this point.
691 */
692 clp->cl_cb_conn.cb_client = NULL;
693 rpc_shutdown_client(clnt);
694 }
695}
696
697static inline void 683static inline void
698free_client(struct nfs4_client *clp) 684free_client(struct nfs4_client *clp)
699{ 685{
@@ -746,7 +732,7 @@ expire_client(struct nfs4_client *clp)
746 se_perclnt); 732 se_perclnt);
747 release_session(ses); 733 release_session(ses);
748 } 734 }
749 shutdown_callback_client(clp); 735 nfsd4_set_callback_client(clp, NULL);
750 if (clp->cl_cb_xprt) 736 if (clp->cl_cb_xprt)
751 svc_xprt_put(clp->cl_cb_xprt); 737 svc_xprt_put(clp->cl_cb_xprt);
752 put_nfs4_client(clp); 738 put_nfs4_client(clp);
@@ -1392,7 +1378,7 @@ nfsd4_destroy_session(struct svc_rqst *r,
1392 spin_unlock(&sessionid_lock); 1378 spin_unlock(&sessionid_lock);
1393 1379
1394 /* wait for callbacks */ 1380 /* wait for callbacks */
1395 shutdown_callback_client(ses->se_client); 1381 nfsd4_set_callback_client(ses->se_client, NULL);
1396 nfsd4_put_session(ses); 1382 nfsd4_put_session(ses);
1397 status = nfs_ok; 1383 status = nfs_ok;
1398out: 1384out:
@@ -4004,16 +3990,27 @@ set_max_delegations(void)
4004static int 3990static int
4005__nfs4_state_start(void) 3991__nfs4_state_start(void)
4006{ 3992{
3993 int ret;
3994
4007 boot_time = get_seconds(); 3995 boot_time = get_seconds();
4008 locks_start_grace(&nfsd4_manager); 3996 locks_start_grace(&nfsd4_manager);
4009 printk(KERN_INFO "NFSD: starting %ld-second grace period\n", 3997 printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
4010 nfsd4_grace); 3998 nfsd4_grace);
3999 ret = set_callback_cred();
4000 if (ret)
4001 return -ENOMEM;
4011 laundry_wq = create_singlethread_workqueue("nfsd4"); 4002 laundry_wq = create_singlethread_workqueue("nfsd4");
4012 if (laundry_wq == NULL) 4003 if (laundry_wq == NULL)
4013 return -ENOMEM; 4004 return -ENOMEM;
4005 ret = nfsd4_create_callback_queue();
4006 if (ret)
4007 goto out_free_laundry;
4014 queue_delayed_work(laundry_wq, &laundromat_work, nfsd4_grace * HZ); 4008 queue_delayed_work(laundry_wq, &laundromat_work, nfsd4_grace * HZ);
4015 set_max_delegations(); 4009 set_max_delegations();
4016 return set_callback_cred(); 4010 return 0;
4011out_free_laundry:
4012 destroy_workqueue(laundry_wq);
4013 return ret;
4017} 4014}
4018 4015
4019int 4016int
@@ -4075,6 +4072,7 @@ nfs4_state_shutdown(void)
4075 nfs4_lock_state(); 4072 nfs4_lock_state();
4076 nfs4_release_reclaim(); 4073 nfs4_release_reclaim();
4077 __nfs4_state_shutdown(); 4074 __nfs4_state_shutdown();
4075 nfsd4_destroy_callback_queue();
4078 nfs4_unlock_state(); 4076 nfs4_unlock_state();
4079} 4077}
4080 4078