qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Liang Li <liang.z.li@intel.com>
To: mst@redhat.com, quintela@redhat.com, amit.shah@redhat.com,
	pbonzini@redhat.com, lcapitulino@redhat.com
Cc: armbru@redhat.com, peter.maydell@linaro.org, rth@twiddle.net,
	ehabkost@redhat.com, james.hogan@imgtec.com,
	aurelien@aurel32.net, leon.alrae@imgtec.com, agraf@suse.de,
	borntraeger@de.ibm.com, cornelia.huck@de.ibm.com,
	qemu-devel@nongnu.org, kvm@vger.kernel.org,
	Liang Li <liang.z.li@intel.com>
Subject: [Qemu-devel] [PATCH QEMU 4/5] migration: filter out free pages during live migration
Date: Tue, 19 Apr 2016 22:20:42 +0800	[thread overview]
Message-ID: <1461075643-3668-5-git-send-email-liang.z.li@intel.com> (raw)
In-Reply-To: <1461075643-3668-1-git-send-email-liang.z.li@intel.com>

After sending out the request for free pages, live migration
process will start without waiting for the free page bitmap is
ready. If the free page bitmap is not ready when doing the 1st
migration_bitmap_sync() after ram_save_setup(), the free page
bitmap will be ignored, this means the free pages will not be
filtered out in this case.
The current implementation can not work with post copy, if post
copy is enabled, we simply ignore the free pages. Will make it
work later.

Signed-off-by: Liang Li <liang.z.li@intel.com>
---
 migration/ram.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 101 insertions(+)

diff --git a/migration/ram.c b/migration/ram.c
index 3f05738..3944426 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -41,6 +41,8 @@
 #include "trace.h"
 #include "exec/ram_addr.h"
 #include "qemu/rcu_queue.h"
+#include "sysemu/balloon.h"
+#include "sysemu/kvm.h"
 
 #ifdef DEBUG_MIGRATION_RAM
 #define DPRINTF(fmt, ...) \
@@ -226,6 +228,8 @@ static QemuMutex migration_bitmap_mutex;
 static uint64_t migration_dirty_pages;
 static uint32_t last_version;
 static bool ram_bulk_stage;
