From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55450) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1edkGl-0005um-Gp for qemu-devel@nongnu.org; Mon, 22 Jan 2018 17:08:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1edkGk-0003RN-CJ for qemu-devel@nongnu.org; Mon, 22 Jan 2018 17:08:47 -0500 From: Max Reitz Date: Mon, 22 Jan 2018 23:07:52 +0100 Message-Id: <20180122220806.22154-3-mreitz@redhat.com> In-Reply-To: <20180122220806.22154-1-mreitz@redhat.com> References: <20180122220806.22154-1-mreitz@redhat.com> Subject: [Qemu-devel] [PATCH v2 02/16] block: BDS deletion in bdrv_do_drained_begin() List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-block@nongnu.org Cc: qemu-devel@nongnu.org, Max Reitz , Kevin Wolf , John Snow , Fam Zheng , Stefan Hajnoczi Draining a BDS (in the main loop) may cause it to go be deleted. That is rather suboptimal if we still plan to access it afterwards, so let us enclose the main body of the function with a bdrv_ref()/bdrv_unref() pair. Signed-off-by: Max Reitz --- block/io.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/block/io.c b/block/io.c index ca7dfecfc9..1ff2ff0adb 100644 --- a/block/io.c +++ b/block/io.c @@ -294,12 +294,27 @@ void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive, BdrvChild *parent) { BdrvChild *child, *next; + bool in_main_loop = + qemu_get_current_aio_context() == qemu_get_aio_context(); + /* bdrv_close() invokes bdrv_drain() with bs->refcnt == 0; then, + * we may not invoke bdrv_ref()/bdrv_unref() because the latter + * would result in the refcount going back to 0, creating an + * infinite loop. + * Also, we have to be in the main loop because we may not call + * bdrv_unref() elsewhere. But because of that, the BDS is not in + * danger of going away without the bdrv_ref()/bdrv_unref() pair + * elsewhere, so we are fine then. */ + bool add_ref = in_main_loop && bs->refcnt > 0; if (qemu_in_coroutine()) { bdrv_co_yield_to_drain(bs, true, recursive, parent); return; } + if (add_ref) { + bdrv_ref(bs); + } + /* Stop things in parent-to-child order */ if (atomic_fetch_inc(&bs->quiesce_counter) == 0) { aio_disable_external(bdrv_get_aio_context(bs)); @@ -315,6 +330,10 @@ void bdrv_do_drained_begin(BlockDriverState *bs, bool recursive, bdrv_do_drained_begin(child->bs, true, child); } } + + if (add_ref) { + bdrv_unref(bs); + } } void bdrv_drained_begin(BlockDriverState *bs) -- 2.14.3