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, 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 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).