From 32c835ba3984728c22d4e73cdb595090a60f437e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 22 Feb 2013 17:36:27 +0100 Subject: migration: run pending/iterate callbacks out of big lock This makes it possible to do blocking writes directly to the socket, with no buffer in the middle. For RAM, only the migration_bitmap_sync() call needs the iothread lock. For block migration, it is needed by the block layer (including bdrv_drain_all and dirty bitmap access), but because some code is shared between iterate and complete, all of mig_save_device_dirty is run with the lock taken. In the savevm case, the iterate callback runs within the big lock. This is annoying because it complicates the rules. Luckily we do not need to do anything about it: the RAM iterate callback does not need the iothread lock, and block migration never runs during savevm. Reviewed-by: Orit Wasserman Reviewed-by: Juan Quintela Signed-off-by: Paolo Bonzini Signed-off-by: Juan Quintela --- arch_init.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'arch_init.c') diff --git a/arch_init.c b/arch_init.c index 8daeafa..32b4378 100644 --- a/arch_init.c +++ b/arch_init.c @@ -379,6 +379,8 @@ static inline bool migration_bitmap_set_dirty(MemoryRegion *mr, return ret; } +/* Needs iothread lock! */ + static void migration_bitmap_sync(void) { RAMBlock *block; @@ -690,7 +692,9 @@ static uint64_t ram_save_pending(QEMUFile *f, void *opaque, uint64_t max_size) remaining_size = ram_save_remaining() * TARGET_PAGE_SIZE; if (remaining_size < max_size) { + qemu_mutex_lock_iothread(); migration_bitmap_sync(); + qemu_mutex_unlock_iothread(); remaining_size = ram_save_remaining() * TARGET_PAGE_SIZE; } return remaining_size; -- cgit v1.1 From 9b0950375277467fd74a9075624477ae43b9bb22 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 22 Feb 2013 17:36:28 +0100 Subject: migration: run setup callbacks out of big lock Only the migration_bitmap_sync() call needs the iothread lock. Reviewed-by: Orit Wasserman Reviewed-by: Juan Quintela Signed-off-by: Paolo Bonzini Signed-off-by: Juan Quintela --- arch_init.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'arch_init.c') diff --git a/arch_init.c b/arch_init.c index 32b4378..6089c53 100644 --- a/arch_init.c +++ b/arch_init.c @@ -570,10 +570,6 @@ static int ram_save_setup(QEMUFile *f, void *opaque) bitmap_set(migration_bitmap, 0, ram_pages); migration_dirty_pages = ram_pages; - qemu_mutex_lock_ramlist(); - bytes_transferred = 0; - reset_ram_globals(); - if (migrate_use_xbzrle()) { XBZRLE.cache = cache_init(migrate_xbzrle_cache_size() / TARGET_PAGE_SIZE, @@ -587,8 +583,14 @@ static int ram_save_setup(QEMUFile *f, void *opaque) acct_clear(); } + qemu_mutex_lock_iothread(); + qemu_mutex_lock_ramlist(); + bytes_transferred = 0; + reset_ram_globals(); + memory_global_dirty_log_start(); migration_bitmap_sync(); + qemu_mutex_unlock_iothread(); qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE); -- cgit v1.1 From ee0b44aa9d9450e873a761ca2030b2fa3ec52eb0 Mon Sep 17 00:00:00 2001 From: Peter Lieven Date: Mon, 25 Feb 2013 19:12:04 +0200 Subject: page_cache: dup memory on insert The page cache frees all data on finish, on resize and if there is collision on insert. So it should be the caches responsibility to dup the data that is stored in the cache. Signed-off-by: Peter Lieven Signed-off-by: Orit Wasserman Reviewed-by: Peter Maydell Signed-off-by: Juan Quintela --- arch_init.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch_init.c') diff --git a/arch_init.c b/arch_init.c index 6089c53..98e2bc6 100644 --- a/arch_init.c +++ b/arch_init.c @@ -293,8 +293,7 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data, if (!cache_is_cached(XBZRLE.cache, current_addr)) { if (!last_stage) { - cache_insert(XBZRLE.cache, current_addr, - g_memdup(current_data, TARGET_PAGE_SIZE)); + cache_insert(XBZRLE.cache, current_addr, current_data); } acct_info.xbzrle_cache_miss++; return -1; -- cgit v1.1