A new field, ram_block_attribute, is introduced in RAMBlock to link to a RamBlockAttribute object. This change centralizes all guest_memfd state information (such as fd and shared_bitmap) within a RAMBlock, simplifying management.
The realize()/unrealized() helpers are used to initialize/uninitialize the RamBlockAttribute object. The object is registered/unregistered in the target RAMBlock's MemoryRegion when creating guest_memfd. Additionally, use the private_shared_manager_state_change() helper to notify the registered PrivateSharedListener of these changes. Signed-off-by: Chenyi Qiang <chenyi.qi...@intel.com> --- Changes in v4: - Remove the replay operations for attribute changes which will be handled in a listener in following patches. - Add some comment in the error path of realize() to remind the future development of the unified error path. Changes in v3: - Use ram_discard_manager_reply_populated/discarded() to set the memory attribute and add the undo support if state_change() failed. - Didn't add Reviewed-by from Alexey due to the new changes in this commit. Changes in v2: - Introduce a new field memory_attribute_manager in RAMBlock. - Move the state_change() handling during page conversion in this patch. - Undo what we did if it fails to set. - Change the order of close(guest_memfd) and memory_attribute_manager cleanup. --- accel/kvm/kvm-all.c | 9 +++++++++ include/exec/ramblock.h | 1 + system/physmem.c | 16 ++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index c1fea69d58..546b58b737 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3088,6 +3088,15 @@ int kvm_convert_memory(hwaddr start, hwaddr size, bool to_private) addr = memory_region_get_ram_ptr(mr) + section.offset_within_region; rb = qemu_ram_block_from_host(addr, false, &offset); + ret = private_shared_manager_state_change(PRIVATE_SHARED_MANAGER(mr->gsm), + offset, size, to_private); + if (ret) { + error_report("Failed to notify the listener the state change of " + "(0x%"HWADDR_PRIx" + 0x%"HWADDR_PRIx") to %s", + start, size, to_private ? "private" : "shared"); + goto out_unref; + } + if (to_private) { if (rb->page_size != qemu_real_host_page_size()) { /* diff --git a/include/exec/ramblock.h b/include/exec/ramblock.h index b8b5469db9..78eb031819 100644 --- a/include/exec/ramblock.h +++ b/include/exec/ramblock.h @@ -46,6 +46,7 @@ struct RAMBlock { int fd; uint64_t fd_offset; int guest_memfd; + RamBlockAttribute *ram_block_attribute; size_t page_size; /* dirty bitmap used during migration */ unsigned long *bmap; diff --git a/system/physmem.c b/system/physmem.c index c76503aea8..fb74321e10 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -1885,6 +1885,20 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) qemu_mutex_unlock_ramlist(); goto out_free; } + + new_block->ram_block_attribute = RAM_BLOCK_ATTRIBUTE(object_new(TYPE_RAM_BLOCK_ATTRIBUTE)); + if (ram_block_attribute_realize(new_block->ram_block_attribute, new_block->mr)) { + error_setg(errp, "Failed to realize ram block attribute"); + /* + * The error path could be unified if the rest of ram_block_add() ever + * develops a need to check for errors. + */ + object_unref(OBJECT(new_block->ram_block_attribute)); + close(new_block->guest_memfd); + ram_block_discard_require(false); + qemu_mutex_unlock_ramlist(); + goto out_free; + } } ram_size = (new_block->offset + new_block->max_length) >> TARGET_PAGE_BITS; @@ -2138,6 +2152,8 @@ static void reclaim_ramblock(RAMBlock *block) } if (block->guest_memfd >= 0) { + ram_block_attribute_unrealize(block->ram_block_attribute); + object_unref(OBJECT(block->ram_block_attribute)); close(block->guest_memfd); ram_block_discard_require(false); } -- 2.43.5