Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 359746
b: refs/heads/master
c: cc630d9
h: refs/heads/master
v: v3
  • Loading branch information
J. Bruce Fields committed Feb 17, 2013
1 parent 91bc50c commit 26a0864
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 35 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e75bafbff2270993926abcc31358361db74a9bc2
refs/heads/master: cc630d9f476445927fca599f81182c7f06f79058
9 changes: 0 additions & 9 deletions trunk/net/sunrpc/svc.c
Original file line number Diff line number Diff line change
Expand Up @@ -515,15 +515,6 @@ EXPORT_SYMBOL_GPL(svc_create_pooled);

void svc_shutdown_net(struct svc_serv *serv, struct net *net)
{
/*
* The set of xprts (contained in the sv_tempsocks and
* sv_permsocks lists) is now constant, since it is modified
* only by accepting new sockets (done by service threads in
* svc_recv) or aging old ones (done by sv_temptimer), or
* configuration changes (excluded by whatever locking the
* caller is using--nfsd_mutex in the case of nfsd). So it's
* safe to traverse those lists and shut everything down:
*/
svc_close_net(serv, net);

if (serv->sv_shutdown)
Expand Down
57 changes: 32 additions & 25 deletions trunk/net/sunrpc/svc_xprt.c
Original file line number Diff line number Diff line change
Expand Up @@ -955,21 +955,24 @@ void svc_close_xprt(struct svc_xprt *xprt)
}
EXPORT_SYMBOL_GPL(svc_close_xprt);

static void svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net)
static int svc_close_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net)
{
struct svc_xprt *xprt;
int ret = 0;

spin_lock(&serv->sv_lock);
list_for_each_entry(xprt, xprt_list, xpt_list) {
if (xprt->xpt_net != net)
continue;
ret++;
set_bit(XPT_CLOSE, &xprt->xpt_flags);
set_bit(XPT_BUSY, &xprt->xpt_flags);
svc_xprt_enqueue(xprt);
}
spin_unlock(&serv->sv_lock);
return ret;
}

static void svc_clear_pools(struct svc_serv *serv, struct net *net)
static struct svc_xprt *svc_dequeue_net(struct svc_serv *serv, struct net *net)
{
struct svc_pool *pool;
struct svc_xprt *xprt;
Expand All @@ -984,42 +987,46 @@ static void svc_clear_pools(struct svc_serv *serv, struct net *net)
if (xprt->xpt_net != net)
continue;
list_del_init(&xprt->xpt_ready);
spin_unlock_bh(&pool->sp_lock);
return xprt;
}
spin_unlock_bh(&pool->sp_lock);
}
return NULL;
}

static void svc_clear_list(struct svc_serv *serv, struct list_head *xprt_list, struct net *net)
static void svc_clean_up_xprts(struct svc_serv *serv, struct net *net)
{
struct svc_xprt *xprt;
struct svc_xprt *tmp;
LIST_HEAD(victims);

spin_lock(&serv->sv_lock);
list_for_each_entry_safe(xprt, tmp, xprt_list, xpt_list) {
if (xprt->xpt_net != net)
continue;
list_move(&xprt->xpt_list, &victims);
}
spin_unlock(&serv->sv_lock);

list_for_each_entry_safe(xprt, tmp, &victims, xpt_list)
while ((xprt = svc_dequeue_net(serv, net))) {
set_bit(XPT_CLOSE, &xprt->xpt_flags);
svc_delete_xprt(xprt);
}
}

/*
* Server threads may still be running (especially in the case where the
* service is still running in other network namespaces).
*
* So we shut down sockets the same way we would on a running server, by
* setting XPT_CLOSE, enqueuing, and letting a thread pick it up to do
* the close. In the case there are no such other threads,
* threads running, svc_clean_up_xprts() does a simple version of a
* server's main event loop, and in the case where there are other
* threads, we may need to wait a little while and then check again to
* see if they're done.
*/
void svc_close_net(struct svc_serv *serv, struct net *net)
{
svc_close_list(serv, &serv->sv_tempsocks, net);
svc_close_list(serv, &serv->sv_permsocks, net);
int delay = 0;

svc_clear_pools(serv, net);
/*
* At this point the sp_sockets lists will stay empty, since
* svc_xprt_enqueue will not add new entries without taking the
* sp_lock and checking XPT_BUSY.
*/
svc_clear_list(serv, &serv->sv_tempsocks, net);
svc_clear_list(serv, &serv->sv_permsocks, net);
while (svc_close_list(serv, &serv->sv_permsocks, net) +
svc_close_list(serv, &serv->sv_tempsocks, net)) {

svc_clean_up_xprts(serv, net);
msleep(delay++);
}
}

/*
Expand Down

0 comments on commit 26a0864

Please sign in to comment.