From patchwork Wed Jul 1 14:21:01 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alberto Garcia X-Patchwork-Id: 490164 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 7418B140271 for ; Thu, 2 Jul 2015 00:23:35 +1000 (AEST) Received: from localhost ([::1]:59161 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZAIvF-0008UG-KW for incoming@patchwork.ozlabs.org; Wed, 01 Jul 2015 10:23:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:59527) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZAIuH-00075D-2N for qemu-devel@nongnu.org; Wed, 01 Jul 2015 10:22:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZAIuA-0000OR-VX for qemu-devel@nongnu.org; Wed, 01 Jul 2015 10:22:33 -0400 Received: from smtp3.mundo-r.com ([212.51.32.191]:23070 helo=smtp4.mundo-r.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZAIuA-0000Ae-PW; Wed, 01 Jul 2015 10:22:26 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AgkGAHb2k1VbdWOb/2dsb2JhbABbgxGBM6p8AQEBAQEBBQGBBAGZEAKBUEwBAQEBAQGBC4QjAQEEJ1IQPxI8GxmIMwHMKgErgk2DT4o0B4QrBY0Chw6LYYE6jESCQ4gDJmNmQxyBVWyCSAEBAQ X-IPAS-Result: AgkGAHb2k1VbdWOb/2dsb2JhbABbgxGBM6p8AQEBAQEBBQGBBAGZEAKBUEwBAQEBAQGBC4QjAQEEJ1IQPxI8GxmIMwHMKgErgk2DT4o0B4QrBY0Chw6LYYE6jESCQ4gDJmNmQxyBVWyCSAEBAQ X-IronPort-AV: E=Sophos;i="5.15,386,1432591200"; d="scan'208";a="374750029" Received: from fanzine.igalia.com ([91.117.99.155]) by smtp4.mundo-r.com with ESMTP; 01 Jul 2015 16:21:37 +0200 Received: from dsl-hkibrasgw4-50df50-128.dhcp.inet.fi ([80.223.80.128] helo=perseus.local) by fanzine.igalia.com with esmtpsa (Cipher TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim) id 1ZAItM-0000Sa-Oe; Wed, 01 Jul 2015 16:21:37 +0200 Received: from berto by perseus.local with local (Exim 4.86_RC3) (envelope-from ) id 1ZAIt9-0007rV-C6; Wed, 01 Jul 2015 17:21:23 +0300 From: Alberto Garcia To: qemu-devel@nongnu.org Date: Wed, 1 Jul 2015 17:21:01 +0300 Message-Id: <0d86a074935ca6c1a0645e5d4af492c7cac12821.1435758248.git.berto@igalia.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: References: In-Reply-To: References: X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 212.51.32.191 Cc: kwolf@redhat.com, Alberto Garcia , qemu-block@nongnu.org, mreitz@redhat.com, stefanha@redhat.com Subject: [Qemu-devel] [PATCH 1/1] block: update BlockDriverState's children in bdrv_set_backing_hd() 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 When a backing image is opened using bdrv_open_inherit(), it is added to the parent image's list of children. However there's no way to remove it from there. In particular, changing a BlockDriverState's backing image does not add the new one to the list nor removes the old one. If the latter is closed then the pointer in the list becomes invalid. This can be reproduced easily using the block-stream command. Signed-off-by: Alberto Garcia Cc: Kevin Wolf Reviewed-by: Max Reitz --- block.c | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/block.c b/block.c index 7e130cc..eaf3ad0 100644 --- a/block.c +++ b/block.c @@ -88,6 +88,13 @@ static int bdrv_open_inherit(BlockDriverState **pbs, const char *filename, const BdrvChildRole *child_role, BlockDriver *drv, Error **errp); +static void bdrv_attach_child(BlockDriverState *parent_bs, + BlockDriverState *child_bs, + const BdrvChildRole *child_role); + +static void bdrv_detach_child(BlockDriverState *parent_bs, + BlockDriverState *child_bs); + static void bdrv_dirty_bitmap_truncate(BlockDriverState *bs); /* If non-zero, use only whitelisted block drivers */ static int use_bdrv_whitelist; @@ -1108,6 +1115,7 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd) if (bs->backing_hd) { assert(bs->backing_blocker); bdrv_op_unblock_all(bs->backing_hd, bs->backing_blocker); + bdrv_detach_child(bs, bs->backing_hd); } else if (backing_hd) { error_setg(&bs->backing_blocker, "node is used as backing hd of '%s'", @@ -1120,6 +1128,11 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd) bs->backing_blocker = NULL; goto out; } + + bdrv_attach_child(bs, backing_hd, &child_backing); + backing_hd->inherits_from = bs; + backing_hd->open_flags = child_backing.inherit_flags(bs->open_flags); + bs->open_flags &= ~BDRV_O_NO_BACKING; pstrcpy(bs->backing_file, sizeof(bs->backing_file), backing_hd->filename); pstrcpy(bs->backing_format, sizeof(bs->backing_format), @@ -1332,7 +1345,16 @@ static void bdrv_attach_child(BlockDriverState *parent_bs, BlockDriverState *child_bs, const BdrvChildRole *child_role) { - BdrvChild *child = g_new(BdrvChild, 1); + BdrvChild *child; + + /* Don't attach the child if it's already attached */ + QLIST_FOREACH(child, &parent_bs->children, next) { + if (child->bs == child_bs) { + return; + } + } + + child = g_new(BdrvChild, 1); *child = (BdrvChild) { .bs = child_bs, .role = child_role, @@ -1341,6 +1363,21 @@ static void bdrv_attach_child(BlockDriverState *parent_bs, QLIST_INSERT_HEAD(&parent_bs->children, child, next); } +static void bdrv_detach_child(BlockDriverState *parent_bs, + BlockDriverState *child_bs) +{ + BdrvChild *child, *next_child; + QLIST_FOREACH_SAFE(child, &parent_bs->children, next, next_child) { + if (child->bs == child_bs) { + if (child->bs->inherits_from == parent_bs) { + child->bs->inherits_from = NULL; + } + QLIST_REMOVE(child, next); + g_free(child); + } + } +} + /* * Opens a disk image (raw, qcow2, vmdk, ...) * @@ -2116,7 +2153,6 @@ void bdrv_append(BlockDriverState *bs_new, BlockDriverState *bs_top) /* The contents of 'tmp' will become bs_top, as we are * swapping bs_new and bs_top contents. */ bdrv_set_backing_hd(bs_top, bs_new); - bdrv_attach_child(bs_top, bs_new, &child_backing); } static void bdrv_delete(BlockDriverState *bs)