aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJason Baron <jbaron@akamai.com>2014-09-24 14:08:00 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-09-24 23:13:37 -0400
commitf279cd008fc9742f5ec294d9b8a793a7a0b163ef (patch)
treeb8622a23661a1937c090c87d29f5393cb559a511 /net
parent173b3afceebe76fa2205b2c8808682d5b541fe3c (diff)
rpc: return sent and err from xs_sendpages()
If an error is returned after the first bits of a packet have already been successfully queued, xs_sendpages() will return a positive 'int' value indicating success. Callers seem to treat this as -EAGAIN. However, there are cases where its not a question of waiting for the write queue to drain. For example, when there is an iptables rule dropping packets to the destination, the lower level code can return -EPERM only after parts of the packet have been successfully queued. In this case, we can end up continuously retrying resulting in a kernel softlockup. This patch is intended to make no changes in behavior but is in preparation for subsequent patches that can make decisions based on both on the number of bytes sent by xs_sendpages() and any errors that may have be returned. Signed-off-by: Jason Baron <jbaron@akamai.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/xprtsock.c81
1 files changed, 42 insertions, 39 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index bffba4e4bfc6..7d9ea6b7113d 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -399,13 +399,13 @@ static int xs_send_kvec(struct socket *sock, struct sockaddr *addr, int addrlen,
399 return kernel_sendmsg(sock, &msg, NULL, 0, 0); 399 return kernel_sendmsg(sock, &msg, NULL, 0, 0);
400} 400}
401 401
402static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more, bool zerocopy) 402static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more, bool zerocopy, int *sent_p)
403{ 403{
404 ssize_t (*do_sendpage)(struct socket *sock, struct page *page, 404 ssize_t (*do_sendpage)(struct socket *sock, struct page *page,
405 int offset, size_t size, int flags); 405 int offset, size_t size, int flags);
406 struct page **ppage; 406 struct page **ppage;
407 unsigned int remainder; 407 unsigned int remainder;
408 int err, sent = 0; 408 int err;
409 409
410 remainder = xdr->page_len - base; 410 remainder = xdr->page_len - base;
411 base += xdr->page_base; 411 base += xdr->page_base;
@@ -424,15 +424,15 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i
424 err = do_sendpage(sock, *ppage, base, len, flags); 424 err = do_sendpage(sock, *ppage, base, len, flags);
425 if (remainder == 0 || err != len) 425 if (remainder == 0 || err != len)
426 break; 426 break;
427 sent += err; 427 *sent_p += err;
428 ppage++; 428 ppage++;
429 base = 0; 429 base = 0;
430 } 430 }
431 if (sent == 0) 431 if (err > 0) {
432 return err; 432 *sent_p += err;
433 if (err > 0) 433 err = 0;
434 sent += err; 434 }
435 return sent; 435 return err;
436} 436}
437 437
438/** 438/**
@@ -443,12 +443,14 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i
443 * @xdr: buffer containing this request 443 * @xdr: buffer containing this request
444 * @base: starting position in the buffer 444 * @base: starting position in the buffer
445 * @zerocopy: true if it is safe to use sendpage() 445 * @zerocopy: true if it is safe to use sendpage()
446 * @sent_p: return the total number of bytes successfully queued for sending
446 * 447 *
447 */ 448 */
448static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, bool zerocopy) 449static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, bool zerocopy, int *sent_p)
449{ 450{
450 unsigned int remainder = xdr->len - base; 451 unsigned int remainder = xdr->len - base;
451 int err, sent = 0; 452 int err = 0;
453 int sent = 0;
452 454
453 if (unlikely(!sock)) 455 if (unlikely(!sock))
454 return -ENOTSOCK; 456 return -ENOTSOCK;
@@ -465,7 +467,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
465 err = xs_send_kvec(sock, addr, addrlen, &xdr->head[0], base, remainder != 0); 467 err = xs_send_kvec(sock, addr, addrlen, &xdr->head[0], base, remainder != 0);
466 if (remainder == 0 || err != len) 468 if (remainder == 0 || err != len)
467 goto out; 469 goto out;
468 sent += err; 470 *sent_p += err;
469 base = 0; 471 base = 0;
470 } else 472 } else
471 base -= xdr->head[0].iov_len; 473 base -= xdr->head[0].iov_len;
@@ -473,23 +475,23 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen,
473 if (base < xdr->page_len) { 475 if (base < xdr->page_len) {
474 unsigned int len = xdr->page_len - base; 476 unsigned int len = xdr->page_len - base;
475 remainder -= len; 477 remainder -= len;
476 err = xs_send_pagedata(sock, xdr, base, remainder != 0, zerocopy); 478 err = xs_send_pagedata(sock, xdr, base, remainder != 0, zerocopy, &sent);
477 if (remainder == 0 || err != len) 479 *sent_p += sent;
480 if (remainder == 0 || sent != len)
478 goto out; 481 goto out;
479 sent += err;
480 base = 0; 482 base = 0;
481 } else 483 } else
482 base -= xdr->page_len; 484 base -= xdr->page_len;
483 485
484 if (base >= xdr->tail[0].iov_len) 486 if (base >= xdr->tail[0].iov_len)
485 return sent; 487 return 0;
486 err = xs_send_kvec(sock, NULL, 0, &xdr->tail[0], base, 0); 488 err = xs_send_kvec(sock, NULL, 0, &xdr->tail[0], base, 0);
487out: 489out:
488 if (sent == 0) 490 if (err > 0) {
489 return err; 491 *sent_p += err;
490 if (err > 0) 492 err = 0;
491 sent += err; 493 }
492 return sent; 494 return err;
493} 495}
494 496
495static void xs_nospace_callback(struct rpc_task *task) 497static void xs_nospace_callback(struct rpc_task *task)
@@ -573,19 +575,20 @@ static int xs_local_send_request(struct rpc_task *task)
573 container_of(xprt, struct sock_xprt, xprt); 575 container_of(xprt, struct sock_xprt, xprt);
574 struct xdr_buf *xdr = &req->rq_snd_buf; 576 struct xdr_buf *xdr = &req->rq_snd_buf;
575 int status; 577 int status;
578 int sent = 0;
576 579
577 xs_encode_stream_record_marker(&req->rq_snd_buf); 580 xs_encode_stream_record_marker(&req->rq_snd_buf);
578 581
579 xs_pktdump("packet data:", 582 xs_pktdump("packet data:",
580 req->rq_svec->iov_base, req->rq_svec->iov_len); 583 req->rq_svec->iov_base, req->rq_svec->iov_len);
581 584
582 status = xs_sendpages(transport->sock, NULL, 0, 585 status = xs_sendpages(transport->sock, NULL, 0, xdr, req->rq_bytes_sent,
583 xdr, req->rq_bytes_sent, true); 586 true, &sent);
584 dprintk("RPC: %s(%u) = %d\n", 587 dprintk("RPC: %s(%u) = %d\n",
585 __func__, xdr->len - req->rq_bytes_sent, status); 588 __func__, xdr->len - req->rq_bytes_sent, status);
586 if (likely(status >= 0)) { 589 if (likely(sent > 0) || status == 0) {
587 req->rq_bytes_sent += status; 590 req->rq_bytes_sent += sent;
588 req->rq_xmit_bytes_sent += status; 591 req->rq_xmit_bytes_sent += sent;
589 if (likely(req->rq_bytes_sent >= req->rq_slen)) { 592 if (likely(req->rq_bytes_sent >= req->rq_slen)) {
590 req->rq_bytes_sent = 0; 593 req->rq_bytes_sent = 0;
591 return 0; 594 return 0;
@@ -626,6 +629,7 @@ static int xs_udp_send_request(struct rpc_task *task)
626 struct rpc_xprt *xprt = req->rq_xprt; 629 struct rpc_xprt *xprt = req->rq_xprt;
627 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); 630 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
628 struct xdr_buf *xdr = &req->rq_snd_buf; 631 struct xdr_buf *xdr = &req->rq_snd_buf;
632 int sent = 0;
629 int status; 633 int status;
630 634
631 xs_pktdump("packet data:", 635 xs_pktdump("packet data:",
@@ -634,17 +638,15 @@ static int xs_udp_send_request(struct rpc_task *task)
634 638
635 if (!xprt_bound(xprt)) 639 if (!xprt_bound(xprt))
636 return -ENOTCONN; 640 return -ENOTCONN;
637 status = xs_sendpages(transport->sock, 641 status = xs_sendpages(transport->sock, xs_addr(xprt), xprt->addrlen,
638 xs_addr(xprt), 642 xdr, req->rq_bytes_sent, true, &sent);
639 xprt->addrlen, xdr,
640 req->rq_bytes_sent, true);
641 643
642 dprintk("RPC: xs_udp_send_request(%u) = %d\n", 644 dprintk("RPC: xs_udp_send_request(%u) = %d\n",
643 xdr->len - req->rq_bytes_sent, status); 645 xdr->len - req->rq_bytes_sent, status);
644 646
645 if (status >= 0) { 647 if (sent > 0 || status == 0) {
646 req->rq_xmit_bytes_sent += status; 648 req->rq_xmit_bytes_sent += sent;
647 if (status >= req->rq_slen) 649 if (sent >= req->rq_slen)
648 return 0; 650 return 0;
649 /* Still some bytes left; set up for a retry later. */ 651 /* Still some bytes left; set up for a retry later. */
650 status = -EAGAIN; 652 status = -EAGAIN;
@@ -713,6 +715,7 @@ static int xs_tcp_send_request(struct rpc_task *task)
713 struct xdr_buf *xdr = &req->rq_snd_buf; 715 struct xdr_buf *xdr = &req->rq_snd_buf;
714 bool zerocopy = true; 716 bool zerocopy = true;
715 int status; 717 int status;
718 int sent;
716 719
717 xs_encode_stream_record_marker(&req->rq_snd_buf); 720 xs_encode_stream_record_marker(&req->rq_snd_buf);
718 721
@@ -730,26 +733,26 @@ static int xs_tcp_send_request(struct rpc_task *task)
730 * to cope with writespace callbacks arriving _after_ we have 733 * to cope with writespace callbacks arriving _after_ we have
731 * called sendmsg(). */ 734 * called sendmsg(). */
732 while (1) { 735 while (1) {
733 status = xs_sendpages(transport->sock, 736 sent = 0;
734 NULL, 0, xdr, req->rq_bytes_sent, 737 status = xs_sendpages(transport->sock, NULL, 0, xdr,
735 zerocopy); 738 req->rq_bytes_sent, zerocopy, &sent);
736 739
737 dprintk("RPC: xs_tcp_send_request(%u) = %d\n", 740 dprintk("RPC: xs_tcp_send_request(%u) = %d\n",
738 xdr->len - req->rq_bytes_sent, status); 741 xdr->len - req->rq_bytes_sent, status);
739 742
740 if (unlikely(status < 0)) 743 if (unlikely(sent == 0 && status < 0))
741 break; 744 break;
742 745
743 /* If we've sent the entire packet, immediately 746 /* If we've sent the entire packet, immediately
744 * reset the count of bytes sent. */ 747 * reset the count of bytes sent. */
745 req->rq_bytes_sent += status; 748 req->rq_bytes_sent += sent;
746 req->rq_xmit_bytes_sent += status; 749 req->rq_xmit_bytes_sent += sent;
747 if (likely(req->rq_bytes_sent >= req->rq_slen)) { 750 if (likely(req->rq_bytes_sent >= req->rq_slen)) {
748 req->rq_bytes_sent = 0; 751 req->rq_bytes_sent = 0;
749 return 0; 752 return 0;
750 } 753 }
751 754
752 if (status != 0) 755 if (sent != 0)
753 continue; 756 continue;
754 status = -EAGAIN; 757 status = -EAGAIN;
755 break; 758 break;