qemu-block
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 2/3] block-backend: add graph change notifier API


From: Stefan Hajnoczi
Subject: [PATCH 2/3] block-backend: add graph change notifier API
Date: Wed, 4 Jan 2023 17:06:30 -0500

The existing blk_add_insert_bs_notifier() and
blk_add_remove_bs_notifier() APIs only monitor changes to the
BlockBackend's root node. There is no way to find out if other nodes are
inserted or removed.

Add an API to monitor changes to the full graph. The next commit will
use this to reset blk_ram_registrar so that
blk_register_buf()/blk_unregister_buf() is called as nodes are
inserted/removed anywhere in the graph.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 include/sysemu/block-backend-global-state.h | 10 +++
 block/block-backend.c                       | 79 +++++++++++++++++++++
 block/trace-events                          |  2 +
 3 files changed, 91 insertions(+)

diff --git a/include/sysemu/block-backend-global-state.h 
b/include/sysemu/block-backend-global-state.h
index 6858e39cb6..736df34bf0 100644
--- a/include/sysemu/block-backend-global-state.h
+++ b/include/sysemu/block-backend-global-state.h
@@ -89,6 +89,16 @@ void blk_remove_aio_context_notifier(BlockBackend *blk,
                                      void *opaque);
 void blk_add_remove_bs_notifier(BlockBackend *blk, Notifier *notify);
 void blk_add_insert_bs_notifier(BlockBackend *blk, Notifier *notify);
+void blk_add_graph_change_notifier(BlockBackend *blk,
+                                   void (*pre_detach)(BlockBackend *, void *),
+                                   void (*post_attach)(BlockBackend *, void *),
+                                   void *opaque);
+void blk_remove_graph_change_notifier(BlockBackend *blk,
+                                      void (*pre_detach)(BlockBackend *,
+                                                         void *),
+                                      void (*post_attach)(BlockBackend *,
+                                                          void *),
+                                      void *opaque);
 BlockBackendRootState *blk_get_root_state(BlockBackend *blk);
 void blk_update_root_state(BlockBackend *blk);
 bool blk_get_detect_zeroes_from_root_state(BlockBackend *blk);
diff --git a/block/block-backend.c b/block/block-backend.c
index ba7bf1d6bc..40d958ffad 100644
--- a/block/block-backend.c
+++ b/block/block-backend.c
@@ -42,6 +42,13 @@ typedef struct BlockBackendAioNotifier {
     QLIST_ENTRY(BlockBackendAioNotifier) list;
 } BlockBackendAioNotifier;
 
+typedef struct BlockBackendGraphChangeNotifier {
+    void (*pre_detach)(BlockBackend *blk, void *opaque);
+    void (*post_attach)(BlockBackend *blk, void *opaque);
+    void *opaque;
+    QLIST_ENTRY(BlockBackendGraphChangeNotifier) list;
+} BlockBackendGraphChangeNotifier;
+
 struct BlockBackend {
     char *name;
     int refcnt;
@@ -79,6 +86,7 @@ struct BlockBackend {
     /* Protected by BQL */
     NotifierList remove_bs_notifiers, insert_bs_notifiers;
     QLIST_HEAD(, BlockBackendAioNotifier) aio_notifiers;
+    QLIST_HEAD(, BlockBackendGraphChangeNotifier) graph_change_notifiers;
 
     int quiesce_counter;
     CoQueue queued_requests;
@@ -308,6 +316,36 @@ static void blk_root_detach(BdrvChild *child)
     }
 }
 
