diff options
author | Claudio Imbrenda <imbrenda@linux.vnet.ibm.com> | 2016-03-22 12:05:51 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-03-22 16:18:41 -0400 |
commit | 6f57e56a1527d58264ae126eff94fdac067744fc (patch) | |
tree | bc5604c18b8e1ea7f9e68c9d22a39d538acf3402 | |
parent | 9a0384c020b055a555500906be8ac314c92f3998 (diff) |
Revert "vsock: Fix blocking ops call in prepare_to_wait"
This reverts commit 5988818008257ca42010d6b43a3e0e48afec9898 ("vsock: Fix
blocking ops call in prepare_to_wait")
The commit reverted with this patch caused us to potentially miss wakeups.
Since the condition is not checked between the prepare_to_wait and the
schedule(), if a wakeup happens after the condition is checked but before
the sleep happens, we will miss it. ( A description of the problem can be
found here: http://www.makelinux.net/ldd3/chp-6-sect-2 ).
By reverting the patch, the behaviour is still incorrect (since we
shouldn't sleep between the prepare_to_wait and the schedule) but at least
it will not miss wakeups.
The next patch in the series actually fixes the behaviour.
Signed-off-by: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/vmw_vsock/af_vsock.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index bbe65dcb9738..7fd1220fbfa0 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c | |||
@@ -1557,6 +1557,8 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1557 | if (err < 0) | 1557 | if (err < 0) |
1558 | goto out; | 1558 | goto out; |
1559 | 1559 | ||
1560 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
1561 | |||
1560 | while (total_written < len) { | 1562 | while (total_written < len) { |
1561 | ssize_t written; | 1563 | ssize_t written; |
1562 | 1564 | ||
@@ -1576,9 +1578,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1576 | goto out_wait; | 1578 | goto out_wait; |
1577 | 1579 | ||
1578 | release_sock(sk); | 1580 | release_sock(sk); |
1579 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
1580 | timeout = schedule_timeout(timeout); | 1581 | timeout = schedule_timeout(timeout); |
1581 | finish_wait(sk_sleep(sk), &wait); | ||
1582 | lock_sock(sk); | 1582 | lock_sock(sk); |
1583 | if (signal_pending(current)) { | 1583 | if (signal_pending(current)) { |
1584 | err = sock_intr_errno(timeout); | 1584 | err = sock_intr_errno(timeout); |
@@ -1588,6 +1588,8 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1588 | goto out_wait; | 1588 | goto out_wait; |
1589 | } | 1589 | } |
1590 | 1590 | ||
1591 | prepare_to_wait(sk_sleep(sk), &wait, | ||
1592 | TASK_INTERRUPTIBLE); | ||
1591 | } | 1593 | } |
1592 | 1594 | ||
1593 | /* These checks occur both as part of and after the loop | 1595 | /* These checks occur both as part of and after the loop |
@@ -1633,6 +1635,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1633 | out_wait: | 1635 | out_wait: |
1634 | if (total_written > 0) | 1636 | if (total_written > 0) |
1635 | err = total_written; | 1637 | err = total_written; |
1638 | finish_wait(sk_sleep(sk), &wait); | ||
1636 | out: | 1639 | out: |
1637 | release_sock(sk); | 1640 | release_sock(sk); |
1638 | return err; | 1641 | return err; |
@@ -1713,6 +1716,7 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
1713 | if (err < 0) | 1716 | if (err < 0) |
1714 | goto out; | 1717 | goto out; |
1715 | 1718 | ||
1719 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
1716 | 1720 | ||
1717 | while (1) { | 1721 | while (1) { |
1718 | s64 ready = vsock_stream_has_data(vsk); | 1722 | s64 ready = vsock_stream_has_data(vsk); |
@@ -1723,7 +1727,7 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
1723 | */ | 1727 | */ |
1724 | 1728 | ||
1725 | err = -ENOMEM; | 1729 | err = -ENOMEM; |
1726 | goto out; | 1730 | goto out_wait; |
1727 | } else if (ready > 0) { | 1731 | } else if (ready > 0) { |
1728 | ssize_t read; | 1732 | ssize_t read; |
1729 | 1733 | ||
@@ -1746,7 +1750,7 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
1746 | vsk, target, read, | 1750 | vsk, target, read, |
1747 | !(flags & MSG_PEEK), &recv_data); | 1751 | !(flags & MSG_PEEK), &recv_data); |
1748 | if (err < 0) | 1752 | if (err < 0) |
1749 | goto out; | 1753 | goto out_wait; |
1750 | 1754 | ||
1751 | if (read >= target || flags & MSG_PEEK) | 1755 | if (read >= target || flags & MSG_PEEK) |
1752 | break; | 1756 | break; |
@@ -1769,9 +1773,7 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
1769 | break; | 1773 | break; |
1770 | 1774 | ||
1771 | release_sock(sk); | 1775 | release_sock(sk); |
1772 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
1773 | timeout = schedule_timeout(timeout); | 1776 | timeout = schedule_timeout(timeout); |
1774 | finish_wait(sk_sleep(sk), &wait); | ||
1775 | lock_sock(sk); | 1777 | lock_sock(sk); |
1776 | 1778 | ||
1777 | if (signal_pending(current)) { | 1779 | if (signal_pending(current)) { |
@@ -1781,6 +1783,9 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
1781 | err = -EAGAIN; | 1783 | err = -EAGAIN; |
1782 | break; | 1784 | break; |
1783 | } | 1785 | } |
1786 | |||
1787 | prepare_to_wait(sk_sleep(sk), &wait, | ||
1788 | TASK_INTERRUPTIBLE); | ||
1784 | } | 1789 | } |
1785 | } | 1790 | } |
1786 | 1791 | ||
@@ -1811,6 +1816,8 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
1811 | err = copied; | 1816 | err = copied; |
1812 | } | 1817 | } |
1813 | 1818 | ||
1819 | out_wait: | ||
1820 | finish_wait(sk_sleep(sk), &wait); | ||
1814 | out: | 1821 | out: |
1815 | release_sock(sk); | 1822 | release_sock(sk); |
1816 | return err; | 1823 | return err; |