diff options
author | WANG Cong <xiyou.wangcong@gmail.com> | 2017-05-19 14:21:59 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-05-22 14:39:36 -0400 |
commit | 499fde662f1957e3cb8d192a94a099ebe19c714b (patch) | |
tree | 657506549f0e9edf08189ae6171c7a2e966f7df4 | |
parent | 72ccc471e13b8266d2ee2104521df5b92ba08e9c (diff) |
vsock: use new wait API for vsock_stream_sendmsg()
As reported by Michal, vsock_stream_sendmsg() could still
sleep at vsock_stream_has_space() after prepare_to_wait():
vsock_stream_has_space
vmci_transport_stream_has_space
vmci_qpair_produce_free_space
qp_lock
qp_acquire_queue_mutex
mutex_lock
Just switch to the new wait API like we did for commit
d9dc8b0f8b4e ("net: fix sleeping for sk_wait_event()").
Reported-by: Michal Kubecek <mkubecek@suse.cz>
Cc: Stefan Hajnoczi <stefanha@redhat.com>
Cc: Jorgen Hansen <jhansen@vmware.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/vmw_vsock/af_vsock.c | 21 |
1 files changed, 8 insertions, 13 deletions
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index 6f7f6757ceef..dfc8c51e4d74 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c | |||
@@ -1540,8 +1540,7 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1540 | long timeout; | 1540 | long timeout; |
1541 | int err; | 1541 | int err; |
1542 | struct vsock_transport_send_notify_data send_data; | 1542 | struct vsock_transport_send_notify_data send_data; |
1543 | 1543 | DEFINE_WAIT_FUNC(wait, woken_wake_function); | |
1544 | DEFINE_WAIT(wait); | ||
1545 | 1544 | ||
1546 | sk = sock->sk; | 1545 | sk = sock->sk; |
1547 | vsk = vsock_sk(sk); | 1546 | vsk = vsock_sk(sk); |
@@ -1584,11 +1583,10 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1584 | if (err < 0) | 1583 | if (err < 0) |
1585 | goto out; | 1584 | goto out; |
1586 | 1585 | ||
1587 | |||
1588 | while (total_written < len) { | 1586 | while (total_written < len) { |
1589 | ssize_t written; | 1587 | ssize_t written; |
1590 | 1588 | ||
1591 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 1589 | add_wait_queue(sk_sleep(sk), &wait); |
1592 | while (vsock_stream_has_space(vsk) == 0 && | 1590 | while (vsock_stream_has_space(vsk) == 0 && |
1593 | sk->sk_err == 0 && | 1591 | sk->sk_err == 0 && |
1594 | !(sk->sk_shutdown & SEND_SHUTDOWN) && | 1592 | !(sk->sk_shutdown & SEND_SHUTDOWN) && |
@@ -1597,33 +1595,30 @@ static int vsock_stream_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1597 | /* Don't wait for non-blocking sockets. */ | 1595 | /* Don't wait for non-blocking sockets. */ |
1598 | if (timeout == 0) { | 1596 | if (timeout == 0) { |
1599 | err = -EAGAIN; | 1597 | err = -EAGAIN; |
1600 | finish_wait(sk_sleep(sk), &wait); | 1598 | remove_wait_queue(sk_sleep(sk), &wait); |
1601 | goto out_err; | 1599 | goto out_err; |
1602 | } | 1600 | } |
1603 | 1601 | ||
1604 | err = transport->notify_send_pre_block(vsk, &send_data); | 1602 | err = transport->notify_send_pre_block(vsk, &send_data); |
1605 | if (err < 0) { | 1603 | if (err < 0) { |
1606 | finish_wait(sk_sleep(sk), &wait); | 1604 | remove_wait_queue(sk_sleep(sk), &wait); |
1607 | goto out_err; | 1605 | goto out_err; |
1608 | } | 1606 | } |
1609 | 1607 | ||
1610 | release_sock(sk); | 1608 | release_sock(sk); |
1611 | timeout = schedule_timeout(timeout); | 1609 | timeout = wait_woken(&wait, TASK_INTERRUPTIBLE, timeout); |
1612 | lock_sock(sk); | 1610 | lock_sock(sk); |
1613 | if (signal_pending(current)) { | 1611 | if (signal_pending(current)) { |
1614 | err = sock_intr_errno(timeout); | 1612 | err = sock_intr_errno(timeout); |
1615 | finish_wait(sk_sleep(sk), &wait); | 1613 | remove_wait_queue(sk_sleep(sk), &wait); |
1616 | goto out_err; | 1614 | goto out_err; |
1617 | } else if (timeout == 0) { | 1615 | } else if (timeout == 0) { |
1618 | err = -EAGAIN; | 1616 | err = -EAGAIN; |
1619 | finish_wait(sk_sleep(sk), &wait); | 1617 | remove_wait_queue(sk_sleep(sk), &wait); |
1620 | goto out_err; | 1618 | goto out_err; |
1621 | } | 1619 | } |
1622 | |||
1623 | prepare_to_wait(sk_sleep(sk), &wait, | ||
1624 | TASK_INTERRUPTIBLE); | ||
1625 | } | 1620 | } |
1626 | finish_wait(sk_sleep(sk), &wait); | 1621 | remove_wait_queue(sk_sleep(sk), &wait); |
1627 | 1622 | ||
1628 | /* These checks occur both as part of and after the loop | 1623 | /* These checks occur both as part of and after the loop |
1629 | * conditional since we need to check before and after | 1624 | * conditional since we need to check before and after |