Merge remote-tracking branch 'quintela/thread.next' into staging
# By Juan Quintela (7) and Paolo Bonzini (6) # Via Juan Quintela * quintela/thread.next: migration: remove argument to qemu_savevm_state_cancel migration: Only go to the iterate stage if there is anything to send migration: unfold rest of migrate_fd_put_ready() into thread migration: move exit condition to migration thread migration: Add buffered_flush error handling migration: move beginning stage to the migration thread qemu-file: Only set last_error if it is not already set migration: fix off-by-one in buffered_rate_limit migration: remove double call to migrate_fd_close migration: make function static use XFER_LIMIT_RATIO consistently Protect migration_bitmap_sync() with the ramlist lock Unlock ramlist lock also in error case
This commit is contained in:
commit
016c718231
@ -642,12 +642,13 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qemu_mutex_unlock_ramlist();
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
bytes_transferred += total_sent;
|
bytes_transferred += total_sent;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
qemu_mutex_unlock_ramlist();
|
|
||||||
qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
|
qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
|
||||||
total_sent += 8;
|
total_sent += 8;
|
||||||
bytes_transferred += total_sent;
|
bytes_transferred += total_sent;
|
||||||
@ -657,9 +658,8 @@ static int ram_save_iterate(QEMUFile *f, void *opaque)
|
|||||||
|
|
||||||
static int ram_save_complete(QEMUFile *f, void *opaque)
|
static int ram_save_complete(QEMUFile *f, void *opaque)
|
||||||
{
|
{
|
||||||
migration_bitmap_sync();
|
|
||||||
|
|
||||||
qemu_mutex_lock_ramlist();
|
qemu_mutex_lock_ramlist();
|
||||||
|
migration_bitmap_sync();
|
||||||
|
|
||||||
/* try transferring iterative blocks of memory */
|
/* try transferring iterative blocks of memory */
|
||||||
|
|
||||||
|
@ -54,7 +54,6 @@ struct MigrationState
|
|||||||
bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
|
bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
|
||||||
int64_t xbzrle_cache_size;
|
int64_t xbzrle_cache_size;
|
||||||
bool complete;
|
bool complete;
|
||||||
bool first_time;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void process_incoming_migration(QEMUFile *f);
|
void process_incoming_migration(QEMUFile *f);
|
||||||
@ -87,8 +86,6 @@ void migrate_fd_error(MigrationState *s);
|
|||||||
|
|
||||||
void migrate_fd_connect(MigrationState *s);
|
void migrate_fd_connect(MigrationState *s);
|
||||||
|
|
||||||
ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
|
|
||||||
size_t size);
|
|
||||||
int migrate_fd_close(MigrationState *s);
|
int migrate_fd_close(MigrationState *s);
|
||||||
|
|
||||||
void add_migration_state_change_notifier(Notifier *notify);
|
void add_migration_state_change_notifier(Notifier *notify);
|
||||||
|
@ -77,7 +77,7 @@ int qemu_savevm_state_begin(QEMUFile *f,
|
|||||||
const MigrationParams *params);
|
const MigrationParams *params);
|
||||||
int qemu_savevm_state_iterate(QEMUFile *f);
|
int qemu_savevm_state_iterate(QEMUFile *f);
|
||||||
int qemu_savevm_state_complete(QEMUFile *f);
|
int qemu_savevm_state_complete(QEMUFile *f);
|
||||||
void qemu_savevm_state_cancel(QEMUFile *f);
|
void qemu_savevm_state_cancel(void);
|
||||||
uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size);
|
uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size);
|
||||||
int qemu_loadvm_state(QEMUFile *f);
|
int qemu_loadvm_state(QEMUFile *f);
|
||||||
|
|
||||||
|
91
migration.c
91
migration.c
@ -302,7 +302,7 @@ static void migrate_fd_completed(MigrationState *s)
|
|||||||
notifier_list_notify(&migration_state_notifiers, s);
|
notifier_list_notify(&migration_state_notifiers, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
|
static ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret;
|
||||||
@ -330,7 +330,7 @@ static void migrate_fd_cancel(MigrationState *s)
|
|||||||
|
|
||||||
s->state = MIG_STATE_CANCELLED;
|
s->state = MIG_STATE_CANCELLED;
|
||||||
notifier_list_notify(&migration_state_notifiers, s);
|
notifier_list_notify(&migration_state_notifiers, s);
|
||||||
qemu_savevm_state_cancel(s->file);
|
qemu_savevm_state_cancel();
|
||||||
|
|
||||||
migrate_fd_cleanup(s);
|
migrate_fd_cleanup(s);
|
||||||
}
|
}
|
||||||
@ -605,7 +605,6 @@ static int buffered_close(void *opaque)
|
|||||||
if (ret >= 0) {
|
if (ret >= 0) {
|
||||||
ret = ret2;
|
ret = ret2;
|
||||||
}
|
}
|
||||||
ret = migrate_fd_close(s);
|
|
||||||
s->complete = true;
|
s->complete = true;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -633,7 +632,7 @@ static int buffered_rate_limit(void *opaque)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->bytes_xfer > s->xfer_limit) {
|
if (s->bytes_xfer >= s->xfer_limit) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -650,7 +649,7 @@ static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate)
|
|||||||
new_rate = SIZE_MAX;
|
new_rate = SIZE_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->xfer_limit = new_rate / 10;
|
s->xfer_limit = new_rate / XFER_LIMIT_RATIO;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
return s->xfer_limit;
|
return s->xfer_limit;
|
||||||
@ -663,37 +662,47 @@ static int64_t buffered_get_rate_limit(void *opaque)
|
|||||||
return s->xfer_limit;
|
return s->xfer_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool migrate_fd_put_ready(MigrationState *s, uint64_t max_size)
|
static void *buffered_file_thread(void *opaque)
|
||||||
{
|
{
|
||||||
int ret;
|
MigrationState *s = opaque;
|
||||||
uint64_t pending_size;
|
int64_t initial_time = qemu_get_clock_ms(rt_clock);
|
||||||
|
int64_t max_size = 0;
|
||||||
bool last_round = false;
|
bool last_round = false;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
qemu_mutex_lock_iothread();
|
||||||
|
DPRINTF("beginning savevm\n");
|
||||||
|
ret = qemu_savevm_state_begin(s->file, &s->params);
|
||||||
|
if (ret < 0) {
|
||||||
|
DPRINTF("failed, %d\n", ret);
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
int64_t current_time = qemu_get_clock_ms(rt_clock);
|
||||||
|
uint64_t pending_size;
|
||||||
|
|
||||||
qemu_mutex_lock_iothread();
|
qemu_mutex_lock_iothread();
|
||||||
if (s->state != MIG_STATE_ACTIVE) {
|
if (s->state != MIG_STATE_ACTIVE) {
|
||||||
DPRINTF("put_ready returning because of non-active state\n");
|
DPRINTF("put_ready returning because of non-active state\n");
|
||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
if (s->first_time) {
|
if (s->complete) {
|
||||||
s->first_time = false;
|
|
||||||
DPRINTF("beginning savevm\n");
|
|
||||||
ret = qemu_savevm_state_begin(s->file, &s->params);
|
|
||||||
if (ret < 0) {
|
|
||||||
DPRINTF("failed, %d\n", ret);
|
|
||||||
migrate_fd_error(s);
|
|
||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
}
|
if (s->bytes_xfer < s->xfer_limit) {
|
||||||
|
|
||||||
DPRINTF("iterate\n");
|
DPRINTF("iterate\n");
|
||||||
pending_size = qemu_savevm_state_pending(s->file, max_size);
|
pending_size = qemu_savevm_state_pending(s->file, max_size);
|
||||||
DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
|
DPRINTF("pending size %lu max %lu\n", pending_size, max_size);
|
||||||
if (pending_size >= max_size) {
|
if (pending_size && pending_size >= max_size) {
|
||||||
ret = qemu_savevm_state_iterate(s->file);
|
ret = qemu_savevm_state_iterate(s->file);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
migrate_fd_error(s);
|
qemu_mutex_unlock_iothread();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int old_vm_running = runstate_is_running();
|
int old_vm_running = runstate_is_running();
|
||||||
@ -707,9 +716,10 @@ static bool migrate_fd_put_ready(MigrationState *s, uint64_t max_size)
|
|||||||
} else {
|
} else {
|
||||||
vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
|
vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
|
||||||
}
|
}
|
||||||
|
ret = qemu_savevm_state_complete(s->file);
|
||||||
if (qemu_savevm_state_complete(s->file) < 0) {
|
if (ret < 0) {
|
||||||
migrate_fd_error(s);
|
qemu_mutex_unlock_iothread();
|
||||||
|
break;
|
||||||
} else {
|
} else {
|
||||||
migrate_fd_completed(s);
|
migrate_fd_completed(s);
|
||||||
}
|
}
|
||||||
@ -723,24 +733,8 @@ static bool migrate_fd_put_ready(MigrationState *s, uint64_t max_size)
|
|||||||
}
|
}
|
||||||
last_round = true;
|
last_round = true;
|
||||||
}
|
}
|
||||||
qemu_mutex_unlock_iothread();
|
|
||||||
|
|
||||||
return last_round;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *buffered_file_thread(void *opaque)
|
|
||||||
{
|
|
||||||
MigrationState *s = opaque;
|
|
||||||
int64_t initial_time = qemu_get_clock_ms(rt_clock);
|
|
||||||
int64_t max_size = 0;
|
|
||||||
bool last_round = false;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
int64_t current_time = qemu_get_clock_ms(rt_clock);
|
|
||||||
|
|
||||||
if (s->complete) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
qemu_mutex_unlock_iothread();
|
||||||
if (current_time >= initial_time + BUFFER_DELAY) {
|
if (current_time >= initial_time + BUFFER_DELAY) {
|
||||||
uint64_t transferred_bytes = s->bytes_xfer;
|
uint64_t transferred_bytes = s->bytes_xfer;
|
||||||
uint64_t time_spent = current_time - initial_time;
|
uint64_t time_spent = current_time - initial_time;
|
||||||
@ -758,17 +752,16 @@ static void *buffered_file_thread(void *opaque)
|
|||||||
/* usleep expects microseconds */
|
/* usleep expects microseconds */
|
||||||
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
|
g_usleep((initial_time + BUFFER_DELAY - current_time)*1000);
|
||||||
}
|
}
|
||||||
if (buffered_flush(s) < 0) {
|
ret = buffered_flush(s);
|
||||||
|
if (ret < 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTF("file is ready\n");
|
|
||||||
if (s->bytes_xfer < s->xfer_limit) {
|
|
||||||
DPRINTF("notifying client\n");
|
|
||||||
last_round = migrate_fd_put_ready(s, max_size);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (ret < 0) {
|
||||||
|
migrate_fd_error(s);
|
||||||
|
}
|
||||||
g_free(s->buffer);
|
g_free(s->buffer);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -790,8 +783,6 @@ void migrate_fd_connect(MigrationState *s)
|
|||||||
s->buffer_size = 0;
|
s->buffer_size = 0;
|
||||||
s->buffer_capacity = 0;
|
s->buffer_capacity = 0;
|
||||||
|
|
||||||
s->first_time = true;
|
|
||||||
|
|
||||||
s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
|
s->xfer_limit = s->bandwidth_limit / XFER_LIMIT_RATIO;
|
||||||
s->complete = false;
|
s->complete = false;
|
||||||
|
|
||||||
|
10
savevm.c
10
savevm.c
@ -419,7 +419,9 @@ int qemu_file_get_error(QEMUFile *f)
|
|||||||
|
|
||||||
static void qemu_file_set_error(QEMUFile *f, int ret)
|
static void qemu_file_set_error(QEMUFile *f, int ret)
|
||||||
{
|
{
|
||||||
|
if (f->last_error == 0) {
|
||||||
f->last_error = ret;
|
f->last_error = ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Flushes QEMUFile buffer
|
/** Flushes QEMUFile buffer
|
||||||
@ -1588,13 +1590,13 @@ int qemu_savevm_state_begin(QEMUFile *f,
|
|||||||
|
|
||||||
ret = se->ops->save_live_setup(f, se->opaque);
|
ret = se->ops->save_live_setup(f, se->opaque);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
qemu_savevm_state_cancel(f);
|
qemu_savevm_state_cancel();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = qemu_file_get_error(f);
|
ret = qemu_file_get_error(f);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
qemu_savevm_state_cancel(f);
|
qemu_savevm_state_cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -1645,7 +1647,7 @@ int qemu_savevm_state_iterate(QEMUFile *f)
|
|||||||
}
|
}
|
||||||
ret = qemu_file_get_error(f);
|
ret = qemu_file_get_error(f);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
qemu_savevm_state_cancel(f);
|
qemu_savevm_state_cancel();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1725,7 +1727,7 @@ uint64_t qemu_savevm_state_pending(QEMUFile *f, uint64_t max_size)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void qemu_savevm_state_cancel(QEMUFile *f)
|
void qemu_savevm_state_cancel(void)
|
||||||
{
|
{
|
||||||
SaveStateEntry *se;
|
SaveStateEntry *se;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user