Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Claudio Imbrenda and committed by
David S. Miller
f7f9b5e7 6f57e56a

+85 -73
+85 -73
net/vmw_vsock/af_vsock.c
··· 1209 1209 1210 1210 if (signal_pending(current)) { 1211 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 1215 } else if (timeout == 0) { 1214 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 1222 prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); ··· 1224 1220 1225 1221 if (sk->sk_err) { 1226 1222 err = -sk->sk_err; 1227 - goto out_wait_error; 1228 - } else 1223 + sk->sk_state = SS_UNCONNECTED; 1224 + sock->state = SS_UNCONNECTED; 1225 + } else { 1229 1226 err = 0; 1227 + } 1230 1228 1231 1229 out_wait: 1232 1230 finish_wait(sk_sleep(sk), &wait); 1233 1231 out: 1234 1232 release_sock(sk); 1235 1233 return err; 1236 - 1237 - out_wait_error: 1238 - sk->sk_state = SS_UNCONNECTED; 1239 - sock->state = SS_UNCONNECTED; 1240 - goto out_wait; 1241 1234 } 1242 1235 1243 1236 static int vsock_accept(struct socket *sock, struct socket *newsock, int flags) ··· 1271 1270 listener->sk_err == 0) { 1272 1271 release_sock(listener); 1273 1272 timeout = schedule_timeout(timeout); 1273 + finish_wait(sk_sleep(listener), &wait); 1274 1274 lock_sock(listener); 1275 1275 1276 1276 if (signal_pending(current)) { 1277 1277 err = sock_intr_errno(timeout); 1278 - goto out_wait; 1278 + goto out; 1279 1279 } else if (timeout == 0) { 1280 1280 err = -EAGAIN; 1281 - goto out_wait; 1281 + goto out; 1282 1282 } 1283 1283 1284 1284 prepare_to_wait(sk_sleep(listener), &wait, TASK_INTERRUPTIBLE); 1285 1285 } 1286 + finish_wait(sk_sleep(listener), &wait); 1286 1287 1287 1288 if (listener->sk_err) 1288 1289 err = -listener->sk_err; ··· 1304 1301 */ 1305 1302 if (err) { 1306 1303 vconnected->rejected = true; 1307 - release_sock(connected); 1308 - sock_put(connected); 1309 - goto out_wait; 1304 + } else { 1305 + newsock->state = SS_CONNECTED; 1306 + sock_graft(connected, newsock); 1310 1307 } 1311 1308 1312 - newsock->state = SS_CONNECTED; 1313 - sock_graft(connected, newsock); 1314 1309 release_sock(connected); 1315 1310 sock_put(connected); 1316 1311 } 1317 1312 1318 - out_wait: 1319 - finish_wait(sk_sleep(listener), &wait); 1320 1313 out: 1321 1314 release_sock(listener); 1322 1315 return err; ··· 1556 1557 if (err < 0) 1557 1558 goto out; 1558 1559 1559 - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 1560 1560 1561 1561 while (total_written < len) { 1562 1562 ssize_t written; 1563 1563 1564 + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 1564 1565 while (vsock_stream_has_space(vsk) == 0 && 1565 1566 sk->sk_err == 0 && 1566 1567 !(sk->sk_shutdown & SEND_SHUTDOWN) && ··· 1569 1570 /* Don't wait for non-blocking sockets. */ 1570 1571 if (timeout == 0) { 1571 1572 err = -EAGAIN; 1572 - goto out_wait; 1573 + finish_wait(sk_sleep(sk), &wait); 1574 + goto out_err; 1573 1575 } 1574 1576 1575 1577 err = transport->notify_send_pre_block(vsk, &send_data); 1576 - if (err < 0) 1577 - goto out_wait; 1578 + if (err < 0) { 1579 + finish_wait(sk_sleep(sk), &wait); 1580 + goto out_err; 1581 + } 1578 1582 1579 1583 release_sock(sk); 1580 1584 timeout = schedule_timeout(timeout); 1581 1585 lock_sock(sk); 1582 1586 if (signal_pending(current)) { 1583 1587 err = sock_intr_errno(timeout); 1584 - goto out_wait; 1588 + finish_wait(sk_sleep(sk), &wait); 1589 + goto out_err; 1585 1590 } else if (timeout == 0) { 1586 1591 err = -EAGAIN; 1587 - goto out_wait; 1592 + finish_wait(sk_sleep(sk), &wait); 1593 + goto out_err; 1588 1594 } 1589 1595 1590 1596 prepare_to_wait(sk_sleep(sk), &wait, 1591 1597 TASK_INTERRUPTIBLE); 1592 1598 } 1599 + finish_wait(sk_sleep(sk), &wait); 1593 1600 1594 1601 /* These checks occur both as part of and after the loop 1595 1602 * conditional since we need to check before and after ··· 1603 1598 */ 1604 1599 if (sk->sk_err) { 1605 1600 err = -sk->sk_err; 1606 - goto out_wait; 1601 + goto out_err; 1607 1602 } else if ((sk->sk_shutdown & SEND_SHUTDOWN) || 1608 1603 (vsk->peer_shutdown & RCV_SHUTDOWN)) { 1609 1604 err = -EPIPE; 1610 - goto out_wait; 1605 + goto out_err; 1611 1606 } 1612 1607 1613 1608 err = transport->notify_send_pre_enqueue(vsk, &send_data); 1614 1609 if (err < 0) 1615 - goto out_wait; 1610 + goto out_err; 1616 1611 1617 1612 /* Note that enqueue will only write as many bytes as are free 1618 1613 * in the produce queue, so we don't need to ensure len is ··· 1625 1620 len - total_written); 1626 1621 if (written < 0) { 1627 1622 err = -ENOMEM; 1628 - goto out_wait; 1623 + goto out_err; 1629 1624 } 1630 1625 1631 1626 total_written += written; ··· 1633 1628 err = transport->notify_send_post_enqueue( 1634 1629 vsk, written, &send_data); 1635 1630 if (err < 0) 1636 - goto out_wait; 1631 + goto out_err; 1637 1632 1638 1633 } 1639 1634 1640 - out_wait: 1635 + out_err: 1641 1636 if (total_written > 0) 1642 1637 err = total_written; 1643 - finish_wait(sk_sleep(sk), &wait); 1644 1638 out: 1645 1639 release_sock(sk); 1646 1640 return err; ··· 1720 1716 if (err < 0) 1721 1717 goto out; 1722 1718 1723 - prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 1724 1719 1725 1720 while (1) { 1726 - s64 ready = vsock_stream_has_data(vsk); 1721 + s64 ready; 1727 1722 1728 - if (ready < 0) { 1729 - /* Invalid queue pair content. XXX This should be 1730 - * changed to a connection reset in a later change. 1731 - */ 1723 + prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); 1724 + ready = vsock_stream_has_data(vsk); 1732 1725 1733 - err = -ENOMEM; 1734 - goto out_wait; 1735 - } else if (ready > 0) { 1726 + if (ready == 0) { 1727 + if (sk->sk_err != 0 || 1728 + (sk->sk_shutdown & RCV_SHUTDOWN) || 1729 + (vsk->peer_shutdown & SEND_SHUTDOWN)) { 1730 + finish_wait(sk_sleep(sk), &wait); 1731 + break; 1732 + } 1733 + /* Don't wait for non-blocking sockets. */ 1734 + if (timeout == 0) { 1735 + err = -EAGAIN; 1736 + finish_wait(sk_sleep(sk), &wait); 1737 + break; 1738 + } 1739 + 1740 + err = transport->notify_recv_pre_block( 1741 + vsk, target, &recv_data); 1742 + if (err < 0) { 1743 + finish_wait(sk_sleep(sk), &wait); 1744 + break; 1745 + } 1746 + release_sock(sk); 1747 + timeout = schedule_timeout(timeout); 1748 + lock_sock(sk); 1749 + 1750 + if (signal_pending(current)) { 1751 + err = sock_intr_errno(timeout); 1752 + finish_wait(sk_sleep(sk), &wait); 1753 + break; 1754 + } else if (timeout == 0) { 1755 + err = -EAGAIN; 1756 + finish_wait(sk_sleep(sk), &wait); 1757 + break; 1758 + } 1759 + } else { 1736 1760 ssize_t read; 1761 + 1762 + finish_wait(sk_sleep(sk), &wait); 1763 + 1764 + if (ready < 0) { 1765 + /* Invalid queue pair content. XXX This should 1766 + * be changed to a connection reset in a later 1767 + * change. 1768 + */ 1769 + 1770 + err = -ENOMEM; 1771 + goto out; 1772 + } 1737 1773 1738 1774 err = transport->notify_recv_pre_dequeue( 1739 1775 vsk, target, &recv_data); ··· 1794 1750 vsk, target, read, 1795 1751 !(flags & MSG_PEEK), &recv_data); 1796 1752 if (err < 0) 1797 - goto out_wait; 1753 + goto out; 1798 1754 1799 1755 if (read >= target || flags & MSG_PEEK) 1800 1756 break; 1801 1757 1802 1758 target -= read; 1803 - } else { 1804 - if (sk->sk_err != 0 || (sk->sk_shutdown & RCV_SHUTDOWN) 1805 - || (vsk->peer_shutdown & SEND_SHUTDOWN)) { 1806 - break; 1807 - } 1808 - /* Don't wait for non-blocking sockets. */ 1809 - if (timeout == 0) { 1810 - err = -EAGAIN; 1811 - break; 1812 - } 1813 - 1814 - err = transport->notify_recv_pre_block( 1815 - vsk, target, &recv_data); 1816 - if (err < 0) 1817 - break; 1818 - 1819 - release_sock(sk); 1820 - timeout = schedule_timeout(timeout); 1821 - lock_sock(sk); 1822 - 1823 - if (signal_pending(current)) { 1824 - err = sock_intr_errno(timeout); 1825 - break; 1826 - } else if (timeout == 0) { 1827 - err = -EAGAIN; 1828 - break; 1829 - } 1830 - 1831 - prepare_to_wait(sk_sleep(sk), &wait, 1832 - TASK_INTERRUPTIBLE); 1833 1759 } 1834 1760 } 1835 1761 ··· 1830 1816 err = copied; 1831 1817 } 1832 1818 1833 - out_wait: 1834 - finish_wait(sk_sleep(sk), &wait); 1835 1819 out: 1836 1820 release_sock(sk); 1837 1821 return err;