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, stefanha@redhat.com, qemu-devel@nongnu.org
Subject: [PULL 16/58] Revert "block: Let replace_child_noperm free children"
Date: Thu, 27 Oct 2022 20:31:04 +0200	[thread overview]
Message-ID: <20221027183146.463129-17-kwolf@redhat.com> (raw)
In-Reply-To: <20221027183146.463129-1-kwolf@redhat.com>

From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>

We are going to reimplement this behavior (clear bs->file / bs->backing
pointers automatically when child->bs is cleared) in a nicer way, see
further commit
"block: Manipulate bs->file / bs->backing pointers in .attach/.detach".

With this revert we bring back a problem that was fixed by b0a9f6fed3d8.
Still the problem was mostly theoretical, we don't have concrete bugs
fixed by b0a9f6fed3d8, we don't have a specific test. Probably some
accidental failures of iotests are related.

Alternatively, we may merge this and following three reverts into final
"block: Manipulate ..." to avoid any kind of regression. But seems that
in this case having separate clear revert commits is better.

This reverts commit b0a9f6fed3d80de610dcd04a7e66f9f30a04174f.

Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Hanna Reitz <hreitz@redhat.com>
Message-Id: <20220726201134.924743-10-vsementsov@yandex-team.ru>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 block.c | 102 +++++++++++++-------------------------------------------
 1 file changed, 23 insertions(+), 79 deletions(-)

diff --git a/block.c b/block.c
index 25a596a612..7a9a6efca8 100644
--- a/block.c
+++ b/block.c
@@ -90,10 +90,8 @@ static BlockDriverState *bdrv_open_inherit(const char *filename,
 static bool bdrv_recurse_has_child(BlockDriverState *bs,
                                    BlockDriverState *child);
 
-static void bdrv_child_free(BdrvChild *child);
 static void bdrv_replace_child_noperm(BdrvChild **child,
-                                      BlockDriverState *new_bs,
-                                      bool free_empty_child);
+                                      BlockDriverState *new_bs);
 static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
                                               BdrvChild *child,
                                               Transaction *tran);
@@ -2345,7 +2343,6 @@ typedef struct BdrvReplaceChildState {
     BdrvChild *child;
     BdrvChild **childp;
     BlockDriverState *old_bs;
-    bool free_empty_child;
 } BdrvReplaceChildState;
 
 static void bdrv_replace_child_commit(void *opaque)
@@ -2353,9 +2350,6 @@ static void bdrv_replace_child_commit(void *opaque)
     BdrvReplaceChildState *s = opaque;
     GLOBAL_STATE_CODE();
 
-    if (s->free_empty_child && !s->child->bs) {
-        bdrv_child_free(s->child);
-    }
     bdrv_unref(s->old_bs);
 }
 
@@ -2373,26 +2367,22 @@ static void bdrv_replace_child_abort(void *opaque)
      *     modify the BdrvChild * pointer we indirectly pass to it, i.e. it
      *     will not modify s->child.  From that perspective, it does not matter
      *     whether we pass s->childp or &s->child.
+     *     (TODO: Right now, bdrv_replace_child_noperm() never modifies that
+     *     pointer anyway (though it will in the future), so at this point it
+     *     absolutely does not matter whether we pass s->childp or &s->child.)
      * (2) If new_bs is not NULL, s->childp will be NULL.  We then cannot use
      *     it here.
      * (3) If new_bs is NULL, *s->childp will have been NULLed by
      *     bdrv_replace_child_tran()'s bdrv_replace_child_noperm() call, and we
      *     must not pass a NULL *s->childp here.
+     *     (TODO: In its current state, bdrv_replace_child_noperm() will not
+     *     have NULLed *s->childp, so this does not apply yet.  It will in the
+     *     future.)
      *
      * So whether new_bs was NULL or not, we cannot pass s->childp here; and in
      * any case, there is no reason to pass it anyway.
      */
