From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1M2NXR-0002bJ-8l for qemu-devel@nongnu.org; Fri, 08 May 2009 06:42:45 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1M2NXH-0002WN-EJ for qemu-devel@nongnu.org; Fri, 08 May 2009 06:42:41 -0400 Received: from [199.232.76.173] (port=33621 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1M2NXH-0002W8-7c for qemu-devel@nongnu.org; Fri, 08 May 2009 06:42:35 -0400 Received: from lizzard.sbs.de ([194.138.37.39]:21771) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1M2NXG-0000fL-2K for qemu-devel@nongnu.org; Fri, 08 May 2009 06:42:34 -0400 Received: from mail2.sbs.de (localhost [127.0.0.1]) by lizzard.sbs.de (8.12.11.20060308/8.12.11) with ESMTP id n48AgSVY010007 for ; Fri, 8 May 2009 12:42:28 +0200 Received: from [139.25.109.167] (mchn012c.ww002.siemens.net [139.25.109.167] (may be forged)) by mail2.sbs.de (8.12.11.20060308/8.12.11) with ESMTP id n48AgSms023133 for ; Fri, 8 May 2009 12:42:28 +0200 Resent-To: qemu-devel Resent-Message-Id: <4A040C92.4050706@siemens.com> From: Jan Kiszka Date: Fri, 08 May 2009 12:34:17 +0200 Message-ID: <20090508103417.6080.92705.stgit@mchn012c.ww002.siemens.net> In-Reply-To: <20090508103416.6080.44298.stgit@mchn012c.ww002.siemens.net> References: <20090508103416.6080.44298.stgit@mchn012c.ww002.siemens.net> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH 02/11] net: Fix and improved ordered packet delivery List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Fix a race in qemu_send_packet when delivering deferred packets and add proper deferring also to qemu_sendv_packet. Signed-off-by: Jan Kiszka --- net.c | 57 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 42 insertions(+), 15 deletions(-) diff --git a/net.c b/net.c index b93b3a6..671138f 100644 --- a/net.c +++ b/net.c @@ -438,8 +438,8 @@ void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size) vlan->delivering = 1; qemu_deliver_packet(vc, buf, size); while ((packet = vlan->send_queue) != NULL) { - qemu_deliver_packet(packet->sender, packet->data, packet->size); vlan->send_queue = packet->next; + qemu_deliver_packet(packet->sender, packet->data, packet->size); qemu_free(packet); } vlan->delivering = 0; @@ -476,30 +476,57 @@ static ssize_t calc_iov_length(const struct iovec *iov, int iovcnt) return offset; } -ssize_t qemu_sendv_packet(VLANClientState *vc1, const struct iovec *iov, +ssize_t qemu_sendv_packet(VLANClientState *sender, const struct iovec *iov, int iovcnt) { - VLANState *vlan = vc1->vlan; + VLANState *vlan = sender->vlan; VLANClientState *vc; + VLANPacket *packet; ssize_t max_len = 0; + int i; - if (vc1->link_down) + if (sender->link_down) return calc_iov_length(iov, iovcnt); - for (vc = vlan->first_client; vc != NULL; vc = vc->next) { - ssize_t len = 0; + if (vlan->delivering) { + max_len = calc_iov_length(iov, iovcnt); - if (vc == vc1) - continue; + packet = qemu_malloc(sizeof(VLANPacket) + max_len); + packet->next = vlan->send_queue; + packet->sender = sender; + packet->size = 0; + for (i = 0; i < iovcnt; i++) { + size_t len = iov[i].iov_len; + + memcpy(packet->data + packet->size, iov[i].iov_base, len); + packet->size += len; + } + vlan->send_queue = packet; + } else { + vlan->delivering = 1; + + for (vc = vlan->first_client; vc != NULL; vc = vc->next) { + ssize_t len = 0; - if (vc->link_down) - len = calc_iov_length(iov, iovcnt); - else if (vc->fd_readv) - len = vc->fd_readv(vc->opaque, iov, iovcnt); - else if (vc->fd_read) - len = vc_sendv_compat(vc, iov, iovcnt); + if (vc == sender) { + continue; + } + if (vc->link_down) { + len = calc_iov_length(iov, iovcnt); + } else if (vc->fd_readv) { + len = vc->fd_readv(vc->opaque, iov, iovcnt); + } else if (vc->fd_read) { + len = vc_sendv_compat(vc, iov, iovcnt); + } + max_len = MAX(max_len, len); + } - max_len = MAX(max_len, len); + while ((packet = vlan->send_queue) != NULL) { + vlan->send_queue = packet->next; + qemu_deliver_packet(packet->sender, packet->data, packet->size); + qemu_free(packet); + } + vlan->delivering = 0; } return max_len;