Commit 27608c7c authored by Peter Maydell's avatar Peter Maydell
Browse files

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



Migration pull 2019-08-15

Marcel's vmxnet3 live migraiton fix (that breaks vmxnet3 compatibility
but makes it work)

Error description improvements from Yury.

Multifd fixes from Ivan and Juan.

A load of small cleanups from Wei.

A small cleanup from Marc-André for a future patch.

# gpg: Signature made Wed 14 Aug 2019 19:00:39 BST
# gpg:                using RSA key 45F5C71B4A0CB7FB977A9FA90516331EBC5BFDE7
# gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" [full]
# Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A  9FA9 0516 331E BC5B FDE7

* remotes/dgilbert/tags/pull-migration-20190814a: (33 commits)
  migration: add some multifd traces
  migration: Make global sem_sync semaphore by channel
  migration: Add traces for multifd terminate threads
  qemu-file: move qemu_{get,put}_counted_string() declarations
  migration/postcopy: use mis->bh instead of allocating a QEMUBH
  migration: rename migration_bitmap_sync_range to ramblock_sync_dirty_bitmap
  migration: update ram_counters for multifd sync packet
  migration: add speed limit for multifd migration
  migration: add qemu_file_update_transfer interface
  migration: always initialise ram_counters for a new migration
  migration: remove unused field bytes_xfer
  hmp: Remove migration capabilities from "info migrate"
  migration/postcopy: use QEMU_IS_ALIGNED to replace host_offset
  migration/postcopy: simplify calculation of run_start and fixup_start_addr
  migration/postcopy: make PostcopyDiscardState a static variable
  migration: extract ram_load_precopy
  migration: return -EINVAL directly when version_id mismatch
  migration: equation is more proper than and to check LOADVM_QUIT
  migration: just pass RAMBlock is enough
  migration: use migration_in_postcopy() to check POSTCOPY_ACTIVE
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents f8f2eac4 7dd59d01
Loading
Loading
Loading
Loading
+2 −50
Original line number Diff line number Diff line
@@ -2141,21 +2141,6 @@ vmxnet3_cleanup_msi(VMXNET3State *s)
    msi_uninit(d);
}

static void
vmxnet3_msix_save(QEMUFile *f, void *opaque)
{
    PCIDevice *d = PCI_DEVICE(opaque);
    msix_save(d, f);
}

static int
vmxnet3_msix_load(QEMUFile *f, void *opaque, int version_id)
{
    PCIDevice *d = PCI_DEVICE(opaque);
    msix_load(d, f);
    return 0;
}

static const MemoryRegionOps b0_ops = {
    .read = vmxnet3_io_bar0_read,
    .write = vmxnet3_io_bar0_write,
@@ -2176,11 +2161,6 @@ static const MemoryRegionOps b1_ops = {
    },
};

static SaveVMHandlers savevm_vmxnet3_msix = {
    .save_state = vmxnet3_msix_save,
    .load_state = vmxnet3_msix_load,
};

static uint64_t vmxnet3_device_serial_num(VMXNET3State *s)
{
    uint64_t dsn_payload;
@@ -2203,7 +2183,6 @@ static uint64_t vmxnet3_device_serial_num(VMXNET3State *s)

static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp)
{
    DeviceState *dev = DEVICE(pci_dev);
    VMXNET3State *s = VMXNET3(pci_dev);
    int ret;

@@ -2249,8 +2228,6 @@ static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp)
        pcie_dev_ser_num_init(pci_dev, VMXNET3_DSN_OFFSET,
                              vmxnet3_device_serial_num(s));
    }

    register_savevm_live(dev, "vmxnet3-msix", -1, 1, &savevm_vmxnet3_msix, s);
}

static void vmxnet3_instance_init(Object *obj)
@@ -2440,29 +2417,6 @@ static const VMStateDescription vmstate_vmxnet3_int_state = {
    }
};

static bool vmxnet3_vmstate_need_pcie_device(void *opaque)
{
    VMXNET3State *s = VMXNET3(opaque);

    return !(s->compat_flags & VMXNET3_COMPAT_FLAG_DISABLE_PCIE);
}

