aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/callback.c24
-rw-r--r--include/linux/sunrpc/svc.h1
-rw-r--r--net/sunrpc/svc.c38
3 files changed, 55 insertions, 8 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index c5e27ebd8da8..73a1f928226c 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -76,7 +76,10 @@ nfs4_callback_svc(void *vrqstp)
76 76
77 set_freezable(); 77 set_freezable();
78 78
79 while (!kthread_should_stop()) { 79 while (!kthread_freezable_should_stop(NULL)) {
80
81 if (signal_pending(current))
82 flush_signals(current);
80 /* 83 /*
81 * Listen for a request on the socket 84 * Listen for a request on the socket
82 */ 85 */
@@ -85,6 +88,8 @@ nfs4_callback_svc(void *vrqstp)
85 continue; 88 continue;
86 svc_process(rqstp); 89 svc_process(rqstp);
87 } 90 }
91 svc_exit_thread(rqstp);
92 module_put_and_exit(0);
88 return 0; 93 return 0;
89} 94}
90 95
@@ -103,9 +108,10 @@ nfs41_callback_svc(void *vrqstp)
103 108
104 set_freezable(); 109 set_freezable();
105 110
106 while (!kthread_should_stop()) { 111 while (!kthread_freezable_should_stop(NULL)) {
107 if (try_to_freeze()) 112
108 continue; 113 if (signal_pending(current))
114 flush_signals(current);
109 115
110 prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE); 116 prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
111 spin_lock_bh(&serv->sv_cb_lock); 117 spin_lock_bh(&serv->sv_cb_lock);
@@ -121,11 +127,13 @@ nfs41_callback_svc(void *vrqstp)
121 error); 127 error);
122 } else { 128 } else {
123 spin_unlock_bh(&serv->sv_cb_lock); 129 spin_unlock_bh(&serv->sv_cb_lock);
124 schedule(); 130 if (!kthread_should_stop())
131 schedule();
125 finish_wait(&serv->sv_cb_waitq, &wq); 132 finish_wait(&serv->sv_cb_waitq, &wq);
126 } 133 }
127 flush_signals(current);
128 } 134 }
135 svc_exit_thread(rqstp);
136 module_put_and_exit(0);
129 return 0; 137 return 0;
130} 138}
131 139
@@ -221,14 +229,14 @@ err_bind:
221static struct svc_serv_ops nfs40_cb_sv_ops = { 229static struct svc_serv_ops nfs40_cb_sv_ops = {
222 .svo_function = nfs4_callback_svc, 230 .svo_function = nfs4_callback_svc,
223 .svo_enqueue_xprt = svc_xprt_do_enqueue, 231 .svo_enqueue_xprt = svc_xprt_do_enqueue,
224 .svo_setup = svc_set_num_threads, 232 .svo_setup = svc_set_num_threads_sync,
225 .svo_module = THIS_MODULE, 233 .svo_module = THIS_MODULE,
226}; 234};
227#if defined(CONFIG_NFS_V4_1) 235#if defined(CONFIG_NFS_V4_1)
228static struct svc_serv_ops nfs41_cb_sv_ops = { 236static struct svc_serv_ops nfs41_cb_sv_ops = {
229 .svo_function = nfs41_callback_svc, 237 .svo_function = nfs41_callback_svc,
230 .svo_enqueue_xprt = svc_xprt_do_enqueue, 238 .svo_enqueue_xprt = svc_xprt_do_enqueue,
231 .svo_setup = svc_set_num_threads, 239 .svo_setup = svc_set_num_threads_sync,
232 .svo_module = THIS_MODULE, 240 .svo_module = THIS_MODULE,
233}; 241};
234 242
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index 6ef19cf658b4..94631026f79c 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -473,6 +473,7 @@ void svc_pool_map_put(void);
473struct svc_serv * svc_create_pooled(struct svc_program *, unsigned int, 473struct svc_serv * svc_create_pooled(struct svc_program *, unsigned int,
474 struct svc_serv_ops *); 474 struct svc_serv_ops *);
475int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int); 475int svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);
476int svc_set_num_threads_sync(struct svc_serv *, struct svc_pool *, int);
476int svc_pool_stats_open(struct svc_serv *serv, struct file *file); 477int svc_pool_stats_open(struct svc_serv *serv, struct file *file);
477void svc_destroy(struct svc_serv *); 478void svc_destroy(struct svc_serv *);
478void svc_shutdown_net(struct svc_serv *, struct net *); 479void svc_shutdown_net(struct svc_serv *, struct net *);
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 98dc33ae738b..bc0f5a0ecbdc 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -795,6 +795,44 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
795} 795}
796EXPORT_SYMBOL_GPL(svc_set_num_threads); 796EXPORT_SYMBOL_GPL(svc_set_num_threads);
797 797
798/* destroy old threads */
799static int
800svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
801{
802 struct task_struct *task;
803 unsigned int state = serv->sv_nrthreads-1;
804
805 /* destroy old threads */
806 do {
807 task = choose_victim(serv, pool, &state);
808 if (task == NULL)
809 break;
810 kthread_stop(task);
811 nrservs++;
812 } while (nrservs < 0);
813 return 0;
814}
815
816int
817svc_set_num_threads_sync(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
818{
819 if (pool == NULL) {
820 /* The -1 assumes caller has done a svc_get() */
821 nrservs -= (serv->sv_nrthreads-1);
822 } else {
823 spin_lock_bh(&pool->sp_lock);
824 nrservs -= pool->sp_nrthreads;
825 spin_unlock_bh(&pool->sp_lock);
826 }
827
828 if (nrservs > 0)
829 return svc_start_kthreads(serv, pool, nrservs);
830 if (nrservs < 0)
831 return svc_stop_kthreads(serv, pool, nrservs);
832 return 0;
833}
834EXPORT_SYMBOL_GPL(svc_set_num_threads_sync);
835
798/* 836/*
799 * Called from a server thread as it's exiting. Caller must hold the "service 837 * Called from a server thread as it's exiting. Caller must hold the "service
800 * mutex" for the service. 838 * mutex" for the service.