Merge branch 'for-3.3' of git://linux-nfs.org/~bfields/linux
[linux-2.6.git] / net / sunrpc / svc_xprt.c
index 38649cf..74cb0d8 100644 (file)
@@ -22,6 +22,7 @@ static struct svc_deferred_req *svc_deferred_dequeue(struct svc_xprt *xprt);
 static int svc_deferred_recv(struct svc_rqst *rqstp);
 static struct cache_deferred_req *svc_defer(struct cache_req *req);
 static void svc_age_temp_xprts(unsigned long closure);
+static void svc_delete_xprt(struct svc_xprt *xprt);
 
 /* apparently the "standard" is that clients close
  * idle connections after 5 minutes, servers after
@@ -147,8 +148,8 @@ EXPORT_SYMBOL_GPL(svc_xprt_put);
  * Called by transport drivers to initialize the transport independent
  * portion of the transport instance.
  */
-void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt,
-                  struct svc_serv *serv)
+void svc_xprt_init(struct net *net, struct svc_xprt_class *xcl,
+                  struct svc_xprt *xprt, struct svc_serv *serv)
 {
        memset(xprt, 0, sizeof(*xprt));
        xprt->xpt_class = xcl;
@@ -163,7 +164,7 @@ void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt,
        spin_lock_init(&xprt->xpt_lock);
        set_bit(XPT_BUSY, &xprt->xpt_flags);
        rpc_init_wait_queue(&xprt->xpt_bc_pending, "xpt_bc_pending");
-       xprt->xpt_net = get_net(&init_net);
+       xprt->xpt_net = get_net(net);
 }
 EXPORT_SYMBOL_GPL(svc_xprt_init);
 
@@ -878,7 +879,7 @@ static void call_xpt_users(struct svc_xprt *xprt)
 /*
  * Remove a dead transport
  */
-void svc_delete_xprt(struct svc_xprt *xprt)
+static void svc_delete_xprt(struct svc_xprt *xprt)
 {
        struct svc_serv *serv = xprt->xpt_server;
        struct svc_deferred_req *dr;
@@ -893,14 +894,7 @@ void svc_delete_xprt(struct svc_xprt *xprt)
        spin_lock_bh(&serv->sv_lock);
        if (!test_and_set_bit(XPT_DETACHED, &xprt->xpt_flags))
                list_del_init(&xprt->xpt_list);
-       /*
-        * The only time we're called while xpt_ready is still on a list
-        * is while the list itself is about to be destroyed (in
-        * svc_destroy).  BUT svc_xprt_enqueue could still be attempting
-        * to add new entries to the sp_sockets list, so we can't leave
-        * a freed xprt on it.
-        */
-       list_del_init(&xprt->xpt_ready);
+       BUG_ON(!list_empty(&xprt->xpt_ready));
        if (test_bit(XPT_TEMP, &xprt->xpt_flags))
                serv->sv_tmpcnt--;
        spin_unlock_bh(&serv->sv_lock);
@@ -928,22 +922,48 @@ void svc_close_xprt(struct svc_xprt *xprt)
 }
 EXPORT_SYMBOL_GPL(svc_close_xprt);
 
-void svc_close_all(struct list_head *xprt_list)
+static void svc_close_list(struct list_head *xprt_list)
+{
+       struct svc_xprt *xprt;
+
+       list_for_each_entry(xprt, xprt_list, xpt_list) {
+               set_bit(XPT_CLOSE, &xprt->xpt_flags);
+               set_bit(XPT_BUSY, &xprt->xpt_flags);
+       }
+}
+
+void svc_close_all(struct svc_serv *serv)
 {
+       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_del_init(&xprt->xpt_ready);
+               }
+               spin_unlock_bh(&pool->sp_lock);
+       }
        /*
-        * The server is shutting down, and no more threads are running.
-        * svc_xprt_enqueue() might still be running, but at worst it
-        * will re-add the xprt to sp_sockets, which will soon get
-        * freed.  So we don't bother with any more locking, and don't
-        * leave the close to the (nonexistent) server threads:
+        * 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, xprt_list, xpt_list) {
-               set_bit(XPT_CLOSE, &xprt->xpt_flags);
+       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));
 }
 
 /*