-    bdrv_replace_child_noperm(&s->child, s->old_bs, true);
-    /*
-     * The child was pre-existing, so s->old_bs must be non-NULL, and
-     * s->child thus must not have been freed
-     */
-    assert(s->child != NULL);
-    if (!new_bs) {
-        /* As described above, *s->childp was cleared, so restore it */
-        assert(s->childp != NULL);
-        *s->childp = s->child;
-    }
+    bdrv_replace_child_noperm(&s->child, s->old_bs);
     bdrv_unref(new_bs);
 }
 
@@ -2409,44 +2399,30 @@ static TransactionActionDrv bdrv_replace_child_drv = {
  *
  * The function doesn't update permissions, caller is responsible for this.
  *
- * (*childp)->bs must not be NULL.
- *
  * Note that if new_bs == NULL, @childp is stored in a state object attached
  * to @tran, so that the old child can be reinstated in the abort handler.
  * Therefore, if @new_bs can be NULL, @childp must stay valid until the
  * transaction is committed or aborted.
  *
- * If @free_empty_child is true and @new_bs is NULL, the BdrvChild is
- * freed (on commit).  @free_empty_child should only be false if the
- * caller will free the BDrvChild themselves (which may be important
- * if this is in turn called in another transactional context).
+ * (TODO: The reinstating does not happen yet, but it will once
+ * bdrv_replace_child_noperm() NULLs *childp when new_bs is NULL.)
  */
 static void bdrv_replace_child_tran(BdrvChild **childp,
                                     BlockDriverState *new_bs,
-                                    Transaction *tran,
-                                    bool free_empty_child)
+                                    Transaction *tran)
 {
     BdrvReplaceChildState *s = g_new(BdrvReplaceChildState, 1);
     *s = (BdrvReplaceChildState) {
         .child = *childp,
         .childp = new_bs == NULL ? childp : NULL,
         .old_bs = (*childp)->bs,
-        .free_empty_child = free_empty_child,
     };
     tran_add(tran, &bdrv_replace_child_drv, s);
 
-    /* The abort handler relies on this */
-    assert(s->old_bs != NULL);
-
     if (new_bs) {
         bdrv_ref(new_bs);
     }
-    /*
-     * Pass free_empty_child=false, we will free the child (if
-     * necessary) in bdrv_replace_child_commit() (if our
-     * @free_empty_child parameter was true).
-     */
-    bdrv_replace_child_noperm(childp, new_bs, false);
+    bdrv_replace_child_noperm(childp, new_bs);
     /* old_bs reference is transparently moved from *childp to @s */
 }
 
@@ -2828,22 +2804,8 @@ uint64_t bdrv_qapi_perm_to_blk_perm(BlockPermission qapi_perm)
     return permissions[qapi_perm];
 }
 
