diff options
author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2012-08-20 10:00:46 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-10-01 18:25:57 -0400 |
commit | b3d19c51723be69fddb64723bebb5a30fb57a483 (patch) | |
tree | af7bd8cc8db0fd669f8edd794f062b32f63c5aa4 | |
parent | 29dcc16a8e29371e11fb58fc1292e01f30ff13c5 (diff) |
NFS: callback per-net usage counting introduced
This patch also introduces refcount-aware nfs_callback_down_net() wrapper for
svc_shutdown_net().
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/callback.c | 19 | ||||
-rw-r--r-- | fs/nfs/netns.h | 1 |
2 files changed, 18 insertions, 2 deletions
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index baafa0f1e555..6dfdc8311f27 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
@@ -260,10 +260,25 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt, | |||
260 | return 0; | 260 | return 0; |
261 | } | 261 | } |
262 | 262 | ||
263 | static void nfs_callback_down_net(u32 minorversion, struct svc_serv *serv, struct net *net) | ||
264 | { | ||
265 | struct nfs_net *nn = net_generic(net, nfs_net_id); | ||
266 | |||
267 | if (--nn->cb_users[minorversion]) | ||
268 | return; | ||
269 | |||
270 | dprintk("NFS: destroy per-net callback data; net=%p\n", net); | ||
271 | svc_shutdown_net(serv, net); | ||
272 | } | ||
273 | |||
263 | static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, struct net *net) | 274 | static int nfs_callback_up_net(int minorversion, struct svc_serv *serv, struct net *net) |
264 | { | 275 | { |
276 | struct nfs_net *nn = net_generic(net, nfs_net_id); | ||
265 | int ret; | 277 | int ret; |
266 | 278 | ||
279 | if (nn->cb_users[minorversion]++) | ||
280 | return 0; | ||
281 | |||
267 | dprintk("NFS: create per-net callback data; net=%p\n", net); | 282 | dprintk("NFS: create per-net callback data; net=%p\n", net); |
268 | 283 | ||
269 | ret = svc_bind(serv, net); | 284 | ret = svc_bind(serv, net); |
@@ -378,7 +393,7 @@ err_create: | |||
378 | return ret; | 393 | return ret; |
379 | 394 | ||
380 | err_start: | 395 | err_start: |
381 | svc_shutdown_net(serv, net); | 396 | nfs_callback_down_net(minorversion, serv, net); |
382 | dprintk("NFS: Couldn't create server thread; err = %d\n", ret); | 397 | dprintk("NFS: Couldn't create server thread; err = %d\n", ret); |
383 | goto err_net; | 398 | goto err_net; |
384 | } | 399 | } |
@@ -391,10 +406,10 @@ void nfs_callback_down(int minorversion, struct net *net) | |||
391 | struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; | 406 | struct nfs_callback_data *cb_info = &nfs_callback_info[minorversion]; |
392 | 407 | ||
393 | mutex_lock(&nfs_callback_mutex); | 408 | mutex_lock(&nfs_callback_mutex); |
409 | nfs_callback_down_net(minorversion, cb_info->serv, net); | ||
394 | cb_info->users--; | 410 | cb_info->users--; |
395 | if (cb_info->users == 0 && cb_info->task != NULL) { | 411 | if (cb_info->users == 0 && cb_info->task != NULL) { |
396 | kthread_stop(cb_info->task); | 412 | kthread_stop(cb_info->task); |
397 | svc_shutdown_net(cb_info->serv, net); | ||
398 | svc_exit_thread(cb_info->rqst); | 413 | svc_exit_thread(cb_info->rqst); |
399 | cb_info->serv = NULL; | 414 | cb_info->serv = NULL; |
400 | cb_info->rqst = NULL; | 415 | cb_info->rqst = NULL; |
diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h index 137238b012fb..b9c7f9b1f91b 100644 --- a/fs/nfs/netns.h +++ b/fs/nfs/netns.h | |||
@@ -24,6 +24,7 @@ struct nfs_net { | |||
24 | struct idr cb_ident_idr; /* Protected by nfs_client_lock */ | 24 | struct idr cb_ident_idr; /* Protected by nfs_client_lock */ |
25 | unsigned short nfs_callback_tcpport; | 25 | unsigned short nfs_callback_tcpport; |
26 | unsigned short nfs_callback_tcpport6; | 26 | unsigned short nfs_callback_tcpport6; |
27 | int cb_users[NFS4_MAX_MINOR_VERSION + 1]; | ||
27 | #endif | 28 | #endif |
28 | spinlock_t nfs_client_lock; | 29 | spinlock_t nfs_client_lock; |
29 | struct timespec boot_time; | 30 | struct timespec boot_time; |