From patchwork Wed Apr 29 19:20:11 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 466253 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 1EBCB1402BC for ; Thu, 30 Apr 2015 05:23:50 +1000 (AEST) Received: from localhost ([::1]:40707 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YnXaG-0006HO-7o for incoming@patchwork.ozlabs.org; Wed, 29 Apr 2015 15:23:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:39029) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YnXXm-0001T6-Ud for qemu-devel@nongnu.org; Wed, 29 Apr 2015 15:21:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YnXXj-0006DT-KX for qemu-devel@nongnu.org; Wed, 29 Apr 2015 15:21:14 -0400 Received: from e19.ny.us.ibm.com ([129.33.205.209]:44679) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YnXXj-0006DE-Fu for qemu-devel@nongnu.org; Wed, 29 Apr 2015 15:21:11 -0400 Received: from /spool/local by e19.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 29 Apr 2015 15:21:11 -0400 Received: from d01dlp03.pok.ibm.com (9.56.250.168) by e19.ny.us.ibm.com (146.89.104.206) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 29 Apr 2015 15:21:10 -0400 Received: from b01cxnp22036.gho.pok.ibm.com (b01cxnp22036.gho.pok.ibm.com [9.57.198.26]) by d01dlp03.pok.ibm.com (Postfix) with ESMTP id 93234C9003E; Wed, 29 Apr 2015 15:12:15 -0400 (EDT) Received: from d01av05.pok.ibm.com (d01av05.pok.ibm.com [9.56.224.195]) by b01cxnp22036.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t3TJL6p659441342; Wed, 29 Apr 2015 19:21:06 GMT Received: from d01av05.pok.ibm.com (localhost [127.0.0.1]) by d01av05.pok.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t3TJL6DI026919; Wed, 29 Apr 2015 15:21:06 -0400 Received: from localhost ([9.80.84.126]) by d01av05.pok.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t3TJL55e026891; Wed, 29 Apr 2015 15:21:05 -0400 From: Michael Roth To: qemu-devel@nongnu.org Date: Wed, 29 Apr 2015 14:20:11 -0500 Message-Id: <1430335224-6716-3-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1430335224-6716-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1430335224-6716-1-git-send-email-mdroth@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15042919-0057-0000-0000-0000000D9A54 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 129.33.205.209 Cc: "Michael S. Tsirkin" , aik@ozlabs.ru, Paolo Bonzini , qemu-ppc@nongnu.org, bharata@linux.vnet.ibm.com, nfont@linux.vnet.ibm.com, david@gibson.dropbear.id.au Subject: [Qemu-devel] [RFC PATCH 02/15] qdev: store DeviceState's canonical path to use when unparenting X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org device_unparent(dev, ...) is called when a device is unparented, either directly, or as a result of a parent device being finalized, and handles some final cleanup for the device. Part of this includes emiting a DEVICE_DELETED QMP event to notify management, which includes the device's path in the composition tree as provided by object_get_canonical_path(). object_get_canonical_path() assumes the device is still connected to the machine/root container, and will assert otherwise, but in some situations this isn't the case: If the parent is finalized as a result of object_unparent(), it will still be attached to the composition tree at the time any children are unparented as a result of that same call to object_unparent(). However, in some cases, object_unparent() will complete without finalizing the parent device, due to lingering references that won't be released till some time later. One such example is if the parent has MemoryRegion children (which take a ref on their parent), who in turn have AddressSpace's (which take a ref on their regions), since those AddressSpaces get cleaned up asynchronously by the RCU thread. In this case qdev:device_unparent() may be called for a child Device that no longer has a path to the root/machine container, causing object_get_canonical_path() to assert. Fix this by storing the canonical path during realize() so the information will still be available for device_unparent() in such cases. Cc: Michael S. Tsirkin Cc: Paolo Bonzini Signed-off-by: Michael Roth --- hw/core/qdev.c | 15 ++++++++++++--- include/hw/qdev-core.h | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 6be5866..fda1d2f 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -1072,6 +1072,12 @@ static void device_set_realized(Object *obj, bool value, Error **errp) goto post_realize_fail; } + /* always re-initialize since we clean up in device_unparent() instead + * of unrealize() + */ + g_free(dev->canonical_path); + dev->canonical_path = object_get_canonical_path(OBJECT(dev)); + if (qdev_get_vmsd(dev)) { vmstate_register_with_alias_id(dev, -1, qdev_get_vmsd(dev), dev, dev->instance_id_alias, @@ -1125,6 +1131,7 @@ child_realize_fail: } post_realize_fail: + g_free(dev->canonical_path); if (dc->unrealize) { dc->unrealize(dev, NULL); } @@ -1248,10 +1255,12 @@ static void device_unparent(Object *obj) /* Only send event if the device had been completely realized */ if (dev->pending_deleted_event) { - gchar *path = object_get_canonical_path(OBJECT(dev)); + g_assert(dev->canonical_path); - qapi_event_send_device_deleted(!!dev->id, dev->id, path, &error_abort); - g_free(path); + qapi_event_send_device_deleted(!!dev->id, dev->id, dev->canonical_path, + &error_abort); + g_free(dev->canonical_path); + dev->canonical_path = NULL; } } diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 4e673f9..17f805e 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -153,6 +153,7 @@ struct DeviceState { /*< public >*/ const char *id; + char *canonical_path; bool realized; bool pending_deleted_event; QemuOpts *opts;