qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Juan Quintela <quintela@redhat.com>
To: qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
	Umesh Deshpande <udeshpan@redhat.com>
Subject: [Qemu-devel] [PATCH 14/41] Separate migration bitmap
Date: Fri, 21 Sep 2012 10:47:08 +0200	[thread overview]
Message-ID: <1348217255-22441-15-git-send-email-quintela@redhat.com> (raw)
In-Reply-To: <1348217255-22441-1-git-send-email-quintela@redhat.com>

This patch creates a migration bitmap, which is periodically kept in
sync with the qemu bitmap. A separate copy of the dirty bitmap for the
migration limits the amount of concurrent access to the qemu bitmap
from iothread and migration thread (which requires taking the big
lock).

We use the qemu bitmap type.  We have to "undo" the dirty_pages
counting optimization on the general dirty bitmap and do the counting
optimization with the migration local bitmap.

Signed-off-by: Umesh Deshpande <udeshpan@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
 arch_init.c     | 63 +++++++++++++++++++++++++++++++++++++++------------------
 cpu-all.h       |  1 -
 exec-obsolete.h | 10 ---------
 3 files changed, 43 insertions(+), 31 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index 6e0d7c4..0279d06 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -31,6 +31,8 @@
 #include "config.h"
 #include "monitor.h"
 #include "sysemu.h"
+#include "bitops.h"
+#include "bitmap.h"
 #include "arch_init.h"
 #include "audio/audio.h"
 #include "hw/pc.h"
