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

Next file: linux/net/sunrpc/stats.c
Previous file: linux/net/sched/sch_api.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.24/linux/net/sunrpc/clnt.c linux/net/sunrpc/clnt.c
@@ -294,7 +294,8 @@
 	task->tk_flags |= flags;
 
 	/* Increment call count */
-	rpcproc_count(task->tk_client, proc)++;
+	if (task->tk_proc < task->tk_client->cl_maxproc)
+		rpcproc_count(task->tk_client, proc)++;
 }
 
 /*
@@ -319,9 +320,14 @@
 call_bind(struct rpc_task *task)
 {
 	struct rpc_clnt	*clnt = task->tk_client;
+	struct rpc_xprt *xprt = clnt->cl_xprt;
 
-	task->tk_action = call_reserve;
+	if (xprt->stream && !xprt->connected)
+		task->tk_action = call_reconnect;
+	else
+		task->tk_action = call_reserve;
 	task->tk_status = 0;
+
 	if (!clnt->cl_port)
 		rpc_getport(task, clnt);
 }
@@ -340,6 +346,7 @@
 			clnt->cl_protname, clnt->cl_server,
 			clnt->cl_softrtry? "giving up" : "retrying");
 		if (!clnt->cl_softrtry) {
+			task->tk_action = call_bind;
 			rpc_delay(task, 5*HZ);
 			return;
 		}
@@ -376,25 +383,27 @@
 
 	if (task->tk_status >= 0) {
 		task->tk_action = call_allocate;
-		goto out;
-	} else if (task->tk_status == -EAGAIN) {
+		return;
+	}
+
+	switch (task->tk_status) {
+	case -EAGAIN:
+	case -ENOBUFS:
 		task->tk_timeout = task->tk_client->cl_timeout.to_resrvval;
 		task->tk_status = 0;
-		xprt_reserve(task);
-		goto out;
-	} else if (task->tk_status == -ETIMEDOUT) {
+		task->tk_action = call_reserve;
+		break;
+	case -ETIMEDOUT:
 		dprintk("RPC: task timed out\n");
 		task->tk_action = call_timeout;
-		goto out;
-	} else {
+		break;
+	default:
 		task->tk_action = NULL;
+		if (!task->tk_rqstp) {
+			printk("RPC: task has no request, exit EIO\n");
+			rpc_exit(task, -EIO);
+		}
 	}
-	if (!task->tk_rqstp) {
-		printk("RPC: task has no request, exit EIO\n");
-		rpc_exit(task, -EIO);
-	}
-out:
-	return;
 }
 
 /*
@@ -424,7 +433,7 @@
 	if (!signalled()) {
 		xprt_release(task);
 		task->tk_action = call_reserve;
-		rpc_delay(task, HZ);
+		rpc_delay(task, HZ>>4);
 		return;
 	}
 
@@ -477,7 +486,7 @@
 		printk("RPC: call_header failed, exit EIO\n");
 		rpc_exit(task, -EIO);
 	} else
-	if ((status = encode(req, p, task->tk_argp)) < 0) {
+	if (encode && (status = encode(req, p, task->tk_argp)) < 0) {
 		printk(KERN_WARNING "%s: can't encode arguments: %d\n",
 				clnt->cl_protname, -status);
 		rpc_exit(task, status);
@@ -508,19 +517,16 @@
 		task->tk_pid, task->tk_status);
 
 	task->tk_action = call_status;
-	/* In case of error, evaluate status */
-	if (task->tk_status < 0)
-		return;
+
+	/* Need to ensure cleanups are performed by xprt_receive_status() */
+	xprt_receive(task);
 
 	/* If we have no decode function, this means we're performing
 	 * a void call (a la lockd message passing). */
 	if (!rpcproc_decode(task->tk_client, task->tk_proc)) {
-		rpc_remove_wait_queue(task); /* remove from xprt_pending */
 		task->tk_action = NULL;
 		return;
 	}
