Commit 0956ee3e authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20180710a' into staging



Migration pull 2018-07-10 (for 3.0)

Migration fixes and migration test fixes, mostly
around postcopy and postcopy recovery

# gpg: Signature made Tue 10 Jul 2018 16:27:19 BST
# gpg:                using RSA key 0516331EBC5BFDE7
# gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>"
# Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A  9FA9 0516 331E BC5B FDE7

* remotes/dgilbert/tags/pull-migration-20180710a:
  migration: reorder MIG_CMD_POSTCOPY_RESUME
  tests: hide stderr for postcopy recovery test
  tests: add postcopy recovery test
  tests: introduce wait_for_migration_status()
  tests: introduce migrate_query*() helpers
  tests: allow migrate() to take extra flags
  tests: introduce migrate_postcopy_* helpers
  migration: show pause/recover state on dst host
  migration: fix incorrect bitmap size calculation
  migration: loosen recovery check when load vm
  migration: simplify check to use qemu file buffer
  migration: unify incoming processing
  migration: unbreak postcopy recovery
  migration: move income process out of multifd
  migration: delay postcopy paused state

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 2b83714d 858b6d62
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -49,9 +49,6 @@ static gboolean exec_accept_incoming_migration(QIOChannel *ioc,
{
    migration_channel_process_incoming(ioc);
    object_unref(OBJECT(ioc));
    if (!migrate_use_multifd()) {
        migration_incoming_process();
    }
    return G_SOURCE_REMOVE;
}

+0 −3
Original line number Diff line number Diff line
@@ -49,9 +49,6 @@ static gboolean fd_accept_incoming_migration(QIOChannel *ioc,
{
    migration_channel_process_incoming(ioc);
    object_unref(OBJECT(ioc));
    if (!migrate_use_multifd()) {
        migration_incoming_process();
    }
    return G_SOURCE_REMOVE;
}

+39 −7
Original line number Diff line number Diff line
@@ -466,7 +466,8 @@ void migration_incoming_process(void)
    qemu_coroutine_enter(co);
}

void migration_fd_process_incoming(QEMUFile *f)
/* Returns true if recovered from a paused migration, otherwise false */
static bool postcopy_try_recover(QEMUFile *f)
{
    MigrationIncomingState *mis = migration_incoming_get_current();

@@ -491,23 +492,52 @@ void migration_fd_process_incoming(QEMUFile *f)
         * that source is ready to reply to page requests.
         */
        qemu_sem_post(&mis->postcopy_pause_sem_dst);
    } else {
        /* New incoming migration */
        return true;
    }

    return false;
}

void migration_fd_process_incoming(QEMUFile *f)
{
    if (postcopy_try_recover(f)) {
        return;
    }

    migration_incoming_setup(f);
    migration_incoming_process();
}
}

void migration_ioc_process_incoming(QIOChannel *ioc)
{
    MigrationIncomingState *mis = migration_incoming_get_current();
    bool start_migration;

    if (!mis->from_src_file) {
        /* The first connection (multifd may have multiple) */
        QEMUFile *f = qemu_fopen_channel_input(ioc);
        migration_incoming_setup(f);

        /* If it's a recovery, we're done */
        if (postcopy_try_recover(f)) {
            return;
        }
    multifd_recv_new_channel(ioc);

        migration_incoming_setup(f);

        /*
         * Common migration only needs one channel, so we can start
         * right now.  Multifd needs more than one channel, we wait.
         */
        start_migration = !migrate_use_multifd();
    } else {
        /* Multiple connections */
        assert(migrate_use_multifd());
        start_migration = multifd_recv_new_channel(ioc);
    }

    if (start_migration) {
        migration_incoming_process();
    }
}