-/**
- * Replace (*childp)->bs by @new_bs.
- *
- * If @new_bs is NULL, *childp will be set to NULL, too: BDS parents
- * generally cannot handle a BdrvChild with .bs == NULL, so clearing
- * BdrvChild.bs should generally immediately be followed by the
- * BdrvChild pointer being cleared as well.
- *
- * If @free_empty_child is true and @new_bs is NULL, the BdrvChild is
- * freed.  @free_empty_child should only be false if the caller will
- * free the BdrvChild themselves (this may be important in a
- * transactional context, where it may only be freed on commit).
- */
 static void bdrv_replace_child_noperm(BdrvChild **childp,
-                                      BlockDriverState *new_bs,
-                                      bool free_empty_child)
+                                      BlockDriverState *new_bs)
 {
     BdrvChild *child = *childp;
     BlockDriverState *old_bs = child->bs;
@@ -2882,9 +2844,6 @@ static void bdrv_replace_child_noperm(BdrvChild **childp,
     }
 
     child->bs = new_bs;
-    if (!new_bs) {
-        *childp = NULL;
-    }
 
     if (new_bs) {
         assert_bdrv_graph_writable(new_bs);
@@ -2915,10 +2874,6 @@ static void bdrv_replace_child_noperm(BdrvChild **childp,
         bdrv_parent_drained_end_single(child);
         drain_saldo++;
     }
-
-    if (free_empty_child && !child->bs) {
-        bdrv_child_free(child);
-    }
 }
 
 /**
@@ -2950,14 +2905,7 @@ static void bdrv_attach_child_common_abort(void *opaque)
     BlockDriverState *bs = child->bs;
 
     GLOBAL_STATE_CODE();
-    /*
-     * Pass free_empty_child=false, because we still need the child
-     * for the AioContext operations on the parent below; those
-     * BdrvChildClass methods all work on a BdrvChild object, so we
-     * need to keep it as an empty shell (after this function, it will
-     * not be attached to any parent, and it will not have a .bs).
-     */
-    bdrv_replace_child_noperm(s->child, NULL, false);
+    bdrv_replace_child_noperm(s->child, NULL);
 
     if (bdrv_get_aio_context(bs) != s->old_child_ctx) {
         bdrv_try_set_aio_context(bs, s->old_child_ctx, &error_abort);
@@ -2979,6 +2927,7 @@ static void bdrv_attach_child_common_abort(void *opaque)
 
     bdrv_unref(bs);
     bdrv_child_free(child);
+    *s->child = NULL;
 }
 
 static TransactionActionDrv bdrv_attach_child_common_drv = {
@@ -3057,9 +3006,7 @@ static int bdrv_attach_child_common(BlockDriverState *child_bs,
     }
 
     bdrv_ref(child_bs);
-    bdrv_replace_child_noperm(&new_child, child_bs, true);
-    /* child_bs was non-NULL, so new_child must not have been freed */
-    assert(new_child != NULL);
+    bdrv_replace_child_noperm(&new_child, child_bs);
 
     *child = new_child;
 
@@ -3120,7 +3067,8 @@ static void bdrv_detach_child(BdrvChild **childp)
     BlockDriverState *old_bs = (*childp)->bs;
 
     GLOBAL_STATE_CODE();
-    bdrv_replace_child_noperm(childp, NULL, true);
+    bdrv_replace_child_noperm(childp, NULL);
+    bdrv_child_free(*childp);
 
     if (old_bs) {
         /*
@@ -5171,11 +5119,7 @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
     }
 
     if (child->bs) {
-        /*
-         * Pass free_empty_child=false, we will free the child in
-         * bdrv_remove_filter_or_cow_child_commit()
-         */
-        bdrv_replace_child_tran(childp, NULL, tran, false);
+        bdrv_replace_child_tran(childp, NULL, tran);
     }
 
     s = g_new(BdrvRemoveFilterOrCowChild, 1);
@@ -5185,6 +5129,8 @@ static void bdrv_remove_file_or_backing_child(BlockDriverState *bs,
         .is_backing = (childp == &bs->backing),
     };
     tran_add(tran, &bdrv_remove_filter_or_cow_child_drv, s);
+
+    *childp = NULL;
 }
 
 /*
@@ -5228,7 +5174,7 @@ static int bdrv_replace_node_noperm(BlockDriverState *from,
          * Passing a pointer to the local variable @c is fine here, because
          * @to is not NULL, and so &c will not be attached to the transaction.
          */
-        bdrv_replace_child_tran(&c, to, tran, true);
+        bdrv_replace_child_tran(&c, to, tran);
     }
 
     return 0;
@@ -5393,9 +5339,7 @@ int bdrv_replace_child_bs(BdrvChild *child, BlockDriverState *new_bs,
     bdrv_drained_begin(old_bs);
     bdrv_drained_begin(new_bs);
 
-    bdrv_replace_child_tran(&child, new_bs, tran, true);
-    /* @new_bs must have been non-NULL, so @child must not have been freed */
-    assert(child != NULL);
+    bdrv_replace_child_tran(&child, new_bs, tran);
 
     found = g_hash_table_new(NULL, NULL);
     refresh_list = bdrv_topological_dfs(refresh_list, found, old_bs);
-- 
2.37.3



  parent reply	other threads:[~2022-10-27 18:34 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-27 18:30 [PULL 00/58] Block layer patches Kevin Wolf
2022-10-27 18:30 ` [PULL 01/58] MAINTAINERS: Fold "Block QAPI, monitor, ..." into "Block layer core" Kevin Wolf
2022-10-27 18:30 ` [PULL 02/58] block: Ignore close() failure in get_tmp_filename() Kevin Wolf
2022-10-27 18:30 ` [PULL 03/58] block: Refactor get_tmp_filename() Kevin Wolf
2022-10-27 18:30 ` [PULL 04/58] vvfat: allow some writes to bootsector Kevin Wolf
2022-10-27 18:30 ` [PULL 05/58] vvfat: allow spaces in file names Kevin Wolf
2022-10-27 18:30 ` [PULL 06/58] block/io_uring: revert "Use io_uring_register_ring_fd() to skip fd operations" Kevin Wolf
2022-10-27 18:30 ` [PULL 07/58] vhost-user-blk: fix the resize crash Kevin Wolf
2022-10-27 18:30 ` [PULL 08/58] block: BlockDriver: add .filtered_child_is_backing field Kevin Wolf
2022-10-27 18:30 ` [PULL 09/58] block: introduce bdrv_open_file_child() helper Kevin Wolf
2022-10-27 18:30 ` [PULL 10/58] block/blklogwrites: don't care to remove bs->file child on failure Kevin Wolf
2022-10-27 18:30 ` [PULL 11/58] test-bdrv-graph-mod: update test_parallel_perm_update test case Kevin Wolf
2022-10-27 18:31 ` [PULL 12/58] tests-bdrv-drain: bdrv_replace_test driver: declare supports_backing Kevin Wolf
2022-10-27 18:31 ` [PULL 13/58] test-bdrv-graph-mod: fix filters to be filters Kevin Wolf
2022-10-27 18:31 ` [PULL 14/58] block: document connection between child roles and bs->backing/bs->file Kevin Wolf
2022-10-27 18:31 ` [PULL 15/58] block/snapshot: stress that we fallback to primary child Kevin Wolf
2022-10-27 18:31 ` Kevin Wolf [this message]
2022-10-27 18:31 ` [PULL 17/58] Revert "block: Let replace_child_tran keep indirect pointer" Kevin Wolf
2022-10-27 18:31 ` [PULL 18/58] Revert "block: Restructure remove_file_or_backing_child()" Kevin Wolf
2022-10-27 18:31 ` [PULL 19/58] Revert "block: Pass BdrvChild ** to replace_child_noperm" Kevin Wolf
2022-10-27 18:31 ` [PULL 20/58] block: Manipulate bs->file / bs->backing pointers in .attach/.detach Kevin Wolf
2022-10-27 18:31 ` [PULL 21/58] block/snapshot: drop indirection around bdrv_snapshot_fallback_ptr Kevin Wolf
2022-10-27 18:31 ` [PULL 22/58] block: refactor bdrv_remove_file_or_backing_child to bdrv_remove_child Kevin Wolf
2022-10-27 18:31 ` [PULL 23/58] block.c: assert bs->aio_context is written under BQL and drains Kevin Wolf
2022-10-27 18:31 ` [PULL 24/58] block: use transactions as a replacement of ->{can_}set_aio_context() Kevin Wolf
2022-10-27 18:31 ` [PULL 25/58] bdrv_change_aio_context: use hash table instead of list of visited nodes Kevin Wolf
2022-10-27 18:31 ` [PULL 26/58] blockjob: implement .change_aio_ctx in child_job Kevin Wolf
2022-10-27 18:31 ` [PULL 27/58] block: implement .change_aio_ctx in child_of_bds Kevin Wolf
2022-10-27 18:31 ` [PULL 28/58] block-backend: implement .change_aio_ctx in child_root Kevin Wolf
2022-10-27 18:31 ` [PULL 29/58] block: use the new _change_ API instead of _can_set_ and _set_ Kevin Wolf
2022-10-27 18:31 ` [PULL 30/58] block: remove all unused ->can_set_aio_ctx and ->set_aio_ctx callbacks Kevin Wolf
2022-10-27 18:31 ` [PULL 31/58] block: rename bdrv_child_try_change_aio_context in bdrv_try_change_aio_context Kevin Wolf
2022-10-27 18:31 ` [PULL 32/58] block: remove bdrv_try_set_aio_context and replace it with bdrv_try_change_aio_context Kevin Wolf
2022-10-27 18:31 ` [PULL 33/58] block/nfs: Fix 32-bit Windows build Kevin Wolf
2022-10-27 18:31 ` [PULL 34/58] backup: remove incorrect coroutine_fn annotation Kevin Wolf
2022-10-27 18:31 ` [PULL 35/58] block: " Kevin Wolf
2022-10-27 18:31 ` [PULL 36/58] monitor: add missing " Kevin Wolf
2022-10-27 18:31 ` [PULL 37/58] ssh: " Kevin Wolf
2022-10-27 18:31 ` [PULL 38/58] block: add missing coroutine_fn annotation to prototypes Kevin Wolf
2022-10-27 18:31 ` [PULL 39/58] coroutine-lock: " Kevin Wolf
2022-10-27 18:31 ` [PULL 40/58] coroutine-io: " Kevin Wolf
2022-10-27 18:31 ` [PULL 41/58] block: add missing coroutine_fn annotation to BlockDriverState callbacks Kevin Wolf
2022-10-27 18:31 ` [PULL 42/58] qcow2: add coroutine_fn annotation for indirect-called functions Kevin Wolf
2022-10-27 18:31 ` [PULL 43/58] blkdebug: add missing " Kevin Wolf
2022-10-27 18:31 ` [PULL 44/58] qcow: manually add more coroutine_fn annotations Kevin Wolf
2022-10-27 18:31 ` [PULL 45/58] qcow2: " Kevin Wolf
2022-10-27 18:31 ` [PULL 46/58] vmdk: " Kevin Wolf
2022-10-27 18:31 ` [PULL 47/58] commit: switch to *_co_* functions Kevin Wolf
2022-10-27 18:31 ` [PULL 48/58] block: " Kevin Wolf
2022-10-27 18:31 ` [PULL 49/58] mirror: " Kevin Wolf
2022-10-27 18:31 ` [PULL 50/58] parallels: " Kevin Wolf
2022-10-27 18:31 ` [PULL 51/58] qcow: " Kevin Wolf
2022-10-27 18:31 ` [PULL 52/58] qcow2: " Kevin Wolf
2022-10-27 18:31 ` [PULL 53/58] qed: " Kevin Wolf
2022-10-27 18:31 ` [PULL 54/58] vdi: " Kevin Wolf
2022-10-27 18:31 ` [PULL 55/58] vhdx: " Kevin Wolf
2022-10-27 18:31 ` [PULL 56/58] vmdk: " Kevin Wolf
2022-10-27 18:31 ` [PULL 57/58] monitor: " Kevin Wolf
2022-10-27 18:31 ` [PULL 58/58] block/block-backend: blk_set_enable_write_cache is IO_CODE Kevin Wolf
2022-10-30 19:16 ` [PULL 00/58] Block layer patches Stefan Hajnoczi
2022-10-31 10:13 ` Stefan Hajnoczi

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=20221027183146.463129-17-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    /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).