The RAM save/restore code needs the RAMBlock in RAMBlockNotifier
callbacks to decide whether migration must be aborted and to update
RAMBlock state for postcopy. Looking up the RAMBlock inside callbacks is
hazardous: with Xen mapcache it can deadlock, and it also leaves the
callback contract unclear.
Pass the RAMBlock explicitly to RAMBlockNotifier callbacks. The
ram_block_resized callback takes a non-const RAMBlock because it may
modify the RAMBlock, while the other callbacks take const RAMBlock.
Xen mapcache passes NULL because mapcache entries do not have a
one-to-one relationship with RAMBlocks. ram_block_resized() is never
called from Xen mapcache, so its RAMBlock argument is always non-NULL.
Drop redundant parameters from ram_block_resized() because they can be
derived from the RAMBlock. Keep them for the other callbacks because
their RAMBlock argument may be NULL.
Signed-off-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
---
include/system/ramlist.h | 18 ++++++++++--------
block/block-ram-registrar.c | 8 ++++----
hw/core/numa.c | 18 ++++++++++--------
hw/xen/xen-mapcache.c | 6 +++---
migration/ram.c | 12 +++---------
system/physmem.c | 7 +++----
target/i386/nvmm/nvmm-all.c | 4 ++--
target/i386/sev.c | 8 ++++----
util/vfio-helpers.c | 7 ++++---
9 files changed, 43 insertions(+), 45 deletions(-)
diff --git a/include/system/ramlist.h b/include/system/ramlist.h
index c7f388f487d7..32157cc84305 100644
--- a/include/system/ramlist.h
+++ b/include/system/ramlist.h
@@ -62,11 +62,11 @@ void qemu_mutex_lock_ramlist(void);
void qemu_mutex_unlock_ramlist(void);
struct RAMBlockNotifier {
- void (*ram_block_added)(RAMBlockNotifier *n, void *host, size_t size,
- size_t max_size);
- void (*ram_block_removed)(RAMBlockNotifier *n, void *host, size_t size,
- size_t max_size);
- void (*ram_block_resized)(RAMBlockNotifier *n, void *host, size_t old_size,
+ void (*ram_block_added)(RAMBlockNotifier *n, const RAMBlock *rb,
+ void *host, size_t size, size_t max_size);
+ void (*ram_block_removed)(RAMBlockNotifier *n, const RAMBlock *rb,
+ void *host, size_t size, size_t max_size);
+ void (*ram_block_resized)(RAMBlockNotifier *n, RAMBlock *rb,
size_t new_size);
QLIST_ENTRY(RAMBlockNotifier) next;
};
@@ -77,9 +77,11 @@ int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque);
void ram_block_notifier_add(RAMBlockNotifier *n);
void ram_block_notifier_remove(RAMBlockNotifier *n);
-void ram_block_notify_add(void *host, size_t size, size_t max_size);
-void ram_block_notify_remove(void *host, size_t size, size_t max_size);
-void ram_block_notify_resize(void *host, size_t old_size, size_t new_size);
+void ram_block_notify_add(const RAMBlock *rb,
+ void *host, size_t size, size_t max_size);
+void ram_block_notify_remove(const RAMBlock *rb,
+ void *host, size_t size, size_t max_size);
+void ram_block_notify_resize(RAMBlock *rb, size_t new_size);
GString *ram_block_format(void);
diff --git a/block/block-ram-registrar.c b/block/block-ram-registrar.c
index fcda2b86afb2..5b938de22587 100644
--- a/block/block-ram-registrar.c
+++ b/block/block-ram-registrar.c
@@ -9,8 +9,8 @@
#include "system/block-ram-registrar.h"
#include "qapi/error.h"
-static void ram_block_added(RAMBlockNotifier *n, void *host, size_t size,
- size_t max_size)
+static void ram_block_added(RAMBlockNotifier *n, const RAMBlock *rb,
+ void *host, size_t size, size_t max_size)
{
BlockRAMRegistrar *r = container_of(n, BlockRAMRegistrar, notifier);
Error *err = NULL;
@@ -26,8 +26,8 @@ static void ram_block_added(RAMBlockNotifier *n, void *host, size_t size,
}
}
-static void ram_block_removed(RAMBlockNotifier *n, void *host, size_t size,
- size_t max_size)
+static void ram_block_removed(RAMBlockNotifier *n, const RAMBlock *rb,
+ void *host, size_t size, size_t max_size)
{
BlockRAMRegistrar *r = container_of(n, BlockRAMRegistrar, notifier);
blk_unregister_buf(r->blk, host, max_size);
diff --git a/hw/core/numa.c b/hw/core/numa.c
index f462883c87cf..40acb98bdd0b 100644
--- a/hw/core/numa.c
+++ b/hw/core/numa.c
@@ -824,7 +824,7 @@ static int ram_block_notify_add_single(RAMBlock *rb, void *opaque)
RAMBlockNotifier *notifier = opaque;
if (host) {
- notifier->ram_block_added(notifier, host, size, max_size);
+ notifier->ram_block_added(notifier, rb, host, size, max_size);
}
return 0;
}
@@ -837,7 +837,7 @@ static int ram_block_notify_remove_single(RAMBlock *rb, void *opaque)
RAMBlockNotifier *notifier = opaque;
if (host) {
- notifier->ram_block_removed(notifier, host, size, max_size);
+ notifier->ram_block_removed(notifier, rb, host, size, max_size);
}
return 0;
}
@@ -861,38 +861,40 @@ void ram_block_notifier_remove(RAMBlockNotifier *n)
}
}
-void ram_block_notify_add(void *host, size_t size, size_t max_size)
+void ram_block_notify_add(const RAMBlock *rb,
+ void *host, size_t size, size_t max_size)
{
RAMBlockNotifier *notifier;
RAMBlockNotifier *next;
QLIST_FOREACH_SAFE(notifier, &ram_list.ramblock_notifiers, next, next) {
if (notifier->ram_block_added) {
- notifier->ram_block_added(notifier, host, size, max_size);
+ notifier->ram_block_added(notifier, rb, host, size, max_size);
}
}
}
-void ram_block_notify_remove(void *host, size_t size, size_t max_size)
+void ram_block_notify_remove(const RAMBlock *rb,
+ void *host, size_t size, size_t max_size)
{
RAMBlockNotifier *notifier;
RAMBlockNotifier *next;
QLIST_FOREACH_SAFE(notifier, &ram_list.ramblock_notifiers, next, next) {
if (notifier->ram_block_removed) {
- notifier->ram_block_removed(notifier, host, size, max_size);
+ notifier->ram_block_removed(notifier, rb, host, size, max_size);
}
}
}
-void ram_block_notify_resize(void *host, size_t old_size, size_t new_size)
+void ram_block_notify_resize(RAMBlock *rb, size_t new_size)
{
RAMBlockNotifier *notifier;
RAMBlockNotifier *next;
QLIST_FOREACH_SAFE(notifier, &ram_list.ramblock_notifiers, next, next) {
if (notifier->ram_block_resized) {
- notifier->ram_block_resized(notifier, host, old_size, new_size);
+ notifier->ram_block_resized(notifier, rb, new_size);
}
}
}
diff --git a/hw/xen/xen-mapcache.c b/hw/xen/xen-mapcache.c
index 85cf0cf359ca..f321c65b630e 100644
--- a/hw/xen/xen-mapcache.c
+++ b/hw/xen/xen-mapcache.c
@@ -222,7 +222,7 @@ static void xen_remap_bucket(MapCache *mc,
if (entry->vaddr_base != NULL) {
if (!(entry->flags & XEN_MAPCACHE_ENTRY_DUMMY)) {
- ram_block_notify_remove(entry->vaddr_base, entry->size,
+ ram_block_notify_remove(NULL, entry->vaddr_base, entry->size,
entry->size);
}
@@ -308,7 +308,7 @@ static void xen_remap_bucket(MapCache *mc,
}
if (!(entry->flags & XEN_MAPCACHE_ENTRY_DUMMY)) {
- ram_block_notify_add(vaddr_base, size, size);
+ ram_block_notify_add(NULL, vaddr_base, size, size);
}
entry->vaddr_base = vaddr_base;
@@ -601,7 +601,7 @@ static void xen_invalidate_map_cache_entry_unlocked(MapCache *mc,
return;
}
- ram_block_notify_remove(entry->vaddr_base, entry->size, entry->size);
+ ram_block_notify_remove(NULL, entry->vaddr_base, entry->size, entry->size);
if (entry->flags & XEN_MAPCACHE_ENTRY_GRANT) {
rc = xengnttab_unmap(xen_region_gnttabdev, entry->vaddr_base,
entry->size >> mc->bucket_shift);
diff --git a/migration/ram.c b/migration/ram.c
index fc38ffbf8af1..6bc7f705d31a 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -4699,18 +4699,12 @@ static SaveVMHandlers savevm_ram_handlers = {
.save_postcopy_prepare = ram_save_postcopy_prepare,
};
-static void ram_mig_ram_block_resized(RAMBlockNotifier *n, void *host,
- size_t old_size, size_t new_size)
+static void ram_mig_ram_block_resized(RAMBlockNotifier *n, RAMBlock *rb,
+ size_t new_size)
{
PostcopyState ps = postcopy_state_get();
- ram_addr_t offset;
- RAMBlock *rb = qemu_ram_block_from_host(host, false, &offset);
Error *err = NULL;
-
- if (!rb) {
- error_report("RAM block not found");
- return;
- }
+ ram_addr_t old_size = qemu_ram_get_used_length(rb);
if (migrate_ram_is_ignored(rb)) {
return;
diff --git a/system/physmem.c b/system/physmem.c
index 54fe820ce828..1427949b72cd 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -2019,7 +2019,6 @@ static int memory_try_enable_merging(void *addr, size_t len)
*/
int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp)
{
- const ram_addr_t oldsize = block->used_length;
const ram_addr_t unaligned_size = newsize;
newsize = TARGET_PAGE_ALIGN(newsize);
@@ -2054,7 +2053,7 @@ int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp)
/* Notify before modifying the ram block and touching the bitmaps. */
if (block->host) {
- ram_block_notify_resize(block->host, oldsize, newsize);
+ ram_block_notify_resize(block, newsize);
}
physical_memory_clear_dirty_range(block->offset, block->used_length);
@@ -2277,7 +2276,7 @@ static void ram_block_add(RAMBlock *new_block, Error **errp)
qemu_madvise(new_block->host, new_block->max_length,
QEMU_MADV_DONTFORK);
}
- ram_block_notify_add(new_block->host, new_block->used_length,
+ ram_block_notify_add(new_block, new_block->host, new_block->used_length,
new_block->max_length);
}
return;
@@ -2588,7 +2587,7 @@ void qemu_ram_free(RAMBlock *block)
}
if (block->host) {
- ram_block_notify_remove(block->host, block->used_length,
+ ram_block_notify_remove(block, block->host, block->used_length,
block->max_length);
}
diff --git a/target/i386/nvmm/nvmm-all.c b/target/i386/nvmm/nvmm-all.c
index 8a1af35ed32b..f29b9c504ea8 100644
--- a/target/i386/nvmm/nvmm-all.c
+++ b/target/i386/nvmm/nvmm-all.c
@@ -1134,8 +1134,8 @@ static MemoryListener nvmm_memory_listener = {
};
static void
-nvmm_ram_block_added(RAMBlockNotifier *n, void *host, size_t size,
- size_t max_size)
+nvmm_ram_block_added(RAMBlockNotifier *n, const RAMBlock *rb,
+ void *host, size_t size, size_t max_size)
{
struct nvmm_machine *mach = get_nvmm_mach();
uintptr_t hva = (uintptr_t)host;
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 99cf30806be7..55e74f1c8f9c 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -329,8 +329,8 @@ sev_set_guest_state(SevCommonState *sev_common, SevState new_state)
}
static void
-sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size,
- size_t max_size)
+sev_ram_block_added(RAMBlockNotifier *n, const RAMBlock *rb,
+ void *host, size_t size, size_t max_size)
{
int r;
struct kvm_enc_region range;
@@ -359,8 +359,8 @@ sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size,
}
static void
-sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size,
- size_t max_size)
+sev_ram_block_removed(RAMBlockNotifier *n, const RAMBlock *rb,
+ void *host, size_t size, size_t max_size)
{
int r;
struct kvm_enc_region range;
diff --git a/util/vfio-helpers.c b/util/vfio-helpers.c
index aab0bf9d485d..5059ed44b8af 100644
--- a/util/vfio-helpers.c
+++ b/util/vfio-helpers.c
@@ -465,8 +465,8 @@ fail_container:
return ret;
}
-static void qemu_vfio_ram_block_added(RAMBlockNotifier *n, void *host,
- size_t size, size_t max_size)
+static void qemu_vfio_ram_block_added(RAMBlockNotifier *n, const RAMBlock *rb,
+ void *host, size_t size, size_t max_size)
{
QEMUVFIOState *s = container_of(n, QEMUVFIOState, ram_notifier);
Error *local_err = NULL;
@@ -481,7 +481,8 @@ static void qemu_vfio_ram_block_added(RAMBlockNotifier *n, void *host,
}
}
-static void qemu_vfio_ram_block_removed(RAMBlockNotifier *n, void *host,
+static void qemu_vfio_ram_block_removed(RAMBlockNotifier *n, const RAMBlock *rb,
+ void *host,
size_t size, size_t max_size)
{
QEMUVFIOState *s = container_of(n, QEMUVFIOState, ram_notifier);
--
2.54.0
© 2016 - 2026 Red Hat, Inc.