static bool vmxnet3_vmstate_test_pci_device(void *opaque, int version_id)
{
    return !vmxnet3_vmstate_need_pcie_device(opaque);
}

static const VMStateDescription vmstate_vmxnet3_pcie_device = {
    .name = "vmxnet3/pcie",
    .version_id = 1,
    .minimum_version_id = 1,
    .needed = vmxnet3_vmstate_need_pcie_device,
    .fields = (VMStateField[]) {
        VMSTATE_PCI_DEVICE(parent_obj, VMXNET3State),
        VMSTATE_END_OF_LIST()
    }
};

static const VMStateDescription vmstate_vmxnet3 = {
    .name = "vmxnet3",
    .version_id = 1,
@@ -2470,9 +2424,8 @@ static const VMStateDescription vmstate_vmxnet3 = {
    .pre_save = vmxnet3_pre_save,
    .post_load = vmxnet3_post_load,
    .fields = (VMStateField[]) {
            VMSTATE_STRUCT_TEST(parent_obj, VMXNET3State,
                                vmxnet3_vmstate_test_pci_device, 0,
                                vmstate_pci_device, PCIDevice),
            VMSTATE_PCI_DEVICE(parent_obj, VMXNET3State),
            VMSTATE_MSIX(parent_obj, VMXNET3State),
            VMSTATE_BOOL(rx_packets_compound, VMXNET3State),
            VMSTATE_BOOL(rx_vlan_stripping, VMXNET3State),
            VMSTATE_BOOL(lro_supported, VMXNET3State),
@@ -2508,7 +2461,6 @@ static const VMStateDescription vmstate_vmxnet3 = {
    },
    .subsections = (const VMStateDescription*[]) {
        &vmxstate_vmxnet3_mcast_list,
        &vmstate_vmxnet3_pcie_device,
        NULL
    }
};
+4 −0
Original line number Diff line number Diff line
@@ -161,6 +161,10 @@ static inline void qemu_get_sbe64s(QEMUFile *f, int64_t *pv)
    qemu_get_be64s(f, (uint64_t *)pv);
}

size_t qemu_get_counted_string(QEMUFile *f, char buf[256]);

void qemu_put_counted_string(QEMUFile *f, const char *name);

int qemu_file_rate_limit(QEMUFile *f);

#endif
+50 −29
Original line number Diff line number Diff line
@@ -823,6 +823,25 @@ bool migration_is_setup_or_active(int state)
    }
}

static void populate_time_info(MigrationInfo *info, MigrationState *s)
{
    info->has_status = true;
    info->has_setup_time = true;
    info->setup_time = s->setup_time;
    if (s->state == MIGRATION_STATUS_COMPLETED) {
        info->has_total_time = true;
        info->total_time = s->total_time;
        info->has_downtime = true;
        info->downtime = s->downtime;
    } else {
        info->has_total_time = true;
        info->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) -
                           s->start_time;
        info->has_expected_downtime = true;
        info->expected_downtime = s->expected_downtime;
    }
}

static void populate_ram_info(MigrationInfo *info, MigrationState *s)
{
    info->has_ram = true;
@@ -909,15 +928,7 @@ static void fill_source_migration_info(MigrationInfo *info)
    case MIGRATION_STATUS_POSTCOPY_PAUSED:
    case MIGRATION_STATUS_POSTCOPY_RECOVER:
        /* TODO add some postcopy stats */
        info->has_status = true;
        info->has_total_time = true;
        info->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME)
            - s->start_time;
        info->has_expected_downtime = true;
        info->expected_downtime = s->expected_downtime;
        info->has_setup_time = true;
        info->setup_time = s->setup_time;

        populate_time_info(info, s);
        populate_ram_info(info, s);
        populate_disk_info(info);
        break;
@@ -926,14 +937,7 @@ static void fill_source_migration_info(MigrationInfo *info)
        /* TODO: display COLO specific information (checkpoint info etc.) */
        break;
    case MIGRATION_STATUS_COMPLETED:
        info->has_status = true;
        info->has_total_time = true;
        info->total_time = s->total_time;
        info->has_downtime = true;
        info->downtime = s->downtime;
        info->has_setup_time = true;
        info->setup_time = s->setup_time;

        populate_time_info(info, s);
        populate_ram_info(info, s);
        break;
    case MIGRATION_STATUS_FAILED:
