migration/next for 20150317
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJVCDhaAAoJEPSH7xhYctcjCmUP/2OdZOznik2BwE+RXYjj+TGn YFaN7G7kwCmbxjrbZgq89QW+lmqUlf5K8L6t4v8oOt4NDGslgKiibYJRekRIbWKm G2xiThCQJFLX+62EJ90nSjAERAGvMF5m/w80nUsXba7f5Ryx19qz/fOqrBcipo5w y9pcJ1kGw/bPXB8Enedb6veREgHOOZHAirTVzsRoy7OD0kQsTYIxsjXlk0cYO7FK vcmMr/E3ahzMge8XdLFYHVaMDCf8DTNjLPl0ZeuQt+IS6PP5uEPTQ8hVllT0FeSr SzCXOrWU2GJB9SbSK6S0sg1DzZIc6+eXYV2djDKdj4AjHRvVuZ+L9L5OErNh3zsE RY7ArWQpkrCfCB9xGT0Iud/cKbgiF23V6+Zy6lrzruoQcvw7Dtj90CwXdLEFsTP3 O0XMpkDCXnNjsuexj9DmyXcMs/1EJHUeYentoo3dj7YP2Dlxd2Zz5PEkE4BoYFa9 n7dOpW/Gf+53Axx7ob0+aWcRUAskAc2FTuc4G16YTmMsnx3Jxpn7fwDcZKinHBtE WvgrEc9CCT+7tniXL9biRaETN1sr2fN5ZLgol2JymmXNvrXJNGiwQNUI3wWI/X4P atJcXLfUmR7yTBG5FM6kzl8jSV78MuKqSnxO02eF3GRW90lV4w/jc873W6gbv5Qj hAZtEkRB+5dgCl7iCAXk =baFB -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/juanquintela/tags/migration/20150317' into staging migration/next for 20150317 # gpg: Signature made Tue Mar 17 14:21:14 2015 GMT using RSA key ID 5872D723 # gpg: Can't check signature: public key not found * remotes/juanquintela/tags/migration/20150317: migration: Expose 'cancelling' status to user migration: Convert 'status' of MigrationInfo to use an enum type hmp: Rename 'MigrationStatus' to 'HMPMigrationStatus' migration: Rename abbreviated macro MIG_STATE_* to MIGRATION_STATUS_* migration: Remove unused functions arch_init: Count the total number of pages by using helper function migrate_incoming: Cleanup/clarify error messages Warn against the use of the string as uri parameter to migrate-incoming migrate_incoming: use hmp_handle_error migration: Fix remaining 32 bit compiler errors migration: Fix some 32 bit compiler errors migration/rdma: clean up qemu_rdma_dest_init a bit migration: Avoid qerror_report_err() outside QMP command handlers Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
d8e33fc980
|
@ -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
|
* Count the total number of pages used by ram blocks not including any
|
||||||
* gaps due to alignment or unplugs.
|
* gaps due to alignment or unplugs.
|
||||||
*/
|
*/
|
||||||
migration_dirty_pages = 0;
|
migration_dirty_pages = ram_bytes_total() >> TARGET_PAGE_BITS;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
memory_global_dirty_log_start();
|
memory_global_dirty_log_start();
|
||||||
migration_bitmap_sync();
|
migration_bitmap_sync();
|
||||||
|
|
21
hmp.c
21
hmp.c
|
@ -162,7 +162,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info->has_status) {
|
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",
|
monitor_printf(mon, "total time: %" PRIu64 " milliseconds\n",
|
||||||
info->total_time);
|
info->total_time);
|
||||||
if (info->has_expected_downtime) {
|
if (info->has_expected_downtime) {
|
||||||
|
@ -1123,11 +1124,7 @@ void hmp_migrate_incoming(Monitor *mon, const QDict *qdict)
|
||||||
|
|
||||||
qmp_migrate_incoming(uri, &err);
|
qmp_migrate_incoming(uri, &err);
|
||||||
|
|
||||||
if (err) {
|
hmp_handle_error(mon, &err);
|
||||||
monitor_printf(mon, "%s\n", error_get_pretty(err));
|
|
||||||
error_free(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hmp_migrate_set_downtime(Monitor *mon, const QDict *qdict)
|
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);
|
hmp_handle_error(mon, &error);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct MigrationStatus
|
typedef struct HMPMigrationStatus
|
||||||
{
|
{
|
||||||
QEMUTimer *timer;
|
QEMUTimer *timer;
|
||||||
Monitor *mon;
|
Monitor *mon;
|
||||||
bool is_block_migration;
|
bool is_block_migration;
|
||||||
} MigrationStatus;
|
} HMPMigrationStatus;
|
||||||
|
|
||||||
static void hmp_migrate_status_cb(void *opaque)
|
static void hmp_migrate_status_cb(void *opaque)
|
||||||
{
|
{
|
||||||
MigrationStatus *status = opaque;
|
HMPMigrationStatus *status = opaque;
|
||||||
MigrationInfo *info;
|
MigrationInfo *info;
|
||||||
|
|
||||||
info = qmp_query_migrate(NULL);
|
info = qmp_query_migrate(NULL);
|
||||||
if (!info->has_status || strcmp(info->status, "active") == 0 ||
|
if (!info->has_status || info->status == MIGRATION_STATUS_ACTIVE ||
|
||||||
strcmp(info->status, "setup") == 0) {
|
info->status == MIGRATION_STATUS_SETUP) {
|
||||||
if (info->has_disk) {
|
if (info->has_disk) {
|
||||||
int progress;
|
int progress;
|
||||||
|
|
||||||
|
@ -1402,7 +1399,7 @@ void hmp_migrate(Monitor *mon, const QDict *qdict)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!detach) {
|
if (!detach) {
|
||||||
MigrationStatus *status;
|
HMPMigrationStatus *status;
|
||||||
|
|
||||||
if (monitor_suspend(mon) < 0) {
|
if (monitor_suspend(mon) < 0) {
|
||||||
monitor_printf(mon, "terminal does not allow synchronous "
|
monitor_printf(mon, "terminal does not allow synchronous "
|
||||||
|
|
|
@ -139,7 +139,6 @@ void migrate_add_blocker(Error *reason);
|
||||||
*/
|
*/
|
||||||
void migrate_del_blocker(Error *reason);
|
void migrate_del_blocker(Error *reason);
|
||||||
|
|
||||||
bool migrate_rdma_pin_all(void);
|
|
||||||
bool migrate_zero_blocks(void);
|
bool migrate_zero_blocks(void);
|
||||||
|
|
||||||
bool migrate_auto_converge(void);
|
bool migrate_auto_converge(void);
|
||||||
|
|
|
@ -133,7 +133,6 @@ bool qemu_file_mode_is_not_valid(const char *mode);
|
||||||
bool qemu_file_is_writable(QEMUFile *f);
|
bool qemu_file_is_writable(QEMUFile *f);
|
||||||
|
|
||||||
QEMUSizedBuffer *qsb_create(const uint8_t *buffer, size_t len);
|
QEMUSizedBuffer *qsb_create(const uint8_t *buffer, size_t len);
|
||||||
QEMUSizedBuffer *qsb_clone(const QEMUSizedBuffer *);
|
|
||||||
void qsb_free(QEMUSizedBuffer *);
|
void qsb_free(QEMUSizedBuffer *);
|
||||||
size_t qsb_set_length(QEMUSizedBuffer *qsb, size_t length);
|
size_t qsb_set_length(QEMUSizedBuffer *qsb, size_t length);
|
||||||
size_t qsb_get_length(const QEMUSizedBuffer *qsb);
|
size_t qsb_get_length(const QEMUSizedBuffer *qsb);
|
||||||
|
|
|
@ -26,16 +26,6 @@
|
||||||
#include "qmp-commands.h"
|
#include "qmp-commands.h"
|
||||||
#include "trace.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 */
|
#define MAX_THROTTLE (32 << 20) /* Migration speed throttling */
|
||||||
|
|
||||||
/* Amount of time to allocate to each "chunk" of bandwidth-throttled
|
/* Amount of time to allocate to each "chunk" of bandwidth-throttled
|
||||||
|
@ -58,7 +48,7 @@ static bool deferred_incoming;
|
||||||
MigrationState *migrate_get_current(void)
|
MigrationState *migrate_get_current(void)
|
||||||
{
|
{
|
||||||
static MigrationState current_migration = {
|
static MigrationState current_migration = {
|
||||||
.state = MIG_STATE_NONE,
|
.state = MIGRATION_STATUS_NONE,
|
||||||
.bandwidth_limit = MAX_THROTTLE,
|
.bandwidth_limit = MAX_THROTTLE,
|
||||||
.xbzrle_cache_size = DEFAULT_MIGRATE_CACHE_SIZE,
|
.xbzrle_cache_size = DEFAULT_MIGRATE_CACHE_SIZE,
|
||||||
.mbps = -1,
|
.mbps = -1,
|
||||||
|
@ -123,8 +113,7 @@ static void process_incoming_migration_co(void *opaque)
|
||||||
/* Make sure all file formats flush their mutable metadata */
|
/* Make sure all file formats flush their mutable metadata */
|
||||||
bdrv_invalidate_cache_all(&local_err);
|
bdrv_invalidate_cache_all(&local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
qerror_report_err(local_err);
|
error_report_err(local_err);
|
||||||
error_free(local_err);
|
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,18 +190,16 @@ MigrationInfo *qmp_query_migrate(Error **errp)
|
||||||
MigrationState *s = migrate_get_current();
|
MigrationState *s = migrate_get_current();
|
||||||
|
|
||||||
switch (s->state) {
|
switch (s->state) {
|
||||||
case MIG_STATE_NONE:
|
case MIGRATION_STATUS_NONE:
|
||||||
/* no migration has happened ever */
|
/* no migration has happened ever */
|
||||||
break;
|
break;
|
||||||
case MIG_STATE_SETUP:
|
case MIGRATION_STATUS_SETUP:
|
||||||
info->has_status = true;
|
info->has_status = true;
|
||||||
info->status = g_strdup("setup");
|
|
||||||
info->has_total_time = false;
|
info->has_total_time = false;
|
||||||
break;
|
break;
|
||||||
case MIG_STATE_ACTIVE:
|
case MIGRATION_STATUS_ACTIVE:
|
||||||
case MIG_STATE_CANCELLING:
|
case MIGRATION_STATUS_CANCELLING:
|
||||||
info->has_status = true;
|
info->has_status = true;
|
||||||
info->status = g_strdup("active");
|
|
||||||
info->has_total_time = true;
|
info->has_total_time = true;
|
||||||
info->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME)
|
info->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME)
|
||||||
- s->total_time;
|
- s->total_time;
|
||||||
|
@ -244,11 +231,10 @@ MigrationInfo *qmp_query_migrate(Error **errp)
|
||||||
|
|
||||||
get_xbzrle_cache_stats(info);
|
get_xbzrle_cache_stats(info);
|
||||||
break;
|
break;
|
||||||
case MIG_STATE_COMPLETED:
|
case MIGRATION_STATUS_COMPLETED:
|
||||||
get_xbzrle_cache_stats(info);
|
get_xbzrle_cache_stats(info);
|
||||||
|
|
||||||
info->has_status = true;
|
info->has_status = true;
|
||||||
info->status = g_strdup("completed");
|
|
||||||
info->has_total_time = true;
|
info->has_total_time = true;
|
||||||
info->total_time = s->total_time;
|
info->total_time = s->total_time;
|
||||||
info->has_downtime = true;
|
info->has_downtime = true;
|
||||||
|
@ -268,15 +254,14 @@ MigrationInfo *qmp_query_migrate(Error **errp)
|
||||||
info->ram->mbps = s->mbps;
|
info->ram->mbps = s->mbps;
|
||||||
info->ram->dirty_sync_count = s->dirty_sync_count;
|
info->ram->dirty_sync_count = s->dirty_sync_count;
|
||||||
break;
|
break;
|
||||||
case MIG_STATE_ERROR:
|
case MIGRATION_STATUS_FAILED:
|
||||||
info->has_status = true;
|
info->has_status = true;
|
||||||
info->status = g_strdup("failed");
|
|
||||||
break;
|
break;
|
||||||
case MIG_STATE_CANCELLED:
|
case MIGRATION_STATUS_CANCELLED:
|
||||||
info->has_status = true;
|
info->has_status = true;
|
||||||
info->status = g_strdup("cancelled");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
info->status = s->state;
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
@ -287,7 +272,8 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
|
||||||
MigrationState *s = migrate_get_current();
|
MigrationState *s = migrate_get_current();
|
||||||
MigrationCapabilityStatusList *cap;
|
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);
|
error_set(errp, QERR_MIGRATION_ACTIVE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -323,12 +309,13 @@ static void migrate_fd_cleanup(void *opaque)
|
||||||
s->file = NULL;
|
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();
|
qemu_savevm_state_cancel();
|
||||||
if (s->state == MIG_STATE_CANCELLING) {
|
if (s->state == MIGRATION_STATUS_CANCELLING) {
|
||||||
migrate_set_state(s, MIG_STATE_CANCELLING, MIG_STATE_CANCELLED);
|
migrate_set_state(s, MIGRATION_STATUS_CANCELLING,
|
||||||
|
MIGRATION_STATUS_CANCELLED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,8 +326,8 @@ void migrate_fd_error(MigrationState *s)
|
||||||
{
|
{
|
||||||
trace_migrate_fd_error();
|
trace_migrate_fd_error();
|
||||||
assert(s->file == NULL);
|
assert(s->file == NULL);
|
||||||
s->state = MIG_STATE_ERROR;
|
s->state = MIGRATION_STATUS_FAILED;
|
||||||
trace_migrate_set_state(MIG_STATE_ERROR);
|
trace_migrate_set_state(MIGRATION_STATUS_FAILED);
|
||||||
notifier_list_notify(&migration_state_notifiers, s);
|
notifier_list_notify(&migration_state_notifiers, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,11 +339,12 @@ static void migrate_fd_cancel(MigrationState *s)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
old_state = s->state;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
migrate_set_state(s, old_state, MIG_STATE_CANCELLING);
|
migrate_set_state(s, old_state, MIGRATION_STATUS_CANCELLING);
|
||||||
} while (s->state != MIG_STATE_CANCELLING);
|
} while (s->state != MIGRATION_STATUS_CANCELLING);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we're unlucky the migration code might be stuck somewhere in a
|
* 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
|
* The outgoing qemu file gets closed in migrate_fd_cleanup that is
|
||||||
* called in a bh, so there is no race against this cancel.
|
* 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);
|
qemu_file_shutdown(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,18 +370,18 @@ void remove_migration_state_change_notifier(Notifier *notify)
|
||||||
|
|
||||||
bool migration_in_setup(MigrationState *s)
|
bool migration_in_setup(MigrationState *s)
|
||||||
{
|
{
|
||||||
return s->state == MIG_STATE_SETUP;
|
return s->state == MIGRATION_STATUS_SETUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool migration_has_finished(MigrationState *s)
|
bool migration_has_finished(MigrationState *s)
|
||||||
{
|
{
|
||||||
return s->state == MIG_STATE_COMPLETED;
|
return s->state == MIGRATION_STATUS_COMPLETED;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool migration_has_failed(MigrationState *s)
|
bool migration_has_failed(MigrationState *s)
|
||||||
{
|
{
|
||||||
return (s->state == MIG_STATE_CANCELLED ||
|
return (s->state == MIGRATION_STATUS_CANCELLED ||
|
||||||
s->state == MIG_STATE_ERROR);
|
s->state == MIGRATION_STATUS_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static MigrationState *migrate_init(const MigrationParams *params)
|
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->xbzrle_cache_size = xbzrle_cache_size;
|
||||||
|
|
||||||
s->bandwidth_limit = bandwidth_limit;
|
s->bandwidth_limit = bandwidth_limit;
|
||||||
s->state = MIG_STATE_SETUP;
|
s->state = MIGRATION_STATUS_SETUP;
|
||||||
trace_migrate_set_state(MIG_STATE_SETUP);
|
trace_migrate_set_state(MIGRATION_STATUS_SETUP);
|
||||||
|
|
||||||
s->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
s->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
||||||
return s;
|
return s;
|
||||||
|
@ -435,11 +423,15 @@ void migrate_del_blocker(Error *reason)
|
||||||
void qmp_migrate_incoming(const char *uri, Error **errp)
|
void qmp_migrate_incoming(const char *uri, Error **errp)
|
||||||
{
|
{
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
static bool once = true;
|
||||||
|
|
||||||
if (!deferred_incoming) {
|
if (!deferred_incoming) {
|
||||||
error_setg(errp, "'-incoming defer' is required for migrate_incoming");
|
error_setg(errp, "For use with '-incoming defer'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!once) {
|
||||||
|
error_setg(errp, "The incoming migration has already been started");
|
||||||
|
}
|
||||||
|
|
||||||
qemu_start_incoming_migration(uri, &local_err);
|
qemu_start_incoming_migration(uri, &local_err);
|
||||||
|
|
||||||
|
@ -448,7 +440,7 @@ void qmp_migrate_incoming(const char *uri, Error **errp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
deferred_incoming = false;
|
once = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_migrate(const char *uri, bool has_blk, bool blk,
|
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.blk = has_blk && blk;
|
||||||
params.shared = has_inc && inc;
|
params.shared = has_inc && inc;
|
||||||
|
|
||||||
if (s->state == MIG_STATE_ACTIVE || s->state == MIG_STATE_SETUP ||
|
if (s->state == MIGRATION_STATUS_ACTIVE ||
|
||||||
s->state == MIG_STATE_CANCELLING) {
|
s->state == MIGRATION_STATUS_SETUP ||
|
||||||
|
s->state == MIGRATION_STATUS_CANCELLING) {
|
||||||
error_set(errp, QERR_MIGRATION_ACTIVE);
|
error_set(errp, QERR_MIGRATION_ACTIVE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -501,7 +494,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk,
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol");
|
error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol");
|
||||||
s->state = MIG_STATE_ERROR;
|
s->state = MIGRATION_STATUS_FAILED;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -576,15 +569,6 @@ void qmp_migrate_set_downtime(double value, Error **errp)
|
||||||
max_downtime = (uint64_t)value;
|
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)
|
bool migrate_auto_converge(void)
|
||||||
{
|
{
|
||||||
MigrationState *s;
|
MigrationState *s;
|
||||||
|
@ -636,9 +620,9 @@ static void *migration_thread(void *opaque)
|
||||||
qemu_savevm_state_begin(s->file, &s->params);
|
qemu_savevm_state_begin(s->file, &s->params);
|
||||||
|
|
||||||
s->setup_time = qemu_clock_get_ms(QEMU_CLOCK_HOST) - setup_start;
|
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;
|
int64_t current_time;
|
||||||
uint64_t pending_size;
|
uint64_t pending_size;
|
||||||
|
|
||||||
|
@ -663,19 +647,22 @@ static void *migration_thread(void *opaque)
|
||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
migrate_set_state(s, MIG_STATE_ACTIVE, MIG_STATE_ERROR);
|
migrate_set_state(s, MIGRATION_STATUS_ACTIVE,
|
||||||
|
MIGRATION_STATUS_FAILED);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!qemu_file_get_error(s->file)) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qemu_file_get_error(s->file)) {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
current_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
||||||
|
@ -707,7 +694,7 @@ static void *migration_thread(void *opaque)
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_mutex_lock_iothread();
|
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);
|
int64_t end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
||||||
uint64_t transferred_bytes = qemu_ftell(s->file);
|
uint64_t transferred_bytes = qemu_ftell(s->file);
|
||||||
s->total_time = end_time - s->total_time;
|
s->total_time = end_time - s->total_time;
|
||||||
|
@ -730,8 +717,8 @@ static void *migration_thread(void *opaque)
|
||||||
|
|
||||||
void migrate_fd_connect(MigrationState *s)
|
void migrate_fd_connect(MigrationState *s)
|
||||||
{
|
{
|
||||||
s->state = MIG_STATE_SETUP;
|
s->state = MIGRATION_STATUS_SETUP;
|
||||||
trace_migrate_set_state(MIG_STATE_SETUP);
|
trace_migrate_set_state(MIGRATION_STATUS_SETUP);
|
||||||
|
|
||||||
/* This is a best 1st approximation. ns to ms */
|
/* This is a best 1st approximation. ns to ms */
|
||||||
s->expected_downtime = max_downtime/1000000;
|
s->expected_downtime = max_downtime/1000000;
|
||||||
|
|
|
@ -365,37 +365,6 @@ ssize_t qsb_write_at(QEMUSizedBuffer *qsb, const uint8_t *source,
|
||||||
return count;
|
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 {
|
typedef struct QEMUBuffer {
|
||||||
QEMUSizedBuffer *qsb;
|
QEMUSizedBuffer *qsb;
|
||||||
QEMUFile *file;
|
QEMUFile *file;
|
||||||
|
|
139
migration/rdma.c
139
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,
|
static inline uint8_t *ram_chunk_start(const RDMALocalBlock *rdma_ram_block,
|
||||||
uint64_t i)
|
uint64_t i)
|
||||||
{
|
{
|
||||||
return (uint8_t *) (((uintptr_t) rdma_ram_block->local_host_addr)
|
return (uint8_t *)(uintptr_t)(rdma_ram_block->local_host_addr +
|
||||||
+ (i << RDMA_REG_CHUNK_SHIFT));
|
(i << RDMA_REG_CHUNK_SHIFT));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint8_t *ram_chunk_end(const RDMALocalBlock *rdma_ram_block,
|
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;
|
RDMALocalBlocks *local = &rdma->local_ram_blocks;
|
||||||
RDMALocalBlock *block = g_hash_table_lookup(rdma->blockmap,
|
RDMALocalBlock *block = g_hash_table_lookup(rdma->blockmap,
|
||||||
(void *) block_offset);
|
(void *)(uintptr_t)block_offset);
|
||||||
RDMALocalBlock *old = local->block;
|
RDMALocalBlock *old = local->block;
|
||||||
|
|
||||||
assert(block == NULL);
|
assert(block == NULL);
|
||||||
|
@ -526,9 +526,11 @@ static int rdma_add_block(RDMAContext *rdma, void *host_addr,
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
for (x = 0; x < local->nb_blocks; x++) {
|
for (x = 0; x < local->nb_blocks; x++) {
|
||||||
g_hash_table_remove(rdma->blockmap, (void *)old[x].offset);
|
g_hash_table_remove(rdma->blockmap,
|
||||||
g_hash_table_insert(rdma->blockmap, (void *)old[x].offset,
|
(void *)(uintptr_t)old[x].offset);
|
||||||
&local->block[x]);
|
g_hash_table_insert(rdma->blockmap,
|
||||||
|
(void *)(uintptr_t)old[x].offset,
|
||||||
|
&local->block[x]);
|
||||||
}
|
}
|
||||||
memcpy(local->block, old, sizeof(RDMALocalBlock) * local->nb_blocks);
|
memcpy(local->block, old, sizeof(RDMALocalBlock) * local->nb_blocks);
|
||||||
g_free(old);
|
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);
|
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,
|
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) *
|
BITS_TO_LONGS(block->nb_chunks) *
|
||||||
sizeof(unsigned long) * 8,
|
sizeof(unsigned long) * 8,
|
||||||
block->nb_chunks);
|
block->nb_chunks);
|
||||||
|
@ -634,7 +636,7 @@ static int rdma_delete_block(RDMAContext *rdma, ram_addr_t block_offset)
|
||||||
block->remote_keys = NULL;
|
block->remote_keys = NULL;
|
||||||
|
|
||||||
for (x = 0; x < local->nb_blocks; x++) {
|
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) {
|
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,
|
trace_rdma_delete_block(local->nb_blocks,
|
||||||
(uint64_t)block->local_host_addr,
|
(uintptr_t)block->local_host_addr,
|
||||||
block->offset, block->length,
|
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) *
|
BITS_TO_LONGS(block->nb_chunks) *
|
||||||
sizeof(unsigned long) * 8, 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) {
|
if (local->nb_blocks) {
|
||||||
for (x = 0; x < local->nb_blocks; x++) {
|
for (x = 0; x < local->nb_blocks; x++) {
|
||||||
g_hash_table_insert(rdma->blockmap, (void *)local->block[x].offset,
|
g_hash_table_insert(rdma->blockmap,
|
||||||
&local->block[x]);
|
(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.
|
* This search cannot fail or the migration will fail.
|
||||||
*/
|
*/
|
||||||
static int qemu_rdma_search_ram_block(RDMAContext *rdma,
|
static int qemu_rdma_search_ram_block(RDMAContext *rdma,
|
||||||
uint64_t block_offset,
|
uintptr_t block_offset,
|
||||||
uint64_t offset,
|
uint64_t offset,
|
||||||
uint64_t length,
|
uint64_t length,
|
||||||
uint64_t *block_index,
|
uint64_t *block_index,
|
||||||
|
@ -1103,7 +1106,7 @@ static int qemu_rdma_search_ram_block(RDMAContext *rdma,
|
||||||
* to perform the actual RDMA operation.
|
* to perform the actual RDMA operation.
|
||||||
*/
|
*/
|
||||||
static int qemu_rdma_register_and_get_keys(RDMAContext *rdma,
|
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,
|
uint32_t *lkey, uint32_t *rkey, int chunk,
|
||||||
uint8_t *chunk_start, uint8_t *chunk_end)
|
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]) {
|
if (!block->pmr[chunk]) {
|
||||||
perror("Failed to register chunk!");
|
perror("Failed to register chunk!");
|
||||||
fprintf(stderr, "Chunk details: block: %d chunk index %d"
|
fprintf(stderr, "Chunk details: block: %d chunk index %d"
|
||||||
" start %" PRIu64 " end %" PRIu64 " host %" PRIu64
|
" start %" PRIuPTR " end %" PRIuPTR
|
||||||
" local %" PRIu64 " registrations: %d\n",
|
" host %" PRIuPTR
|
||||||
block->index, chunk, (uint64_t) chunk_start,
|
" local %" PRIuPTR " registrations: %d\n",
|
||||||
(uint64_t) chunk_end, (uint64_t) host_addr,
|
block->index, chunk, (uintptr_t)chunk_start,
|
||||||
(uint64_t) block->local_host_addr,
|
(uintptr_t)chunk_end, host_addr,
|
||||||
|
(uintptr_t)block->local_host_addr,
|
||||||
rdma->total_registrations);
|
rdma->total_registrations);
|
||||||
return -1;
|
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]);
|
RDMALocalBlock *block = &(rdma->local_ram_blocks.block[index]);
|
||||||
|
|
||||||
trace_qemu_rdma_poll_write(print_wrid(wr_id), wr_id, rdma->nb_sent,
|
trace_qemu_rdma_poll_write(print_wrid(wr_id), wr_id, rdma->nb_sent,
|
||||||
index, chunk,
|
index, chunk, block->local_host_addr,
|
||||||
block->local_host_addr, (void *)block->remote_host_addr);
|
(void *)(uintptr_t)block->remote_host_addr);
|
||||||
|
|
||||||
clear_bit(chunk, block->transit_bitmap);
|
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];
|
RDMAWorkRequestData *wr = &rdma->wr_data[RDMA_WRID_CONTROL];
|
||||||
struct ibv_send_wr *bad_wr;
|
struct ibv_send_wr *bad_wr;
|
||||||
struct ibv_sge sge = {
|
struct ibv_sge sge = {
|
||||||
.addr = (uint64_t)(wr->control),
|
.addr = (uintptr_t)(wr->control),
|
||||||
.length = head->len + sizeof(RDMAControlHeader),
|
.length = head->len + sizeof(RDMAControlHeader),
|
||||||
.lkey = wr->control_mr->lkey,
|
.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_recv_wr *bad_wr;
|
||||||
struct ibv_sge sge = {
|
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,
|
.length = RDMA_CONTROL_MAX_BUFFER,
|
||||||
.lkey = rdma->wr_data[idx].control_mr->lkey,
|
.lkey = rdma->wr_data[idx].control_mr->lkey,
|
||||||
};
|
};
|
||||||
|
@ -1823,11 +1827,12 @@ static int qemu_rdma_write_one(QEMUFile *f, RDMAContext *rdma,
|
||||||
};
|
};
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
sge.addr = (uint64_t)(block->local_host_addr +
|
sge.addr = (uintptr_t)(block->local_host_addr +
|
||||||
(current_addr - block->offset));
|
(current_addr - block->offset));
|
||||||
sge.length = length;
|
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);
|
chunk_start = ram_chunk_start(block, chunk);
|
||||||
|
|
||||||
if (block->is_ram_block) {
|
if (block->is_ram_block) {
|
||||||
|
@ -1880,8 +1885,9 @@ retry:
|
||||||
* memset() + madvise() the entire chunk without RDMA.
|
* memset() + madvise() the entire chunk without RDMA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (can_use_buffer_find_nonzero_offset((void *)sge.addr, length)
|
if (can_use_buffer_find_nonzero_offset((void *)(uintptr_t)sge.addr,
|
||||||
&& buffer_find_nonzero_offset((void *)sge.addr,
|
length)
|
||||||
|
&& buffer_find_nonzero_offset((void *)(uintptr_t)sge.addr,
|
||||||
length) == length) {
|
length) == length) {
|
||||||
RDMACompress comp = {
|
RDMACompress comp = {
|
||||||
.offset = current_addr,
|
.offset = current_addr,
|
||||||
|
@ -1931,8 +1937,7 @@ retry:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* try to overlap this single registration with the one we sent. */
|
/* try to overlap this single registration with the one we sent. */
|
||||||
if (qemu_rdma_register_and_get_keys(rdma, block,
|
if (qemu_rdma_register_and_get_keys(rdma, block, sge.addr,
|
||||||
(uint8_t *) sge.addr,
|
|
||||||
&sge.lkey, NULL, chunk,
|
&sge.lkey, NULL, chunk,
|
||||||
chunk_start, chunk_end)) {
|
chunk_start, chunk_end)) {
|
||||||
error_report("cannot get lkey");
|
error_report("cannot get lkey");
|
||||||
|
@ -1951,8 +1956,7 @@ retry:
|
||||||
block->remote_host_addr = reg_result->host_addr;
|
block->remote_host_addr = reg_result->host_addr;
|
||||||
} else {
|
} else {
|
||||||
/* already registered before */
|
/* already registered before */
|
||||||
if (qemu_rdma_register_and_get_keys(rdma, block,
|
if (qemu_rdma_register_and_get_keys(rdma, block, sge.addr,
|
||||||
(uint8_t *)sge.addr,
|
|
||||||
&sge.lkey, NULL, chunk,
|
&sge.lkey, NULL, chunk,
|
||||||
chunk_start, chunk_end)) {
|
chunk_start, chunk_end)) {
|
||||||
error_report("cannot get lkey!");
|
error_report("cannot get lkey!");
|
||||||
|
@ -1964,7 +1968,7 @@ retry:
|
||||||
} else {
|
} else {
|
||||||
send_wr.wr.rdma.rkey = block->remote_rkey;
|
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,
|
&sge.lkey, NULL, chunk,
|
||||||
chunk_start, chunk_end)) {
|
chunk_start, chunk_end)) {
|
||||||
error_report("cannot get lkey!");
|
error_report("cannot get lkey!");
|
||||||
|
@ -2364,10 +2368,10 @@ err_rdma_source_connect:
|
||||||
|
|
||||||
static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
|
static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
|
||||||
{
|
{
|
||||||
int ret = -EINVAL, idx;
|
int ret, idx;
|
||||||
struct rdma_cm_id *listen_id;
|
struct rdma_cm_id *listen_id;
|
||||||
char ip[40] = "unknown";
|
char ip[40] = "unknown";
|
||||||
struct rdma_addrinfo *res;
|
struct rdma_addrinfo *res, *e;
|
||||||
char port_str[16];
|
char port_str[16];
|
||||||
|
|
||||||
for (idx = 0; idx < RDMA_WRID_MAX; idx++) {
|
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;
|
rdma->wr_data[idx].control_curr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rdma->host == NULL) {
|
if (!rdma->host || !rdma->host[0]) {
|
||||||
ERROR(errp, "RDMA host is not set!");
|
ERROR(errp, "RDMA host is not set!");
|
||||||
rdma->error_state = -EINVAL;
|
rdma->error_state = -EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2398,40 +2402,33 @@ static int qemu_rdma_dest_init(RDMAContext *rdma, Error **errp)
|
||||||
snprintf(port_str, 16, "%d", rdma->port);
|
snprintf(port_str, 16, "%d", rdma->port);
|
||||||
port_str[15] = '\0';
|
port_str[15] = '\0';
|
||||||
|
|
||||||
if (rdma->host && strcmp("", rdma->host)) {
|
ret = rdma_getaddrinfo(rdma->host, port_str, NULL, &res);
|
||||||
struct rdma_addrinfo *e;
|
if (ret < 0) {
|
||||||
|
ERROR(errp, "could not rdma_getaddrinfo address %s", rdma->host);
|
||||||
ret = rdma_getaddrinfo(rdma->host, port_str, NULL, &res);
|
goto err_dest_init_bind_addr;
|
||||||
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);
|
||||||
for (e = res; e != NULL; e = e->ai_next) {
|
trace_qemu_rdma_dest_init_trying(rdma->host, ip);
|
||||||
inet_ntop(e->ai_family,
|
ret = rdma_bind_addr(listen_id, e->ai_dst_addr);
|
||||||
&((struct sockaddr_in *) e->ai_dst_addr)->sin_addr, ip, sizeof ip);
|
if (ret) {
|
||||||
trace_qemu_rdma_dest_init_trying(rdma->host, ip);
|
continue;
|
||||||
ret = rdma_bind_addr(listen_id, e->ai_dst_addr);
|
}
|
||||||
if (!ret) {
|
if (e->ai_family == AF_INET6) {
|
||||||
if (e->ai_family == AF_INET6) {
|
ret = qemu_rdma_broken_ipv6_kernel(errp, listen_id->verbs);
|
||||||
ret = qemu_rdma_broken_ipv6_kernel(errp, listen_id->verbs);
|
if (ret) {
|
||||||
if (ret) {
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
goto listen;
|
|
||||||
}
|
if (!e) {
|
||||||
}
|
ERROR(errp, "Error: could not rdma_bind_addr!");
|
||||||
|
|
||||||
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;
|
goto err_dest_init_bind_addr;
|
||||||
}
|
}
|
||||||
listen:
|
|
||||||
|
|
||||||
rdma->listen_id = listen_id;
|
rdma->listen_id = listen_id;
|
||||||
qemu_rdma_dump_gid("dest_init", 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++) {
|
for (i = 0; i < local->nb_blocks; i++) {
|
||||||
rdma->block[i].remote_host_addr =
|
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) {
|
if (rdma->pin_all) {
|
||||||
rdma->block[i].remote_rkey = local->block[i].mr->rkey;
|
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_start = ram_chunk_start(block, chunk);
|
||||||
chunk_end = ram_chunk_end(block, chunk + reg->chunks);
|
chunk_end = ram_chunk_end(block, chunk + reg->chunks);
|
||||||
if (qemu_rdma_register_and_get_keys(rdma, block,
|
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)) {
|
chunk, chunk_start, chunk_end)) {
|
||||||
error_report("cannot get rkey");
|
error_report("cannot get rkey");
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
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(
|
trace_qemu_rdma_registration_handle_register_rkey(
|
||||||
reg_result->rkey);
|
reg_result->rkey);
|
||||||
|
|
|
@ -410,19 +410,43 @@
|
||||||
'cache-miss': 'int', 'cache-miss-rate': 'number',
|
'cache-miss': 'int', 'cache-miss-rate': 'number',
|
||||||
'overflow': 'int' } }
|
'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
|
# @MigrationInfo
|
||||||
#
|
#
|
||||||
# Information about current migration process.
|
# Information about current migration process.
|
||||||
#
|
#
|
||||||
# @status: #optional string describing the current migration status.
|
# @status: #optional @MigrationStatus describing the current migration status.
|
||||||
# As of 0.14.0 this can be 'setup', 'active', 'completed', 'failed' or
|
# If this field is not returned, no migration process
|
||||||
# 'cancelled'. If this field is not returned, no migration process
|
|
||||||
# has been initiated
|
# has been initiated
|
||||||
#
|
#
|
||||||
# @ram: #optional @MigrationStats containing detailed migration
|
# @ram: #optional @MigrationStats containing detailed migration
|
||||||
# status, only returned if status is 'active' or
|
# status, only returned if status is 'active' or
|
||||||
# 'completed'. 'comppleted' (since 1.2)
|
# 'completed'(since 1.2)
|
||||||
#
|
#
|
||||||
# @disk: #optional @MigrationStats containing detailed disk migration
|
# @disk: #optional @MigrationStats containing detailed disk migration
|
||||||
# status, only returned if status is 'active' and it is a block
|
# status, only returned if status is 'active' and it is a block
|
||||||
|
@ -453,7 +477,7 @@
|
||||||
# Since: 0.14.0
|
# Since: 0.14.0
|
||||||
##
|
##
|
||||||
{ 'type': 'MigrationInfo',
|
{ 'type': 'MigrationInfo',
|
||||||
'data': {'*status': 'str', '*ram': 'MigrationStats',
|
'data': {'*status': 'MigrationStatus', '*ram': 'MigrationStats',
|
||||||
'*disk': 'MigrationStats',
|
'*disk': 'MigrationStats',
|
||||||
'*xbzrle-cache': 'XBZRLECacheStats',
|
'*xbzrle-cache': 'XBZRLECacheStats',
|
||||||
'*total-time': 'int',
|
'*total-time': 'int',
|
||||||
|
@ -1750,6 +1774,9 @@
|
||||||
# Returns: nothing on success
|
# Returns: nothing on success
|
||||||
#
|
#
|
||||||
# Since: 2.3
|
# 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' } }
|
{ 'command': 'migrate-incoming', 'data': {'uri': 'str' } }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue