]> git.hungrycats.org Git - linux/commitdiff
[PATCH] eliminate hangs during RPC client shutdown
authorChuck Lever <cel@citi.umich.edu>
Mon, 26 Aug 2002 04:01:55 +0000 (21:01 -0700)
committerLinus Torvalds <torvalds@penguin.transmeta.com>
Mon, 26 Aug 2002 04:01:55 +0000 (21:01 -0700)
this eliminates an infinite loop in rpciod if an RPC client's reference
counter accidentally goes negative.  i've been running this under load
since 2.5.30 with no ill effects.

net/sunrpc/clnt.c

index 048978395042a4af840815744e1ae9bd38e65b2a..984342395ac76e87da94077858260fe9bfd93386 100644 (file)
@@ -138,19 +138,27 @@ out_no_auth:
 int
 rpc_shutdown_client(struct rpc_clnt *clnt)
 {
-       dprintk("RPC: shutting down %s client for %s\n",
-               clnt->cl_protname, clnt->cl_server);
-       while (atomic_read(&clnt->cl_users)) {
-#ifdef RPC_DEBUG
-               dprintk("RPC: rpc_shutdown_client: client %s, tasks=%d\n",
-                       clnt->cl_protname, atomic_read(&clnt->cl_users));
-#endif
+       dprintk("RPC: shutting down %s client for %s, tasks=%d\n",
+                       clnt->cl_protname, clnt->cl_server,
+                       atomic_read(&clnt->cl_users));
+
+       while (atomic_read(&clnt->cl_users) > 0) {
                /* Don't let rpc_release_client destroy us */
                clnt->cl_oneshot = 0;
                clnt->cl_dead = 0;
                rpc_killall_tasks(clnt);
                sleep_on_timeout(&destroy_wait, 1*HZ);
        }
+
+       if (atomic_read(&clnt->cl_users) < 0) {
+               printk(KERN_ERR "RPC: rpc_shutdown_client clnt %p tasks=%d\n",
+                               clnt, atomic_read(&clnt->cl_users));
+#ifdef RPC_DEBUG
+               rpc_show_tasks();
+#endif
+               BUG();
+       }
+
        return rpc_destroy_client(clnt);
 }