diff options
-rw-r--r-- | arch_init.c | 8 | ||||
-rw-r--r-- | hmp.c | 21 | ||||
-rw-r--r-- | include/migration/migration.h | 1 | ||||
-rw-r--r-- | include/migration/qemu-file.h | 1 | ||||
-rw-r--r-- | migration/migration.c | 115 | ||||
-rw-r--r-- | migration/qemu-file-buf.c | 31 | ||||
-rw-r--r-- | migration/rdma.c | 127 | ||||
-rw-r--r-- | qapi-schema.json | 37 |
8 files changed, 155 insertions, 186 deletions
diff --git a/arch_init.c b/arch_init.c index c3f7d3f56d..fcfa32828d 100644 --- a/arch_init.c +++ b/arch_init.c @@ -895,13 +895,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque) * Count the total number of pages used by ram blocks not including any * gaps due to alignment or unplugs. */ - migration_dirty_pages = 0; - QLIST_FOREACH_RCU(block, &ram_list.blocks, next) { - uint64_t block_pages; - - block_pages = block->used_length >> TARGET_PAGE_BITS; - migration_dirty_pages += block_pages; - } + migration_dirty_pages = ram_bytes_total() >> TARGET_PAGE_BITS; memory_global_dirty_log_start(); migration_bitmap_sync(); @@ -162,7 +162,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict) } if (info->has_status) { - monitor_printf(mon, "Migration status: %s\n", info->status); + monitor_printf(mon, "Migration status: %s\n", + MigrationStatus_lookup[info->status]); monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n", info->total_time); if (info->has_expected_downtime) { @@ -1123,11 +1124,7 @@ void hmp_migrate_incoming(Monitor *mon, const QDict *qdict) qmp_migrate_incoming(uri, &err); - if (err) { - monitor_printf(mon, "%s\n", error_get_pretty(err)); - error_free(err); - return; - } + hmp_handle_error(mon, &err); } void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict) @@ -1345,21 +1342,21 @@ void hmp_block_job_complete(Monitor *mon, const QDict *qdict) hmp_handle_error(mon, &error); } -typedef struct MigrationStatus +typedef struct HMPMigrationStatus { QEMUTimer *timer; Monitor *mon; bool is_block_migration; -} MigrationStatus; +} HMPMigrationStatus; static void hmp_migrate_status_cb(void *opaque) { - MigrationStatus *status = opaque; + HMPMigrationStatus *status = opaque; MigrationInfo *info; info = qmp_query_migrate(NULL); - if (!info->has_status || strcmp(info->status, "active") == 0 || - strcmp(info->status, "setup") == 0) { + if (!info->has_status || info->status == MIGRATION_STATUS_ACTIVE || + info->status == MIGRATION_STATUS_SETUP) { if (info->has_disk) { int progress; @@ -1402,7 +1399,7 @@ void hmp_migrate(Monitor *mon, const QDict *qdict) } if (!detach) { - MigrationStatus *status; + HMPMigrationStatus *status; if (monitor_suspend(mon) < 0) { monitor_printf(mon, "terminal does not allow synchronous " diff --git a/include/migration/migration.h b/include/migration/migration.h index 5e16af60fd..bf09968d76 100644 --- a/include/migration/migration.h +++ b/include/migration/migration.h @@ -139,7 +139,6 @@ void migrate_add_blocker(Error *reason); */ void migrate_del_blocker(Error *reason); -bool migrate_rdma_pin_all(void); bool migrate_zero_blocks(void); bool migrate_auto_converge(void); diff --git a/include/migration/qemu-file.h b/include/migration/qemu-file.h index 94a8c978a4..745a850e51 100644 --- a/include/migration/qemu-file.h +++ b/include/migration/qemu-file.h @@ -133,7 +133,6 @@ bool qemu_file_mode_is_not_valid(const char *mode); bool qemu_file_is_writable(QEMUFile *f); QEMUSizedBuffer *qsb_create(const uint8_t *buffer, size_t len); -QEMUSizedBuffer *qsb_clone(const QEMUSizedBuffer *); void qsb_free(QEMUSizedBuffer *); size_t qsb_set_length(QEMUSizedBuffer *qsb, size_t length); size_t qsb_get_length(const QEMUSizedBuffer *qsb); diff --git a/migration/migration.c b/migration/migration.c index 2c805f11f5..bc424907f3 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -26,16 +26,6 @@ #include "qmp-commands.h" #include "trace.h" -enum { - MIG_STATE_ERROR = -1, - MIG_STATE_NONE, - MIG_STATE_SETUP, - MIG_STATE_CANCELLING, - MIG_STATE_CANCELLED, - MIG_STATE_ACTIVE, - MIG_STATE_COMPLETED, -}; - #define MAX_THROTTLE (32 << 20) /* Migration speed throttling */ /* Amount of time to allocate to each "chunk" of bandwidth-throttled @@ -58,7 +48,7 @@ static bool deferred_incoming; MigrationState *migrate_get_current(void) { static MigrationState current_migration = { - .state = MIG_STATE_NONE, + .state = MIGRATION_STATUS_NONE, .bandwidth_limit = MAX_THROTTLE, .xbzrle_cache_size = DEFAULT_MIGRATE_CACHE_SIZE, .mbps = -1, @@ -123,8 +113,7 @@ static void process_incoming_migration_co(void *opaque) /* Make sure all file formats flush their mutable metadata */ bdrv_invalidate_cache_all(&local_err); if (local_err) { - qerror_report_err(local_err); - error_free(local_err); + error_report_err(local_err); exit(EXIT_FAILURE); } @@ -201,18 +190,16 @@ MigrationInfo *qmp_query_migrate(Error **errp) MigrationState *s = migrate_get_current(); switch (s->state) { - case MIG_STATE_NONE: + case MIGRATION_STATUS_NONE: /* no migration has happened ever */ break; - case MIG_STATE_SETUP: + case MIGRATION_STATUS_SETUP: info->has_status = true; - info->status = g_strdup("setup"); info->has_total_time = false; break; - case MIG_STATE_ACTIVE: - case MIG_STATE_CANCELLING: + case MIGRATION_STATUS_ACTIVE: + case MIGRATION_STATUS_CANCELLING: info->has_status = true; - info->status = g_strdup("active"); info->has_total_time = true; info->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) - s->total_time; @@ -244,11 +231,10 @@ MigrationInfo *qmp_query_migrate(Error **errp) get_xbzrle_cache_stats(info); break; - case MIG_STATE_COMPLETED: + case MIGRATION_STATUS_COMPLETED: get_xbzrle_cache_stats(info); info->has_status = true; - info->status = g_strdup("completed"); info->has_total_time = true; info->total_time = s->total_time; info->has_downtime = true; @@ -268,15 +254,14 @@ MigrationInfo *qmp_query_migrate(Error **errp) info->ram->mbps = s->mbps; info->ram->dirty_sync_count = s->dirty_sync_count; break; - case MIG_STATE_ERROR: + case MIGRATION_STATUS_FAILED: info->has_status = true; - info->status = g_strdup("failed"); break; - case MIG_STATE_CANCELLED: + case MIGRATION_STATUS_CANCELLED: info->has_status = true; - info->status = g_strdup("cancelled"); break; } + info->status = s->state; return info; } @@ -287,7 +272,8 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params, MigrationState *s = migrate_get_current(); MigrationCapabilityStatusList *cap; - if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP) { + if (s->state == MIGRATION_STATUS_ACTIVE || + s->state == MIGRATION_STATUS_SETUP) { error_set(errp, QERR_MIGRATION_ACTIVE); return; } @@ -323,12 +309,13 @@ static void migrate_fd_cleanup(void *opaque) s->file = NULL; } - assert(s->state != MIG_STATE_ACTIVE); + assert(s->state != MIGRATION_STATUS_ACTIVE); - if (s->state != MIG_STATE_COMPLETED) { + if (s->state != MIGRATION_STATUS_COMPLETED) { qemu_savevm_state_cancel(); - if (s->state == MIG_STATE_CANCELLING) { - migrate_set_state(s, MIG_STATE_CANCELLING, MIG_STATE_CANCELLED); + if (s->state == MIGRATION_STATUS_CANCELLING) { + migrate_set_state(s, MIGRATION_STATUS_CANCELLING, + MIGRATION_STATUS_CANCELLED); } } @@ -339,8 +326,8 @@ void migrate_fd_error(MigrationState *s) { trace_migrate_fd_error(); assert(s->file == NULL); - s->state = MIG_STATE_ERROR; - trace_migrate_set_state(MIG_STATE_ERROR); + s->state = MIGRATION_STATUS_FAILED; + trace_migrate_set_state(MIGRATION_STATUS_FAILED); notifier_list_notify(&migration_state_notifiers, s); } @@ -352,11 +339,12 @@ static void migrate_fd_cancel(MigrationState *s) do { old_state = s->state; - if (old_state != MIG_STATE_SETUP && old_state != MIG_STATE_ACTIVE) { + if (old_state != MIGRATION_STATUS_SETUP && + old_state != MIGRATION_STATUS_ACTIVE) { break; } - migrate_set_state(s, old_state, MIG_STATE_CANCELLING); - } while (s->state != MIG_STATE_CANCELLING); + migrate_set_state(s, old_state, MIGRATION_STATUS_CANCELLING); + } while (s->state != MIGRATION_STATUS_CANCELLING); /* * If we're unlucky the migration code might be stuck somewhere in a @@ -365,7 +353,7 @@ static void migrate_fd_cancel(MigrationState *s) * The outgoing qemu file gets closed in migrate_fd_cleanup that is * called in a bh, so there is no race against this cancel. */ - if (s->state == MIG_STATE_CANCELLING && f) { + if (s->state == MIGRATION_STATUS_CANCELLING && f) { qemu_file_shutdown(f); } } @@ -382,18 +370,18 @@ void remove_migration_state_change_notifier(Notifier *notify) bool migration_in_setup(MigrationState *s) { - return s->state == MIG_STATE_SETUP; + return s->state == MIGRATION_STATUS_SETUP; } bool migration_has_finished(MigrationState *s) { - return s->state == MIG_STATE_COMPLETED; + return s->state == MIGRATION_STATUS_COMPLETED; } bool migration_has_failed(MigrationState *s) { - return (s->state == MIG_STATE_CANCELLED || - s->state == MIG_STATE_ERROR); + return (s->state == MIGRATION_STATUS_CANCELLED || + s->state == MIGRATION_STATUS_FAILED); } static MigrationState *migrate_init(const MigrationParams *params) @@ -413,8 +401,8 @@ static MigrationState *migrate_init(const MigrationParams *params) s->xbzrle_cache_size = xbzrle_cache_size; s->bandwidth_limit = bandwidth_limit; - s->state = MIG_STATE_SETUP; - trace_migrate_set_state(MIG_STATE_SETUP); + s->state = MIGRATION_STATUS_SETUP; + trace_migrate_set_state(MIGRATION_STATUS_SETUP); s->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); return s; @@ -435,11 +423,15 @@ void migrate_del_blocker(Error *reason) void qmp_migrate_incoming(const char *uri, Error **errp) { Error *local_err = NULL; + static bool once = true; if (!deferred_incoming) { - error_setg(errp, "'-incoming defer' is required for migrate_incoming"); + error_setg(errp, "For use with '-incoming defer'"); return; } + if (!once) { + error_setg(errp, "The incoming migration has already been started"); + } qemu_start_incoming_migration(uri, &local_err); @@ -448,7 +440,7 @@ void qmp_migrate_incoming(const char *uri, Error **errp) return; } - deferred_incoming = false; + once = false; } void qmp_migrate(const char *uri, bool has_blk, bool blk, @@ -463,8 +455,9 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, params.blk = has_blk && blk; params.shared = has_inc && inc; - if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP || - s->state == MIG_STATE_CANCELLING) { + if (s->state == MIGRATION_STATUS_ACTIVE || + s->state == MIGRATION_STATUS_SETUP || + s->state == MIGRATION_STATUS_CANCELLING) { error_set(errp, QERR_MIGRATION_ACTIVE); return; } @@ -501,7 +494,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, #endif } else { error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol"); - s->state = MIG_STATE_ERROR; + s->state = MIGRATION_STATUS_FAILED; return; } @@ -576,15 +569,6 @@ void qmp_migrate_set_downtime(double value, Error **errp) max_downtime = (uint64_t)value; } -bool migrate_rdma_pin_all(void) -{ - MigrationState *s; - - s = migrate_get_current(); - - return s->enabled_capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL]; -} - bool migrate_auto_converge(void) { MigrationState *s; @@ -636,9 +620,9 @@ static void *migration_thread(void *opaque) qemu_savevm_state_begin(s->file, &s->params); s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start; - migrate_set_state(s, MIG_STATE_SETUP, MIG_STATE_ACTIVE); + migrate_set_state(s, MIGRATION_STATUS_SETUP, MIGRATION_STATUS_ACTIVE); - while (s->state == MIG_STATE_ACTIVE) { + while (s->state == MIGRATION_STATUS_ACTIVE) { int64_t current_time; uint64_t pending_size; @@ -663,19 +647,22 @@ static void *migration_thread(void *opaque) qemu_mutex_unlock_iothread(); if (ret < 0) { - migrate_set_state(s, MIG_STATE_ACTIVE, MIG_STATE_ERROR); + migrate_set_state(s, MIGRATION_STATUS_ACTIVE, + MIGRATION_STATUS_FAILED); break; } if (!qemu_file_get_error(s->file)) { - migrate_set_state(s, MIG_STATE_ACTIVE, MIG_STATE_COMPLETED); + migrate_set_state(s, MIGRATION_STATUS_ACTIVE, + MIGRATION_STATUS_COMPLETED); break; } } } if (qemu_file_get_error(s->file)) { - migrate_set_state(s, MIG_STATE_ACTIVE, MIG_STATE_ERROR); + migrate_set_state(s, MIGRATION_STATUS_ACTIVE, + MIGRATION_STATUS_FAILED); break; } current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); @@ -707,7 +694,7 @@ static void *migration_thread(void *opaque) } qemu_mutex_lock_iothread(); - if (s->state == MIG_STATE_COMPLETED) { + if (s->state == MIGRATION_STATUS_COMPLETED) { int64_t end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME); uint64_t transferred_bytes = qemu_ftell(s->file); s->total_time = end_time - s->total_time; @@ -730,8 +717,8 @@ static void *migration_thread(void *opaque) void migrate_fd_connect(MigrationState *s) { - s->state = MIG_STATE_SETUP; - trace_migrate_set_state(MIG_STATE_SETUP); + s->state = MIGRATION_STATUS_SETUP; + trace_migrate_set_state(MIGRATION_STATUS_SETUP); /* This is a best 1st approximation. ns to ms */ s->expected_downtime = max_downtime/1000000; diff --git a/migration/qemu-file-buf.c b/migration/qemu-file-buf.c index e56a8ad1e0..16a51a1e17 100644 --- a/migration/qemu-file-buf.c +++ b/migration/qemu-file-buf.c @@ -365,37 +365,6 @@ ssize_t qsb_write_at(QEMUSizedBuffer *qsb, const uint8_t *source, return count; } -/** - * Create a deep copy of the given QEMUSizedBuffer. - * - * @qsb: A QEMUSizedBuffer - * - * Returns a clone of @qsb or NULL on allocation failure - */ -QEMUSizedBuffer *qsb_clone(const QEMUSizedBuffer *qsb) -{ - QEMUSizedBuffer *out = qsb_create(NULL, qsb_get_length(qsb)); - size_t i; - ssize_t res; - off_t pos = 0; - - if (!out) { - return NULL; - } - - for (i = 0; i < qsb->n_iov; i++) { - res = qsb_write_at(out, qsb->iov[i].iov_base, - pos, qsb->iov[i].iov_len); - if (res < 0) { - qsb_free(out); - return NULL; - } - pos += res; - } - - return out; -} - typedef struct QEMUBuffer { QEMUSizedBuffer *qsb; QEMUFile *file; diff --git a/migration/rdma.c b/migration/rdma.c index d1c19ffdac..e6c3a67b54 100644 --- a/migration/rdma.c +++ b/migration/rdma.c @@ -493,8 +493,8 @@ static inline uint64_t ram_chunk_index(const uint8_t *start, static inline uint8_t *ram_chunk_start(const RDMALocalBlock *rdma_ram_block, uint64_t i) { - return (uint8_t *) (((uintptr_t) rdma_ram_block->local_host_addr) - + (i << RDMA_REG_CHUNK_SHIFT)); + return (uint8_t *)(uintptr_t)(rdma_ram_block->local_host_addr + + (i << RDMA_REG_CHUNK_SHIFT)); } static inline uint8_t *ram_chunk_end(const RDMALocalBlock *rdma_ram_block, @@ -515,7 +515,7 @@ static int rdma_add_block(RDMAContext *rdma, void *host_addr, { RDMALocalBlocks *local = &rdma->local_ram_blocks; RDMALocalBlock *block = g_hash_table_lookup(rdma->blockmap, - (void *) block_offset); + (void *)(uintptr_t)block_offset); RDMALocalBlock *old = local->block; assert(block == NULL); @@ -526,9 +526,11 @@ static int rdma_add_block(RDMAContext *rdma, void *host_addr, int x; for (x = 0; x < local->nb_blocks; x++) { - g_hash_table_remove(rdma->blockmap, (void *)old[x].offset); - g_hash_table_insert(rdma->blockmap, (void *)old[x].offset, - &local->block[x]); + g_hash_table_remove(rdma->blockmap, + (void *)(uintptr_t)old[x].offset); + g_hash_table_insert(rdma->blockmap, + (void *)(uintptr_t)old[x].offset, + &local->block[x]); } memcpy(local->block, old, sizeof(RDMALocalBlock) * local->nb_blocks); g_free(old); @@ -551,9 +553,9 @@ static int rdma_add_block(RDMAContext *rdma, void *host_addr, g_hash_table_insert(rdma->blockmap, (void *) block_offset, block); - trace_rdma_add_block(local->nb_blocks, (uint64_t) block->local_host_addr, + trace_rdma_add_block(local->nb_blocks, (uintptr_t) block->local_host_addr, block->offset, block->length, - (uint64_t) (block->local_host_addr + block->length), + (uintptr_t) (block->local_host_addr + block->length), BITS_TO_LONGS(block->nb_chunks) * sizeof(unsigned long) * 8, block->nb_chunks); @@ -634,7 +636,7 @@ static int rdma_delete_block(RDMAContext *rdma, ram_addr_t block_offset) block->remote_keys = NULL; for (x = 0; x < local->nb_blocks; x++) { - g_hash_table_remove(rdma->blockmap, (void *)old[x].offset); + g_hash_table_remove(rdma->blockmap, (void *)(uintptr_t)old[x].offset); } if (local->nb_blocks > 1) { @@ -657,9 +659,9 @@ static int rdma_delete_block(RDMAContext *rdma, ram_addr_t block_offset) } trace_rdma_delete_block(local->nb_blocks, - (uint64_t)block->local_host_addr, + (uintptr_t)block->local_host_addr, block->offset, block->length, - (uint64_t)(block->local_host_addr + block->length), + (uintptr_t)(block->local_host_addr + block->length), BITS_TO_LONGS(block->nb_chunks) * sizeof(unsigned long) * 8, block->nb_chunks); @@ -669,8 +671,9 @@ static int rdma_delete_block(RDMAContext *rdma, ram_addr_t block_offset) if (local->nb_blocks) { for (x = 0; x < local->nb_blocks; x++) { - g_hash_table_insert(rdma->blockmap, (void *)local->block[x].offset, - &local->block[x]); + g_hash_table_insert(rdma->blockmap, + (void *)(uintptr_t)local->block[x].offset, + &local->block[x]); } } @@ -1075,7 +1078,7 @@ static int qemu_rdma_reg_whole_ram_blocks(RDMAContext *rdma) * This search cannot fail or the migration will fail. */ static int qemu_rdma_search_ram_block(RDMAContext *rdma, - uint64_t block_offset, + uintptr_t block_offset, uint64_t offset, uint64_t length, uint64_t *block_index, @@ -1103,7 +1106,7 @@ static int qemu_rdma_search_ram_block(RDMAContext *rdma, * to perform the actual RDMA operation. */ static int qemu_rdma_register_and_get_keys(RDMAContext *rdma, - RDMALocalBlock *block, uint8_t *host_addr, + RDMALocalBlock *block, uintptr_t host_addr, uint32_t *lkey, uint32_t *rkey, int chunk, uint8_t *chunk_start, uint8_t *chunk_end) { @@ -1140,11 +1143,12 @@ static int qemu_rdma_register_and_get_keys(RDMAContext *rdma, if (!block->pmr[chunk]) { perror("Failed to register chunk!"); fprintf(stderr, "Chunk details: block: %d chunk index %d" - " start %" PRIu64 " end %" PRIu64 " host %" PRIu64 - " local %" PRIu64 " registrations: %d\n", - block->index, chunk, (uint64_t) chunk_start, - (uint64_t) chunk_end, (uint64_t) host_addr, - (uint64_t) block->local_host_addr, + " start %" PRIuPTR " end %" PRIuPTR + " host %" PRIuPTR + " local %" PRIuPTR " registrations: %d\n", + block->index, chunk, (uintptr_t)chunk_start, + (uintptr_t)chunk_end, host_addr, + (uintptr_t)block->local_host_addr, rdma->total_registrations); return -1; } @@ -1378,8 +1382,8 @@ static uint64_t qemu_rdma_poll(RDMAContext *rdma, uint64_t *wr_id_out, RDMALocalBlock *block = &(rdma->local_ram_blocks.block[index]); trace_qemu_rdma_poll_write(print_wrid(wr_id), wr_id, rdma->nb_sent, - index, chunk, - block->local_host_addr, (void *)block->remote_host_addr); + index, chunk, block->local_host_addr, + (void *)(uintptr_t)block->remote_host_addr); clear_bit(chunk, block->transit_bitmap); @@ -1522,7 +1526,7 @@ static int qemu_rdma_post_send_control(RDMAContext *rdma, uint8_t *buf, RDMAWorkRequestData *wr = &rdma->wr_data[RDMA_WRID_CONTROL]; struct ibv_send_wr *bad_wr; struct ibv_sge sge = { - .addr = (uint64_t)(wr->control), + .addr = (uintptr_t)(wr->control), .length = head->len + sizeof(RDMAControlHeader), .lkey = wr->control_mr->lkey, }; @@ -1576,7 +1580,7 @@ static int qemu_rdma_post_recv_control(RDMAContext *rdma, int idx) { struct ibv_recv_wr *bad_wr; struct ibv_sge sge = { - .addr = (uint64_t)(rdma->wr_data[idx].control), + .addr = (uintptr_t)(rdma->wr_data[idx].control), .length = RDMA_CONTROL_MAX_BUFFER, .lkey = rdma->wr_data[idx].control_mr->lkey, }; @@ -1823,11 +1827,12 @@ static int qemu_rdma_write_one(QEMUFile *f, RDMAContext *rdma, }; retry: - sge.addr = (uint64_t)(block->local_host_addr + + sge.addr = (uintptr_t)(block->local_host_addr + (current_addr - block->offset)); sge.length = length; - chunk = ram_chunk_index(block->local_host_addr, (uint8_t *) sge.addr); + chunk = ram_chunk_index(block->local_host_addr, + (uint8_t *)(uintptr_t)sge.addr); chunk_start = ram_chunk_start(block, chunk); if (block->is_ram_block) { @@ -1880,8 +1885,9 @@ retry: * memset() + madvise() the entire chunk without RDMA. */ - if (can_use_buffer_find_nonzero_offset((void *)sge.addr, length) - && buffer_find_nonzero_offset((void *)sge.addr, + if (can_use_buffer_find_nonzero_offset((void *)(uintptr_t)sge.addr, + length) + && buffer_find_nonzero_offset((void *)(uintptr_t)sge.addr, length) == length) { RDMACompress comp = { .offset = current_addr, @@ -1931,8 +1937,7 @@ retry: } /* try to overlap this single registration with the one we sent. */ - if (qemu_rdma_register_and_get_keys(rdma, block, - (uint8_t *) sge.addr, + if (qemu_rdma_register_and_get_keys(rdma, block, sge.addr, &sge.lkey, NULL, chunk, chunk_start, chunk_end)) { error_report("cannot get lkey"); @@ -1951,8 +1956,7 @@ retry: block->remote_host_addr = reg_result->host_addr; } else { /* already registered before */ - if (qemu_rdma_register_and_get_keys(rdma, block, - (uint8_t *)sge.addr, + if (qemu_rdma_register_and_get_keys(rdma, block, sge.addr, &sge.lkey, NULL, chunk, chunk_start, chunk_end)) { error_report("cannot get lkey!"); @@ -1964,7 +1968,7 @@ retry: } else { send_wr.wr.rdma.rkey = block->remote_rkey; - if (qemu_rdma_register_and_get_keys(rdma, block, (uint8_t *)sge.addr, + if (qemu_rdma_register_and_get_keys(rdma, block, sge.addr, &sge.lkey, NULL, chunk, chunk_start, chunk_end)) { error_report("cannot get lkey!"); @@ -2364,10 +2368,10 @@ err_rdma_source_connect: static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp) { - int ret = -EINVAL, idx; + int ret, idx; struct rdma_cm_id *listen_id; char ip[40] = "unknown"; - struct rdma_addrinfo *res; + struct rdma_addrinfo *res, *e; char port_str[16]; for (idx = 0; idx < RDMA_WRID_MAX; idx++) { @@ -2375,7 +2379,7 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp) rdma->wr_data[idx].control_curr = NULL; } - if (rdma->host == NULL) { + if (!rdma->host || !rdma->host[0]) { ERROR(errp, "RDMA host is not set!"); rdma->error_state = -EINVAL; return -1; @@ -2398,40 +2402,33 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp) snprintf(port_str, 16, "%d", rdma->port); port_str[15] = '\0'; - if (rdma->host && strcmp("", rdma->host)) { - struct rdma_addrinfo *e; + ret = rdma_getaddrinfo(rdma->host, port_str, NULL, &res); + if (ret < 0) { + ERROR(errp, "could not rdma_getaddrinfo address %s", rdma->host); + goto err_dest_init_bind_addr; + } - ret = rdma_getaddrinfo(rdma->host, port_str, NULL, &res); - if (ret < 0) { - ERROR(errp, "could not rdma_getaddrinfo address %s", rdma->host); - goto err_dest_init_bind_addr; + for (e = res; e != NULL; e = e->ai_next) { + inet_ntop(e->ai_family, + &((struct sockaddr_in *) e->ai_dst_addr)->sin_addr, ip, sizeof ip); + trace_qemu_rdma_dest_init_trying(rdma->host, ip); + ret = rdma_bind_addr(listen_id, e->ai_dst_addr); + if (ret) { + continue; } - - for (e = res; e != NULL; e = e->ai_next) { - inet_ntop(e->ai_family, - &((struct sockaddr_in *) e->ai_dst_addr)->sin_addr, ip, sizeof ip); - trace_qemu_rdma_dest_init_trying(rdma->host, ip); - ret = rdma_bind_addr(listen_id, e->ai_dst_addr); - if (!ret) { - if (e->ai_family == AF_INET6) { - ret = qemu_rdma_broken_ipv6_kernel(errp, listen_id->verbs); - if (ret) { - continue; - } - } - - goto listen; + if (e->ai_family == AF_INET6) { + ret = qemu_rdma_broken_ipv6_kernel(errp, listen_id->verbs); + if (ret) { + continue; } } + break; + } + if (!e) { ERROR(errp, "Error: could not rdma_bind_addr!"); goto err_dest_init_bind_addr; - } else { - ERROR(errp, "migration host and port not specified!"); - ret = -EINVAL; - goto err_dest_init_bind_addr; } -listen: rdma->listen_id = listen_id; qemu_rdma_dump_gid("dest_init", listen_id); @@ -2977,7 +2974,7 @@ static int qemu_rdma_registration_handle(QEMUFile *f, void *opaque, */ for (i = 0; i < local->nb_blocks; i++) { rdma->block[i].remote_host_addr = - (uint64_t)(local->block[i].local_host_addr); + (uintptr_t)(local->block[i].local_host_addr); if (rdma->pin_all) { rdma->block[i].remote_rkey = local->block[i].mr->rkey; @@ -3034,14 +3031,14 @@ static int qemu_rdma_registration_handle(QEMUFile *f, void *opaque, chunk_start = ram_chunk_start(block, chunk); chunk_end = ram_chunk_end(block, chunk + reg->chunks); if (qemu_rdma_register_and_get_keys(rdma, block, - (uint8_t *)host_addr, NULL, ®_result->rkey, + (uintptr_t)host_addr, NULL, ®_result->rkey, chunk, chunk_start, chunk_end)) { error_report("cannot get rkey"); ret = -EINVAL; goto out; } - reg_result->host_addr = (uint64_t) block->local_host_addr; + reg_result->host_addr = (uintptr_t)block->local_host_addr; trace_qemu_rdma_registration_handle_register_rkey( reg_result->rkey); diff --git a/qapi-schema.json b/qapi-schema.json index 2b3e275983..ac9594d66d 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -410,19 +410,43 @@ 'cache-miss': 'int', 'cache-miss-rate': 'number', 'overflow': 'int' } } +# @MigrationStatus: +# +# An enumeration of migration status. +# +# @none: no migration has ever happened. +# +# @setup: migration process has been initiated. +# +# @cancelling: in the process of cancelling migration. +# +# @cancelled: cancelling migration is finished. +# +# @active: in the process of doing migration. +# +# @completed: migration is finished. +# +# @failed: some error occurred during migration process. +# +# Since: 2.3 +# +## +{ 'enum': 'MigrationStatus', + 'data': [ 'none', 'setup', 'cancelling', 'cancelled', + 'active', 'completed', 'failed' ] } + ## # @MigrationInfo # # Information about current migration process. # -# @status: #optional string describing the current migration status. -# As of 0.14.0 this can be 'setup', 'active', 'completed', 'failed' or -# 'cancelled'. If this field is not returned, no migration process +# @status: #optional @MigrationStatus describing the current migration status. +# If this field is not returned, no migration process # has been initiated # # @ram: #optional @MigrationStats containing detailed migration # status, only returned if status is 'active' or -# 'completed'. 'comppleted' (since 1.2) +# 'completed'(since 1.2) # # @disk: #optional @MigrationStats containing detailed disk migration # status, only returned if status is 'active' and it is a block @@ -453,7 +477,7 @@ # Since: 0.14.0 ## { 'type': 'MigrationInfo', - 'data': {'*status': 'str', '*ram': 'MigrationStats', + 'data': {'*status': 'MigrationStatus', '*ram': 'MigrationStats', '*disk': 'MigrationStats', '*xbzrle-cache': 'XBZRLECacheStats', '*total-time': 'int', @@ -1750,6 +1774,9 @@ # Returns: nothing on success # # Since: 2.3 +# Note: It's a bad idea to use a string for the uri, but it needs to stay +# compatible with -incoming and the format of the uri is already exposed +# above libvirt ## { 'command': 'migrate-incoming', 'data': {'uri': 'str' } } |