On 11/23/2010 05:03 PM, Juan Quintela wrote:
From: Juan Quintela<quint...@trasno.org>
Calculate the number of dirty pages takes a lot on hosts with lots
of memory. Just maintain how many pages are dirty. Only sync bitmaps
if number is small enough.
There needs to be numbers that justify this as part of the commit message.
This only works for KVM because it happens to use set_dirty() whenever
it dirties memory. I don't think will work with TCG.
I also think that the fundamental problem is the kernel dirty bitmap.
Perhaps it should return a multiple level table instead of a simple
linear bitmap.
Regards,
Anthony Liguori
Signed-off-by: Juan Quintela<quint...@trasno.org>
Signed-off-by: Juan Quintela<quint...@redhat.com>
---
arch_init.c | 15 +--------------
cpu-all.h | 7 +++++++
exec.c | 1 +
3 files changed, 9 insertions(+), 14 deletions(-)
diff --git a/arch_init.c b/arch_init.c
index b463798..c2bc144 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -176,20 +176,7 @@ static uint64_t bytes_transferred;
static uint64_t ram_save_remaining(void)
{
- RAMBlock *block;
- uint64_t count = 0;
-
- QLIST_FOREACH(block,&ram_list.blocks, next) {
- ram_addr_t addr;
- for (addr = block->offset; addr< block->offset + block->length;
- addr += TARGET_PAGE_SIZE) {
- if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
- count++;
- }
- }
- }
-
- return count;
+ return ram_list.dirty_pages;
}
uint64_t ram_bytes_remaining(void)
diff --git a/cpu-all.h b/cpu-all.h
index 30ae17d..5dc27c6 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -874,6 +874,7 @@ typedef struct RAMBlock {
typedef struct RAMList {
uint8_t *phys_dirty;
+ uint64_t dirty_pages;
QLIST_HEAD(ram, RAMBlock) blocks;
} RAMList;
extern RAMList ram_list;
@@ -922,6 +923,9 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t
addr,
static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
{
+ if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
+ ram_list.dirty_pages++;
+
ram_list.phys_dirty[addr>> TARGET_PAGE_BITS] = 0xff;
}
@@ -942,6 +946,9 @@ static inline void
cpu_physical_memory_mask_dirty_range(ram_addr_t start,
mask = ~dirty_flags;
p = ram_list.phys_dirty + (start>> TARGET_PAGE_BITS);
for (i = 0; i< len; i++) {
+ if (cpu_physical_memory_get_dirty(start + i * TARGET_PAGE_SIZE,
+ MIGRATION_DIRTY_FLAG& dirty_flags))
+ ram_list.dirty_pages--;
p[i]&= mask;
}
}
diff --git a/exec.c b/exec.c
index f5b2386..ca2506e 100644
--- a/exec.c
+++ b/exec.c
@@ -2866,6 +2866,7 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev,
const char *name,
last_ram_offset()>> TARGET_PAGE_BITS);
memset(ram_list.phys_dirty + (new_block->offset>> TARGET_PAGE_BITS),
0xff, size>> TARGET_PAGE_BITS);
+ ram_list.dirty_pages += size>> TARGET_PAGE_BITS;
if (kvm_enabled())
kvm_setup_guest_memory(new_block->host, size);