/**
@@ -881,6 +911,8 @@ static void fill_destination_migration_info(MigrationInfo *info)
    case MIGRATION_STATUS_CANCELLED:
    case MIGRATION_STATUS_ACTIVE:
    case MIGRATION_STATUS_POSTCOPY_ACTIVE:
    case MIGRATION_STATUS_POSTCOPY_PAUSED:
    case MIGRATION_STATUS_POSTCOPY_RECOVER:
    case MIGRATION_STATUS_FAILED:
    case MIGRATION_STATUS_COLO:
        info->has_status = true;
+18 −14
Original line number Diff line number Diff line
@@ -235,7 +235,7 @@ int64_t ramblock_recv_bitmap_send(QEMUFile *file,
    bitmap_to_le(le_bitmap, block->receivedmap, nbits);

    /* Size of the bitmap, in bytes */
    size = nbits / 8;
    size = DIV_ROUND_UP(nbits, 8);

    /*
     * size is always aligned to 8 bytes for 64bit machines, but it
@@ -1311,7 +1311,8 @@ bool multifd_recv_all_channels_created(void)
    return thread_count == atomic_read(&multifd_recv_state->count);
}

void multifd_recv_new_channel(QIOChannel *ioc)
/* Return true if multifd is ready for the migration, otherwise false */
bool multifd_recv_new_channel(QIOChannel *ioc)
{
    MultiFDRecvParams *p;
    Error *local_err = NULL;
@@ -1320,7 +1321,7 @@ void multifd_recv_new_channel(QIOChannel *ioc)
    id = multifd_recv_initial_packet(ioc, &local_err);
    if (id < 0) {
        multifd_recv_terminate_threads(local_err);
        return;
        return false;
    }

    p = &multifd_recv_state->params[id];
@@ -1328,7 +1329,7 @@ void multifd_recv_new_channel(QIOChannel *ioc)
        error_setg(&local_err, "multifd: received id '%d' already setup'",
                   id);
        multifd_recv_terminate_threads(local_err);
        return;
        return false;
    }
    p->c = ioc;
    object_ref(OBJECT(ioc));
@@ -1339,9 +1340,7 @@ void multifd_recv_new_channel(QIOChannel *ioc)
    qemu_thread_create(&p->thread, p->name, multifd_recv_thread, p,
                       QEMU_THREAD_JOINABLE);
    atomic_inc(&multifd_recv_state->count);
    if (multifd_recv_state->count == migrate_multifd_channels()) {
        migration_incoming_process();
    }
    return multifd_recv_state->count == migrate_multifd_channels();
}

/**
@@ -3581,7 +3580,7 @@ static int ram_load_postcopy(QEMUFile *f)
{
    int flags = 0, ret = 0;
    bool place_needed = false;
    bool matching_page_sizes = false;
    bool matches_target_page_size = false;
    MigrationIncomingState *mis = migration_incoming_get_current();
    /* Temporary page that is later 'placed' */
    void *postcopy_host_page = postcopy_get_tmp_page(mis);
@@ -3621,7 +3620,7 @@ static int ram_load_postcopy(QEMUFile *f)
                ret = -EINVAL;
                break;
            }
            matching_page_sizes = block->page_size == TARGET_PAGE_SIZE;
            matches_target_page_size = block->page_size == TARGET_PAGE_SIZE;
            /*
             * Postcopy requires that we place whole host pages atomically;
             * these may be huge pages for RAMBlocks that are backed by
@@ -3669,12 +3668,17 @@ static int ram_load_postcopy(QEMUFile *f)

        case RAM_SAVE_FLAG_PAGE:
            all_zero = false;
            if (!place_needed || !matching_page_sizes) {
            if (!matches_target_page_size) {
                /* For huge pages, we always use temporary buffer */
                qemu_get_buffer(f, page_buffer, TARGET_PAGE_SIZE);
            } else {
                /* Avoids the qemu_file copy during postcopy, which is
                 * going to do a copy later; can only do it when we
                 * do this read in one go (matching page sizes)
                /*
                 * For small pages that matches target page size, we
                 * avoid the qemu_file copy.  Instead we directly use
                 * the buffer of QEMUFile to place the page.  Note: we
                 * cannot do any QEMUFile operation before using that
                 * buffer to make sure the buffer is valid when
                 * placing the page.
                 */
                qemu_get_buffer_in_place(f, (uint8_t **)&place_source,
                                         TARGET_PAGE_SIZE);
@@ -3940,7 +3944,7 @@ int ram_dirty_bitmap_reload(MigrationState *s, RAMBlock *block)
    int ret = -EINVAL;
    QEMUFile *file = s->rp_state.from_dst_file;
    unsigned long *le_bitmap, nbits = block->used_length >> TARGET_PAGE_BITS;
    uint64_t local_size = nbits / 8;
    uint64_t local_size = DIV_ROUND_UP(nbits, 8);
    uint64_t size, end_mark;

    trace_ram_dirty_bitmap_reload_begin(block->idstr);
+1 −1
Original line number Diff line number Diff line
@@ -46,7 +46,7 @@ int multifd_save_cleanup(Error **errp);
int multifd_load_setup(void);
int multifd_load_cleanup(Error **errp);
bool multifd_recv_all_channels_created(void);
void multifd_recv_new_channel(QIOChannel *ioc);
bool multifd_recv_new_channel(QIOChannel *ioc);

uint64_t ram_pagesize_summary(void);
int ram_save_queue_pages(const char *rbname, ram_addr_t start, ram_addr_t len);
Loading