qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Dr. David Alan Gilbert (git)" <dgilbert@redhat.com>
To: qemu-devel@nongnu.org
Cc: aarcange@redhat.com, yamahata@private.email.ne.jp,
	lilei@linux.vnet.ibm.com, quintela@redhat.com
Subject: [Qemu-devel] [PATCH 36/46] Page request: Consume pages off the post-copy queue
Date: Fri,  4 Jul 2014 18:41:47 +0100	[thread overview]
Message-ID: <1404495717-4239-37-git-send-email-dgilbert@redhat.com> (raw)
In-Reply-To: <1404495717-4239-1-git-send-email-dgilbert@redhat.com>

From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

When transmitting RAM pages, consume pages that have been queued by
MIG_RPCOMM_REQPAGE commands and send them ahead of normal page scanning.

Note:
  a) After a queued page the linear walk carries on from after the
unqueued page; there is a reasonable chance that the destination
was about to ask for other closeby pages anyway.

  b) We have to be careful of any assumptions that the page walking
code makes, in particular it does some short cuts on its first linear
walk that break as soon as we do a queued page.

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
---
 arch_init.c | 130 +++++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 106 insertions(+), 24 deletions(-)

diff --git a/arch_init.c b/arch_init.c
index cc4acea..c006d21 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -458,6 +458,19 @@ static inline bool migration_bitmap_set_dirty(ram_addr_t addr)
     return ret;
 }
 
+static inline bool migration_bitmap_clear_dirty(ram_addr_t addr)
+{
+    bool ret;
+    int nr = addr >> TARGET_PAGE_BITS;
+
+    ret = test_and_clear_bit(nr, migration_bitmap);
+
+    if (ret) {
+        migration_dirty_pages--;
+    }
+    return ret;
+}
+
 static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length)
 {
     ram_addr_t addr;
@@ -658,6 +671,39 @@ static int ram_save_page(QEMUFile *f, RAMBlock* block, ram_addr_t offset,
 }
 
 /*
+ * Unqueue a page from the queue fed by postcopy page requests
+ *
+ * Returns:   The RAMBlock* to transmit from (or NULL if the queue is empty)
+ *      ms:   MigrationState in
+ *  offset:   the byte offset within the RAMBlock for the start of the page
+ * bitoffset: global offset in the dirty/sent bitmaps
+ */
+static RAMBlock *ram_save_unqueue_page(MigrationState *ms, ram_addr_t *offset,
+                                       unsigned long *bitoffset)
+{
+    RAMBlock *result = NULL;
+    qemu_mutex_lock(&ms->src_page_req_mutex);
+    if (!QSIMPLEQ_EMPTY(&ms->src_page_requests)) {
+        struct MigrationSrcPageRequest *entry =
+                                    QSIMPLEQ_FIRST(&ms->src_page_requests);
+        result = entry->rb;
+        *offset = entry->offset;
+        *bitoffset = (entry->offset + entry->rb->offset) >> TARGET_PAGE_BITS;
+
+        if (entry->len > TARGET_PAGE_SIZE) {
+            entry->len -= TARGET_PAGE_SIZE;
+            entry->offset += TARGET_PAGE_SIZE;
+        } else {
+            QSIMPLEQ_REMOVE_HEAD(&ms->src_page_requests, next_req);
+            g_free(entry);
+        }
+    }
+    qemu_mutex_unlock(&ms->src_page_req_mutex);
+
+    return result;
+}
+
+/*
  * Queue the pages for transmission, e.g. a request from postcopy destination
  *   ms: MigrationStatus in which the queue is held
  *   rbname: The RAMBlock the request is for - may be NULL (to mean reuse last)
@@ -718,44 +764,80 @@ int ram_save_queue_pages(MigrationState *ms, const char *rbname,
 
 static int ram_find_and_save_block(QEMUFile *f, bool last_stage)
 {
+    MigrationState *ms = migrate_get_current();
     RAMBlock *block = last_seen_block;
+    RAMBlock *tmpblock;
     ram_addr_t offset = last_offset;
+    ram_addr_t tmpoffset;
     bool complete_round = false;
     int bytes_sent = 0;
-    MemoryRegion *mr;
     unsigned long bitoffset;
 
     if (!block)
         block = QTAILQ_FIRST(&ram_list.blocks);
 
-    while (true) {
-        mr = block->mr;
-        offset = migration_bitmap_find_and_reset_dirty(mr, offset, &bitoffset);
-        if (complete_round && block == last_seen_block &&
-            offset >= last_offset) {
-            break;
-        }
-        if (offset >= block->length) {
-            offset = 0;
-            block = QTAILQ_NEXT(block, next);
-            if (!block) {
-                block = QTAILQ_FIRST(&ram_list.blocks);
-                complete_round = true;
-                ram_bulk_stage = false;
+    while (true) { /* Until we send a block or run out of stuff to send */
+        tmpblock = ram_save_unqueue_page(ms, &tmpoffset, &bitoffset);
+        if (tmpblock) {
+            /* We've got a block from the postcopy queue */
+            DPRINTF("%s: Got postcopy item '%s' offset=%zx bitoffset=%zx",
+                    __func__, tmpblock->idstr, tmpoffset, bitoffset);
+            /* We're sending this page, and since it's postcopy nothing else
+             * will dirty it, and we must make sure it doesn't get sent again.
+             */
+            if (!migration_bitmap_clear_dirty(bitoffset << TARGET_PAGE_BITS)) {
+                DPRINTF("%s: Not dirty for postcopy %s/%zx bito=%zx (sent=%d)",
+                        __func__, tmpblock->idstr, tmpoffset, bitoffset,
+                        test_bit(bitoffset, ms->sentmap));
+                continue;
             }
+            /*
+             * As soon as we start servicing pages out of order, then we have
+             * to kill the bulk stage, since the bulk stage assumes
+             * in (migration_bitmap_find_and_reset_dirty) that every page is
+             * dirty, that's no longer true.
+             */
+            ram_bulk_stage = false;
+            /*
+             * We mustn't change block/offset unless it's to a valid one
+             * otherwise we can go down some of the exit cases in the normal
+             * path.
+             */
+            block = tmpblock;
+            offset = tmpoffset;
         } else {
-            bytes_sent = ram_save_page(f, block, offset, last_stage);
-
-            /* if page is unmodified, continue to the next */
-            if (bytes_sent > 0) {
-                MigrationState *s = migrate_get_current();
-                if (s->sentmap) {
-                    set_bit(bitoffset, s->sentmap);
+            MemoryRegion *mr;
+            /* priority queue empty, so just search for something dirty */
+            mr = block->mr;
+            offset = migration_bitmap_find_and_reset_dirty(mr, offset,
+                                                           &bitoffset);
+            if (complete_round && block == last_seen_block &&
+                offset >= last_offset) {
+                break;
+            }
+            if (offset >= block->length) {
+                offset = 0;
+                block = QTAILQ_NEXT(block, next);
+                if (!block) {
+                    block = QTAILQ_FIRST(&ram_list.blocks);
+                    complete_round = true;
+                    ram_bulk_stage = false;
                 }
+                continue; /* pick an offset in the new block */
+            }
+        }
 
-                last_sent_block = block;
-                break;
+        /* We have a page to send, so send it */
+        bytes_sent = ram_save_page(f, block, offset, last_stage);
+
+        /* if page is unmodified, continue to the next */
+        if (bytes_sent > 0) {
+            if (ms->sentmap) {
+                set_bit(bitoffset, ms->sentmap);
             }
+
+            last_sent_block = block;
+            break;
         }
     }
     last_seen_block = block;
-- 
1.9.3

  parent reply	other threads:[~2014-07-04 17:43 UTC|newest]

Thread overview: 83+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-04 17:41 [Qemu-devel] [PATCH 00/46] Postcopy implementation Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 01/46] qemu_ram_foreach_block: pass up error value, and down the ramblock name Dr. David Alan Gilbert (git)
2014-07-07 15:46   ` Eric Blake
2014-07-07 15:48     ` Dr. David Alan Gilbert
2014-07-04 17:41 ` [Qemu-devel] [PATCH 02/46] Move QEMUFile structure to qemu-file.h Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 03/46] QEMUSizedBuffer/QEMUFile Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 04/46] improve DPRINTF macros, add to savevm Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 05/46] Add qemu_get_counted_string to read a string prefixed by a count byte Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 06/46] Create MigrationIncomingState Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 07/46] Return path: Open a return path on QEMUFile for sockets Dr. David Alan Gilbert (git)
2014-07-05 10:06   ` Paolo Bonzini
2014-07-16  9:37     ` Dr. David Alan Gilbert
2014-07-16  9:50       ` Paolo Bonzini
2014-07-16 11:52         ` Dr. David Alan Gilbert
2014-07-16 12:31           ` Paolo Bonzini
2014-07-16 17:10             ` Dr. David Alan Gilbert
2014-07-17  6:25               ` Paolo Bonzini
2014-07-04 17:41 ` [Qemu-devel] [PATCH 08/46] Return path: socket_writev_buffer: Block even on non-blocking fd's Dr. David Alan Gilbert (git)
2014-07-05 10:07   ` Paolo Bonzini
2014-07-04 17:41 ` [Qemu-devel] [PATCH 09/46] Migration commands Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 10/46] Return path: Control commands Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 11/46] Return path: Send responses from destination to source Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 12/46] Return path: Source handling of return path Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 13/46] qemu_loadvm debug Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 14/46] ram_debug_dump_bitmap: Dump a migration bitmap as text Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 15/46] Rework loadvm path for subloops Dr. David Alan Gilbert (git)
2014-07-05 10:26   ` Paolo Bonzini
2014-07-07 14:35     ` Dr. David Alan Gilbert
2014-07-07 14:53       ` Paolo Bonzini
2014-07-07 15:04         ` Dr. David Alan Gilbert
2014-07-16  9:25         ` Dr. David Alan Gilbert
2014-07-04 17:41 ` [Qemu-devel] [PATCH 16/46] Add migration-capability boolean for postcopy-ram Dr. David Alan Gilbert (git)
2014-07-07 19:41   ` Eric Blake
2014-07-07 20:23     ` Dr. David Alan Gilbert
2014-07-10 16:17       ` Paolo Bonzini
2014-07-10 19:02         ` Dr. David Alan Gilbert
2014-07-04 17:41 ` [Qemu-devel] [PATCH 17/46] Add wrappers and handlers for sending/receiving the postcopy-ram migration messages Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 18/46] QEMU_VM_CMD_PACKAGED: Send a packaged chunk of migration stream Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 19/46] migrate_init: Call from savevm Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 20/46] Allow savevm handlers to state whether they could go into postcopy Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 21/46] postcopy: OS support test Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 22/46] Migration parameters: Add qmp/hmp commands for setting/viewing Dr. David Alan Gilbert (git)
2014-07-07 19:50   ` Eric Blake
2014-07-04 17:41 ` [Qemu-devel] [PATCH 23/46] MIG_STATE_POSTCOPY_ACTIVE: Add new migration state Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 24/46] qemu_savevm_state_complete: Postcopy changes Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 25/46] Postcopy: Maintain sentmap during postcopy pre phase Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 26/46] Postcopy page-map-incoming (PMI) structure Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 27/46] postcopy: Add incoming_init/cleanup functions Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 28/46] postcopy: Incoming initialisation Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 29/46] postcopy: ram_enable_notify to switch on userfault Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 30/46] Postcopy: postcopy_start Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 31/46] Postcopy: Rework migration thread for postcopy mode Dr. David Alan Gilbert (git)
2014-07-05 10:19   ` Paolo Bonzini
2014-08-28 11:04     ` Dr. David Alan Gilbert
2014-08-28 11:23       ` Paolo Bonzini
2014-07-04 17:41 ` [Qemu-devel] [PATCH 32/46] mig fd_connect: open return path Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 33/46] Postcopy: Create a fault handler thread before marking the ram as userfault Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 34/46] Page request: Add MIG_RPCOMM_REQPAGES reverse command Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 35/46] Page request: Process incoming page request Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` Dr. David Alan Gilbert (git) [this message]
2014-07-04 17:41 ` [Qemu-devel] [PATCH 37/46] Add assertion to check migration_dirty_pages doesn't go -ve; have seen it happen once but not sure why Dr. David Alan Gilbert (git)
2014-07-11 15:20   ` Eric Blake
2014-07-11 15:41     ` Dr. David Alan Gilbert
2014-07-04 17:41 ` [Qemu-devel] [PATCH 38/46] postcopy_ram.c: place_page and helpers Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 39/46] Postcopy: Use helpers to map pages during migration Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 40/46] qemu_ram_block_from_host Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 41/46] Handle userfault requests (although userfaultfd not done yet) Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 42/46] Start up a postcopy/listener thread ready for incoming page data Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 43/46] postcopy: Wire up loadvm_postcopy_ram_handle_{run, end} commands Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 44/46] postcopy: Use userfaultfd Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 45/46] End of migration for postcopy Dr. David Alan Gilbert (git)
2014-07-04 17:41 ` [Qemu-devel] [PATCH 46/46] Start documenting how postcopy works Dr. David Alan Gilbert (git)
2014-07-05 10:28 ` [Qemu-devel] [PATCH 00/46] Postcopy implementation Paolo Bonzini
2014-07-07 14:02   ` Dr. David Alan Gilbert
2014-07-07 14:35     ` Paolo Bonzini
2014-07-07 14:58       ` Dr. David Alan Gilbert
2014-07-10 11:29       ` Dr. David Alan Gilbert
2014-07-10 12:48         ` Eric Blake
2014-07-10 13:37           ` Dr. David Alan Gilbert
2014-07-10 15:33             ` Andrea Arcangeli
2014-07-10 15:49               ` Dr. David Alan Gilbert
2014-07-11  4:05                 ` Sanidhya Kashyap
2014-08-11 15:31           ` Dr. David Alan Gilbert

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=1404495717-4239-37-git-send-email-dgilbert@redhat.com \
    --to=dgilbert@redhat.com \
    --cc=aarcange@redhat.com \
    --cc=lilei@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=quintela@redhat.com \
    --cc=yamahata@private.email.ne.jp \
    /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).