[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 3/3] block-ram-registrar: reset when the graph changes
From: |
Stefan Hajnoczi |
Subject: |
[PATCH 3/3] block-ram-registrar: reset when the graph changes |
Date: |
Wed, 4 Jan 2023 17:06:31 -0500 |
The BDRV_REQ_REGISTERED_BUF flag can be set on I/O requests to indicate
that I/O buffers were previously registered using bdrv_register_buf().
block-ram-registrar automatically registers guest RAM so that emulated
storage controllers can set BDRV_REQ_REGISTERED_BUF without having to
worry about registering buffers themselves.
Kevin Wolf <kwolf@redhat.com> pointed out that block-ram-registrar does
not handle graph changes. This means buffers aren't unregistered when a
node is removed from the graph and buffer registrations aren't replayed
when a new node is inserted in the graph. Therefore
BDRV_REQ_REGISTERED_BUF may be set but the buffer wasn't previously
registered with the new node.
Fix this by monitoring graph changes and replaying buffer registration.
Note that the ram_block_notifier_add() API enumerates all RAM blocks so
we don't need to manually replay them.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
block/block-ram-registrar.c | 40 ++++++++++++++++++++++++++++++++-----
1 file changed, 35 insertions(+), 5 deletions(-)
diff --git a/block/block-ram-registrar.c b/block/block-ram-registrar.c
index 25dbafa789..1a111ac124 100644
--- a/block/block-ram-registrar.c
+++ b/block/block-ram-registrar.c
@@ -33,6 +33,35 @@ static void ram_block_removed(RAMBlockNotifier *n, void
*host, size_t size,
blk_unregister_buf(r->blk, host, max_size);
}
+static void remove_ram_block_notifier(BlockRAMRegistrar *r)
+{
+ if (r->ok) {
+ ram_block_notifier_remove(&r->notifier);
+ }
+}
+
+static void add_ram_block_notifier(BlockRAMRegistrar *r)
+{
+ r->ok = true; /* reset flag in case it was false */
+ ram_block_notifier_add(&r->notifier);
+}
+
+static void graph_change_pre_detach(BlockBackend *blk, void *opaque)
+{
+ BlockRAMRegistrar *r = opaque;
+
+ /* Unregisters all buffers from all BDSes */
+ remove_ram_block_notifier(r);
+}
+
+static void graph_change_post_attach(BlockBackend *blk, void *opaque)
+{
+ BlockRAMRegistrar *r = opaque;
+
+ /* Re-registers all buffers with all BDSes */
+ add_ram_block_notifier(r);
+}
+
void blk_ram_registrar_init(BlockRAMRegistrar *r, BlockBackend *blk)
{
r->blk = blk;
@@ -45,14 +74,15 @@ void blk_ram_registrar_init(BlockRAMRegistrar *r,
BlockBackend *blk)
* value that does not change across resize.
*/
};
- r->ok = true;
- ram_block_notifier_add(&r->notifier);
+ blk_add_graph_change_notifier(blk, graph_change_pre_detach,
+ graph_change_post_attach, r);
+ add_ram_block_notifier(r);
}
void blk_ram_registrar_destroy(BlockRAMRegistrar *r)
{
- if (r->ok) {
- ram_block_notifier_remove(&r->notifier);
- }
+ remove_ram_block_notifier(r);
+ blk_remove_graph_change_notifier(r->blk, graph_change_pre_detach,
+ graph_change_post_attach, r);
}
--
2.39.0