+static bool ignore_freepage_rsp;
+static bool drop_page_cache;
 
 /* used by the search for pages to send */
 struct PageSearchStatus {
@@ -242,6 +246,7 @@ static struct BitmapRcu {
     struct rcu_head rcu;
     /* Main migration bitmap */
     unsigned long *bmap;
+    unsigned long *free_page_bmap;
     /* bitmap of pages that haven't been sent even once
      * only maintained and used in postcopy at the moment
      * where it's used to send the dirtymap at the start
@@ -639,6 +644,7 @@ static void migration_bitmap_sync(void)
     rcu_read_unlock();
     qemu_mutex_unlock(&migration_bitmap_mutex);
 
+    ignore_freepage_rsp = true;
     trace_migration_bitmap_sync_end(migration_dirty_pages
                                     - num_dirty_pages_init);
     num_dirty_pages_period += migration_dirty_pages - num_dirty_pages_init;
@@ -1417,6 +1423,9 @@ static void migration_bitmap_free(struct BitmapRcu *bmap)
 {
     g_free(bmap->bmap);
     g_free(bmap->unsentmap);
+    if (balloon_free_pages_support() && !migrate_postcopy_ram()) {
+        g_free(bmap->free_page_bmap);
+    }
     g_free(bmap);
 }
 
@@ -1487,6 +1496,90 @@ void migration_bitmap_extend(ram_addr_t old, ram_addr_t new)
     }
 }
 
+static void filter_out_guest_free_page(unsigned long *free_page_bmap,
+                                       long nbits)
+{
+    long i, page_count = 0, len;
+    unsigned long *bitmap;
+
+    tighten_guest_free_page_bmap(free_page_bmap);
+    qemu_mutex_lock(&migration_bitmap_mutex);
+    bitmap = atomic_rcu_read(&migration_bitmap_rcu)->bmap;
+    slow_bitmap_complement(bitmap, free_page_bmap, nbits);
+
+    len = (last_ram_offset() >> TARGET_PAGE_BITS) / BITS_PER_LONG;
+    for (i = 0; i < len; i++) {
+        page_count += hweight_long(bitmap[i]);
+    }
+
+    migration_dirty_pages = page_count;
+    qemu_mutex_unlock(&migration_bitmap_mutex);
+}
+
+static void ram_request_free_page(unsigned long *bmap, unsigned long max_pfn)
+{
+    FreePageStatus status;
+
+    /* drop_page_cache should be set by user, the related code will be
+     * added later, set it to ture temporarily.
+     */
+    drop_page_cache = true;
+
+    status = balloon_get_free_pages(bmap, max_pfn, drop_page_cache);
+    switch (status) {
+    case FREE_PAGE_REQ:
+        ignore_freepage_rsp = false;
+        break;
+    case FREE_PAGE_ERROR:
+        error_report("Errro happend when request free page");
+        break;
+    default:
+        error_report("unexpected response status: %d", status);
+        break;
+    }
+}
+
+static void ram_handle_free_page(void)
+{
+    unsigned long nbits;
+    RAMBlock *pc_ram_block;
+    FreePageStatus status;
+
+    status = balloon_get_free_pages(migration_bitmap_rcu->free_page_bmap,
+                                    get_guest_max_pfn(), drop_page_cache);
+    switch (status) {
+    case FREE_PAGE_READY:
+        rcu_read_lock();
+        pc_ram_block = QLIST_FIRST_RCU(&ram_list.blocks);
+        nbits = pc_ram_block->used_length >> TARGET_PAGE_BITS;
+        filter_out_guest_free_page(migration_bitmap_rcu->free_page_bmap, nbits);
+        rcu_read_unlock();
+
+        qemu_mutex_lock_iothread();
+        migration_bitmap_sync();
+        qemu_mutex_unlock_iothread();
+        /*
+         * bulk stage assumes in (migration_bitmap_find_and_reset_dirty) that
+         * every page is dirty, that's no longer ture at this point.
+         */
+        ram_bulk_stage = false;
+        last_seen_block = NULL;
+        last_sent_block = NULL;
+        last_offset = 0;
+        break;
+    case FREE_PAGE_ERROR:
+        ignore_freepage_rsp = true;
+        error_report("failed to get free page");
+        break;
+    case FREE_PAGE_INVALID_PARAM:
+        ignore_freepage_rsp = true;
+        error_report("buffer overflow");
+        break;
+    default:
+        break;
+    }
+}
+
 /*
  * 'expected' is the value you expect the bitmap mostly to be full
  * of; it won't bother printing lines that are all this value.
@@ -1950,6 +2043,11 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
     qemu_mutex_unlock_ramlist();
     qemu_mutex_unlock_iothread();
 
+    if (balloon_free_pages_support() && !migrate_postcopy_ram()) {
+        unsigned long max_pfn = get_guest_max_pfn();
+        migration_bitmap_rcu->free_page_bmap = bitmap_new(max_pfn);
+        ram_request_free_page(migration_bitmap_rcu->free_page_bmap, max_pfn);
+    }
     qemu_put_be64(f, ram_bytes_total() | RAM_SAVE_FLAG_MEM_SIZE);
 
     QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
@@ -1990,6 +2088,9 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
     while ((ret = qemu_file_rate_limit(f)) == 0) {
         int pages;
 
+        if (!ignore_freepage_rsp) {
+            ram_handle_free_page();
+        }
         pages = ram_find_and_save_block(f, false, &bytes_transferred);
         /* no more pages to sent */
         if (pages == 0) {
-- 
1.8.3.1

  parent reply	other threads:[~2016-04-19 14:30 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-19 14:20 [Qemu-devel] [PATCH QEMU 0/5] spee up live migration by skipping free pages Liang Li
2016-04-19 14:20 ` [Qemu-devel] [PATCH QEMU 1/5] bitmap: Add a new bitmap_move function Liang Li
2016-04-19 14:20 ` [Qemu-devel] [PATCH QEMU 2/5] kvm: Add two new arch specific functions Liang Li
2016-04-19 14:20 ` [Qemu-devel] [PATCH QEMU 3/5] virtio-balloon: Add a new feature to balloon device Liang Li
2016-04-19 16:32   ` Michael S. Tsirkin
2016-04-19 14:20 ` Liang Li [this message]
2016-04-19 14:20 ` [Qemu-devel] [PATCH QEMU 5/5] migration: Add the interface for cache drop control Liang Li
2016-04-19 14:52   ` Eric Blake
2016-04-19 14:59     ` Li, Liang Z
2016-04-19 14:37 ` [Qemu-devel] [PATCH QEMU 0/5] spee up live migration by skipping free pages Alexander Graf

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=1461075643-3668-5-git-send-email-liang.z.li@intel.com \
    --to=liang.z.li@intel.com \
    --cc=agraf@suse.de \
    --cc=amit.shah@redhat.com \
    --cc=armbru@redhat.com \
    --cc=aurelien@aurel32.net \
    --cc=borntraeger@de.ibm.com \
    --cc=cornelia.huck@de.ibm.com \
    --cc=ehabkost@redhat.com \
    --cc=james.hogan@imgtec.com \
    --cc=kvm@vger.kernel.org \
    --cc=lcapitulino@redhat.com \
    --cc=leon.alrae@imgtec.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    --cc=rth@twiddle.net \
    /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).