diff options
Diffstat (limited to 'net/sunrpc/svc_xprt.c')
-rw-r--r-- | net/sunrpc/svc_xprt.c | 51 |
1 files changed, 36 insertions, 15 deletions
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 74cb0d8..4bda09d 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -922,48 +922,65 @@ void svc_close_xprt(struct svc_xprt *xprt) } EXPORT_SYMBOL_GPL(svc_close_xprt); -static void svc_close_list(struct list_head *xprt_list) +static void svc_close_list(struct list_head *xprt_list, struct net *net) { struct svc_xprt *xprt; list_for_each_entry(xprt, xprt_list, xpt_list) { + if (xprt->xpt_net != net) + continue; set_bit(XPT_CLOSE, &xprt->xpt_flags); set_bit(XPT_BUSY, &xprt->xpt_flags); } } -void svc_close_all(struct svc_serv *serv) +static void svc_clear_pools(struct svc_serv *serv, struct net *net) { struct svc_pool *pool; struct svc_xprt *xprt; struct svc_xprt *tmp; int i; - svc_close_list(&serv->sv_tempsocks); - svc_close_list(&serv->sv_permsocks); - for (i = 0; i < serv->sv_nrpools; i++) { pool = &serv->sv_pools[i]; spin_lock_bh(&pool->sp_lock); - while (!list_empty(&pool->sp_sockets)) { - xprt = list_first_entry(&pool->sp_sockets, struct svc_xprt, xpt_ready); + list_for_each_entry_safe(xprt, tmp, &pool->sp_sockets, xpt_ready) { + if (xprt->xpt_net != net) + continue; list_del_init(&xprt->xpt_ready); } spin_unlock_bh(&pool->sp_lock); } +} + +static void svc_clear_list(struct list_head *xprt_list, struct net *net) +{ + struct svc_xprt *xprt; + struct svc_xprt *tmp; + + list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) { + if (xprt->xpt_net != net) + continue; + svc_delete_xprt(xprt); + } + list_for_each_entry(xprt, xprt_list, xpt_list) + BUG_ON(xprt->xpt_net == net); +} + +void svc_close_net(struct svc_serv *serv, struct net *net) +{ + svc_close_list(&serv->sv_tempsocks, net); + svc_close_list(&serv->sv_permsocks, net); + + svc_clear_pools(serv, net); /* * At this point the sp_sockets lists will stay empty, since * svc_enqueue will not add new entries without taking the * sp_lock and checking XPT_BUSY. */ - list_for_each_entry_safe(xprt, tmp, &serv->sv_tempsocks, xpt_list) - svc_delete_xprt(xprt); - list_for_each_entry_safe(xprt, tmp, &serv->sv_permsocks, xpt_list) - svc_delete_xprt(xprt); - - BUG_ON(!list_empty(&serv->sv_permsocks)); - BUG_ON(!list_empty(&serv->sv_tempsocks)); + svc_clear_list(&serv->sv_tempsocks, net); + svc_clear_list(&serv->sv_permsocks, net); } /* @@ -1089,6 +1106,7 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt) * svc_find_xprt - find an RPC transport instance * @serv: pointer to svc_serv to search * @xcl_name: C string containing transport's class name + * @net: owner net pointer * @af: Address family of transport's local address * @port: transport's IP port number * @@ -1101,7 +1119,8 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt) * service's list that has a matching class name. */ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, - const sa_family_t af, const unsigned short port) + struct net *net, const sa_family_t af, + const unsigned short port) { struct svc_xprt *xprt; struct svc_xprt *found = NULL; @@ -1112,6 +1131,8 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name, spin_lock_bh(&serv->sv_lock); list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) { + if (xprt->xpt_net != net) + continue; if (strcmp(xprt->xpt_class->xcl_name, xcl_name)) continue; if (af != AF_UNSPEC && af != xprt->xpt_local.ss_family) |