aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/clnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/clnt.c')
-rw-r--r--net/sunrpc/clnt.c143
1 files changed, 136 insertions, 7 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 5abab094441f..5bc2f45bddf0 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -36,7 +36,9 @@
36#include <linux/sunrpc/clnt.h> 36#include <linux/sunrpc/clnt.h>
37#include <linux/sunrpc/rpc_pipe_fs.h> 37#include <linux/sunrpc/rpc_pipe_fs.h>
38#include <linux/sunrpc/metrics.h> 38#include <linux/sunrpc/metrics.h>
39#include <linux/sunrpc/bc_xprt.h>
39 40
41#include "sunrpc.h"
40 42
41#ifdef RPC_DEBUG 43#ifdef RPC_DEBUG
42# define RPCDBG_FACILITY RPCDBG_CALL 44# define RPCDBG_FACILITY RPCDBG_CALL
@@ -63,6 +65,9 @@ static void call_decode(struct rpc_task *task);
63static void call_bind(struct rpc_task *task); 65static void call_bind(struct rpc_task *task);
64static void call_bind_status(struct rpc_task *task); 66static void call_bind_status(struct rpc_task *task);
65static void call_transmit(struct rpc_task *task); 67static void call_transmit(struct rpc_task *task);
68#if defined(CONFIG_NFS_V4_1)
69static void call_bc_transmit(struct rpc_task *task);
70#endif /* CONFIG_NFS_V4_1 */
66static void call_status(struct rpc_task *task); 71static void call_status(struct rpc_task *task);
67static void call_transmit_status(struct rpc_task *task); 72static void call_transmit_status(struct rpc_task *task);
68static void call_refresh(struct rpc_task *task); 73static void call_refresh(struct rpc_task *task);
@@ -613,6 +618,50 @@ rpc_call_async(struct rpc_clnt *clnt, const struct rpc_message *msg, int flags,
613} 618}
614EXPORT_SYMBOL_GPL(rpc_call_async); 619EXPORT_SYMBOL_GPL(rpc_call_async);
615 620
621#if defined(CONFIG_NFS_V4_1)
622/**
623 * rpc_run_bc_task - Allocate a new RPC task for backchannel use, then run
624 * rpc_execute against it
625 * @ops: RPC call ops
626 */
627struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req,
628 const struct rpc_call_ops *tk_ops)
629{
630 struct rpc_task *task;
631 struct xdr_buf *xbufp = &req->rq_snd_buf;
632 struct rpc_task_setup task_setup_data = {
633 .callback_ops = tk_ops,
634 };
635
636 dprintk("RPC: rpc_run_bc_task req= %p\n", req);
637 /*
638 * Create an rpc_task to send the data
639 */
640 task = rpc_new_task(&task_setup_data);
641 if (!task) {
642 xprt_free_bc_request(req);
643 goto out;
644 }
645 task->tk_rqstp = req;
646
647 /*
648 * Set up the xdr_buf length.
649 * This also indicates that the buffer is XDR encoded already.
650 */
651 xbufp->len = xbufp->head[0].iov_len + xbufp->page_len +
652 xbufp->tail[0].iov_len;
653
654 task->tk_action = call_bc_transmit;
655 atomic_inc(&task->tk_count);
656 BUG_ON(atomic_read(&task->tk_count) != 2);
657 rpc_execute(task);
658
659out:
660 dprintk("RPC: rpc_run_bc_task: task= %p\n", task);
661 return task;
662}
663#endif /* CONFIG_NFS_V4_1 */
664
616void 665void
617rpc_call_start(struct rpc_task *task) 666rpc_call_start(struct rpc_task *task)
618{ 667{
@@ -695,6 +744,19 @@ void rpc_force_rebind(struct rpc_clnt *clnt)
695EXPORT_SYMBOL_GPL(rpc_force_rebind); 744EXPORT_SYMBOL_GPL(rpc_force_rebind);
696 745
697/* 746/*
747 * Restart an (async) RPC call from the call_prepare state.
748 * Usually called from within the exit handler.
749 */
750void
751rpc_restart_call_prepare(struct rpc_task *task)
752{
753 if (RPC_ASSASSINATED(task))
754 return;
755 task->tk_action = rpc_prepare_task;
756}
757EXPORT_SYMBOL_GPL(rpc_restart_call_prepare);
758
759/*
698 * Restart an (async) RPC call. Usually called from within the 760 * Restart an (async) RPC call. Usually called from within the
699 * exit handler. 761 * exit handler.
700 */ 762 */
@@ -1085,7 +1147,7 @@ call_transmit(struct rpc_task *task)
1085 * in order to allow access to the socket to other RPC requests. 1147 * in order to allow access to the socket to other RPC requests.
1086 */ 1148 */
1087 call_transmit_status(task); 1149 call_transmit_status(task);
1088 if (task->tk_msg.rpc_proc->p_decode != NULL) 1150 if (rpc_reply_expected(task))
1089 return; 1151 return;
1090 task->tk_action = rpc_exit_task; 1152 task->tk_action = rpc_exit_task;
1091 rpc_wake_up_queued_task(&task->tk_xprt->pending, task); 1153 rpc_wake_up_queued_task(&task->tk_xprt->pending, task);
@@ -1120,6 +1182,72 @@ call_transmit_status(struct rpc_task *task)
1120 } 1182 }
1121} 1183}
1122 1184
1185#if defined(CONFIG_NFS_V4_1)
1186/*
1187 * 5b. Send the backchannel RPC reply. On error, drop the reply. In
1188 * addition, disconnect on connectivity errors.
1189 */
1190static void
1191call_bc_transmit(struct rpc_task *task)
1192{
1193 struct rpc_rqst *req = task->tk_rqstp;
1194
1195 BUG_ON(task->tk_status != 0);
1196 task->tk_status = xprt_prepare_transmit(task);
1197 if (task->tk_status == -EAGAIN) {
1198 /*
1199 * Could not reserve the transport. Try again after the
1200 * transport is released.
1201 */
1202 task->tk_status = 0;
1203 task->tk_action = call_bc_transmit;
1204 return;
1205 }
1206
1207 task->tk_action = rpc_exit_task;
1208 if (task->tk_status < 0) {
1209 printk(KERN_NOTICE "RPC: Could not send backchannel reply "
1210 "error: %d\n", task->tk_status);
1211 return;
1212 }
1213
1214 xprt_transmit(task);
1215 xprt_end_transmit(task);
1216 dprint_status(task);
1217 switch (task->tk_status) {
1218 case 0:
1219 /* Success */
1220 break;
1221 case -EHOSTDOWN:
1222 case -EHOSTUNREACH:
1223 case -ENETUNREACH:
1224 case -ETIMEDOUT:
1225 /*
1226 * Problem reaching the server. Disconnect and let the
1227 * forechannel reestablish the connection. The server will
1228 * have to retransmit the backchannel request and we'll
1229 * reprocess it. Since these ops are idempotent, there's no
1230 * need to cache our reply at this time.
1231 */
1232 printk(KERN_NOTICE "RPC: Could not send backchannel reply "
1233 "error: %d\n", task->tk_status);
1234 xprt_conditional_disconnect(task->tk_xprt,
1235 req->rq_connect_cookie);
1236 break;
1237 default:
1238 /*
1239 * We were unable to reply and will have to drop the
1240 * request. The server should reconnect and retransmit.
1241 */
1242 BUG_ON(task->tk_status == -EAGAIN);
1243 printk(KERN_NOTICE "RPC: Could not send backchannel reply "
1244 "error: %d\n", task->tk_status);
1245 break;
1246 }
1247 rpc_wake_up_queued_task(&req->rq_xprt->pending, task);
1248}
1249#endif /* CONFIG_NFS_V4_1 */
1250
1123/* 1251/*
1124 * 6. Sort out the RPC call status 1252 * 6. Sort out the RPC call status
1125 */ 1253 */
@@ -1130,8 +1258,8 @@ call_status(struct rpc_task *task)
1130 struct rpc_rqst *req = task->tk_rqstp; 1258 struct rpc_rqst *req = task->tk_rqstp;
1131 int status; 1259 int status;
1132 1260
1133 if (req->rq_received > 0 && !req->rq_bytes_sent) 1261 if (req->rq_reply_bytes_recvd > 0 && !req->rq_bytes_sent)
1134 task->tk_status = req->rq_received; 1262 task->tk_status = req->rq_reply_bytes_recvd;
1135 1263
1136 dprint_status(task); 1264 dprint_status(task);
1137 1265
@@ -1248,7 +1376,7 @@ call_decode(struct rpc_task *task)
1248 1376
1249 /* 1377 /*
1250 * Ensure that we see all writes made by xprt_complete_rqst() 1378 * Ensure that we see all writes made by xprt_complete_rqst()
1251 * before it changed req->rq_received. 1379 * before it changed req->rq_reply_bytes_recvd.
1252 */ 1380 */
1253 smp_rmb(); 1381 smp_rmb();
1254 req->rq_rcv_buf.len = req->rq_private_buf.len; 1382 req->rq_rcv_buf.len = req->rq_private_buf.len;
@@ -1289,7 +1417,7 @@ out_retry:
1289 task->tk_status = 0; 1417 task->tk_status = 0;
1290 /* Note: rpc_verify_header() may have freed the RPC slot */ 1418 /* Note: rpc_verify_header() may have freed the RPC slot */
1291 if (task->tk_rqstp == req) { 1419 if (task->tk_rqstp == req) {
1292 req->rq_received = req->rq_rcv_buf.len = 0; 1420 req->rq_reply_bytes_recvd = req->rq_rcv_buf.len = 0;
1293 if (task->tk_client->cl_discrtry) 1421 if (task->tk_client->cl_discrtry)
1294 xprt_conditional_disconnect(task->tk_xprt, 1422 xprt_conditional_disconnect(task->tk_xprt,
1295 req->rq_connect_cookie); 1423 req->rq_connect_cookie);
@@ -1377,13 +1505,14 @@ rpc_verify_header(struct rpc_task *task)
1377 } 1505 }
1378 if ((len -= 3) < 0) 1506 if ((len -= 3) < 0)
1379 goto out_overflow; 1507 goto out_overflow;
1380 p += 1; /* skip XID */
1381 1508
1509 p += 1; /* skip XID */
1382 if ((n = ntohl(*p++)) != RPC_REPLY) { 1510 if ((n = ntohl(*p++)) != RPC_REPLY) {
1383 dprintk("RPC: %5u %s: not an RPC reply: %x\n", 1511 dprintk("RPC: %5u %s: not an RPC reply: %x\n",
1384 task->tk_pid, __func__, n); 1512 task->tk_pid, __func__, n);
1385 goto out_garbage; 1513 goto out_garbage;
1386 } 1514 }
1515
1387 if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { 1516 if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
1388 if (--len < 0) 1517 if (--len < 0)
1389 goto out_overflow; 1518 goto out_overflow;