From: Marcelo Tosatti <mtosatti@redhat.com>
To: Avi Kivity <avi@qumranet.com>, Anthony Liguori <aliguori@us.ibm.com>
Cc: kvm-devel <kvm-devel@lists.sourceforge.net>
Subject: [patch 09/13] QEMU: network device locking
Date: Thu, 17 Apr 2008 17:10:30 -0300 [thread overview]
Message-ID: <20080417203026.834828995@localhost.localdomain> (raw)
In-Reply-To: 20080417201021.515148882@localhost.localdomain
[-- Attachment #1: qemu-net --]
[-- Type: text/plain, Size: 7360 bytes --]
Grab device locks when moving data through network devices in the host->guest
direction.
Index: kvm-userspace.io/qemu/hw/e1000.c
===================================================================
--- kvm-userspace.io.orig/qemu/hw/e1000.c
+++ kvm-userspace.io/qemu/hw/e1000.c
@@ -1008,6 +1008,7 @@ pci_e1000_init(PCIBus *bus, NICInfo *nd,
d->vc = qemu_new_vlan_client(nd->vlan, e1000_receive,
e1000_can_receive, d);
+ d->vc->qemu_dev = &d->dev.qemu_dev;
snprintf(d->vc->info_str, sizeof(d->vc->info_str),
"%s macaddr=%02x:%02x:%02x:%02x:%02x:%02x", info_str,
Index: kvm-userspace.io/qemu/net.h
===================================================================
--- kvm-userspace.io.orig/qemu/net.h
+++ kvm-userspace.io/qemu/net.h
@@ -13,6 +13,7 @@ struct VLANClientState {
void *opaque;
struct VLANClientState *next;
struct VLANState *vlan;
+ QEMUDevice *qemu_dev;
char info_str[256];
};
Index: kvm-userspace.io/qemu/qemu-device.h
===================================================================
--- kvm-userspace.io.orig/qemu/qemu-device.h
+++ kvm-userspace.io/qemu/qemu-device.h
@@ -88,6 +88,8 @@ static inline void qemu_mutex_init(qemu_
#endif /* DEBUG_PTHREADS */
#endif /* _POSIX_THREADS */
+#define NOLOCK -1
+
struct QEMUDevice {
qemu_mutex_t lock;
};
Index: kvm-userspace.io/qemu/vl.c
===================================================================
--- kvm-userspace.io.orig/qemu/vl.c
+++ kvm-userspace.io/qemu/vl.c
@@ -3830,6 +3830,18 @@ VLANClientState *qemu_new_vlan_client(VL
return vc;
}
+void qemu_net_lock(VLANClientState *vc)
+{
+ if (vc->qemu_dev != NOLOCK)
+ qemu_mutex_lock(&vc->qemu_dev->lock);
+}
+
+void qemu_net_unlock(VLANClientState *vc)
+{
+ if (vc->qemu_dev != NOLOCK)
+ qemu_mutex_unlock(&vc->qemu_dev->lock);
+}
+
int qemu_can_send_packet(VLANClientState *vc1)
{
VLANState *vlan = vc1->vlan;
@@ -3855,7 +3867,9 @@ void qemu_send_packet(VLANClientState *v
#endif
for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
if (vc != vc1) {
+ qemu_net_lock(vc);
vc->fd_read(vc->opaque, buf, size);
+ qemu_net_unlock(vc);
}
}
}
@@ -4131,6 +4145,7 @@ static TAPState *net_tap_fd_init(VLANSta
s->no_poll = 0;
enable_sigio_timer(fd);
s->vc = qemu_new_vlan_client(vlan, tap_receive, NULL, s);
+ s->vc->qemu_dev = NOLOCK;
qemu_set_fd_handler2(s->fd, tap_read_poll, tap_send, NULL, s);
snprintf(s->vc->info_str, sizeof(s->vc->info_str), "tap: fd=%d", fd);
return s;
Index: kvm-userspace.io/qemu/hw/virtio-net.c
===================================================================
--- kvm-userspace.io.orig/qemu/hw/virtio-net.c
+++ kvm-userspace.io/qemu/hw/virtio-net.c
@@ -64,7 +64,6 @@ typedef struct VirtIONet
int can_receive;
int tap_fd;
struct VirtIONet *next;
- int do_notify;
QEMUTimer *tx_timer;
int tx_timer_active;
} VirtIONet;
@@ -113,6 +112,8 @@ static void virtio_net_receive(void *opa
struct virtio_net_hdr *hdr;
int offset, i;
+ assert_is_locked(&n->vdev.pci_dev.qemu_dev.lock);
+
/* FIXME: the drivers really need to set their status better */
if (n->rx_vq->vring.avail == NULL) {
n->can_receive = 0;
@@ -144,6 +145,18 @@ static void virtio_net_receive(void *opa
virtio_notify(&n->vdev, n->rx_vq);
}
+
+void virtio_net_lock(VirtIONet *vnet)
+{
+ qemu_mutex_lock(&vnet->vdev.pci_dev.qemu_dev.lock);
+}
+
+void virtio_net_unlock(VirtIONet *vnet)
+{
+ qemu_mutex_unlock(&vnet->vdev.pci_dev.qemu_dev.lock);
+}
+
+
/* -net tap receive handler */
void virtio_net_poll(void)
{
@@ -160,31 +173,39 @@ void virtio_net_poll(void)
tv.tv_sec = 0;
tv.tv_usec = 0;
- while (1) {
+ do {
+ did_notify = 0;
// Prepare the set of device to select from
for (vnet = VirtIONetHead; vnet; vnet = vnet->next) {
+ int ret;
if (vnet->tap_fd == -1)
continue;
- vnet->do_notify = 0;
+ virtio_net_lock(vnet);
//first check if the driver is ok
- if (!virtio_net_can_receive(vnet))
+ ret = virtio_net_can_receive(vnet);
+ if (!ret) {
+ virtio_net_unlock(vnet);
continue;
+ }
/* FIXME: the drivers really need to set their status better */
if (vnet->rx_vq->vring.avail == NULL) {
vnet->can_receive = 0;
+ virtio_net_unlock(vnet);
continue;
}
+ virtio_net_unlock(vnet);
+
FD_SET(vnet->tap_fd, &rfds);
if (max_fd < vnet->tap_fd) max_fd = vnet->tap_fd;
}
if (select(max_fd + 1, &rfds, NULL, NULL, &tv) <= 0)
- break;
+ return;
// Now check who has data pending in the tap
for (vnet = VirtIONetHead; vnet; vnet = vnet->next) {
@@ -192,14 +213,17 @@ void virtio_net_poll(void)
if (!FD_ISSET(vnet->tap_fd, &rfds))
continue;
+ virtio_net_lock(vnet);
if (virtqueue_pop(vnet->rx_vq, &elem) == 0) {
vnet->can_receive = 0;
+ virtio_net_unlock(vnet);
continue;
}
hdr = (void *)elem.in_sg[0].iov_base;
hdr->flags = 0;
hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
+ virtio_net_unlock(vnet);
again:
len = readv(vnet->tap_fd, &elem.in_sg[1], elem.in_num - 1);
if (len == -1) {
@@ -208,21 +232,13 @@ again:
else
fprintf(stderr, "reading network error %d", len);
}
+ did_notify = 1;
+ virtio_net_lock(vnet);
virtqueue_push(vnet->rx_vq, &elem, sizeof(*hdr) + len);
- vnet->do_notify = 1;
+ virtio_notify(&vnet->vdev, vnet->rx_vq);
+ virtio_net_unlock(vnet);
}
-
- /* signal other side */
- did_notify = 0;
- for (vnet = VirtIONetHead; vnet; vnet = vnet->next)
- if (vnet->do_notify) {
- virtio_notify(&vnet->vdev, vnet->rx_vq);
- did_notify++;
- }
- if (!did_notify)
- break;
- }
-
+ } while (did_notify);
}
/* TX */
@@ -231,6 +247,8 @@ static void virtio_net_flush_tx(VirtIONe
VirtQueueElement elem;
int count = 0;
+ assert_is_locked(&n->vdev.pci_dev.qemu_dev.lock);
+
if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
return;
@@ -280,8 +298,10 @@ static void virtio_net_tx_timer(void *op
if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
return;
+ virtio_net_lock(n);
n->tx_vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
virtio_net_flush_tx(n, n->tx_vq);
+ virtio_net_unlock(n);
}
PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
--
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference
Don't miss this year's exciting event. There's still time to save $100.
Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
next prev parent reply other threads:[~2008-04-17 20:10 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-04-17 20:10 [patch 00/13] RFC: split the global mutex Marcelo Tosatti
2008-04-17 20:10 ` [patch 01/13] QEMU: get rid of global cpu_single_env Marcelo Tosatti
2008-04-17 20:10 ` [patch 02/13] QEMU: introduce QEMUDevice Marcelo Tosatti
2008-04-17 20:10 ` [patch 03/13] QEMU: make esp.c build conditional to SPARC target Marcelo Tosatti
2008-04-17 20:10 ` [patch 04/13] QEMU: plug QEMUDevice pt1 / ioport awareness Marcelo Tosatti
2008-04-17 20:10 ` [patch 05/13] QEMU: add a mutex to protect IRQ chip data structures Marcelo Tosatti
2008-04-17 20:10 ` [patch 06/13] QEMU: plug QEMUDevice pt2 / iomem awareness Marcelo Tosatti
2008-04-17 20:10 ` [patch 07/13] QEMU: grab device lock for ioport/iomem processing Marcelo Tosatti
2008-04-17 20:10 ` [patch 08/13] QEMU: character device locking Marcelo Tosatti
2008-04-17 20:10 ` Marcelo Tosatti [this message]
2008-04-17 20:10 ` [patch 10/13] QEMU: get rid of aiocb cache Marcelo Tosatti
2008-04-17 20:10 ` [patch 11/13] QEMU: block device locking Marcelo Tosatti
2008-04-17 20:10 ` [patch 12/13] QEMU: scsi-disk reentrancy fix Marcelo Tosatti
2008-04-17 20:10 ` [patch 13/13] QEMU/KVM: get rid of global lock Marcelo Tosatti
2008-04-20 11:16 ` [patch 00/13] RFC: split the global mutex Avi Kivity
2008-04-21 0:00 ` Marcelo Tosatti
2008-04-21 6:10 ` Avi Kivity
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=20080417203026.834828995@localhost.localdomain \
--to=mtosatti@redhat.com \
--cc=aliguori@us.ibm.com \
--cc=avi@qumranet.com \
--cc=kvm-devel@lists.sourceforge.net \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.