@@ -332,39 +334,57 @@ static int save_xbzrle_page(QEMUFile *f, uint8_t *current_data,

 static RAMBlock *last_block;
 static ram_addr_t last_offset;
+static unsigned long *migration_bitmap;
+static uint64_t migration_dirty_pages;

 static inline bool migration_bitmap_test_and_reset_dirty(MemoryRegion *mr,
                                                          ram_addr_t offset)
 {
-    bool ret = memory_region_get_dirty(mr, offset, TARGET_PAGE_SIZE,
-                                       DIRTY_MEMORY_MIGRATION);
+    bool ret;
+    int nr = (mr->ram_addr + offset) >> TARGET_PAGE_BITS;
+
+    ret = test_and_clear_bit(nr, migration_bitmap);

     if (ret) {
-        memory_region_reset_dirty(mr, offset, TARGET_PAGE_SIZE,
-                                  DIRTY_MEMORY_MIGRATION);
+        migration_dirty_pages--;
     }
     return ret;
 }

-static inline void migration_bitmap_set_dirty(MemoryRegion *mr, int length)
+static inline bool migration_bitmap_set_dirty(MemoryRegion *mr,
+                                              ram_addr_t offset)
 {
-    ram_addr_t addr;
+    bool ret;
+    int nr = (mr->ram_addr + offset) >> TARGET_PAGE_BITS;

-    for (addr = 0; addr < length; addr += TARGET_PAGE_SIZE) {
-        if (!memory_region_get_dirty(mr, addr, TARGET_PAGE_SIZE,
-                                     DIRTY_MEMORY_MIGRATION)) {
-            memory_region_set_dirty(mr, addr, TARGET_PAGE_SIZE);
-        }
+    ret = test_and_set_bit(nr, migration_bitmap);
+
+    if (!ret) {
+        migration_dirty_pages++;
     }
+    return ret;
 }

 static void migration_bitmap_sync(void)
 {
-    uint64_t num_dirty_pages_init = ram_list.dirty_pages;
+    RAMBlock *block;
+    ram_addr_t addr;
+    uint64_t num_dirty_pages_init = migration_dirty_pages;

     trace_migration_bitmap_sync_start();
     memory_global_sync_dirty_bitmap(get_system_memory());
-    trace_migration_bitmap_sync_end(ram_list.dirty_pages
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        for (addr = 0; addr < block->length; addr += TARGET_PAGE_SIZE) {
+            if (memory_region_get_dirty(block->mr, addr, TARGET_PAGE_SIZE,
+                                        DIRTY_MEMORY_MIGRATION)) {
+                migration_bitmap_set_dirty(block->mr, addr);
+            }
+        }
+        memory_region_reset_dirty(block->mr, 0, block->length,
+                                  DIRTY_MEMORY_MIGRATION);
+    }
+    trace_migration_bitmap_sync_end(migration_dirty_pages
                                     - num_dirty_pages_init);
 }

@@ -443,7 +463,7 @@ static uint64_t bytes_transferred;

 static ram_addr_t ram_save_remaining(void)
 {
-    return ram_list.dirty_pages;
+    return migration_dirty_pages;
 }

 uint64_t ram_bytes_remaining(void)
@@ -528,8 +548,13 @@ static void reset_ram_globals(void)
 static int ram_save_setup(QEMUFile *f, void *opaque)
 {
     RAMBlock *block;
+    int64_t ram_pages = last_ram_offset() >> TARGET_PAGE_BITS;

-    memory_global_sync_dirty_bitmap(get_system_memory());
+    migration_bitmap = bitmap_new(ram_pages);
+    bitmap_set(migration_bitmap, 1, ram_pages);
+    migration_dirty_pages = ram_pages;
+
+    migration_bitmap_sync();
     bytes_transferred = 0;
     reset_ram_globals();

@@ -546,11 +571,6 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
         acct_clear();
     }

-    /* Make sure all dirty bits are set */
-    QLIST_FOREACH(block, &ram_list.blocks, next) {
-        migration_bitmap_set_dirty(block->mr, block->length);
-    }
-
     memory_global_dirty_log_start();

     qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
@@ -656,6 +676,9 @@ static int ram_save_complete(QEMUFile *f, void *opaque)

     qemu_put_be64(f, RAM_SAVE_FLAG_EOS);

+    g_free(migration_bitmap);
+    migration_bitmap = NULL;
+
     return 0;
 }

diff --git a/cpu-all.h b/cpu-all.h
index 5408782..db25f73 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -497,7 +497,6 @@ typedef struct RAMBlock {
 typedef struct RAMList {
     uint8_t *phys_dirty;
     QLIST_HEAD(, RAMBlock) blocks;
-    uint64_t dirty_pages;
 } RAMList;
 extern RAMList ram_list;

diff --git a/exec-obsolete.h b/exec-obsolete.h
index c099256..f8ffce6 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -74,11 +74,6 @@ static inline int cpu_physical_memory_get_dirty(ram_addr_t start,
 static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
                                                       int dirty_flags)
 {
-    if ((dirty_flags & MIGRATION_DIRTY_FLAG) &&
-        !cpu_physical_memory_get_dirty(addr, TARGET_PAGE_SIZE,
-                                       MIGRATION_DIRTY_FLAG)) {
-        ram_list.dirty_pages++;
-    }
     return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
 }

@@ -92,11 +87,6 @@ static inline int cpu_physical_memory_clear_dirty_flags(ram_addr_t addr,
 {
     int mask = ~dirty_flags;

-    if ((dirty_flags & MIGRATION_DIRTY_FLAG) &&
-        cpu_physical_memory_get_dirty(addr, TARGET_PAGE_SIZE,
-                                      MIGRATION_DIRTY_FLAG)) {
-        ram_list.dirty_pages--;
-    }
     return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] &= mask;
 }

-- 
1.7.11.4

  parent reply	other threads:[~2012-09-21  8:48 UTC|newest]

Thread overview: 95+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-21  8:46 [Qemu-devel] [PATCH 00/41] Migration cleanups, refactorings, stats, and more Juan Quintela
2012-09-21  8:46 ` [Qemu-devel] [PATCH 01/41] buffered_file: g_realloc() can't fail Juan Quintela
2012-09-21 12:11   ` Paolo Bonzini
2012-09-25  8:08   ` Orit Wasserman
2012-09-21  8:46 ` [Qemu-devel] [PATCH 02/41] fix migration sync Juan Quintela
2012-09-21 12:17   ` Paolo Bonzini
2012-09-25  8:45     ` Paolo Bonzini
2012-10-02 10:43       ` Juan Quintela
2012-10-02 10:53         ` Paolo Bonzini
2012-09-21  8:46 ` [Qemu-devel] [PATCH 03/41] migration: store end_time in a local variable Juan Quintela
2012-09-21 12:17   ` Paolo Bonzini
2012-09-25  8:10   ` Orit Wasserman
2012-09-21  8:46 ` [Qemu-devel] [PATCH 04/41] migration: print total downtime for final phase of migration Juan Quintela
2012-09-21 12:19   ` Paolo Bonzini
2012-09-25  8:18   ` Orit Wasserman
2012-09-21  8:46 ` [Qemu-devel] [PATCH 05/41] migration: rename expected_time to expected_downtime Juan Quintela
2012-09-21 12:19   ` Paolo Bonzini
2012-09-25  8:21   ` Orit Wasserman
2012-09-21  8:47 ` [Qemu-devel] [PATCH 06/41] migration: export migrate_get_current() Juan Quintela
2012-09-21  8:47 ` [Qemu-devel] [PATCH 07/41] migration: print expected downtime in info migrate Juan Quintela
2012-09-21 12:22   ` Paolo Bonzini
2012-10-02 10:47     ` Juan Quintela
2012-09-21  8:47 ` [Qemu-devel] [PATCH 08/41] savevm: Factorize ram globals reset in its own function Juan Quintela
2012-09-25  8:37   ` Orit Wasserman
2012-09-21  8:47 ` [Qemu-devel] [PATCH 09/41] ram: introduce migration_bitmap_set_dirty() Juan Quintela
2012-09-25  8:38   ` Orit Wasserman
2012-09-21  8:47 ` [Qemu-devel] [PATCH 10/41] ram: Introduce migration_bitmap_test_and_reset_dirty() Juan Quintela
2012-09-25  9:35   ` Orit Wasserman
2012-09-21  8:47 ` [Qemu-devel] [PATCH 11/41] ram: Export last_ram_offset() Juan Quintela
2012-09-21  8:47 ` [Qemu-devel] [PATCH 12/41] ram: introduce migration_bitmap_sync() Juan Quintela
2012-09-21  8:47 ` [Qemu-devel] [PATCH 13/41] ram: create trace event for migration sync bitmap Juan Quintela
2012-09-21  8:47 ` Juan Quintela [this message]
2012-09-21  8:47 ` [Qemu-devel] [PATCH 15/41] migration: Add dirty_pages_rate to query migrate output Juan Quintela
2012-09-21 12:33   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 16/41] BufferedFile: append, then flush Juan Quintela
2012-09-21  8:47 ` [Qemu-devel] [PATCH 17/41] buffered_file: rename opaque to migration_state Juan Quintela
2012-09-25 11:41   ` Orit Wasserman
2012-10-02 10:54     ` Juan Quintela
2012-09-21  8:47 ` [Qemu-devel] [PATCH 18/41] buffered_file: opaque is MigrationState Juan Quintela
2012-09-25 11:46   ` Orit Wasserman
2012-09-28  7:33     ` Juan Quintela
2012-09-28  7:48       ` Orit Wasserman
2012-09-21  8:47 ` [Qemu-devel] [PATCH 19/41] buffered_file: unfold migrate_fd_put_buffer Juan Quintela
2012-09-21  8:47 ` [Qemu-devel] [PATCH 20/41] buffered_file: unfold migrate_fd_put_ready Juan Quintela
2012-09-21  8:47 ` [Qemu-devel] [PATCH 21/41] buffered_file: unfold migrate_fd_put_buffer Juan Quintela
2012-09-21 12:34   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 22/41] " Juan Quintela
2012-09-21 12:35   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 23/41] buffered_file: We can access directly to bandwidth_limit Juan Quintela
2012-09-21 12:35   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 24/41] buffered_file: callers of buffered_flush() already check for errors Juan Quintela
2012-09-21 12:39   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 25/41] buffered_file: make buffered_flush return the error code Juan Quintela
2012-09-21 12:43   ` Paolo Bonzini
2012-10-02 11:06     ` Juan Quintela
2012-10-02 11:16       ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 26/41] migration: make migrate_fd_wait_for_unfreeze() return errors Juan Quintela
2012-09-21 12:44   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 27/41] savevm: unexport qemu_fflush Juan Quintela
2012-09-21 12:45   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 28/41] virtio-net: use qemu_get_buffer() in a temp buffer Juan Quintela
2012-09-21 12:45   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 29/41] savevm: Remove qemu_fseek() Juan Quintela
2012-09-21 12:46   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 30/41] savevm: make qemu_fflush() return an error code Juan Quintela
2012-09-21 12:46   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 31/41] savevm: unfold qemu_fclose_internal() Juan Quintela
2012-09-21 12:48   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 32/41] savevm: unexport qemu_ftell() Juan Quintela
2012-09-21 12:48   ` Paolo Bonzini
2012-09-21 15:42     ` Juan Quintela
2012-09-21  8:47 ` [Qemu-devel] [PATCH 33/41] savevm: make qemu_fill_buffer() be consistent Juan Quintela
2012-09-21 12:48   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 34/41] savevm: Only qemu_fflush() can generate errors Juan Quintela
2012-09-21 12:49   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 35/41] buffered_file: buffered_put_buffer() don't need to set last_error Juan Quintela
2012-09-21 12:50   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 36/41] block-migration: make flush_blks() return errors Juan Quintela
2012-09-21 12:50   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 37/41] block-migration: Switch meaning of return value Juan Quintela
2012-09-21 12:51   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 38/41] block-migration: handle errors with the return codes correctly Juan Quintela
2012-09-21 12:53   ` Paolo Bonzini
2012-09-24 18:24     ` Juan Quintela
2012-09-25  6:36       ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 39/41] savevm: un-export qemu_file_set_error() Juan Quintela
2012-09-21 12:53   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 40/41] savevm: make qemu_file_put_notify() return errors Juan Quintela
2012-09-21 12:53   ` Paolo Bonzini
2012-09-21  8:47 ` [Qemu-devel] [PATCH 41/41] cpus: create qemu_cpu_is_vcpu() Juan Quintela
2012-09-21 12:54   ` Paolo Bonzini
2012-09-21 14:48     ` Andreas Färber
2012-09-21 15:36       ` Paolo Bonzini
2012-09-24 18:11     ` Juan Quintela
  -- strict thread matches above, loose matches on Subject: below --
2012-10-02 11:32 [Qemu-devel] [PATCH v2 00/41] Migration cleanups, refactorings, stats, and more Juan Quintela
2012-10-02 11:33 ` [Qemu-devel] [PATCH 14/41] Separate migration bitmap Juan Quintela

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1348217255-22441-15-git-send-email-quintela@redhat.com \
    --to=quintela@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=udeshpan@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).