Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 340e01248478ba8b78a6d4d1809b1eff > files > 177

kvm-83-270.el5_11.src.rpm

From 51d03b1696a5f38f5eaf24c900b5dddaf92181fe Mon Sep 17 00:00:00 2001
From: Juan Quintela <quintela@redhat.com>
Date: Mon, 22 Nov 2010 15:57:08 -0200
Subject: [PATCH 4/6] Maintaing number of dirty pages

RH-Author: Juan Quintela <quintela@redhat.com>
Message-id: <45c762f4c255efddb7fdd905ae052af34f2c2d0f.1290441250.git.quintela@redhat.com>
Patchwork-id: 13778
O-Subject: [PATCH 4/6] Maintaing number of dirty pages
Bugzilla: 513765 589017
RH-Acked-by: Glauber Costa <glommer@redhat.com>
RH-Acked-by: Jes Sorensen <Jes.Sorensen@redhat.com>
RH-Acked-by: Alex Williamson <alex.williamson@redhat.com>

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.

Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 qemu/cpu-all.h |    5 +++++
 qemu/exec.c    |   28 +++++++++++++++++++++++++++-
 qemu/vl.c      |   29 +++++++++++++++++------------
 3 files changed, 49 insertions(+), 13 deletions(-)

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 qemu/cpu-all.h |    5 +++++
 qemu/exec.c    |   28 +++++++++++++++++++++++++++-
 qemu/vl.c      |   29 +++++++++++++++++------------
 3 files changed, 49 insertions(+), 13 deletions(-)

diff --git a/qemu/cpu-all.h b/qemu/cpu-all.h
index 4c3a669..14634c4 100644
--- a/qemu/cpu-all.h
+++ b/qemu/cpu-all.h
@@ -959,8 +959,13 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
     return phys_ram_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
 }
 
+extern uint64_t migration_dirty_pages;
+
 static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
 {
+    if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
+        migration_dirty_pages++;
+
     phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
 }
 
diff --git a/qemu/exec.c b/qemu/exec.c
index 37bcc7a..2b621b4 100644
--- a/qemu/exec.c
+++ b/qemu/exec.c
@@ -1863,8 +1863,12 @@ void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
 #endif
     mask = ~dirty_flags;
     p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
-    for(i = 0; i < len; i++)
+    for(i = 0; i < len; i++) {
+        if (cpu_physical_memory_get_dirty(start + i * TARGET_PAGE_SIZE,
+                                          MIGRATION_DIRTY_FLAG & dirty_flags))
+            migration_dirty_pages--;
         p[i] &= mask;
+    }
 
     if (kvm_enabled())
         return;
@@ -2512,6 +2516,9 @@ static void notdirty_mem_writeb(void *opaque, target_phys_addr_t ram_addr,
         kqemu_modify_page(cpu_single_env, ram_addr);
 #endif
     dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
+    if (!cpu_physical_memory_get_dirty(ram_addr, MIGRATION_DIRTY_FLAG))
+        migration_dirty_pages++;
+
     phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
     /* we remove the notdirty callback only if the code has been
        flushed */
@@ -2537,6 +2544,9 @@ static void notdirty_mem_writew(void *opaque, target_phys_addr_t ram_addr,
         kqemu_modify_page(cpu_single_env, ram_addr);
 #endif
     dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
+    if (!cpu_physical_memory_get_dirty(ram_addr, MIGRATION_DIRTY_FLAG))
+        migration_dirty_pages++;
+
     phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
     /* we remove the notdirty callback only if the code has been
        flushed */
@@ -2562,6 +2572,9 @@ static void notdirty_mem_writel(void *opaque, target_phys_addr_t ram_addr,
         kqemu_modify_page(cpu_single_env, ram_addr);
 #endif
     dirty_flags |= (0xff & ~CODE_DIRTY_FLAG);
+    if (!cpu_physical_memory_get_dirty(ram_addr, MIGRATION_DIRTY_FLAG))
+        migration_dirty_pages++;
+
     phys_ram_dirty[ram_addr >> TARGET_PAGE_BITS] = dirty_flags;
     /* we remove the notdirty callback only if the code has been
        flushed */
@@ -2863,6 +2876,7 @@ static void io_mem_init(void)
     /* alloc dirty bits array */
     phys_ram_dirty = qemu_vmalloc(phys_ram_size >> TARGET_PAGE_BITS);
     memset(phys_ram_dirty, 0xff, phys_ram_size >> TARGET_PAGE_BITS);
+    migration_dirty_pages = phys_ram_size >> TARGET_PAGE_BITS;
 }
 
 /* mem_read and mem_write are arrays of functions containing the
@@ -3023,6 +3037,9 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
                     /* invalidate code */
                     tb_invalidate_phys_page_range(addr1, addr1 + l, 0);
                     /* set dirty bit */
+                    if (!cpu_physical_memory_get_dirty(addr1, MIGRATION_DIRTY_FLAG))
+                        migration_dirty_pages++;
+
                     phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
                         (0xff & ~CODE_DIRTY_FLAG);
                 }
@@ -3267,6 +3284,9 @@ void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val)
                 /* invalidate code */
                 tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
                 /* set dirty bit */
