diff options
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/sched.c | 33 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 2 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 23 |
3 files changed, 39 insertions, 19 deletions
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 385f427bedad..ff50a0546865 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -293,11 +293,6 @@ static void rpc_make_runnable(struct rpc_task *task) | |||
293 | rpc_clear_queued(task); | 293 | rpc_clear_queued(task); |
294 | if (rpc_test_and_set_running(task)) | 294 | if (rpc_test_and_set_running(task)) |
295 | return; | 295 | return; |
296 | /* We might have raced */ | ||
297 | if (RPC_IS_QUEUED(task)) { | ||
298 | rpc_clear_running(task); | ||
299 | return; | ||
300 | } | ||
301 | if (RPC_IS_ASYNC(task)) { | 296 | if (RPC_IS_ASYNC(task)) { |
302 | int status; | 297 | int status; |
303 | 298 | ||
@@ -607,7 +602,9 @@ void rpc_release_calldata(const struct rpc_call_ops *ops, void *calldata) | |||
607 | */ | 602 | */ |
608 | static void __rpc_execute(struct rpc_task *task) | 603 | static void __rpc_execute(struct rpc_task *task) |
609 | { | 604 | { |
610 | int status = 0; | 605 | struct rpc_wait_queue *queue; |
606 | int task_is_async = RPC_IS_ASYNC(task); | ||
607 | int status = 0; | ||
611 | 608 | ||
612 | dprintk("RPC: %5u __rpc_execute flags=0x%x\n", | 609 | dprintk("RPC: %5u __rpc_execute flags=0x%x\n", |
613 | task->tk_pid, task->tk_flags); | 610 | task->tk_pid, task->tk_flags); |
@@ -647,15 +644,25 @@ static void __rpc_execute(struct rpc_task *task) | |||
647 | */ | 644 | */ |
648 | if (!RPC_IS_QUEUED(task)) | 645 | if (!RPC_IS_QUEUED(task)) |
649 | continue; | 646 | continue; |
650 | rpc_clear_running(task); | 647 | /* |
651 | if (RPC_IS_ASYNC(task)) { | 648 | * The queue->lock protects against races with |
652 | /* Careful! we may have raced... */ | 649 | * rpc_make_runnable(). |
653 | if (RPC_IS_QUEUED(task)) | 650 | * |
654 | return; | 651 | * Note that once we clear RPC_TASK_RUNNING on an asynchronous |
655 | if (rpc_test_and_set_running(task)) | 652 | * rpc_task, rpc_make_runnable() can assign it to a |
656 | return; | 653 | * different workqueue. We therefore cannot assume that the |
654 | * rpc_task pointer may still be dereferenced. | ||
655 | */ | ||
656 | queue = task->tk_waitqueue; | ||
657 | spin_lock_bh(&queue->lock); | ||
658 | if (!RPC_IS_QUEUED(task)) { | ||
659 | spin_unlock_bh(&queue->lock); | ||
657 | continue; | 660 | continue; |
658 | } | 661 | } |
662 | rpc_clear_running(task); | ||
663 | spin_unlock_bh(&queue->lock); | ||
664 | if (task_is_async) | ||
665 | return; | ||
659 | 666 | ||
660 | /* sync task: sleep here */ | 667 | /* sync task: sleep here */ |
661 | dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid); | 668 | dprintk("RPC: %5u sync task going to sleep\n", task->tk_pid); |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 29e401bb612e..62098d101a1f 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -663,7 +663,7 @@ void xprt_connect(struct rpc_task *task) | |||
663 | xprt, (xprt_connected(xprt) ? "is" : "is not")); | 663 | xprt, (xprt_connected(xprt) ? "is" : "is not")); |
664 | 664 | ||
665 | if (!xprt_bound(xprt)) { | 665 | if (!xprt_bound(xprt)) { |
666 | task->tk_status = -EIO; | 666 | task->tk_status = -EAGAIN; |
667 | return; | 667 | return; |
668 | } | 668 | } |
669 | if (!xprt_lock_write(xprt, task)) | 669 | if (!xprt_lock_write(xprt, task)) |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index b49e434c094f..568330eebbfe 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -467,7 +467,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, | |||
467 | int err, sent = 0; | 467 | int err, sent = 0; |
468 | 468 | ||
469 | if (unlikely(!sock)) | 469 | if (unlikely(!sock)) |
470 | return -ENOTCONN; | 470 | return -ENOTSOCK; |
471 | 471 | ||
472 | clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags); | 472 | clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags); |
473 | if (base != 0) { | 473 | if (base != 0) { |
@@ -577,6 +577,8 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
577 | req->rq_svec->iov_base, | 577 | req->rq_svec->iov_base, |
578 | req->rq_svec->iov_len); | 578 | req->rq_svec->iov_len); |
579 | 579 | ||
580 | if (!xprt_bound(xprt)) | ||
581 | return -ENOTCONN; | ||
580 | status = xs_sendpages(transport->sock, | 582 | status = xs_sendpages(transport->sock, |
581 | xs_addr(xprt), | 583 | xs_addr(xprt), |
582 | xprt->addrlen, xdr, | 584 | xprt->addrlen, xdr, |
@@ -594,6 +596,10 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
594 | } | 596 | } |
595 | 597 | ||
596 | switch (status) { | 598 | switch (status) { |
599 | case -ENOTSOCK: | ||
600 | status = -ENOTCONN; | ||
601 | /* Should we call xs_close() here? */ | ||
602 | break; | ||
597 | case -EAGAIN: | 603 | case -EAGAIN: |
598 | xs_nospace(task); | 604 | xs_nospace(task); |
599 | break; | 605 | break; |
@@ -693,6 +699,10 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
693 | } | 699 | } |
694 | 700 | ||
695 | switch (status) { | 701 | switch (status) { |
702 | case -ENOTSOCK: | ||
703 | status = -ENOTCONN; | ||
704 | /* Should we call xs_close() here? */ | ||
705 | break; | ||
696 | case -EAGAIN: | 706 | case -EAGAIN: |
697 | xs_nospace(task); | 707 | xs_nospace(task); |
698 | break; | 708 | break; |
@@ -1512,7 +1522,7 @@ static void xs_udp_connect_worker4(struct work_struct *work) | |||
1512 | struct socket *sock = transport->sock; | 1522 | struct socket *sock = transport->sock; |
1513 | int err, status = -EIO; | 1523 | int err, status = -EIO; |
1514 | 1524 | ||
1515 | if (xprt->shutdown || !xprt_bound(xprt)) | 1525 | if (xprt->shutdown) |
1516 | goto out; | 1526 | goto out; |
1517 | 1527 | ||
1518 | /* Start by resetting any existing state */ | 1528 | /* Start by resetting any existing state */ |
@@ -1553,7 +1563,7 @@ static void xs_udp_connect_worker6(struct work_struct *work) | |||
1553 | struct socket *sock = transport->sock; | 1563 | struct socket *sock = transport->sock; |
1554 | int err, status = -EIO; | 1564 | int err, status = -EIO; |
1555 | 1565 | ||
1556 | if (xprt->shutdown || !xprt_bound(xprt)) | 1566 | if (xprt->shutdown) |
1557 | goto out; | 1567 | goto out; |
1558 | 1568 | ||
1559 | /* Start by resetting any existing state */ | 1569 | /* Start by resetting any existing state */ |
@@ -1637,6 +1647,9 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
1637 | write_unlock_bh(&sk->sk_callback_lock); | 1647 | write_unlock_bh(&sk->sk_callback_lock); |
1638 | } | 1648 | } |
1639 | 1649 | ||
1650 | if (!xprt_bound(xprt)) | ||
1651 | return -ENOTCONN; | ||
1652 | |||
1640 | /* Tell the socket layer to start connecting... */ | 1653 | /* Tell the socket layer to start connecting... */ |
1641 | xprt->stat.connect_count++; | 1654 | xprt->stat.connect_count++; |
1642 | xprt->stat.connect_start = jiffies; | 1655 | xprt->stat.connect_start = jiffies; |
@@ -1657,7 +1670,7 @@ static void xs_tcp_connect_worker4(struct work_struct *work) | |||
1657 | struct socket *sock = transport->sock; | 1670 | struct socket *sock = transport->sock; |
1658 | int err, status = -EIO; | 1671 | int err, status = -EIO; |
1659 | 1672 | ||
1660 | if (xprt->shutdown || !xprt_bound(xprt)) | 1673 | if (xprt->shutdown) |
1661 | goto out; | 1674 | goto out; |
1662 | 1675 | ||
1663 | if (!sock) { | 1676 | if (!sock) { |
@@ -1717,7 +1730,7 @@ static void xs_tcp_connect_worker6(struct work_struct *work) | |||
1717 | struct socket *sock = transport->sock; | 1730 | struct socket *sock = transport->sock; |
1718 | int err, status = -EIO; | 1731 | int err, status = -EIO; |
1719 | 1732 | ||
1720 | if (xprt->shutdown || !xprt_bound(xprt)) | 1733 | if (xprt->shutdown) |
1721 | goto out; | 1734 | goto out; |
1722 | 1735 | ||
1723 | if (!sock) { | 1736 | if (!sock) { |