@@ -1695,7 +1699,6 @@ void migrate_init(MigrationState *s)
     * parameters/capabilities that the user set, and
     * locks.
     */
    s->bytes_xfer = 0;
    s->cleanup_bh = 0;
    s->to_dst_file = NULL;
    s->state = MIGRATION_STATUS_NONE;
@@ -1908,6 +1911,11 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc,
    }

    migrate_init(s);
    /*
     * set ram_counters memory to zero for a
     * new migration
     */
    memset(&ram_counters, 0, sizeof(ram_counters));

    return true;
}
@@ -2963,6 +2971,7 @@ static MigThrError migration_detect_error(MigrationState *s)
{
    int ret;
    int state = s->state;
    Error *local_error = NULL;

    if (state == MIGRATION_STATUS_CANCELLING ||
        state == MIGRATION_STATUS_CANCELLED) {
@@ -2971,13 +2980,18 @@ static MigThrError migration_detect_error(MigrationState *s)
    }

    /* Try to detect any file errors */
    ret = qemu_file_get_error(s->to_dst_file);

    ret = qemu_file_get_error_obj(s->to_dst_file, &local_error);
    if (!ret) {
        /* Everything is fine */
        assert(!local_error);
        return MIG_THR_ERR_NONE;
    }

    if (local_error) {
        migrate_set_error(s, local_error);
        error_free(local_error);
    }

    if (state == MIGRATION_STATUS_POSTCOPY_ACTIVE && ret == -EIO) {
        /*
         * For postcopy, we allow the network to be down for a
@@ -3025,6 +3039,17 @@ static void migration_calculate_complete(MigrationState *s)
    }
}

static void update_iteration_initial_status(MigrationState *s)
{
    /*
     * Update these three fields at the same time to avoid mismatch info lead
     * wrong speed calculation.
     */
    s->iteration_start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
    s->iteration_initial_bytes = migration_total_bytes(s);
    s->iteration_initial_pages = ram_get_total_transferred_pages();
}

static void migration_update_counters(MigrationState *s,
                                      int64_t current_time)
{
@@ -3060,9 +3085,7 @@ static void migration_update_counters(MigrationState *s,

    qemu_file_reset_rate_limit(s->to_dst_file);

    s->iteration_start_time = current_time;
    s->iteration_initial_bytes = current_bytes;
    s->iteration_initial_pages = ram_get_total_transferred_pages();
    update_iteration_initial_status(s);

    trace_migrate_transferred(transferred, time_spent,
                              bandwidth, s->threshold_size);
@@ -3093,8 +3116,7 @@ static MigIterateState migration_iteration_run(MigrationState *s)

    if (pending_size && pending_size >= s->threshold_size) {
        /* Still a significant amount to transfer */
        if (migrate_postcopy() && !in_postcopy &&
            pend_pre <= s->threshold_size &&
        if (!in_postcopy && pend_pre <= s->threshold_size &&
            atomic_read(&s->start_postcopy)) {
            if (postcopy_start(s)) {
                error_report("%s: postcopy failed to start", __func__);
@@ -3186,7 +3208,7 @@ static void *migration_thread(void *opaque)
    rcu_register_thread();

    object_ref(OBJECT(s));
    s->iteration_start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
    update_iteration_initial_status(s);

    qemu_savevm_state_header(s->to_dst_file);

@@ -3251,8 +3273,7 @@ static void *migration_thread(void *opaque)
             * the local variables. This is important to avoid
             * breaking transferred_bytes and bandwidth calculation
             */
            s->iteration_start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
            s->iteration_initial_bytes = 0;
            update_iteration_initial_status(s);
        }

        current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
+0 −1
Original line number Diff line number Diff line
@@ -132,7 +132,6 @@ struct MigrationState
    DeviceState parent_obj;

    /*< public >*/
    size_t bytes_xfer;
    QemuThread thread;
    QEMUBH *cleanup_bh;
    QEMUFile *to_dst_file;
+30 −40
Original line number Diff line number Diff line
@@ -1377,22 +1377,16 @@ void postcopy_fault_thread_notify(MigrationIncomingState *mis)
 *   asking to discard individual ranges.
 *
 * @ms: The current migration state.
 * @offset: the bitmap offset of the named RAMBlock in the migration
 *   bitmap.
 * @offset: the bitmap offset of the named RAMBlock in the migration bitmap.
 * @name: RAMBlock that discards will operate on.
 *
 * returns: a new PDS.
 */
PostcopyDiscardState *postcopy_discard_send_init(MigrationState *ms,
                                                 const char *name)
static PostcopyDiscardState pds = {0};
void postcopy_discard_send_init(MigrationState *ms, const char *name)
{
    PostcopyDiscardState *res = g_malloc0(sizeof(PostcopyDiscardState));

    if (res) {
        res->ramblock_name = name;
    }

    return res;
    pds.ramblock_name = name;
    pds.cur_entry = 0;
    pds.nsentwords = 0;
    pds.nsentcmds = 0;
}

/**
@@ -1401,30 +1395,29 @@ PostcopyDiscardState *postcopy_discard_send_init(MigrationState *ms,
 *   be sent later.
 *
 * @ms: Current migration state.
 * @pds: Structure initialised by postcopy_discard_send_init().
 * @start,@length: a range of pages in the migration bitmap in the
 *   RAM block passed to postcopy_discard_send_init() (length=1 is one page)
 */
void postcopy_discard_send_range(MigrationState *ms, PostcopyDiscardState *pds,
                                unsigned long start, unsigned long length)
void postcopy_discard_send_range(MigrationState *ms, unsigned long start,
                                 unsigned long length)
{
    size_t tp_size = qemu_target_page_size();
    /* Convert to byte offsets within the RAM block */
    pds->start_list[pds->cur_entry] = start  * tp_size;
    pds->length_list[pds->cur_entry] = length * tp_size;
    trace_postcopy_discard_send_range(pds->ramblock_name, start, length);
    pds->cur_entry++;
    pds->nsentwords++;
    pds.start_list[pds.cur_entry] = start  * tp_size;
    pds.length_list[pds.cur_entry] = length * tp_size;
    trace_postcopy_discard_send_range(pds.ramblock_name, start, length);
    pds.cur_entry++;
    pds.nsentwords++;

    if (pds->cur_entry == MAX_DISCARDS_PER_COMMAND) {
    if (pds.cur_entry == MAX_DISCARDS_PER_COMMAND) {
        /* Full set, ship it! */
        qemu_savevm_send_postcopy_ram_discard(ms->to_dst_file,
                                              pds->ramblock_name,
                                              pds->cur_entry,
                                              pds->start_list,
                                              pds->length_list);
        pds->nsentcmds++;
        pds->cur_entry = 0;
                                              pds.ramblock_name,
                                              pds.cur_entry,
                                              pds.start_list,
                                              pds.length_list);
        pds.nsentcmds++;
        pds.cur_entry = 0;
    }
}

@@ -1433,24 +1426,21 @@ void postcopy_discard_send_range(MigrationState *ms, PostcopyDiscardState *pds,
 * bitmap code. Sends any outstanding discard messages, frees the PDS
 *
 * @ms: Current migration state.
 * @pds: Structure initialised by postcopy_discard_send_init().
 */
void postcopy_discard_send_finish(MigrationState *ms, PostcopyDiscardState *pds)
void postcopy_discard_send_finish(MigrationState *ms)
{
    /* Anything unsent? */
    if (pds->cur_entry) {
    if (pds.cur_entry) {
        qemu_savevm_send_postcopy_ram_discard(ms->to_dst_file,
                                              pds->ramblock_name,
                                              pds->cur_entry,
                                              pds->start_list,
                                              pds->length_list);
        pds->nsentcmds++;
                                              pds.ramblock_name,
                                              pds.cur_entry,
                                              pds.start_list,
                                              pds.length_list);
        pds.nsentcmds++;
    }

    trace_postcopy_discard_send_finish(pds->ramblock_name, pds->nsentwords,
                                       pds->nsentcmds);

    g_free(pds);
    trace_postcopy_discard_send_finish(pds.ramblock_name, pds.nsentwords,
                                       pds.nsentcmds);
}

/*
Loading