summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-08-29 20:03:51 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2016-09-19 13:08:36 -0400
commitbb6aeba736ba9fd4d9569eec4bc3f7aecb42162a (patch)
tree2a2ceddf74b880b166462d2cfaa68470d6eebf9d
parent3b01c11ee8bfa9d5d14b028e9fbe861a0f22d328 (diff)
NFSv4.x: Switch to using svc_set_num_threads() to manage the callback threads
This will allow us to bump the number of callback threads at will. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r--fs/nfs/callback.c79
-rw-r--r--fs/nfs/callback.h2
2 files changed, 15 insertions, 66 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index b125f02ddf8b..b91c49f4670b 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -31,8 +31,6 @@
31struct nfs_callback_data { 31struct nfs_callback_data {
32 unsigned int users; 32 unsigned int users;
33 struct svc_serv *serv; 33 struct svc_serv *serv;
34 struct svc_rqst *rqst;
35 struct task_struct *task;
36}; 34};
37 35
38static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1]; 36static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1];
@@ -89,15 +87,6 @@ nfs4_callback_svc(void *vrqstp)
89 return 0; 87 return 0;
90} 88}
91 89
92/*
93 * Prepare to bring up the NFSv4 callback service
94 */
95static struct svc_rqst *
96nfs4_callback_up(struct svc_serv *serv)
97{
98 return svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE);
99}
100
101#if defined(CONFIG_NFS_V4_1) 90#if defined(CONFIG_NFS_V4_1)
102/* 91/*
103 * The callback service for NFSv4.1 callbacks 92 * The callback service for NFSv4.1 callbacks
@@ -139,19 +128,6 @@ nfs41_callback_svc(void *vrqstp)
139 return 0; 128 return 0;
140} 129}
141 130
142/*
143 * Bring up the NFSv4.1 callback service
144 */
145static struct svc_rqst *
146nfs41_callback_up(struct svc_serv *serv)
147{
148 struct svc_rqst *rqstp;
149
150 rqstp = svc_prepare_thread(serv, &serv->sv_pools[0], NUMA_NO_NODE);
151 dprintk("--> %s return %d\n", __func__, PTR_ERR_OR_ZERO(rqstp));
152 return rqstp;
153}
154
155static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, 131static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
156 struct svc_serv *serv) 132 struct svc_serv *serv)
157{ 133{
@@ -163,12 +139,6 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
163 xprt->bc_serv = serv; 139 xprt->bc_serv = serv;
164} 140}
165#else 141#else
166static struct svc_rqst *
167nfs41_callback_up(struct svc_serv *serv)
168{
169 return ERR_PTR(-ENOTSUPP);
170}
171
172static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt, 142static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
173 struct svc_serv *serv) 143 struct svc_serv *serv)
174{ 144{
@@ -178,42 +148,19 @@ static inline void nfs_callback_bc_serv(u32 minorversion, struct rpc_xprt *xprt,
178static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt, 148static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt,
179 struct svc_serv *serv) 149 struct svc_serv *serv)
180{ 150{
181 struct svc_rqst *rqstp; 151 const int nrservs = NFS4_NR_CALLBACK_THREADS;
182 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
183 int ret; 152 int ret;
184 153
185 nfs_callback_bc_serv(minorversion, xprt, serv); 154 nfs_callback_bc_serv(minorversion, xprt, serv);
186 155
187 if (cb_info->task) 156 if (serv->sv_nrthreads-1 == nrservs)
188 return 0; 157 return 0;
189 158
190 switch (minorversion) { 159 ret = serv->sv_ops->svo_setup(serv, NULL, nrservs);
191 case 0: 160 if (ret) {
192 /* v4.0 callback setup */ 161 serv->sv_ops->svo_setup(serv, NULL, 0);
193 rqstp = nfs4_callback_up(serv);
194 break;
195 default:
196 rqstp = nfs41_callback_up(serv);
197 }
198
199 if (IS_ERR(rqstp))
200 return PTR_ERR(rqstp);
201
202 svc_sock_update_bufs(serv);
203
204 cb_info->rqst = rqstp;
205 cb_info->task = kthread_create(serv->sv_ops->svo_function,
206 cb_info->rqst,
207 "nfsv4.%u-svc", minorversion);
208 if (IS_ERR(cb_info->task)) {
209 ret = PTR_ERR(cb_info->task);
210 svc_exit_thread(cb_info->rqst);
211 cb_info->rqst = NULL;
212 cb_info->task = NULL;
213 return ret; 162 return ret;
214 } 163 }
215 rqstp->rq_task = cb_info->task;
216 wake_up_process(cb_info->task);
217 dprintk("nfs_callback_up: service started\n"); 164 dprintk("nfs_callback_up: service started\n");
218 return 0; 165 return 0;
219} 166}
@@ -270,12 +217,14 @@ err_bind:
270static struct svc_serv_ops nfs40_cb_sv_ops = { 217static struct svc_serv_ops nfs40_cb_sv_ops = {
271 .svo_function = nfs4_callback_svc, 218 .svo_function = nfs4_callback_svc,
272 .svo_enqueue_xprt = svc_xprt_do_enqueue, 219 .svo_enqueue_xprt = svc_xprt_do_enqueue,
220 .svo_setup = svc_set_num_threads,
273 .svo_module = THIS_MODULE, 221 .svo_module = THIS_MODULE,
274}; 222};
275#if defined(CONFIG_NFS_V4_1) 223#if defined(CONFIG_NFS_V4_1)
276static struct svc_serv_ops nfs41_cb_sv_ops = { 224static struct svc_serv_ops nfs41_cb_sv_ops = {
277 .svo_function = nfs41_callback_svc, 225 .svo_function = nfs41_callback_svc,
278 .svo_enqueue_xprt = svc_xprt_do_enqueue, 226 .svo_enqueue_xprt = svc_xprt_do_enqueue,
227 .svo_setup = svc_set_num_threads,
279 .svo_module = THIS_MODULE, 228 .svo_module = THIS_MODULE,
280}; 229};
281 230
@@ -394,20 +343,18 @@ err_start:
394void nfs_callback_down(int minorversion, struct net *net) 343void nfs_callback_down(int minorversion, struct net *net)
395{ 344{
396 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; 345 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
346 struct svc_serv *serv;
397 347
398 mutex_lock(&nfs_callback_mutex); 348 mutex_lock(&nfs_callback_mutex);
399 nfs_callback_down_net(minorversion, cb_info->serv, net); 349 serv = cb_info->serv;
350 nfs_callback_down_net(minorversion, serv, net);
400 cb_info->users--; 351 cb_info->users--;
401 if (cb_info->users == 0) { 352 if (cb_info->users == 0) {
402 if (cb_info->task != NULL) { 353 svc_get(serv);
403 kthread_stop(cb_info->task); 354 serv->sv_ops->svo_setup(serv, NULL, 0);
404 dprintk("nfs_callback_down: service stopped\n"); 355 svc_destroy(serv);
405 }
406 svc_exit_thread(cb_info->rqst);
407 dprintk("nfs_callback_down: service destroyed\n"); 356 dprintk("nfs_callback_down: service destroyed\n");
408 cb_info->serv = NULL; 357 cb_info->serv = NULL;
409 cb_info->rqst = NULL;
410 cb_info->task = NULL;
411 } 358 }
412 mutex_unlock(&nfs_callback_mutex); 359 mutex_unlock(&nfs_callback_mutex);
413} 360}
diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
index 5fe1cecbf9f0..14bd863495db 100644
--- a/fs/nfs/callback.h
+++ b/fs/nfs/callback.h
@@ -198,6 +198,8 @@ extern void nfs_callback_down(int minorversion, struct net *net);
198#define NFS41_BC_MIN_CALLBACKS 1 198#define NFS41_BC_MIN_CALLBACKS 1
199#define NFS41_BC_MAX_CALLBACKS 1 199#define NFS41_BC_MAX_CALLBACKS 1
200 200
201#define NFS4_NR_CALLBACK_THREADS 1
202
201extern unsigned int nfs_callback_set_tcpport; 203extern unsigned int nfs_callback_set_tcpport;
202 204
203#endif /* __LINUX_FS_NFS_CALLBACK_H */ 205#endif /* __LINUX_FS_NFS_CALLBACK_H */