patch-2.1.58 linux/net/sunrpc/clnt.c

Next file: linux/net/sunrpc/pmap_clnt.c
Previous file: linux/mm/vmscan.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.57/linux/net/sunrpc/clnt.c linux/net/sunrpc/clnt.c
@@ -116,17 +116,23 @@
 
 /*
  * Properly shut down an RPC client, terminating all outstanding
- * requests.
+ * requests. Note that we must be certain that cl_oneshot and
+ * cl_dead are cleared, or else the client would be destroyed
+ * when the last task releases it.
  */
 int
 rpc_shutdown_client(struct rpc_clnt *clnt)
 {
 	dprintk("RPC: shutting down %s client for %s\n",
-			clnt->cl_protname, clnt->cl_server);
+		clnt->cl_protname, clnt->cl_server);
 	while (clnt->cl_users) {
-		dprintk("sigmask %08lx\n", current->signal);
-		dprintk("users %d\n", clnt->cl_users);
-		clnt->cl_dead = 1;
+#ifdef RPC_DEBUG
+		printk("rpc_shutdown_client: client %s, tasks=%d\n",
+			clnt->cl_protname, clnt->cl_users);
+#endif
+		/* Don't let rpc_release_client destroy us */
+		clnt->cl_oneshot = 0;
+		clnt->cl_dead = 0;
 		rpc_killall_tasks(clnt);
 		sleep_on(&destroy_wait);
 	}
@@ -162,12 +168,16 @@
 {
 	dprintk("RPC:      rpc_release_client(%p, %d)\n",
 				clnt, clnt->cl_users);
-	if (--(clnt->cl_users) == 0) {
-		wake_up(&destroy_wait);
-		if (clnt->cl_oneshot || clnt->cl_dead)
-			rpc_destroy_client(clnt);
-	}
-	dprintk("RPC:      rpc_release_client done\n");
+	if (clnt->cl_users) {
+		if (--(clnt->cl_users) > 0)
+			return;
+	} else
+		printk("rpc_release_client: %s client already free??\n",
+			clnt->cl_protname);
+
+	wake_up(&destroy_wait);
+	if (clnt->cl_oneshot || clnt->cl_dead)
+		rpc_destroy_client(clnt);
 }
 
 /*
@@ -205,10 +215,9 @@
 	if ((async = (flags & RPC_TASK_ASYNC)) != 0) {
 		if (!func)
 			func = rpc_default_callback;
-		if (!(task = rpc_new_task(clnt, func, flags))) {
-			current->blocked = oldmask;
-			return -ENOMEM;
-		}
+		status = -ENOMEM;
+		if (!(task = rpc_new_task(clnt, func, flags)))
+			goto out;
 		task->tk_calldata = data;
 	} else {
 		rpc_init_task(task, clnt, NULL, flags);
@@ -222,12 +231,13 @@
 	} else
 		async = 0;
 
+	status = 0;
 	if (!async) {
 		status = task->tk_status;
 		rpc_release_task(task);
-	} else
-		status = 0;
+	}
 
+out:
 	current->blocked = oldmask;
 	return status;
 }
@@ -354,6 +364,7 @@
 
 	if ((task->tk_buffer = rpc_malloc(task, bufsiz)) != NULL)
 		return;
+	printk("RPC: buffer allocation failed for task %p\n", task); 
 
 	if (1 || !signalled()) {
 		xprt_release(task);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov