All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: qemu-block@nongnu.org
Cc: kwolf@redhat.com, peter.maydell@linaro.org, qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 08/13] tests: Extend commit by drained_end test
Date: Fri, 19 Jul 2019 15:43:40 +0200	[thread overview]
Message-ID: <20190719134345.23526-9-kwolf@redhat.com> (raw)
In-Reply-To: <20190719134345.23526-1-kwolf@redhat.com>

From: Max Reitz <mreitz@redhat.com>

Signed-off-by: Max Reitz <mreitz@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
 tests/test-bdrv-drain.c | 36 ++++++++++++++++++++++++++++++++----
 1 file changed, 32 insertions(+), 4 deletions(-)

diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c
index 3503ce3b69..03fa1142a1 100644
--- a/tests/test-bdrv-drain.c
+++ b/tests/test-bdrv-drain.c
@@ -1532,6 +1532,7 @@ typedef struct TestDropBackingBlockJob {
     BlockJob common;
     bool should_complete;
     bool *did_complete;
+    BlockDriverState *detach_also;
 } TestDropBackingBlockJob;
 
 static int coroutine_fn test_drop_backing_job_run(Job *job, Error **errp)
@@ -1552,6 +1553,7 @@ static void test_drop_backing_job_commit(Job *job)
         container_of(job, TestDropBackingBlockJob, common.job);
 
     bdrv_set_backing_hd(blk_bs(s->common.blk), NULL, &error_abort);
+    bdrv_set_backing_hd(s->detach_also, NULL, &error_abort);
 
     *s->did_complete = true;
 }
@@ -1571,9 +1573,6 @@ static const BlockJobDriver test_drop_backing_job_driver = {
  * Creates a child node with three parent nodes on it, and then runs a
  * block job on the final one, parent-node-2.
  *
- * (TODO: parent-node-0 currently serves no purpose, but will as of a
- * follow-up patch.)
- *
  * The job is then asked to complete before a section where the child
  * is drained.
  *
@@ -1585,7 +1584,7 @@ static const BlockJobDriver test_drop_backing_job_driver = {
  *
  * Ending the drain on parent-node-1 will poll the AioContext, which
  * lets job_exit() and thus test_drop_backing_job_commit() run.  That
- * function removes the child as parent-node-2's backing file.
+ * function first removes the child as parent-node-2's backing file.
  *
  * In old (and buggy) implementations, there are two problems with
  * that:
@@ -1604,6 +1603,34 @@ static const BlockJobDriver test_drop_backing_job_driver = {
  * bdrv_replace_child_noperm() therefore must call drained_end() on
  * the parent only if it really is still drained because the child is
  * drained.
+ *
+ * If removing child from parent-node-2 was successful (as it should
+ * be), test_drop_backing_job_commit() will then also remove the child
+ * from parent-node-0.
+ *
+ * With an old version of our drain infrastructure ((A) above), that
+ * resulted in the following flow:
+ *
+ * 1. child attempts to leave its drained section.  The call recurses
+ *    to its parents.
+ *
+ * 2. parent-node-2 leaves the drained section.  Polling in
+ *    bdrv_drain_invoke() will schedule job_exit().
+ *
+ * 3. parent-node-1 leaves the drained section.  Polling in
+ *    bdrv_drain_invoke() will run job_exit(), thus disconnecting
+ *    parent-node-0 from the child node.
+ *
+ * 4. bdrv_parent_drained_end() uses a QLIST_FOREACH_SAFE() loop to
+ *    iterate over the parents.  Thus, it now accesses the BdrvChild
+ *    object that used to connect parent-node-0 and the child node.
+ *    However, that object no longer exists, so it accesses a dangling
+ *    pointer.
+ *
+ * The solution is to only poll once when running a bdrv_drained_end()
+ * operation, specifically at the end when all drained_end()
+ * operations for all involved nodes have been scheduled.
+ * Note that this also solves (A) above, thus hiding (B).
  */
 static void test_blockjob_commit_by_drained_end(void)
 {
@@ -1627,6 +1654,7 @@ static void test_blockjob_commit_by_drained_end(void)
                            bs_parents[2], 0, BLK_PERM_ALL, 0, 0, NULL, NULL,
                            &error_abort);
 
+    job->detach_also = bs_parents[0];
     job->did_complete = &job_has_completed;
 
     job_start(&job->common.job);
-- 
2.20.1



  parent reply	other threads:[~2019-07-19 13:46 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-19 13:43 [Qemu-devel] [PULL 00/13] Block layer patches Kevin Wolf
2019-07-19 13:43 ` [Qemu-devel] [PULL 01/13] iotests: Set read-zeroes on in null block driver for Valgrind Kevin Wolf
2019-07-24  7:18   ` Christian Borntraeger
2019-07-24  7:30     ` Andrey Shinkevich
2019-07-24  7:33       ` Christian Borntraeger
2019-07-24  7:37         ` Andrey Shinkevich
2019-07-24  7:38       ` Kevin Wolf
2019-07-24  7:57         ` Andrey Shinkevich
2019-07-24  8:05           ` Kevin Wolf
2019-07-24  8:23             ` Andrey Shinkevich
2019-07-19 13:43 ` [Qemu-devel] [PULL 02/13] block: Introduce BdrvChild.parent_quiesce_counter Kevin Wolf
2019-07-19 13:43 ` [Qemu-devel] [PULL 03/13] tests: Add job commit by drained_end test Kevin Wolf
2019-07-19 13:43 ` [Qemu-devel] [PULL 04/13] block: Add @drained_end_counter Kevin Wolf
2019-07-19 13:43 ` [Qemu-devel] [PULL 05/13] block: Make bdrv_parent_drained_[^_]*() static Kevin Wolf
2019-07-19 13:43 ` [Qemu-devel] [PULL 06/13] tests: Lock AioContexts in test-block-iothread Kevin Wolf
2019-07-19 13:43 ` [Qemu-devel] [PULL 07/13] block: Do not poll in bdrv_do_drained_end() Kevin Wolf
2019-07-19 13:43 ` Kevin Wolf [this message]
2019-07-19 13:43 ` [Qemu-devel] [PULL 09/13] block: Loop unsafely in bdrv*drained_end() Kevin Wolf
2019-07-19 13:43 ` [Qemu-devel] [PULL 10/13] iotests: Add @has_quit to vm.shutdown() Kevin Wolf
2019-07-19 13:43 ` [Qemu-devel] [PULL 11/13] iotests: Test commit with a filter on the chain Kevin Wolf
2019-07-19 13:43 ` [Qemu-devel] [PULL 12/13] vl: Drain before (block) job cancel when quitting Kevin Wolf
2019-07-19 13:43 ` [Qemu-devel] [PULL 13/13] iotests: Test quitting with job on throttled node Kevin Wolf
2019-07-22  9:11 ` [Qemu-devel] [PULL 00/13] Block layer patches Peter Maydell

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=20190719134345.23526-9-kwolf@redhat.com \
    --to=kwolf@redhat.com \
    --cc=peter.maydell@linaro.org \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.