From patchwork Tue Aug 6 18:13:12 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 2839521 Return-Path: X-Original-To: patchwork-kvm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 02FC0BF535 for ; Tue, 6 Aug 2013 18:13:30 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id BF6DC2021C for ; Tue, 6 Aug 2013 18:13:28 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id C493820219 for ; Tue, 6 Aug 2013 18:13:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756331Ab3HFSNY (ORCPT ); Tue, 6 Aug 2013 14:13:24 -0400 Received: from service87.mimecast.com ([91.220.42.44]:44637 "EHLO service87.mimecast.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756269Ab3HFSNX (ORCPT ); Tue, 6 Aug 2013 14:13:23 -0400 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Tue, 06 Aug 2013 19:13:21 +0100 Received: from e102391-lin.cambridge.arm.com ([10.1.255.212]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.0); Tue, 6 Aug 2013 19:13:18 +0100 From: Marc Zyngier To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: Sasha Levin , Pekka Enberg , Will Deacon Subject: [PATCH] kvm tools: plug race between uip_init and virtio_net_rx_thread Date: Tue, 6 Aug 2013 19:13:12 +0100 Message-Id: <1375812792-25849-1-git-send-email-marc.zyngier@arm.com> X-Mailer: git-send-email 1.8.2.3 X-OriginalArrivalTime: 06 Aug 2013 18:13:18.0591 (UTC) FILETIME=[A09E60F0:01CE92D0] X-MC-Unique: 113080619132101301 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When fa7226f (kvm tools: init network devices only when the virtio driver is ready to go) was introduced, a tiny detail was overlooked: - Initialization of the uip layer is now coming in very late (only when the guest driver says it is ready). - In parallel, the rx thread is created quite early (as soon as the queues are allocated). This cause the rx thread to call uip_rx, which calls uip_buf_get_used, which starts to use buf_lock mutex/the buf_used_cond, which haven't been initialized yet. Tears and devastation follow, not to mention a certain lack of network connectivity for the unsuspecting guest. The (not so pretty) fix is to split uip_init: - uip_static_init: initialize the lists, mutexes and conditions, called from virtio_net__init_one. - uip_init: perform the dynamic memory allocations, called from notify_status. This allows the network to be safely initialized. Cc: Sasha Levin Cc: Pekka Enberg Cc: Will Deacon Signed-off-by: Marc Zyngier --- tools/kvm/include/kvm/uip.h | 1 + tools/kvm/net/uip/core.c | 19 +++++++++++++------ tools/kvm/virtio/net.c | 1 + 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/tools/kvm/include/kvm/uip.h b/tools/kvm/include/kvm/uip.h index 4e63808..a9a8d85 100644 --- a/tools/kvm/include/kvm/uip.h +++ b/tools/kvm/include/kvm/uip.h @@ -334,6 +334,7 @@ static inline u16 uip_eth_hdrlen(struct uip_eth *eth) int uip_tx(struct iovec *iov, u16 out, struct uip_info *info); int uip_rx(struct iovec *iov, u16 in, struct uip_info *info); +void uip_static_init(struct uip_info *info); int uip_init(struct uip_info *info); int uip_tx_do_ipv4_udp_dhcp(struct uip_tx_arg *arg); diff --git a/tools/kvm/net/uip/core.c b/tools/kvm/net/uip/core.c index 789b814..b3cd8c2 100644 --- a/tools/kvm/net/uip/core.c +++ b/tools/kvm/net/uip/core.c @@ -94,19 +94,15 @@ int uip_rx(struct iovec *iov, u16 in, struct uip_info *info) return len; } -int uip_init(struct uip_info *info) +void uip_static_init(struct uip_info *info) { struct list_head *udp_socket_head; struct list_head *tcp_socket_head; struct list_head *buf_head; - struct uip_buf *buf; - int buf_nr; - int i; udp_socket_head = &info->udp_socket_head; tcp_socket_head = &info->tcp_socket_head; buf_head = &info->buf_head; - buf_nr = info->buf_nr; INIT_LIST_HEAD(udp_socket_head); INIT_LIST_HEAD(tcp_socket_head); @@ -119,6 +115,18 @@ int uip_init(struct uip_info *info) pthread_cond_init(&info->buf_used_cond, NULL); pthread_cond_init(&info->buf_free_cond, NULL); + info->buf_used_nr = 0; +} + +int uip_init(struct uip_info *info) +{ + struct list_head *buf_head; + struct uip_buf *buf; + int buf_nr; + int i; + + buf_head = &info->buf_head; + buf_nr = info->buf_nr; for (i = 0; i < buf_nr; i++) { buf = malloc(sizeof(*buf)); @@ -141,7 +149,6 @@ int uip_init(struct uip_info *info) } info->buf_free_nr = buf_nr; - info->buf_used_nr = 0; uip_dhcp_get_dns(info); diff --git a/tools/kvm/virtio/net.c b/tools/kvm/virtio/net.c index 298903c..2c34996 100644 --- a/tools/kvm/virtio/net.c +++ b/tools/kvm/virtio/net.c @@ -712,6 +712,7 @@ static int virtio_net__init_one(struct virtio_net_params *params) ndev->info.guest_netmask = ntohl(inet_addr("255.255.255.0")); ndev->info.buf_nr = 20, ndev->ops = &uip_ops; + uip_static_init(&ndev->info); } if (params->trans && strcmp(params->trans, "mmio") == 0)