qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, mreitz@redhat.com, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH for-3.1 v2 1/2] block: Don't inactivate children before parents
Date: Mon, 26 Nov 2018 15:16:38 +0100	[thread overview]
Message-ID: <20181126141639.13208-2-kwolf@redhat.com> (raw)
In-Reply-To: <20181126141639.13208-1-kwolf@redhat.com>

bdrv_child_cb_inactivate() asserts that parents are already inactive
when children get inactivated. This precondition is necessary because
parents could still issue requests in their inactivation code.

When block nodes are created individually with -blockdev, all of them
are monitor owned and will be returned by bdrv_next() in an undefined
order (in practice, in the order of their creation, which is usually
children before parents), which obviously fails the assertion:

qemu: block.c:899: bdrv_child_cb_inactivate: Assertion `bs->open_flags & BDRV_O_INACTIVE' failed.

This patch fixes the ordering by skipping nodes with still active
parents in bdrv_inactivate_recurse() because we know that they will be
covered by recursion when the last active parent becomes inactive.

Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/block.c b/block.c
index 5ba3435f8f..e9181c3be7 100644
--- a/block.c
+++ b/block.c
@@ -4612,6 +4612,22 @@ void bdrv_invalidate_cache_all(Error **errp)
     }
 }
 
+static bool bdrv_has_bds_parent(BlockDriverState *bs, bool only_active)
+{
+    BdrvChild *parent;
+
+    QLIST_FOREACH(parent, &bs->parents, next_parent) {
+        if (parent->role->parent_is_bds) {
+            BlockDriverState *parent_bs = parent->opaque;
+            if (!only_active || !(parent_bs->open_flags & BDRV_O_INACTIVE)) {
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
 static int bdrv_inactivate_recurse(BlockDriverState *bs,
                                    bool setting_flag)
 {
@@ -4622,6 +4638,14 @@ static int bdrv_inactivate_recurse(BlockDriverState *bs,
         return -ENOMEDIUM;
     }
 
+    /* Make sure that we don't inactivate a child before its parent.
+     * It will be covered by recursion from the yet active parent. */
+    if (bdrv_has_bds_parent(bs, true)) {
+        return 0;
+    }
+
+    assert(!(bs->open_flags & BDRV_O_INACTIVE));
+
     if (!setting_flag && bs->drv->bdrv_inactivate) {
         ret = bs->drv->bdrv_inactivate(bs);
         if (ret < 0) {
@@ -4629,7 +4653,7 @@ static int bdrv_inactivate_recurse(BlockDriverState *bs,
         }
     }
 
-    if (setting_flag && !(bs->open_flags & BDRV_O_INACTIVE)) {
+    if (setting_flag) {
         uint64_t perm, shared_perm;
 
         QLIST_FOREACH(parent, &bs->parents, next_parent) {
@@ -4682,6 +4706,12 @@ int bdrv_inactivate_all(void)
      * is allowed. */
     for (pass = 0; pass < 2; pass++) {
         for (bs = bdrv_first(&it); bs; bs = bdrv_next(&it)) {
+            /* Nodes with BDS parents are covered by recursion from the last
+             * parent that gets inactivated. Don't inactivate them a second
+             * time if that has already happened. */
+            if (bdrv_has_bds_parent(bs, false)) {
+                continue;
+            }
             ret = bdrv_inactivate_recurse(bs, pass);
             if (ret < 0) {
                 bdrv_next_cleanup(&it);
-- 
2.19.1

  reply	other threads:[~2018-11-26 14:16 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-11-26 14:16 [Qemu-devel] [PATCH for-3.1 v2 0/2] block: Fix crash on migration with explicit child nodes Kevin Wolf
2018-11-26 14:16 ` Kevin Wolf [this message]
2018-11-26 14:34   ` [Qemu-devel] [PATCH for-3.1 v2 1/2] block: Don't inactivate children before parents Max Reitz
2018-11-26 14:16 ` [Qemu-devel] [PATCH for-3.1 v2 2/2] iotests: Test migration with -blockdev Kevin Wolf
2018-11-26 14:37   ` Max Reitz

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181126141639.13208-2-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).