-
-	xprt_receive(task);
 }
 
 /*
@@ -530,6 +536,7 @@
 call_status(struct rpc_task *task)
 {
 	struct rpc_clnt	*clnt = task->tk_client;
+	struct rpc_xprt *xprt = clnt->cl_xprt;
 	struct rpc_rqst	*req;
 	int		status = task->tk_status;
 
@@ -538,28 +545,49 @@
 
 	if (status >= 0) {
 		task->tk_action = call_decode;
-	} else if (status == -ETIMEDOUT) {
+		return;
+	}
+
+	task->tk_status = 0;
+	req = task->tk_rqstp;
+	switch(status) {
+	case -ETIMEDOUT:
 		task->tk_action = call_timeout;
-	} else if (status == -EAGAIN) {
-		if (!(req = task->tk_rqstp))
+		break;
+	case -EAGAIN:
+		if (!req)
 			task->tk_action = call_reserve;
 		else if (!task->tk_buffer)
 			task->tk_action = call_allocate;
-		else if (req->rq_damaged)
+		else if (req->rq_damaged) {
 			task->tk_action = call_encode;
-		else
+			clnt->cl_stats->rpcretrans++;
+		} else {
 			task->tk_action = call_transmit;
-	} else if (status == -ENOTCONN) {
-		task->tk_action = call_reconnect;
-	} else if (status == -ECONNREFUSED && clnt->cl_autobind) {
-		task->tk_action = call_bind;
-		clnt->cl_port = 0;
-	} else {
+			clnt->cl_stats->rpcretrans++;
+		}
+		break;
+	case -ECONNREFUSED:
+	case -ENOTCONN:
+		if (clnt->cl_autobind || !clnt->cl_port) {
+			clnt->cl_port = 0;
+			task->tk_action = call_bind;
+		} else if (xprt->stream)
+			task->tk_action = call_reconnect;
+		else {
+			rpc_delay(task, 5*HZ); /* Hope it all wears off */
+			if (req->rq_damaged)
+				task->tk_action = call_encode;
+			else
+				task->tk_action = call_transmit;
+			clnt->cl_stats->rpcretrans++;
+		}
+		break;
+	default:
 		if (clnt->cl_chatty)
 			printk("%s: RPC call returned error %d\n",
-				clnt->cl_protname, -status);
-		task->tk_action = NULL;
-		return;
+			       clnt->cl_protname, -status);
+		rpc_exit(task, status);
 	}
 }
 
@@ -600,7 +628,7 @@
 		if (req)
 			printk("%s: server %s not responding, still trying\n",
 				clnt->cl_protname, clnt->cl_server);
-		else 
+		else
 			printk("%s: task %d can't get a request slot\n",
 				clnt->cl_protname, task->tk_pid);
 	}
@@ -610,6 +638,8 @@
 minor_timeout:
 	if (!clnt->cl_port) {
 		task->tk_action = call_bind;
+	} else if (clnt->cl_xprt->stream && !clnt->cl_xprt->connected) {
+		task->tk_action = call_reconnect;
 	} else if (!req) {
 		task->tk_action = call_reserve;
 	} else if (req->rq_damaged) {
@@ -628,14 +658,12 @@
 static void
 call_reconnect(struct rpc_task *task)
 {
+	struct rpc_clnt *clnt = task->tk_client;
 	dprintk("RPC: %4d call_reconnect status %d\n",
 				task->tk_pid, task->tk_status);
-	if (task->tk_status == 0) {
-		task->tk_action = call_status;
-		task->tk_status = -EAGAIN;
-		return;
-	}
-	task->tk_client->cl_stats->netreconn++;
+	task->tk_action = call_reserve;
+	task->tk_status = 0;
+	clnt->cl_stats->netreconn++;
 	xprt_reconnect(task);
 }
 
@@ -685,7 +713,9 @@
 	}
 
 	task->tk_action = NULL;
-	task->tk_status = decode(req, p, task->tk_resp);
+
+	if (decode)
+		task->tk_status = decode(req, p, task->tk_resp);
 	dprintk("RPC: %4d call_decode result %d\n", task->tk_pid,
 					task->tk_status);
 }
@@ -714,11 +744,10 @@
 	dprintk("RPC: %4d call_refreshresult (status %d)\n", 
 				task->tk_pid, task->tk_status);
 
-	if (task->tk_status < 0) {
-		task->tk_status = -EACCES;
-		task->tk_action = NULL;
-	} else
-		task->tk_action = call_reserve;
+	if (task->tk_status < 0)
+		rpc_exit(task, -EACCES);
+	else
+		task->tk_action = call_bind;
 }
 
 /*

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)