From: Stefan Hajnoczi <stefanha@redhat.com>
To: qemu-devel@nongnu.org
Cc: Max Reitz <mreitz@redhat.com>,
qemu-block@nongnu.org, Stefano Panella <spanella@gmail.com>,
Kevin Wolf <kwolf@redhat.com>,
Stefan Hajnoczi <stefanha@redhat.com>
Subject: [Qemu-devel] [PATCH 1/2] block: let blk_add/remove_aio_context_notifier() tolerate BDS changes
Date: Tue, 6 Mar 2018 20:48:18 +0000 [thread overview]
Message-ID: <20180306204819.11266-2-stefanha@redhat.com> (raw)
In-Reply-To: <20180306204819.11266-1-stefanha@redhat.com>
Commit 2019ba0a0197 ("block: Add AioContextNotifier functions to BB")
added blk_add/remove_aio_context_notifier() and implemented them by
passing through the bdrv_*() equivalent.
This doesn't work across bdrv_append(), which detaches child->bs and
re-attaches it to a new BlockDriverState. When
blk_remove_aio_context_notifier() is called we will access the new BDS
instead of the one where the notifier was added!
>From the point of view of the blk_*() API user, changes to the root BDS
should be transparent.
This patch maintains a list of AioContext notifiers in BlockBackend and
adds/removes them from the BlockDriverState as needed.
Reported-by: Stefano Panella <spanella@gmail.com>
Cc: Max Reitz <mreitz@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/block-backend.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++
block/trace-events | 2 ++
2 files changed, 65 insertions(+)
diff --git a/block/block-backend.c b/block/block-backend.c
index 94ffbb6a60..aa27698820 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -31,6 +31,13 @@
static AioContext *blk_aiocb_get_aio_context(BlockAIOCB *acb);
+typedef struct BlockBackendAioNotifier {
+ void (*attached_aio_context)(AioContext *new_context, void *opaque);
+ void (*detach_aio_context)(void *opaque);
+ void *opaque;
+ QLIST_ENTRY(BlockBackendAioNotifier) list;
+} BlockBackendAioNotifier;
+
struct BlockBackend {
char *name;
int refcnt;
@@ -69,6 +76,7 @@ struct BlockBackend {
bool allow_write_beyond_eof;
NotifierList remove_bs_notifiers, insert_bs_notifiers;
+ QLIST_HEAD(, BlockBackendAioNotifier) aio_notifiers;
int quiesce_counter;
VMChangeStateEntry *vmsh;
@@ -239,6 +247,36 @@ static int blk_root_inactivate(BdrvChild *child)
return 0;
}
+static void blk_root_attach(BdrvChild *child)
+{
+ BlockBackend *blk = child->opaque;
+ BlockBackendAioNotifier *notifier;
+
+ trace_blk_root_attach(child, blk, child->bs);
+
+ QLIST_FOREACH(notifier, &blk->aio_notifiers, list) {
+ bdrv_add_aio_context_notifier(child->bs,
+ notifier->attached_aio_context,
+ notifier->detach_aio_context,
+ notifier->opaque);
+ }
+}
+
+static void blk_root_detach(BdrvChild *child)
+{
+ BlockBackend *blk = child->opaque;
+ BlockBackendAioNotifier *notifier;
+
+ trace_blk_root_detach(child, blk, child->bs);
+
+ QLIST_FOREACH(notifier, &blk->aio_notifiers, list) {
+ bdrv_remove_aio_context_notifier(child->bs,
+ notifier->attached_aio_context,
+ notifier->detach_aio_context,
+ notifier->opaque);
+ }
+}
+
static const BdrvChildRole child_root = {
.inherit_options = blk_root_inherit_options,
@@ -252,6 +290,9 @@ static const BdrvChildRole child_root = {
.activate = blk_root_activate,
.inactivate = blk_root_inactivate,
+
+ .attach = blk_root_attach,
+ .detach = blk_root_detach,
};
/*
@@ -279,6 +320,7 @@ BlockBackend *blk_new(uint64_t perm, uint64_t shared_perm)
notifier_list_init(&blk->remove_bs_notifiers);
notifier_list_init(&blk->insert_bs_notifiers);
+ QLIST_INIT(&blk->aio_notifiers);
QTAILQ_INSERT_TAIL(&block_backends, blk, link);
return blk;
@@ -356,6 +398,7 @@ static void blk_delete(BlockBackend *blk)
}
assert(QLIST_EMPTY(&blk->remove_bs_notifiers.notifiers));
assert(QLIST_EMPTY(&blk->insert_bs_notifiers.notifiers));
+ assert(QLIST_EMPTY(&blk->aio_notifiers));
QTAILQ_REMOVE(&block_backends, blk, link);
drive_info_del(blk->legacy_dinfo);
block_acct_cleanup(&blk->stats);
@@ -1813,8 +1856,15 @@ void blk_add_aio_context_notifier(BlockBackend *blk,
void (*attached_aio_context)(AioContext *new_context, void *opaque),
void (*detach_aio_context)(void *opaque), void *opaque)
{
+ BlockBackendAioNotifier *notifier;
BlockDriverState *bs = blk_bs(blk);
+ notifier = g_new(BlockBackendAioNotifier, 1);
+ notifier->attached_aio_context = attached_aio_context;
+ notifier->detach_aio_context = detach_aio_context;
+ notifier->opaque = opaque;
+ QLIST_INSERT_HEAD(&blk->aio_notifiers, notifier, list);
+
if (bs) {
bdrv_add_aio_context_notifier(bs, attached_aio_context,
detach_aio_context, opaque);
@@ -1827,12 +1877,25 @@ void blk_remove_aio_context_notifier(BlockBackend *blk,
void (*detach_aio_context)(void *),
void *opaque)
{
+ BlockBackendAioNotifier *notifier;
BlockDriverState *bs = blk_bs(blk);
if (bs) {
bdrv_remove_aio_context_notifier(bs, attached_aio_context,
detach_aio_context, opaque);
}
+
+ QLIST_FOREACH(notifier, &blk->aio_notifiers, list) {
+ if (notifier->attached_aio_context == attached_aio_context &&
+ notifier->detach_aio_context == detach_aio_context &&
+ notifier->opaque == opaque) {
+ QLIST_REMOVE(notifier, list);
+ g_free(notifier);
+ return;
+ }
+ }
+
+ abort();
}
void blk_add_remove_bs_notifier(BlockBackend *blk, Notifier *notify)
diff --git a/block/trace-events b/block/trace-events
index 02dd80ff0c..7493d521dc 100644
--- a/block/trace-events
+++ b/block/trace-events
@@ -7,6 +7,8 @@ bdrv_lock_medium(void *bs, bool locked) "bs %p locked %d"
# block/block-backend.c
blk_co_preadv(void *blk, void *bs, int64_t offset, unsigned int bytes, int flags) "blk %p bs %p offset %"PRId64" bytes %u flags 0x%x"
blk_co_pwritev(void *blk, void *bs, int64_t offset, unsigned int bytes, int flags) "blk %p bs %p offset %"PRId64" bytes %u flags 0x%x"
+blk_root_attach(void *child, void *blk, void *bs) "child %p blk %p bs %p"
+blk_root_detach(void *child, void *blk, void *bs) "child %p blk %p bs %p"
# block/io.c
bdrv_co_preadv(void *bs, int64_t offset, int64_t nbytes, unsigned int flags) "bs %p offset %"PRId64" nbytes %"PRId64" flags 0x%x"
--
2.14.3
next prev parent reply other threads:[~2018-03-06 20:49 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-03-06 20:48 [Qemu-devel] [PATCH 0/2] block: fix nbd-server-stop crash after blockdev-snapshot-sync Stefan Hajnoczi
2018-03-06 20:48 ` Stefan Hajnoczi [this message]
2018-03-09 15:56 ` [Qemu-devel] [PATCH 1/2] block: let blk_add/remove_aio_context_notifier() tolerate BDS changes Eric Blake
2018-03-12 11:27 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi
2018-03-12 12:26 ` Eric Blake
2018-03-12 16:17 ` [Qemu-devel] " Max Reitz
2018-03-06 20:48 ` [Qemu-devel] [PATCH 2/2] iotests: add 208 nbd-server + blockdev-snapshot-sync test case Stefan Hajnoczi
2018-03-06 23:25 ` Stefano Panella
2018-03-07 10:55 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi
2018-03-07 13:57 ` Stefano Panella
2018-03-07 16:16 ` Stefan Hajnoczi
2018-03-07 16:43 ` Stefano Panella
2018-03-07 16:46 ` Max Reitz
2018-03-07 16:43 ` Max Reitz
2018-03-09 16:08 ` [Qemu-devel] " Eric Blake
2018-03-12 16:27 ` Max Reitz
2018-03-07 23:27 ` [Qemu-devel] [PATCH 0/2] block: fix nbd-server-stop crash after blockdev-snapshot-sync Eric Blake
2018-03-08 17:37 ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi
2018-03-13 1:27 ` Eric Blake
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=20180306204819.11266-2-stefanha@redhat.com \
--to=stefanha@redhat.com \
--cc=kwolf@redhat.com \
--cc=mreitz@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=spanella@gmail.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).