diff options
| author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2012-01-31 05:09:17 -0500 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-02-15 00:19:45 -0500 |
| commit | 7b147f1ff267d12e0d189ca3d4156ed5a76b8d99 (patch) | |
| tree | 651496e6e08521de934b2ad0953e2b81d3f5da2f | |
| parent | 3a22bf506c9df47e93e8dc8a68d86cd8ae384d98 (diff) | |
SUNRPC: service destruction in network namespace context
v2: Added comment to BUG_ON's in svc_destroy() to make code looks clearer.
This patch introduces network namespace filter for service destruction
function.
Nothing special here - just do exactly the same operations, but only for
tranports in passed networks namespace context.
BTW, BUG_ON() checks for empty service transports lists were returned into
svc_destroy() function. This is because of swithing generic svc_close_all() to
networks namespace dependable svc_close_net().
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
| -rw-r--r-- | include/linux/sunrpc/svcsock.h | 2 | ||||
| -rw-r--r-- | net/sunrpc/svc.c | 13 | ||||
| -rw-r--r-- | net/sunrpc/svc_xprt.c | 27 |
3 files changed, 29 insertions, 13 deletions
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index c84e9741cb2a..cb4ac69e1f33 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h | |||
| @@ -34,7 +34,7 @@ struct svc_sock { | |||
| 34 | /* | 34 | /* |
| 35 | * Function prototypes. | 35 | * Function prototypes. |
| 36 | */ | 36 | */ |
| 37 | void svc_close_all(struct svc_serv *); | 37 | void svc_close_net(struct svc_serv *, struct net *); |
| 38 | int svc_recv(struct svc_rqst *, long); | 38 | int svc_recv(struct svc_rqst *, long); |
| 39 | int svc_send(struct svc_rqst *); | 39 | int svc_send(struct svc_rqst *); |
| 40 | void svc_drop(struct svc_rqst *); | 40 | void svc_drop(struct svc_rqst *); |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index a8b49a044619..6cc0ea3d26f1 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
| @@ -517,6 +517,8 @@ EXPORT_SYMBOL_GPL(svc_create_pooled); | |||
| 517 | void | 517 | void |
| 518 | svc_destroy(struct svc_serv *serv) | 518 | svc_destroy(struct svc_serv *serv) |
| 519 | { | 519 | { |
| 520 | struct net *net = current->nsproxy->net_ns; | ||
| 521 | |||
| 520 | dprintk("svc: svc_destroy(%s, %d)\n", | 522 | dprintk("svc: svc_destroy(%s, %d)\n", |
| 521 | serv->sv_program->pg_name, | 523 | serv->sv_program->pg_name, |
| 522 | serv->sv_nrthreads); | 524 | serv->sv_nrthreads); |
| @@ -539,10 +541,17 @@ svc_destroy(struct svc_serv *serv) | |||
| 539 | * caller is using--nfsd_mutex in the case of nfsd). So it's | 541 | * caller is using--nfsd_mutex in the case of nfsd). So it's |
| 540 | * safe to traverse those lists and shut everything down: | 542 | * safe to traverse those lists and shut everything down: |
| 541 | */ | 543 | */ |
| 542 | svc_close_all(serv); | 544 | svc_close_net(serv, net); |
| 545 | |||
| 546 | /* | ||
| 547 | * The last user is gone and thus all sockets have to be destroyed to | ||
| 548 | * the point. Check this. | ||
| 549 | */ | ||
| 550 | BUG_ON(!list_empty(&serv->sv_permsocks)); | ||
| 551 | BUG_ON(!list_empty(&serv->sv_tempsocks)); | ||
| 543 | 552 | ||
| 544 | if (serv->sv_shutdown) | 553 | if (serv->sv_shutdown) |
| 545 | serv->sv_shutdown(serv, current->nsproxy->net_ns); | 554 | serv->sv_shutdown(serv, net); |
| 546 | 555 | ||
| 547 | cache_clean_deferred(serv); | 556 | cache_clean_deferred(serv); |
| 548 | 557 | ||
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 493e70b72b71..4bda09d7e1a4 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
| @@ -922,17 +922,19 @@ void svc_close_xprt(struct svc_xprt *xprt) | |||
| 922 | } | 922 | } |
| 923 | EXPORT_SYMBOL_GPL(svc_close_xprt); | 923 | EXPORT_SYMBOL_GPL(svc_close_xprt); |
| 924 | 924 | ||
| 925 | static void svc_close_list(struct list_head *xprt_list) | 925 | static void svc_close_list(struct list_head *xprt_list, struct net *net) |
| 926 | { | 926 | { |
| 927 | struct svc_xprt *xprt; | 927 | struct svc_xprt *xprt; |
| 928 | 928 | ||
| 929 | list_for_each_entry(xprt, xprt_list, xpt_list) { | 929 | list_for_each_entry(xprt, xprt_list, xpt_list) { |
| 930 | if (xprt->xpt_net != net) | ||
| 931 | continue; | ||
| 930 | set_bit(XPT_CLOSE, &xprt->xpt_flags); | 932 | set_bit(XPT_CLOSE, &xprt->xpt_flags); |
| 931 | set_bit(XPT_BUSY, &xprt->xpt_flags); | 933 | set_bit(XPT_BUSY, &xprt->xpt_flags); |
| 932 | } | 934 | } |
| 933 | } | 935 | } |
| 934 | 936 | ||
| 935 | static void svc_clear_pools(struct svc_serv *serv) | 937 | static void svc_clear_pools(struct svc_serv *serv, struct net *net) |
| 936 | { | 938 | { |
| 937 | struct svc_pool *pool; | 939 | struct svc_pool *pool; |
| 938 | struct svc_xprt *xprt; | 940 | struct svc_xprt *xprt; |
| @@ -944,36 +946,41 @@ static void svc_clear_pools(struct svc_serv *serv) | |||
| 944 | 946 | ||
| 945 | spin_lock_bh(&pool->sp_lock); | 947 | spin_lock_bh(&pool->sp_lock); |
| 946 | list_for_each_entry_safe(xprt, tmp, &pool->sp_sockets, xpt_ready) { | 948 | list_for_each_entry_safe(xprt, tmp, &pool->sp_sockets, xpt_ready) { |
| 949 | if (xprt->xpt_net != net) | ||
| 950 | continue; | ||
| 947 | list_del_init(&xprt->xpt_ready); | 951 | list_del_init(&xprt->xpt_ready); |
| 948 | } | 952 | } |
| 949 | spin_unlock_bh(&pool->sp_lock); | 953 | spin_unlock_bh(&pool->sp_lock); |
| 950 | } | 954 | } |
| 951 | } | 955 | } |
| 952 | 956 | ||
| 953 | static void svc_clear_list(struct list_head *xprt_list) | 957 | static void svc_clear_list(struct list_head *xprt_list, struct net *net) |
| 954 | { | 958 | { |
| 955 | struct svc_xprt *xprt; | 959 | struct svc_xprt *xprt; |
| 956 | struct svc_xprt *tmp; | 960 | struct svc_xprt *tmp; |
| 957 | 961 | ||
| 958 | list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { | 962 | list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { |
| 963 | if (xprt->xpt_net != net) | ||
| 964 | continue; | ||
| 959 | svc_delete_xprt(xprt); | 965 | svc_delete_xprt(xprt); |
| 960 | } | 966 | } |
| 961 | BUG_ON(!list_empty(xprt_list)); | 967 | list_for_each_entry(xprt, xprt_list, xpt_list) |
| 968 | BUG_ON(xprt->xpt_net == net); | ||
| 962 | } | 969 | } |
| 963 | 970 | ||
| 964 | void svc_close_all(struct svc_serv *serv) | 971 | void svc_close_net(struct svc_serv *serv, struct net *net) |
| 965 | { | 972 | { |
| 966 | svc_close_list(&serv->sv_tempsocks); | 973 | svc_close_list(&serv->sv_tempsocks, net); |
| 967 | svc_close_list(&serv->sv_permsocks); | 974 | svc_close_list(&serv->sv_permsocks, net); |
| 968 | 975 | ||
| 969 | svc_clear_pools(serv); | 976 | svc_clear_pools(serv, net); |
| 970 | /* | 977 | /* |
| 971 | * At this point the sp_sockets lists will stay empty, since | 978 | * At this point the sp_sockets lists will stay empty, since |
| 972 | * svc_enqueue will not add new entries without taking the | 979 | * svc_enqueue will not add new entries without taking the |
| 973 | * sp_lock and checking XPT_BUSY. | 980 | * sp_lock and checking XPT_BUSY. |
| 974 | */ | 981 | */ |
| 975 | svc_clear_list(&serv->sv_tempsocks); | 982 | svc_clear_list(&serv->sv_tempsocks, net); |
| 976 | svc_clear_list(&serv->sv_permsocks); | 983 | svc_clear_list(&serv->sv_permsocks, net); |
| 977 | } | 984 | } |
| 978 | 985 | ||
| 979 | /* | 986 | /* |
