diff options
author | Claudio Imbrenda <imbrenda@linux.vnet.ibm.com> | 2016-03-22 12:05:52 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-03-22 16:18:41 -0400 |
commit | f7f9b5e7f8eccfd68ffa7b8d74b07c478bb9e7f0 (patch) | |
tree | 8ca3e07cbeae365ba4d5d359e5931261ed0151e4 | |
parent | 6f57e56a1527d58264ae126eff94fdac067744fc (diff) |
AF_VSOCK: Shrink the area influenced by prepare_to_wait
When a thread is prepared for waiting by calling prepare_to_wait, sleeping
is not allowed until either the wait has taken place or finish_wait has
been called. The existing code in af_vsock imposed unnecessary no-sleep
assumptions to a broad list of backend functions.
This patch shrinks the influence of prepare_to_wait to the area where it
is strictly needed, therefore relaxing the no-sleep restriction there.
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 | 158 |
1 files changed, 85 insertions, 73 deletions
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 7fd1220fbfa0..3dce53ebea92 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c | |||
@@ -1209,10 +1209,14 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr, | |||
1209 | 1209 | ||
1210 | if (signal_pending(current)) { | 1210 | if (signal_pending(current)) { |
1211 | err = sock_intr_errno(timeout); | 1211 | err = sock_intr_errno(timeout); |
1212 | goto out_wait_error; | 1212 | sk->sk_state = SS_UNCONNECTED; |
1213 | sock->state = SS_UNCONNECTED; | ||
1214 | goto out_wait; | ||
1213 | } else if (timeout == 0) { | 1215 | } else if (timeout == 0) { |
1214 | err = -ETIMEDOUT; | 1216 | err = -ETIMEDOUT; |
1215 | goto out_wait_error; | 1217 | sk->sk_state = SS_UNCONNECTED; |
1218 | sock->state = SS_UNCONNECTED; | ||
1219 | goto out_wait; | ||
1216 | } | 1220 | } |
1217 | 1221 | ||
1218 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 1222 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
@@ -1220,20 +1224,17 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr, | |||
1220 | 1224 | ||
1221 | if (sk->sk_err) { | 1225 | if (sk->sk_err) { |
1222 | err = -sk->sk_err; | 1226 | err = -sk->sk_err; |
1223 | goto out_wait_error; | 1227 | sk->sk_state = SS_UNCONNECTED; |
1224 | } else | 1228 | sock->state = SS_UNCONNECTED; |
1229 | } else { | ||
1225 | err = 0; | 1230 | err = 0; |
1231 | } | ||
1226 | 1232 | ||
1227 | out_wait: | 1233 | out_wait: |
1228 | finish_wait(sk_sleep(sk), &wait); | 1234 | finish_wait(sk_sleep(sk), &wait); |
1229 | out: | 1235 | out: |
1230 | release_sock(sk); | 1236 | release_sock(sk); |
1231 | return err; | 1237 | return err; |
1232 | |||
1233 | out_wait_error: | ||
1234 | sk->sk_state = SS_UNCONNECTED; | ||
1235 | sock->state = SS_UNCONNECTED; | ||
1236 | goto out_wait; | ||
1237 | } | 1238 | } |
1238 | 1239 | ||
1239 | static int vsock_accept(struct socket *sock, struct socket *newsock, int flags) | 1240 | static int vsock_accept(struct socket *sock, struct socket *newsock, int flags) |
@@ -1270,18 +1271,20 @@ static int vsock_accept(struct socket *sock, struct socket *newsock, int flags) | |||
1270 | listener->sk_err == 0) { | 1271 | listener->sk_err == 0) { |
1271 | release_sock(listener); | 1272 | release_sock(listener); |
1272 | timeout = schedule_timeout(timeout); | 1273 | timeout = schedule_timeout(timeout); |
1274 | finish_wait(sk_sleep(listener), &wait); | ||
1273 | lock_sock(listener); | 1275 | lock_sock(listener); |
1274 | 1276 | ||
1275 | if (signal_pending(current)) { | 1277 | if (signal_pending(current)) { |
1276 | err = sock_intr_errno(timeout); | 1278 | err = sock_intr_errno(timeout); |
1277 | goto out_wait; | 1279 | goto out; |
1278 | } else if (timeout == 0) { | 1280 | } else if (timeout == 0) { |
1279 | err = -EAGAIN; | 1281 | err = -EAGAIN; |
1280 | goto out_wait; | 1282 | goto out; |
1281 | } | 1283 | } |
1282 | 1284 | ||
1283 | prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE); | 1285 | prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE); |
1284 | } | 1286 | } |
1287 | finish_wait(sk_sleep(listener), &wait); | ||
1285 | 1288 | ||
1286 | if (listener->sk_err) | 1289 | if (listener->sk_err) |
1287 | err = -listener->sk_err; | 1290 | err = -listener->sk_err; |
@@ -1301,19 +1304,15 @@ static int vsock_accept(struct socket *sock, struct socket *newsock, int flags) | |||
1301 | */ | 1304 | */ |
1302 | if (err) { | 1305 | if (err) { |
1303 | vconnected->rejected = true; | 1306 | vconnected->rejected = true; |
1304 | release_sock(connected); | 1307 | } else { |
1305 | sock_put(connected); | 1308 | newsock->state = SS_CONNECTED; |
1306 | goto out_wait; | 1309 | sock_graft(connected, newsock); |
1307 | } | 1310 | } |
1308 | 1311 | ||
1309 | newsock->state = SS_CONNECTED; | ||
1310 | sock_graft(connected, newsock); | ||
1311 | release_sock(connected); | 1312 | release_sock(connected); |
1312 | sock_put(connected); | 1313 | sock_put(connected); |
1313 | } | 1314 | } |
1314 | 1315 | ||
1315 | out_wait: | ||
1316 | finish_wait(sk_sleep(listener), &wait); | ||
1317 | out: | 1316 | out: |
1318 | release_sock(listener); | 1317 | release_sock(listener); |
1319 | return err; | 1318 | return err; |
@@ -1557,11 +1556,11 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1557 | if (err < 0) | 1556 | if (err < 0) |
1558 | goto out; | 1557 | goto out; |
1559 | 1558 | ||
1560 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
1561 | 1559 | ||
1562 | while (total_written < len) { | 1560 | while (total_written < len) { |
1563 | ssize_t written; | 1561 | ssize_t written; |
1564 | 1562 | ||
1563 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
1565 | while (vsock_stream_has_space(vsk) == 0 && | 1564 | while (vsock_stream_has_space(vsk) == 0 && |
1566 | sk->sk_err == 0 && | 1565 | sk->sk_err == 0 && |
1567 | !(sk->sk_shutdown & SEND_SHUTDOWN) && | 1566 | !(sk->sk_shutdown & SEND_SHUTDOWN) && |
@@ -1570,27 +1569,33 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1570 | /* Don't wait for non-blocking sockets. */ | 1569 | /* Don't wait for non-blocking sockets. */ |
1571 | if (timeout == 0) { | 1570 | if (timeout == 0) { |
1572 | err = -EAGAIN; | 1571 | err = -EAGAIN; |
1573 | goto out_wait; | 1572 | finish_wait(sk_sleep(sk), &wait); |
1573 | goto out_err; | ||
1574 | } | 1574 | } |
1575 | 1575 | ||
1576 | err = transport->notify_send_pre_block(vsk, &send_data); | 1576 | err = transport->notify_send_pre_block(vsk, &send_data); |
1577 | if (err < 0) | 1577 | if (err < 0) { |
1578 | goto out_wait; | 1578 | finish_wait(sk_sleep(sk), &wait); |
1579 | goto out_err; | ||
1580 | } | ||
1579 | 1581 | ||
1580 | release_sock(sk); | 1582 | release_sock(sk); |
1581 | timeout = schedule_timeout(timeout); | 1583 | timeout = schedule_timeout(timeout); |
1582 | lock_sock(sk); | 1584 | lock_sock(sk); |
1583 | if (signal_pending(current)) { | 1585 | if (signal_pending(current)) { |
1584 | err = sock_intr_errno(timeout); | 1586 | err = sock_intr_errno(timeout); |
1585 | goto out_wait; | 1587 | finish_wait(sk_sleep(sk), &wait); |
1588 | goto out_err; | ||
1586 | } else if (timeout == 0) { | 1589 | } else if (timeout == 0) { |
1587 | err = -EAGAIN; | 1590 | err = -EAGAIN; |
1588 | goto out_wait; | 1591 | finish_wait(sk_sleep(sk), &wait); |
1592 | goto out_err; | ||
1589 | } | 1593 | } |
1590 | 1594 | ||
1591 | prepare_to_wait(sk_sleep(sk), &wait, | 1595 | prepare_to_wait(sk_sleep(sk), &wait, |
1592 | TASK_INTERRUPTIBLE); | 1596 | TASK_INTERRUPTIBLE); |
1593 | } | 1597 | } |
1598 | finish_wait(sk_sleep(sk), &wait); | ||
1594 | 1599 | ||
1595 | /* These checks occur both as part of and after the loop | 1600 | /* These checks occur both as part of and after the loop |
1596 | * conditional since we need to check before and after | 1601 | * conditional since we need to check before and after |
@@ -1598,16 +1603,16 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1598 | */ | 1603 | */ |
1599 | if (sk->sk_err) { | 1604 | if (sk->sk_err) { |
1600 | err = -sk->sk_err; | 1605 | err = -sk->sk_err; |
1601 | goto out_wait; | 1606 | goto out_err; |
1602 | } else if ((sk->sk_shutdown & SEND_SHUTDOWN) || | 1607 | } else if ((sk->sk_shutdown & SEND_SHUTDOWN) || |
1603 | (vsk->peer_shutdown & RCV_SHUTDOWN)) { | 1608 | (vsk->peer_shutdown & RCV_SHUTDOWN)) { |
1604 | err = -EPIPE; | 1609 | err = -EPIPE; |
1605 | goto out_wait; | 1610 | goto out_err; |
1606 | } | 1611 | } |
1607 | 1612 | ||
1608 | err = transport->notify_send_pre_enqueue(vsk, &send_data); | 1613 | err = transport->notify_send_pre_enqueue(vsk, &send_data); |
1609 | if (err < 0) | 1614 | if (err < 0) |
1610 | goto out_wait; | 1615 | goto out_err; |
1611 | 1616 | ||
1612 | /* Note that enqueue will only write as many bytes as are free | 1617 | /* Note that enqueue will only write as many bytes as are free |
1613 | * in the produce queue, so we don't need to ensure len is | 1618 | * in the produce queue, so we don't need to ensure len is |
@@ -1620,7 +1625,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1620 | len - total_written); | 1625 | len - total_written); |
1621 | if (written < 0) { | 1626 | if (written < 0) { |
1622 | err = -ENOMEM; | 1627 | err = -ENOMEM; |
1623 | goto out_wait; | 1628 | goto out_err; |
1624 | } | 1629 | } |
1625 | 1630 | ||
1626 | total_written += written; | 1631 | total_written += written; |
@@ -1628,14 +1633,13 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1628 | err = transport->notify_send_post_enqueue( | 1633 | err = transport->notify_send_post_enqueue( |
1629 | vsk, written, &send_data); | 1634 | vsk, written, &send_data); |
1630 | if (err < 0) | 1635 | if (err < 0) |
1631 | goto out_wait; | 1636 | goto out_err; |
1632 | 1637 | ||
1633 | } | 1638 | } |
1634 | 1639 | ||
1635 | out_wait: | 1640 | out_err: |
1636 | if (total_written > 0) | 1641 | if (total_written > 0) |
1637 | err = total_written; | 1642 | err = total_written; |
1638 | finish_wait(sk_sleep(sk), &wait); | ||
1639 | out: | 1643 | out: |
1640 | release_sock(sk); | 1644 | release_sock(sk); |
1641 | return err; | 1645 | return err; |
@@ -1716,21 +1720,61 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
1716 | if (err < 0) | 1720 | if (err < 0) |
1717 | goto out; | 1721 | goto out; |
1718 | 1722 | ||
1719 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
1720 | 1723 | ||
1721 | while (1) { | 1724 | while (1) { |
1722 | s64 ready = vsock_stream_has_data(vsk); | 1725 | s64 ready; |
1723 | 1726 | ||
1724 | if (ready < 0) { | 1727 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1725 | /* Invalid queue pair content. XXX This should be | 1728 | ready = vsock_stream_has_data(vsk); |
1726 | * changed to a connection reset in a later change. | ||
1727 | */ | ||
1728 | 1729 | ||
1729 | err = -ENOMEM; | 1730 | if (ready == 0) { |
1730 | goto out_wait; | 1731 | if (sk->sk_err != 0 || |
1731 | } else if (ready > 0) { | 1732 | (sk->sk_shutdown & RCV_SHUTDOWN) || |
1733 | (vsk->peer_shutdown & SEND_SHUTDOWN)) { | ||
1734 | finish_wait(sk_sleep(sk), &wait); | ||
1735 | break; | ||
1736 | } | ||
1737 | /* Don't wait for non-blocking sockets. */ | ||
1738 | if (timeout == 0) { | ||
1739 | err = -EAGAIN; | ||
1740 | finish_wait(sk_sleep(sk), &wait); | ||
1741 | break; | ||
1742 | } | ||
1743 | |||
1744 | err = transport->notify_recv_pre_block( | ||
1745 | vsk, target, &recv_data); | ||
1746 | if (err < 0) { | ||
1747 | finish_wait(sk_sleep(sk), &wait); | ||
1748 | break; | ||
1749 | } | ||
1750 | release_sock(sk); | ||
1751 | timeout = schedule_timeout(timeout); | ||
1752 | lock_sock(sk); | ||
1753 | |||
1754 | if (signal_pending(current)) { | ||
1755 | err = sock_intr_errno(timeout); | ||
1756 | finish_wait(sk_sleep(sk), &wait); | ||
1757 | break; | ||
1758 | } else if (timeout == 0) { | ||
1759 | err = -EAGAIN; | ||
1760 | finish_wait(sk_sleep(sk), &wait); | ||
1761 | break; | ||
1762 | } | ||
1763 | } else { | ||
1732 | ssize_t read; | 1764 | ssize_t read; |
1733 | 1765 | ||
1766 | finish_wait(sk_sleep(sk), &wait); | ||
1767 | |||
1768 | if (ready < 0) { | ||
1769 | /* Invalid queue pair content. XXX This should | ||
1770 | * be changed to a connection reset in a later | ||
1771 | * change. | ||
1772 | */ | ||
1773 | |||
1774 | err = -ENOMEM; | ||
1775 | goto out; | ||
1776 | } | ||
1777 | |||
1734 | err = transport->notify_recv_pre_dequeue( | 1778 | err = transport->notify_recv_pre_dequeue( |
1735 | vsk, target, &recv_data); | 1779 | vsk, target, &recv_data); |
1736 | if (err < 0) | 1780 | if (err < 0) |
@@ -1750,42 +1794,12 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
1750 | vsk, target, read, | 1794 | vsk, target, read, |
1751 | !(flags & MSG_PEEK), &recv_data); | 1795 | !(flags & MSG_PEEK), &recv_data); |
1752 | if (err < 0) | 1796 | if (err < 0) |
1753 | goto out_wait; | 1797 | goto out; |
1754 | 1798 | ||
1755 | if (read >= target || flags & MSG_PEEK) | 1799 | if (read >= target || flags & MSG_PEEK) |
1756 | break; | 1800 | break; |
1757 | 1801 | ||
1758 | target -= read; | 1802 | target -= read; |
1759 | } else { | ||
1760 | if (sk->sk_err != 0 || (sk->sk_shutdown & RCV_SHUTDOWN) | ||
1761 | || (vsk->peer_shutdown & SEND_SHUTDOWN)) { | ||
1762 | break; | ||
1763 | } | ||
1764 | /* Don't wait for non-blocking sockets. */ | ||
1765 | if (timeout == 0) { | ||
1766 | err = -EAGAIN; | ||
1767 | break; | ||
1768 | } | ||
1769 | |||
1770 | err = transport->notify_recv_pre_block( | ||
1771 | vsk, target, &recv_data); | ||
1772 | if (err < 0) | ||
1773 | break; | ||
1774 | |||
1775 | release_sock(sk); | ||
1776 | timeout = schedule_timeout(timeout); | ||
1777 | lock_sock(sk); | ||
1778 | |||
1779 | if (signal_pending(current)) { | ||
1780 | err = sock_intr_errno(timeout); | ||
1781 | break; | ||
1782 | } else if (timeout == 0) { | ||
1783 | err = -EAGAIN; | ||
1784 | break; | ||
1785 | } | ||
1786 | |||
1787 | prepare_to_wait(sk_sleep(sk), &wait, | ||
1788 | TASK_INTERRUPTIBLE); | ||
1789 | } | 1803 | } |
1790 | } | 1804 | } |
1791 | 1805 | ||
@@ -1816,8 +1830,6 @@ vsock_stream_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, | |||
1816 | err = copied; | 1830 | err = copied; |
1817 | } | 1831 | } |
1818 | 1832 | ||
1819 | out_wait: | ||
1820 | finish_wait(sk_sleep(sk), &wait); | ||
1821 | out: | 1833 | out: |
1822 | release_sock(sk); | 1834 | release_sock(sk); |
1823 | return err; | 1835 | return err; |