aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/callback.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/callback.c')
-rw-r--r--fs/nfs/callback.c50
1 files changed, 24 insertions, 26 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 37815f3216aa..e69b8f61189e 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -36,7 +36,7 @@ struct nfs_callback_data {
36 struct task_struct *task; 36 struct task_struct *task;
37}; 37};
38 38
39static struct nfs_callback_data nfs_callback_info; 39static struct nfs_callback_data nfs_callback_info[NFS4_MAX_MINOR_VERSION + 1];
40static DEFINE_MUTEX(nfs_callback_mutex); 40static DEFINE_MUTEX(nfs_callback_mutex);
41static struct svc_program nfs4_callback_program; 41static struct svc_program nfs4_callback_program;
42 42
@@ -60,7 +60,7 @@ module_param_call(callback_tcpport, param_set_port, param_get_int,
60 &nfs_callback_set_tcpport, 0644); 60 &nfs_callback_set_tcpport, 0644);
61 61
62/* 62/*
63 * This is the callback kernel thread. 63 * This is the NFSv4 callback kernel thread.
64 */ 64 */
65static int 65static int
66nfs4_callback_svc(void *vrqstp) 66nfs4_callback_svc(void *vrqstp)
@@ -174,8 +174,6 @@ nfs41_callback_svc(void *vrqstp)
174 finish_wait(&serv->sv_cb_waitq, &wq); 174 finish_wait(&serv->sv_cb_waitq, &wq);
175 } 175 }
176 unlock_kernel(); 176 unlock_kernel();
177 nfs_callback_info.task = NULL;
178 svc_exit_thread(rqstp);
179 return 0; 177 return 0;
180} 178}
181 179
@@ -251,13 +249,14 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
251 struct svc_serv *serv = NULL; 249 struct svc_serv *serv = NULL;
252 struct svc_rqst *rqstp; 250 struct svc_rqst *rqstp;
253 int (*callback_svc)(void *vrqstp); 251 int (*callback_svc)(void *vrqstp);
252 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
254 char svc_name[12]; 253 char svc_name[12];
255 int ret = 0; 254 int ret = 0;
256 int minorversion_setup; 255 int minorversion_setup;
257 256
258 mutex_lock(&nfs_callback_mutex); 257 mutex_lock(&nfs_callback_mutex);
259 if (nfs_callback_info.users++ || nfs_callback_info.task != NULL) { 258 if (cb_info->users++ || cb_info->task != NULL) {
260 nfs_callback_bc_serv(minorversion, xprt, &nfs_callback_info); 259 nfs_callback_bc_serv(minorversion, xprt, cb_info);
261 goto out; 260 goto out;
262 } 261 }
263 serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL); 262 serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, NULL);
@@ -282,17 +281,14 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt)
282 svc_sock_update_bufs(serv); 281 svc_sock_update_bufs(serv);
283 282
284 sprintf(svc_name, "nfsv4.%u-svc", minorversion); 283 sprintf(svc_name, "nfsv4.%u-svc", minorversion);
285 nfs_callback_info.serv = serv; 284 cb_info->serv = serv;
286 nfs_callback_info.rqst = rqstp; 285 cb_info->rqst = rqstp;
287 nfs_callback_info.task = kthread_run(callback_svc, 286 cb_info->task = kthread_run(callback_svc, cb_info->rqst, svc_name);
288 nfs_callback_info.rqst, 287 if (IS_ERR(cb_info->task)) {
289 svc_name); 288 ret = PTR_ERR(cb_info->task);
290 if (IS_ERR(nfs_callback_info.task)) { 289 svc_exit_thread(cb_info->rqst);
291 ret = PTR_ERR(nfs_callback_info.task); 290 cb_info->rqst = NULL;
292 svc_exit_thread(nfs_callback_info.rqst); 291 cb_info->task = NULL;
293 nfs_callback_info.serv = NULL;
294 nfs_callback_info.rqst = NULL;
295 nfs_callback_info.task = NULL;
296 goto out_err; 292 goto out_err;
297 } 293 }
298out: 294out:
@@ -309,23 +305,25 @@ out:
309out_err: 305out_err:
310 dprintk("NFS: Couldn't create callback socket or server thread; " 306 dprintk("NFS: Couldn't create callback socket or server thread; "
311 "err = %d\n", ret); 307 "err = %d\n", ret);
312 nfs_callback_info.users--; 308 cb_info->users--;
313 goto out; 309 goto out;
314} 310}
315 311
316/* 312/*
317 * Kill the callback thread if it's no longer being used. 313 * Kill the callback thread if it's no longer being used.
318 */ 314 */
319void nfs_callback_down(void) 315void nfs_callback_down(int minorversion)
320{ 316{
317 struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion];
318
321 mutex_lock(&nfs_callback_mutex); 319 mutex_lock(&nfs_callback_mutex);
322 nfs_callback_info.users--; 320 cb_info->users--;
323 if (nfs_callback_info.users == 0 && nfs_callback_info.task != NULL) { 321 if (cb_info->users == 0 && cb_info->task != NULL) {
324 kthread_stop(nfs_callback_info.task); 322 kthread_stop(cb_info->task);
325 svc_exit_thread(nfs_callback_info.rqst); 323 svc_exit_thread(cb_info->rqst);
326 nfs_callback_info.serv = NULL; 324 cb_info->serv = NULL;
327 nfs_callback_info.rqst = NULL; 325 cb_info->rqst = NULL;
328 nfs_callback_info.task = NULL; 326 cb_info->task = NULL;
329 } 327 }
330 mutex_unlock(&nfs_callback_mutex); 328 mutex_unlock(&nfs_callback_mutex);
331} 329}