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 | /* |