linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jason Wang <jasowang@redhat.com>
To: mst@redhat.com, jasowang@redhat.com, kvm@vger.kernel.org,
	virtualization@lists.linux-foundation.org,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Tonghao Zhang <xiangxia.m.yue@gmail.com>
Subject: [PATCH net 2/4] vhost_net: rework on the lock ordering for busy polling
Date: Mon, 10 Dec 2018 17:44:52 +0800	[thread overview]
Message-ID: <20181210094454.21144-3-jasowang@redhat.com> (raw)
In-Reply-To: <20181210094454.21144-1-jasowang@redhat.com>

When we try to do rx busy polling in tx path in commit 441abde4cd84
("net: vhost: add rx busy polling in tx path"), we lock rx vq mutex
after tx vq mutex is held. This may lead deadlock so we try to lock vq
one by one in commit 78139c94dc8c ("net: vhost: lock the vqs one by
one"). With this commit, we avoid the deadlock with the assumption
that handle_rx() and handle_tx() run in a same process. But this
commit remove the protection for IOTLB updating which requires the
mutex of each vq to be held.

To solve this issue, the first step is to have a exact same lock
ordering for vhost_net. This is done through:

- For handle_rx(), if busy polling is enabled, lock tx vq immediately.
- For handle_tx(), always lock rx vq before tx vq, and unlock it if
  busy polling is not enabled.
- Remove the tricky locking codes in busy polling.

With this, we can have a exact same lock ordering for vhost_net, this
allows us to safely revert commit 78139c94dc8c ("net: vhost: lock the
vqs one by one") in next patch.

The patch will add two more atomic operations on the tx path during
each round of handle_tx(). 1 byte TCP_RR does not notice such
overhead.

Fixes: commit 78139c94dc8c ("net: vhost: lock the vqs one by one")
Cc: Tonghao Zhang <xiangxia.m.yue@gmail.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
 drivers/vhost/net.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index ab11b2bee273..5f272ab4d5b4 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -513,7 +513,6 @@ static void vhost_net_busy_poll(struct vhost_net *net,
 	struct socket *sock;
 	struct vhost_virtqueue *vq = poll_rx ? tvq : rvq;
 
-	mutex_lock_nested(&vq->mutex, poll_rx ? VHOST_NET_VQ_TX: VHOST_NET_VQ_RX);
 	vhost_disable_notify(&net->dev, vq);
 	sock = rvq->private_data;
 
@@ -543,8 +542,6 @@ static void vhost_net_busy_poll(struct vhost_net *net,
 		vhost_net_busy_poll_try_queue(net, vq);
 	else if (!poll_rx) /* On tx here, sock has no rx data. */
 		vhost_enable_notify(&net->dev, rvq);
-
-	mutex_unlock(&vq->mutex);
 }
 
 static int vhost_net_tx_get_vq_desc(struct vhost_net *net,
@@ -913,10 +910,16 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock)
 static void handle_tx(struct vhost_net *net)
 {
 	struct vhost_net_virtqueue *nvq = &net->vqs[VHOST_NET_VQ_TX];
+	struct vhost_net_virtqueue *nvq_rx = &net->vqs[VHOST_NET_VQ_RX];
 	struct vhost_virtqueue *vq = &nvq->vq;
+	struct vhost_virtqueue *vq_rx = &nvq_rx->vq;
 	struct socket *sock;
 
+	mutex_lock_nested(&vq_rx->mutex, VHOST_NET_VQ_RX);
 	mutex_lock_nested(&vq->mutex, VHOST_NET_VQ_TX);
+	if (!vq->busyloop_timeout)
+		mutex_unlock(&vq_rx->mutex);
+
 	sock = vq->private_data;
 	if (!sock)
 		goto out;
@@ -933,6 +936,8 @@ static void handle_tx(struct vhost_net *net)
 		handle_tx_copy(net, sock);
 
 out:
+	if (vq->busyloop_timeout)
+		mutex_unlock(&vq_rx->mutex);
 	mutex_unlock(&vq->mutex);
 }
 
@@ -1060,7 +1065,9 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
 static void handle_rx(struct vhost_net *net)
 {
 	struct vhost_net_virtqueue *nvq = &net->vqs[VHOST_NET_VQ_RX];
+	struct vhost_net_virtqueue *nvq_tx = &net->vqs[VHOST_NET_VQ_TX];
 	struct vhost_virtqueue *vq = &nvq->vq;
+	struct vhost_virtqueue *vq_tx = &nvq_tx->vq;
 	unsigned uninitialized_var(in), log;
 	struct vhost_log *vq_log;
 	struct msghdr msg = {
@@ -1086,6 +1093,9 @@ static void handle_rx(struct vhost_net *net)
 	int recv_pkts = 0;
 
 	mutex_lock_nested(&vq->mutex, VHOST_NET_VQ_RX);
+	if (vq->busyloop_timeout)
+		mutex_lock_nested(&vq_tx->mutex, VHOST_NET_VQ_TX);
+
 	sock = vq->private_data;
 	if (!sock)
 		goto out;
@@ -1200,6 +1210,8 @@ static void handle_rx(struct vhost_net *net)
 out:
 	vhost_net_signal_used(nvq);
 	mutex_unlock(&vq->mutex);
+	if (vq->busyloop_timeout)
+		mutex_unlock(&vq_tx->mutex);
 }
 
 static void handle_tx_kick(struct vhost_work *work)
-- 
2.17.1


  parent reply	other threads:[~2018-12-10  9:45 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-10  9:44 [PATCH net 0/4] Fix various issue of vhost Jason Wang
2018-12-10  9:44 ` [PATCH net 1/4] vhost: make sure used idx is seen before log in vhost_add_used_n() Jason Wang
2018-12-10  9:44 ` Jason Wang [this message]
2018-12-11  1:34   ` [PATCH net 2/4] vhost_net: rework on the lock ordering for busy polling Michael S. Tsirkin
2018-12-11  3:06     ` Jason Wang
2018-12-11  4:04       ` Michael S. Tsirkin
2018-12-12  3:03         ` Jason Wang
2018-12-12  3:40           ` Michael S. Tsirkin
2018-12-10  9:44 ` [PATCH net 3/4] Revert "net: vhost: lock the vqs one by one" Jason Wang
2018-12-10  9:44 ` [PATCH net 4/4] vhost: log dirty page correctly Jason Wang
2018-12-10 15:14   ` kbuild test robot
2018-12-11  1:30     ` Michael S. Tsirkin
2018-12-19 17:29   ` kbuild test robot
2018-12-10 19:47 ` [PATCH net 0/4] Fix various issue of vhost David Miller
2018-12-11  3:01   ` Jason Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181210094454.21144-3-jasowang@redhat.com \
    --to=jasowang@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=virtualization@lists.linux-foundation.org \
    --cc=xiangxia.m.yue@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).