summaryrefslogtreecommitdiffstats
path: root/net/sunrpc/xprtsock.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2014-02-10 11:18:39 -0500
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-02-11 14:01:20 -0500
commit2ea24497a1b30dd03dd42b873fa5097913587f4d (patch)
tree1e1b3d1c95e712dcce68be4d011620b46a6271c7 /net/sunrpc/xprtsock.c
parent628356791b04ea988fee070f66a748a823d001bb (diff)
SUNRPC: RPC callbacks may be split across several TCP segments
Since TCP is a stream protocol, our callback read code needs to take into account the fact that RPC callbacks are not always confined to a single TCP segment. This patch adds support for multiple TCP segments by ensuring that we only remove the rpc_rqst structure from the 'free backchannel requests' list once the data has been completely received. We rely on the fact that TCP data is ordered for the duration of the connection. Reported-by: shaobingqing <shaobingqing@bwstor.com.cn> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r--net/sunrpc/xprtsock.c28
1 files changed, 8 insertions, 20 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 0addefca8e77..966763d735e9 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1306,41 +1306,29 @@ static inline int xs_tcp_read_reply(struct rpc_xprt *xprt,
1306 * If we're unable to obtain the rpc_rqst we schedule the closing of the 1306 * If we're unable to obtain the rpc_rqst we schedule the closing of the
1307 * connection and return -1. 1307 * connection and return -1.
1308 */ 1308 */
1309static inline int xs_tcp_read_callback(struct rpc_xprt *xprt, 1309static int xs_tcp_read_callback(struct rpc_xprt *xprt,
1310 struct xdr_skb_reader *desc) 1310 struct xdr_skb_reader *desc)
1311{ 1311{
1312 struct sock_xprt *transport = 1312 struct sock_xprt *transport =
1313 container_of(xprt, struct sock_xprt, xprt); 1313 container_of(xprt, struct sock_xprt, xprt);
1314 struct rpc_rqst *req; 1314 struct rpc_rqst *req;
1315 1315
1316 req = xprt_alloc_bc_request(xprt); 1316 /* Look up and lock the request corresponding to the given XID */
1317 spin_lock(&xprt->transport_lock);
1318 req = xprt_lookup_bc_request(xprt, transport->tcp_xid);
1317 if (req == NULL) { 1319 if (req == NULL) {
1320 spin_unlock(&xprt->transport_lock);
1318 printk(KERN_WARNING "Callback slot table overflowed\n"); 1321 printk(KERN_WARNING "Callback slot table overflowed\n");
1319 xprt_force_disconnect(xprt); 1322 xprt_force_disconnect(xprt);
1320 return -1; 1323 return -1;
1321 } 1324 }
1322 1325
1323 req->rq_xid = transport->tcp_xid;
1324 dprintk("RPC: read callback XID %08x\n", ntohl(req->rq_xid)); 1326 dprintk("RPC: read callback XID %08x\n", ntohl(req->rq_xid));
1325 xs_tcp_read_common(xprt, desc, req); 1327 xs_tcp_read_common(xprt, desc, req);
1326 1328
1327 if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) { 1329 if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
1328 struct svc_serv *bc_serv = xprt->bc_serv; 1330 xprt_complete_bc_request(req, transport->tcp_copied);
1329 1331 spin_unlock(&xprt->transport_lock);
1330 /*
1331 * Add callback request to callback list. The callback
1332 * service sleeps on the sv_cb_waitq waiting for new
1333 * requests. Wake it up after adding enqueing the
1334 * request.
1335 */
1336 dprintk("RPC: add callback request to list\n");
1337 spin_lock(&bc_serv->sv_cb_lock);
1338 list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
1339 spin_unlock(&bc_serv->sv_cb_lock);
1340 wake_up(&bc_serv->sv_cb_waitq);
1341 }
1342
1343 req->rq_private_buf.len = transport->tcp_copied;
1344 1332
1345 return 0; 1333 return 0;
1346} 1334}