+static void blk_root_pre_detach(BdrvChild *child, BdrvChild *to_detach)
+{
+    BlockBackend *blk = child->opaque;
+    BlockBackendGraphChangeNotifier *notifier;
+    BlockBackendGraphChangeNotifier *next;
+
+    trace_blk_root_pre_detach(child, blk, to_detach, to_detach->bs);
+
+    QLIST_FOREACH_SAFE(notifier, &blk->graph_change_notifiers, list, next) {
+        if (notifier->pre_detach) {
+            notifier->pre_detach(blk, notifier->opaque);
+        }
+    }
+}
+
+static void blk_root_post_attach(BdrvChild *child, BdrvChild *attached)
+{
+    BlockBackend *blk = child->opaque;
+    BlockBackendGraphChangeNotifier *notifier;
+    BlockBackendGraphChangeNotifier *next;
+
+    trace_blk_root_post_attach(child, blk, attached, attached->bs);
+
+    QLIST_FOREACH_SAFE(notifier, &blk->graph_change_notifiers, list, next) {
+        if (notifier->post_attach) {
+            notifier->post_attach(blk, notifier->opaque);
+        }
+    }
+}
+
 static AioContext *blk_root_get_parent_aio_context(BdrvChild *c)
 {
     BlockBackend *blk = c->opaque;
@@ -334,6 +372,9 @@ static const BdrvChildClass child_root = {
     .attach             = blk_root_attach,
     .detach             = blk_root_detach,
 
+    .pre_detach         = blk_root_pre_detach,
+    .post_attach        = blk_root_post_attach,
+
     .change_aio_ctx     = blk_root_change_aio_ctx,
 
     .get_parent_aio_context = blk_root_get_parent_aio_context,
@@ -372,6 +413,7 @@ BlockBackend *blk_new(AioContext *ctx, 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);
+    QLIST_INIT(&blk->graph_change_notifiers);
 
     QTAILQ_INSERT_TAIL(&block_backends, blk, link);
     return blk;
@@ -485,6 +527,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));
+    assert(QLIST_EMPTY(&blk->graph_change_notifiers));
     QTAILQ_REMOVE(&block_backends, blk, link);
     drive_info_del(blk->legacy_dinfo);
     block_acct_cleanup(&blk->stats);
@@ -2315,6 +2358,42 @@ void blk_add_insert_bs_notifier(BlockBackend *blk, 
Notifier *notify)
     notifier_list_add(&blk->insert_bs_notifiers, notify);
 }
 
+void blk_add_graph_change_notifier(BlockBackend *blk,
+        void (*pre_detach)(BlockBackend *blk, void *),
+        void (*post_attach)(BlockBackend *blk, void *),
+        void *opaque)
+{
+    BlockBackendGraphChangeNotifier *notifier;
+    GLOBAL_STATE_CODE();
+
+    notifier = g_new(BlockBackendGraphChangeNotifier, 1);
+    notifier->pre_detach = pre_detach;
+    notifier->post_attach = post_attach;
+    notifier->opaque = opaque;
+    QLIST_INSERT_HEAD(&blk->graph_change_notifiers, notifier, list);
+}
+
+void blk_remove_graph_change_notifier(BlockBackend *blk,
+        void (*pre_detach)(BlockBackend *blk, void *),
+        void (*post_attach)(BlockBackend *blk, void *),
+        void *opaque)
+{
+    BlockBackendGraphChangeNotifier *notifier;
+    GLOBAL_STATE_CODE();
+
+    QLIST_FOREACH(notifier, &blk->graph_change_notifiers, list) {
+        if (notifier->pre_detach == pre_detach &&
+            notifier->post_attach == post_attach &&
+            notifier->opaque == opaque) {
+            QLIST_REMOVE(notifier, list);
+            g_free(notifier);
+            return;
+        }
+    }
+
+    abort();
+}
+
 void blk_io_plug(BlockBackend *blk)
 {
     BlockDriverState *bs = blk_bs(blk);
diff --git a/block/trace-events b/block/trace-events
index 48dbf10c66..74f05b50b9 100644
--- a/block/trace-events
+++ b/block/trace-events
@@ -9,6 +9,8 @@ blk_co_preadv(void *blk, void *bs, int64_t offset, int64_t 
bytes, int flags) "bl
 blk_co_pwritev(void *blk, void *bs, int64_t offset, int64_t bytes, int flags) 
"blk %p bs %p offset %"PRId64" bytes %" PRId64 " 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"
+blk_root_pre_detach(void *child, void *blk, void *to_detach, void 
*to_detach_bs) "child %p blk %p to_detach %p to_detach_bs %p"
+blk_root_post_attach(void *child, void *blk, void *attached, void 
*attached_bs) "child %p blk %p attached %p attached_bs %p"
 
 # io.c
 bdrv_co_preadv_part(void *bs, int64_t offset, int64_t bytes, unsigned int 
flags) "bs %p offset %" PRId64 " bytes %" PRId64 " flags 0x%x"
-- 
2.39.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]