+                if (!cpu_physical_memory_get_dirty(addr1, MIGRATION_DIRTY_FLAG))
+                    migration_dirty_pages++;
+
                 phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
                     (0xff & ~CODE_DIRTY_FLAG);
             }
@@ -3336,6 +3356,9 @@ void stl_phys(target_phys_addr_t addr, uint32_t val)
             /* invalidate code */
             tb_invalidate_phys_page_range(addr1, addr1 + 4, 0);
             /* set dirty bit */
+            if (!cpu_physical_memory_get_dirty(addr1, MIGRATION_DIRTY_FLAG))
+                migration_dirty_pages++;
+
             phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
                 (0xff & ~CODE_DIRTY_FLAG);
         }
@@ -3386,6 +3409,9 @@ void stw_phys_atomic(target_phys_addr_t addr, uint32_t val)
             /* invalidate code */
             tb_invalidate_phys_page_range(addr1, addr1 + 2, 0);
             /* set dirty bit */
+            if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
+                migration_dirty_pages++;
+
             phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |=
                 (0xff & ~CODE_DIRTY_FLAG);
         }
diff --git a/qemu/vl.c b/qemu/vl.c
index 23fe8ff..409daa7 100644
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -3385,6 +3385,8 @@ static int is_dup_page(uint8_t *page, uint8_t ch)
     return 1;
 }
 
+uint64_t migration_dirty_pages;
+
 static int ram_save_block(QEMUFile *f)
 {
     static ram_addr_t current_addr = 0;
@@ -3432,15 +3434,7 @@ static uint64_t bytes_transferred = 0;
 
 static ram_addr_t ram_save_remaining(void)
 {
-    ram_addr_t addr;
-    ram_addr_t count = 0;
-
-    for (addr = 0; addr < phys_ram_size; addr += TARGET_PAGE_SIZE) {
-        if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
-            count++;
-    }
-
-    return count;
+    return migration_dirty_pages;
 }
 
 uint64_t ram_bytes_remaining(void)
@@ -3516,9 +3510,20 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque)
 
     qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
 
-    expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
-
-    return (stage == 2) && (expected_time <= migrate_max_downtime());
+    if (stage == 2) {
+        expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
+        if (expected_time <= migrate_max_downtime()) {
+            int r;
+            if (kvm_enabled() && (r = kvm_update_dirty_pages_log())) {
+                printf("%s: update dirty pages log failed %d\n", __FUNCTION__, r);
+                qemu_file_set_has_error(f);
+                return 0;
+            }
+            expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
+            return expected_time <= migrate_max_downtime();
+        }
+    }
+    return 0;
 }
 
 static int ram_load_dead(QEMUFile *f, void *opaque)
-- 
1.7.3.2