From 0046c45bc1c70b5b985822f8639bb718f6d535a5 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 30 Sep 2011 19:28:45 +0200 Subject: [PATCH 01/42] savevm: teach qemu_fill_buffer to do partial refills We will need on next patch to be able to lookahead on next patch v2: rename "used" to "pending" (Alex Williams) Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- savevm.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/savevm.c b/savevm.c index bf4d0e76c..aa6fef08a 100644 --- a/savevm.c +++ b/savevm.c @@ -455,6 +455,7 @@ void qemu_fflush(QEMUFile *f) static void qemu_fill_buffer(QEMUFile *f) { int len; + int pending; if (!f->get_buffer) return; @@ -462,10 +463,17 @@ static void qemu_fill_buffer(QEMUFile *f) if (f->is_write) abort(); - len = f->get_buffer(f->opaque, f->buf, f->buf_offset, IO_BUF_SIZE); + pending = f->buf_size - f->buf_index; + if (pending > 0) { + memmove(f->buf, f->buf + f->buf_index, pending); + } + f->buf_index = 0; + f->buf_size = pending; + + len = f->get_buffer(f->opaque, f->buf + pending, f->buf_offset, + IO_BUF_SIZE - pending); if (len > 0) { - f->buf_index = 0; - f->buf_size = len; + f->buf_size += len; f->buf_offset += len; } else if (len != -EAGAIN) f->has_error = 1; From b9ce1454e14ec918acb90d899ce7724f69682f45 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 4 Oct 2011 13:55:32 +0200 Subject: [PATCH 02/42] savevm: some coding style cleanups This patch will make moving code on next patches and having checkpatch happy easier. Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- savevm.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/savevm.c b/savevm.c index aa6fef08a..6e4bb3a3d 100644 --- a/savevm.c +++ b/savevm.c @@ -536,8 +536,9 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1) { int size, l; - if (f->is_write) + if (f->is_write) { abort(); + } size = size1; while (size > 0) { @@ -545,11 +546,13 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1) if (l == 0) { qemu_fill_buffer(f); l = f->buf_size - f->buf_index; - if (l == 0) + if (l == 0) { break; + } } - if (l > size) + if (l > size) { l = size; + } memcpy(buf, f->buf + f->buf_index, l); f->buf_index += l; buf += l; @@ -560,26 +563,30 @@ int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1) static int qemu_peek_byte(QEMUFile *f) { - if (f->is_write) + if (f->is_write) { abort(); + } if (f->buf_index >= f->buf_size) { qemu_fill_buffer(f); - if (f->buf_index >= f->buf_size) + if (f->buf_index >= f->buf_size) { return 0; + } } return f->buf[f->buf_index]; } int qemu_get_byte(QEMUFile *f) { - if (f->is_write) + if (f->is_write) { abort(); + } if (f->buf_index >= f->buf_size) { qemu_fill_buffer(f); - if (f->buf_index >= f->buf_size) + if (f->buf_index >= f->buf_size) { return 0; + } } return f->buf[f->buf_index++]; } From 65f3bb3da3d5b46daebbfc54bd41ee493fdaba86 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Thu, 6 Oct 2011 14:29:32 +0200 Subject: [PATCH 03/42] savevm: define qemu_get_byte() using qemu_peek_byte() Signed-off-by: Juan Quintela --- savevm.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/savevm.c b/savevm.c index 6e4bb3a3d..038099979 100644 --- a/savevm.c +++ b/savevm.c @@ -578,17 +578,14 @@ static int qemu_peek_byte(QEMUFile *f) int qemu_get_byte(QEMUFile *f) { - if (f->is_write) { - abort(); - } + int result; - if (f->buf_index >= f->buf_size) { - qemu_fill_buffer(f); - if (f->buf_index >= f->buf_size) { - return 0; - } + result = qemu_peek_byte(f); + + if (f->buf_index < f->buf_size) { + f->buf_index++; } - return f->buf[f->buf_index++]; + return result; } int64_t qemu_ftell(QEMUFile *f) From c63807244fb55071675907460a0ecf228c1766c8 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 4 Oct 2011 15:28:31 +0200 Subject: [PATCH 04/42] savevm: improve subsections detection on load We add qemu_peek_buffer, that is identical to qemu_get_buffer, just that it don't update f->buf_index. We add a paramenter to qemu_peek_byte() to be able to peek more than one byte. Once this is done, to see if we have a subsection we look: - 1st byte is QEMU_VM_SUBSECTION - 2nd byte is a length, and is bigger than section name - 3rd element is a string that starts with section_name So, we shouldn't have false positives (yes, content could still get us wrong but probabilities are really low). v2: - Alex Williamsom found that we could get negative values on index. - Rework code to fix that part. - Rewrite qemu_get_buffer() using qemu_peek_buffer() v3: - return "done" on error case v4: - fix qemu_file_skip() off by one. Signed-off-by: Juan Quintela --- savevm.c | 122 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 81 insertions(+), 41 deletions(-) diff --git a/savevm.c b/savevm.c index 038099979..a4cb3157b 100644 --- a/savevm.c +++ b/savevm.c @@ -532,59 +532,85 @@ void qemu_put_byte(QEMUFile *f, int v) qemu_fflush(f); } -int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1) +static void qemu_file_skip(QEMUFile *f, int size) { - int size, l; - - if (f->is_write) { - abort(); + if (f->buf_index + size <= f->buf_size) { + f->buf_index += size; } - - size = size1; - while (size > 0) { - l = f->buf_size - f->buf_index; - if (l == 0) { - qemu_fill_buffer(f); - l = f->buf_size - f->buf_index; - if (l == 0) { - break; - } - } - if (l > size) { - l = size; - } - memcpy(buf, f->buf + f->buf_index, l); - f->buf_index += l; - buf += l; - size -= l; - } - return size1 - size; } -static int qemu_peek_byte(QEMUFile *f) +static int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset) { + int pending; + int index; + if (f->is_write) { abort(); } - if (f->buf_index >= f->buf_size) { + index = f->buf_index + offset; + pending = f->buf_size - index; + if (pending < size) { qemu_fill_buffer(f); - if (f->buf_index >= f->buf_size) { + index = f->buf_index + offset; + pending = f->buf_size - index; + } + + if (pending <= 0) { + return 0; + } + if (size > pending) { + size = pending; + } + + memcpy(buf, f->buf + index, size); + return size; +} + +int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size) +{ + int pending = size; + int done = 0; + + while (pending > 0) { + int res; + + res = qemu_peek_buffer(f, buf, pending, 0); + if (res == 0) { + return done; + } + qemu_file_skip(f, res); + buf += res; + pending -= res; + done += res; + } + return done; +} + +static int qemu_peek_byte(QEMUFile *f, int offset) +{ + int index = f->buf_index + offset; + + if (f->is_write) { + abort(); + } + + if (index >= f->buf_size) { + qemu_fill_buffer(f); + index = f->buf_index + offset; + if (index >= f->buf_size) { return 0; } } - return f->buf[f->buf_index]; + return f->buf[index]; } int qemu_get_byte(QEMUFile *f) { int result; - result = qemu_peek_byte(f); - - if (f->buf_index < f->buf_size) { - f->buf_index++; - } + result = qemu_peek_byte(f, 0); + qemu_file_skip(f, 1); return result; } @@ -1684,22 +1710,36 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, return 0; } - while (qemu_peek_byte(f) == QEMU_VM_SUBSECTION) { + while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) { char idstr[256]; int ret; - uint8_t version_id, len; + uint8_t version_id, len, size; const VMStateDescription *sub_vmsd; - qemu_get_byte(f); /* subsection */ - len = qemu_get_byte(f); - qemu_get_buffer(f, (uint8_t *)idstr, len); - idstr[len] = 0; - version_id = qemu_get_be32(f); + len = qemu_peek_byte(f, 1); + if (len < strlen(vmsd->name) + 1) { + /* subsection name has be be "section_name/a" */ + return 0; + } + size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2); + if (size != len) { + return 0; + } + idstr[size] = 0; + if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) { + /* it don't have a valid subsection name */ + return 0; + } sub_vmsd = vmstate_get_subsection(sub, idstr); if (sub_vmsd == NULL) { return -ENOENT; } + qemu_file_skip(f, 1); /* subsection */ + qemu_file_skip(f, 1); /* len */ + qemu_file_skip(f, len); /* idstr */ + version_id = qemu_get_be32(f); + assert(!sub_vmsd->subsections); ret = vmstate_load_state(f, sub_vmsd, opaque, version_id); if (ret) { From 3da9eebda96780ead8ba44b8140c54f4a54c61f6 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 30 Sep 2011 19:46:43 +0200 Subject: [PATCH 05/42] Revert "savevm: fix corruption in vmstate_subsection_load()." This reverts commit eb60260de0b050a5e8ab725e84d377d0b44c43ae. Conflicts: savevm.c We changed qemu_peek_byte() prototype, just fixed the rejects. Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- savevm.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/savevm.c b/savevm.c index a4cb3157b..ca9e233c9 100644 --- a/savevm.c +++ b/savevm.c @@ -1704,12 +1704,6 @@ static const VMStateDescription *vmstate_get_subsection(const VMStateSubsection static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, void *opaque) { - const VMStateSubsection *sub = vmsd->subsections; - - if (!sub || !sub->needed) { - return 0; - } - while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) { char idstr[256]; int ret; @@ -1731,7 +1725,7 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, /* it don't have a valid subsection name */ return 0; } - sub_vmsd = vmstate_get_subsection(sub, idstr); + sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr); if (sub_vmsd == NULL) { return -ENOENT; } @@ -1740,7 +1734,6 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd, qemu_file_skip(f, len); /* idstr */ version_id = qemu_get_be32(f); - assert(!sub_vmsd->subsections); ret = vmstate_load_state(f, sub_vmsd, opaque, version_id); if (ret) { return ret; @@ -1764,7 +1757,6 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd, qemu_put_byte(f, len); qemu_put_buffer(f, (uint8_t *)vmsd->name, len); qemu_put_be32(f, vmsd->version_id); - assert(!vmsd->subsections); vmstate_save_state(f, vmsd, opaque); } sub++; From 3a230256e8418f5cc9761f36feb6952d7ca38d73 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 13 Sep 2011 14:41:18 +0200 Subject: [PATCH 06/42] ds1225y: Use stdio instead of QEMUFile QEMUFile * is only intended for migration nowadays. Using it for anything else just adds pain and a layer of buffers for no good reason. Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- hw/ds1225y.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/hw/ds1225y.c b/hw/ds1225y.c index 9875c445f..6852a61d0 100644 --- a/hw/ds1225y.c +++ b/hw/ds1225y.c @@ -29,7 +29,7 @@ typedef struct { DeviceState qdev; uint32_t chip_size; char *filename; - QEMUFile *file; + FILE *file; uint8_t *contents; } NvRamState; @@ -70,9 +70,9 @@ static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t val) s->contents[addr] = val; if (s->file) { - qemu_fseek(s->file, addr, SEEK_SET); - qemu_put_byte(s->file, (int)val); - qemu_fflush(s->file); + fseek(s->file, addr, SEEK_SET); + fputc(val, s->file); + fflush(s->file); } } @@ -108,15 +108,17 @@ static int nvram_post_load(void *opaque, int version_id) /* Close file, as filename may has changed in load/store process */ if (s->file) { - qemu_fclose(s->file); + fclose(s->file); } /* Write back nvram contents */ - s->file = qemu_fopen(s->filename, "wb"); + s->file = fopen(s->filename, "wb"); if (s->file) { /* Write back contents, as 'wb' mode cleaned the file */ - qemu_put_buffer(s->file, s->contents, s->chip_size); - qemu_fflush(s->file); + if (fwrite(s->contents, s->chip_size, 1, s->file) != 1) { + printf("nvram_post_load: short write\n"); + } + fflush(s->file); } return 0; @@ -143,7 +145,7 @@ typedef struct { static int nvram_sysbus_initfn(SysBusDevice *dev) { NvRamState *s = &FROM_SYSBUS(SysBusNvRamState, dev)->nvram; - QEMUFile *file; + FILE *file; int s_io; s->contents = g_malloc0(s->chip_size); @@ -153,11 +155,13 @@ static int nvram_sysbus_initfn(SysBusDevice *dev) sysbus_init_mmio(dev, s->chip_size, s_io); /* Read current file */ - file = qemu_fopen(s->filename, "rb"); + file = fopen(s->filename, "rb"); if (file) { /* Read nvram contents */ - qemu_get_buffer(file, s->contents, s->chip_size); - qemu_fclose(file); + if (fread(s->contents, s->chip_size, 1, file) != 1) { + printf("nvram_sysbus_initfn: short read\n"); + } + fclose(file); } nvram_post_load(s, 0); From c0b2ba46c5ceb806a1639bb86b0b457309674b23 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 13 Sep 2011 15:11:38 +0200 Subject: [PATCH 07/42] migration: simplify state assignmente Once there, make sure that if we already know that there is one error, just call migration_fd_cleanup() with the ERROR state. Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/migration.c b/migration.c index 77a51adc5..7fd6c23fa 100644 --- a/migration.c +++ b/migration.c @@ -371,7 +371,6 @@ void migrate_fd_put_ready(void *opaque) DPRINTF("iterate\n"); if (qemu_savevm_state_iterate(s->mon, s->file) == 1) { - int state; int old_vm_running = runstate_is_running(); DPRINTF("done iterating\n"); @@ -381,20 +380,18 @@ void migrate_fd_put_ready(void *opaque) if (old_vm_running) { vm_start(); } - state = MIG_STATE_ERROR; - } else { - state = MIG_STATE_COMPLETED; + s->state = MIG_STATE_ERROR; } if (migrate_fd_cleanup(s) < 0) { if (old_vm_running) { vm_start(); } - state = MIG_STATE_ERROR; + s->state = MIG_STATE_ERROR; } - if (state == MIG_STATE_COMPLETED) { + if (s->state == MIG_STATE_ACTIVE) { + s->state = MIG_STATE_COMPLETED; runstate_set(RUN_STATE_POSTMIGRATE); } - s->state = state; notifier_list_notify(&migration_state_notifiers, NULL); } } From e6494061690df2af7368752f35f5c22b5856e83c Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 11 May 2010 22:39:51 +0200 Subject: [PATCH 08/42] migration: Check that migration is active before cancel it Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/migration.c b/migration.c index 7fd6c23fa..71b8aade8 100644 --- a/migration.c +++ b/migration.c @@ -133,9 +133,9 @@ int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data) { MigrationState *s = current_migration; - if (s) + if (s && s->get_status(s) == MIG_STATE_ACTIVE) { s->cancel(s); - + } return 0; } From 2350e13c93c28f717e2ba1b31560b49ac6f81d4d Mon Sep 17 00:00:00 2001 From: Yoshiaki Tamura Date: Wed, 23 Feb 2011 00:01:24 +0900 Subject: [PATCH 09/42] migration: add error handling to migrate_fd_put_notify(). Although migrate_fd_put_buffer() sets MIG_STATE_ERROR if it failed, since migrate_fd_put_notify() isn't checking error of underlying QEMUFile, those resources are kept open. This patch checks it and calls migrate_fd_error() in case of error. Signed-off-by: Yoshiaki Tamura Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/migration.c b/migration.c index 71b8aade8..f41a40b49 100644 --- a/migration.c +++ b/migration.c @@ -313,6 +313,9 @@ void migrate_fd_put_notify(void *opaque) qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); qemu_file_put_notify(s->file); + if (qemu_file_has_error(s->file)) { + migrate_fd_error(s); + } } ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) @@ -329,9 +332,6 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) if (ret == -EAGAIN) { qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s); - } else if (ret < 0) { - s->state = MIG_STATE_ERROR; - notifier_list_notify(&migration_state_notifiers, NULL); } return ret; From 4fc7d8195f9c8433f8661b6156e5c57ff8d8e4fb Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 23 Feb 2011 20:17:45 +0100 Subject: [PATCH 10/42] migration: If there is one error, it makes no sense to continue Once there, add a comment about what each error mean. Signed-off-by: Juan Quintela --- buffered_file.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index 486af575d..94ecbbcea 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -189,13 +189,19 @@ static int buffered_close(void *opaque) return ret; } +/* + * The meaning of the return values is: + * 0: We can continue sending + * 1: Time to stop + * -1: There has been an error + */ static int buffered_rate_limit(void *opaque) { QEMUFileBuffered *s = opaque; - if (s->has_error) - return 0; - + if (s->has_error) { + return -1; + } if (s->freeze_output) return 1; From db448a088c4b3403c74adfa9b27eb6e624181d9b Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 21 Sep 2011 18:12:58 +0200 Subject: [PATCH 11/42] buffered_file: Use right "opaque" buffered_close 's' variable is of type QEMUFileBuffered, and wait_for_unfreeze() expect to receive a MigrationState, that 'coincidentaly' is s->opaque. Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- buffered_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buffered_file.c b/buffered_file.c index 94ecbbcea..decc3bf92 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -176,7 +176,7 @@ static int buffered_close(void *opaque) while (!s->has_error && s->buffer_size) { buffered_flush(s); if (s->freeze_output) - s->wait_for_unfreeze(s); + s->wait_for_unfreeze(s->opaque); } ret = s->close(s->opaque); From eff28a5c3b36fdca2a15e9570f67924eecb2db4f Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 21 Sep 2011 22:32:08 +0200 Subject: [PATCH 12/42] buffered_file: reuse QEMUFile has_error field Instead of having two has_error fields in QEMUFile & QEMUBufferedFile, reuse the 1st one. Notice that the one in buffered_file is only set after a file operation. Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- buffered_file.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/buffered_file.c b/buffered_file.c index decc3bf92..4f4976387 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -27,7 +27,6 @@ typedef struct QEMUFileBuffered BufferedCloseFunc *close; void *opaque; QEMUFile *file; - int has_error; int freeze_output; size_t bytes_xfer; size_t xfer_limit; @@ -73,7 +72,7 @@ static void buffered_flush(QEMUFileBuffered *s) { size_t offset = 0; - if (s->has_error) { + if (qemu_file_has_error(s->file)) { DPRINTF("flush when error, bailing\n"); return; } @@ -93,7 +92,7 @@ static void buffered_flush(QEMUFileBuffered *s) if (ret <= 0) { DPRINTF("error flushing data, %zd\n", ret); - s->has_error = 1; + qemu_file_set_error(s->file); break; } else { DPRINTF("flushed %zd byte(s)\n", ret); @@ -114,7 +113,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos); - if (s->has_error) { + if (qemu_file_has_error(s->file)) { DPRINTF("flush when error, bailing\n"); return -EINVAL; } @@ -139,7 +138,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in if (ret <= 0) { DPRINTF("error putting\n"); - s->has_error = 1; + qemu_file_set_error(s->file); offset = -EINVAL; break; } @@ -173,7 +172,7 @@ static int buffered_close(void *opaque) DPRINTF("closing\n"); - while (!s->has_error && s->buffer_size) { + while (!qemu_file_has_error(s->file) && s->buffer_size) { buffered_flush(s); if (s->freeze_output) s->wait_for_unfreeze(s->opaque); @@ -199,7 +198,7 @@ static int buffered_rate_limit(void *opaque) { QEMUFileBuffered *s = opaque; - if (s->has_error) { + if (qemu_file_has_error(s->file)) { return -1; } if (s->freeze_output) @@ -214,7 +213,7 @@ static int buffered_rate_limit(void *opaque) static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate) { QEMUFileBuffered *s = opaque; - if (s->has_error) + if (qemu_file_has_error(s->file)) goto out; if (new_rate > SIZE_MAX) { @@ -238,7 +237,7 @@ static void buffered_rate_tick(void *opaque) { QEMUFileBuffered *s = opaque; - if (s->has_error) { + if (qemu_file_has_error(s->file)) { buffered_close(s); return; } From fdbecb5d0e6a1caca5b4a732beb68771eacc7736 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 21 Sep 2011 22:37:29 +0200 Subject: [PATCH 13/42] migration: don't "write" when migration is not active If migration is not active, just ignore writes. Signed-off-by: Juan Quintela --- migration.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/migration.c b/migration.c index f41a40b49..260e5b5fc 100644 --- a/migration.c +++ b/migration.c @@ -323,6 +323,10 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) FdMigrationState *s = opaque; ssize_t ret; + if (s->state != MIG_STATE_ACTIVE) { + return -EIO; + } + do { ret = s->write(s, data, size); } while (ret == -1 && ((s->get_error(s)) == EINTR)); From af509450816d17b4cbfff673be21b830f05018fc Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 21 Sep 2011 22:46:36 +0200 Subject: [PATCH 14/42] migration: set error if select return one error Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/migration.c b/migration.c index 260e5b5fc..a68216868 100644 --- a/migration.c +++ b/migration.c @@ -453,6 +453,10 @@ void migrate_fd_wait_for_unfreeze(void *opaque) ret = select(s->fd + 1, NULL, &wfds, NULL, NULL); } while (ret == -1 && (s->get_error(s)) == EINTR); + + if (ret == -1) { + qemu_file_set_error(s->file); + } } int migrate_fd_close(void *opaque) From dcd1d224dfcad1154a516e683ab55ea848497f50 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 21 Sep 2011 23:01:54 +0200 Subject: [PATCH 15/42] migration: change has_error to contain errno values We normally already have an errno value. When not, abuse EIO. Signed-off-by: Juan Quintela --- arch_init.c | 2 +- block-migration.c | 11 ++++++----- buffered_file.c | 4 ++-- hw/hw.h | 2 +- migration.c | 2 +- savevm.c | 8 ++++---- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/arch_init.c b/arch_init.c index a6c69c75a..941d585e0 100644 --- a/arch_init.c +++ b/arch_init.c @@ -263,7 +263,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) } if (cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX) != 0) { - qemu_file_set_error(f); + qemu_file_set_error(f, -EINVAL); return 0; } diff --git a/block-migration.c b/block-migration.c index e2775ee50..325c90530 100644 --- a/block-migration.c +++ b/block-migration.c @@ -263,7 +263,7 @@ static int mig_save_device_bulk(Monitor *mon, QEMUFile *f, error: monitor_printf(mon, "Error reading sector %" PRId64 "\n", cur_sector); - qemu_file_set_error(f); + qemu_file_set_error(f, -EIO); g_free(blk->buf); g_free(blk); return 0; @@ -383,6 +383,7 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f, int64_t total_sectors = bmds->total_sectors; int64_t sector; int nr_sectors; + int ret = -EIO; for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) { if (bmds_aio_inflight(bmds, sector)) { @@ -418,8 +419,8 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f, block_mig_state.submitted++; bmds_set_aio_inflight(bmds, sector, nr_sectors, 1); } else { - if (bdrv_read(bmds->bs, sector, blk->buf, - nr_sectors) < 0) { + ret = bdrv_read(bmds->bs, sector, blk->buf, nr_sectors); + if (ret < 0) { goto error; } blk_send(f, blk); @@ -439,7 +440,7 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f, error: monitor_printf(mon, "Error reading sector %" PRId64 "\n", sector); - qemu_file_set_error(f); + qemu_file_set_error(f, ret); g_free(blk->buf); g_free(blk); return 0; @@ -473,7 +474,7 @@ static void flush_blks(QEMUFile* f) break; } if (blk->ret < 0) { - qemu_file_set_error(f); + qemu_file_set_error(f, blk->ret); break; } blk_send(f, blk); diff --git a/buffered_file.c b/buffered_file.c index 4f4976387..94ca8d11f 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -92,7 +92,7 @@ static void buffered_flush(QEMUFileBuffered *s) if (ret <= 0) { DPRINTF("error flushing data, %zd\n", ret); - qemu_file_set_error(s->file); + qemu_file_set_error(s->file, ret); break; } else { DPRINTF("flushed %zd byte(s)\n", ret); @@ -138,7 +138,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in if (ret <= 0) { DPRINTF("error putting\n"); - qemu_file_set_error(s->file); + qemu_file_set_error(s->file, ret); offset = -EINVAL; break; } diff --git a/hw/hw.h b/hw/hw.h index a124da9c2..6cf8cd205 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -86,7 +86,7 @@ int qemu_file_rate_limit(QEMUFile *f); int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate); int64_t qemu_file_get_rate_limit(QEMUFile *f); int qemu_file_has_error(QEMUFile *f); -void qemu_file_set_error(QEMUFile *f); +void qemu_file_set_error(QEMUFile *f, int error); /* Try to send any outstanding data. This function is useful when output is * halted due to rate limiting or EAGAIN errors occur as it can be used to diff --git a/migration.c b/migration.c index a68216868..d5876a9d9 100644 --- a/migration.c +++ b/migration.c @@ -455,7 +455,7 @@ void migrate_fd_wait_for_unfreeze(void *opaque) } while (ret == -1 && (s->get_error(s)) == EINTR); if (ret == -1) { - qemu_file_set_error(s->file); + qemu_file_set_error(s->file, -s->get_error(s)); } } diff --git a/savevm.c b/savevm.c index ca9e233c9..5bef61851 100644 --- a/savevm.c +++ b/savevm.c @@ -430,9 +430,9 @@ int qemu_file_has_error(QEMUFile *f) return f->has_error; } -void qemu_file_set_error(QEMUFile *f) +void qemu_file_set_error(QEMUFile *f, int ret) { - f->has_error = 1; + f->has_error = ret; } void qemu_fflush(QEMUFile *f) @@ -447,7 +447,7 @@ void qemu_fflush(QEMUFile *f) if (len > 0) f->buf_offset += f->buf_index; else - f->has_error = 1; + f->has_error = -EINVAL; f->buf_index = 0; } } @@ -476,7 +476,7 @@ static void qemu_fill_buffer(QEMUFile *f) f->buf_size += len; f->buf_offset += len; } else if (len != -EAGAIN) - f->has_error = 1; + f->has_error = len; } int qemu_fclose(QEMUFile *f) From 3934638539c763ad23026b70483e60be34078c57 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Thu, 22 Sep 2011 11:02:14 +0200 Subject: [PATCH 16/42] migration: return real error code make functions propagate errno, instead of just using -EIO. Add a comment about what are the return value of qemu_savevm_state_iterate(). Signed-off-by: Juan Quintela --- migration.c | 6 +++++- savevm.c | 41 ++++++++++++++++++++++------------------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/migration.c b/migration.c index d5876a9d9..c1d647c10 100644 --- a/migration.c +++ b/migration.c @@ -367,6 +367,7 @@ void migrate_fd_connect(FdMigrationState *s) void migrate_fd_put_ready(void *opaque) { FdMigrationState *s = opaque; + int ret; if (s->state != MIG_STATE_ACTIVE) { DPRINTF("put_ready returning because of non-active state\n"); @@ -374,7 +375,10 @@ void migrate_fd_put_ready(void *opaque) } DPRINTF("iterate\n"); - if (qemu_savevm_state_iterate(s->mon, s->file) == 1) { + ret = qemu_savevm_state_iterate(s->mon, s->file); + if (ret < 0) { + migrate_fd_error(s); + } else if (ret == 1) { int old_vm_running = runstate_is_running(); DPRINTF("done iterating\n"); diff --git a/savevm.c b/savevm.c index 5bef61851..b2f22bdc8 100644 --- a/savevm.c +++ b/savevm.c @@ -1504,6 +1504,7 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable, int shared) { SaveStateEntry *se; + int ret; QTAILQ_FOREACH(se, &savevm_handlers, entry) { if(se->set_params == NULL) { @@ -1535,15 +1536,21 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable, se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque); } - - if (qemu_file_has_error(f)) { + ret = qemu_file_has_error(f); + if (ret != 0) { qemu_savevm_state_cancel(mon, f); - return -EIO; } - return 0; + return ret; + } +/* + * this funtion has three return values: + * negative: there was one error, and we have -errno. + * 0 : We haven't finished, caller have to go again + * 1 : We have finished, we can go to complete phase + */ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f) { SaveStateEntry *se; @@ -1566,16 +1573,14 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f) break; } } - - if (ret) - return 1; - - if (qemu_file_has_error(f)) { - qemu_savevm_state_cancel(mon, f); - return -EIO; + if (ret != 0) { + return ret; } - - return 0; + ret = qemu_file_has_error(f); + if (ret != 0) { + qemu_savevm_state_cancel(mon, f); + } + return ret; } int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f) @@ -1618,10 +1623,7 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f) qemu_put_byte(f, QEMU_VM_EOF); - if (qemu_file_has_error(f)) - return -EIO; - - return 0; + return qemu_file_has_error(f); } void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f) @@ -1661,8 +1663,9 @@ static int qemu_savevm_state(Monitor *mon, QEMUFile *f) ret = qemu_savevm_state_complete(mon, f); out: - if (qemu_file_has_error(f)) - ret = -EIO; + if (ret == 0) { + ret = qemu_file_has_error(f); + } if (!ret && saved_vm_running) vm_start(); From 624b9cc20922fe7b046cd79c839d1f3a5a5fc27e Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 5 Oct 2011 01:02:52 +0200 Subject: [PATCH 17/42] migration: rename qemu_file_has_error to qemu_file_get_error Now the function returned errno, so it is better the new name. Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- arch_init.c | 2 +- block-migration.c | 8 ++++---- buffered_file.c | 14 +++++++------- hw/hw.h | 2 +- migration.c | 2 +- savevm.c | 13 +++++++------ 6 files changed, 21 insertions(+), 20 deletions(-) diff --git a/arch_init.c b/arch_init.c index 941d585e0..9128be0b0 100644 --- a/arch_init.c +++ b/arch_init.c @@ -451,7 +451,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id) qemu_get_buffer(f, host, TARGET_PAGE_SIZE); } - if (qemu_file_has_error(f)) { + if (qemu_file_get_error(f)) { return -EIO; } } while (!(flags & RAM_SAVE_FLAG_EOS)); diff --git a/block-migration.c b/block-migration.c index 325c90530..56907a664 100644 --- a/block-migration.c +++ b/block-migration.c @@ -580,7 +580,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) flush_blks(f); - if (qemu_file_has_error(f)) { + if (qemu_file_get_error(f)) { blk_mig_cleanup(mon); return 0; } @@ -608,7 +608,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) flush_blks(f); - if (qemu_file_has_error(f)) { + if (qemu_file_get_error(f)) { blk_mig_cleanup(mon); return 0; } @@ -625,7 +625,7 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) /* report completion */ qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS); - if (qemu_file_has_error(f)) { + if (qemu_file_get_error(f)) { return 0; } @@ -705,7 +705,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id) fprintf(stderr, "Unknown flags\n"); return -EINVAL; } - if (qemu_file_has_error(f)) { + if (qemu_file_get_error(f)) { return -EIO; } } while (!(flags & BLK_MIG_FLAG_EOS)); diff --git a/buffered_file.c b/buffered_file.c index 94ca8d11f..41c659cbd 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -72,7 +72,7 @@ static void buffered_flush(QEMUFileBuffered *s) { size_t offset = 0; - if (qemu_file_has_error(s->file)) { + if (qemu_file_get_error(s->file)) { DPRINTF("flush when error, bailing\n"); return; } @@ -113,7 +113,7 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos); - if (qemu_file_has_error(s->file)) { + if (qemu_file_get_error(s->file)) { DPRINTF("flush when error, bailing\n"); return -EINVAL; } @@ -172,7 +172,7 @@ static int buffered_close(void *opaque) DPRINTF("closing\n"); - while (!qemu_file_has_error(s->file) && s->buffer_size) { + while (!qemu_file_get_error(s->file) && s->buffer_size) { buffered_flush(s); if (s->freeze_output) s->wait_for_unfreeze(s->opaque); @@ -198,7 +198,7 @@ static int buffered_rate_limit(void *opaque) { QEMUFileBuffered *s = opaque; - if (qemu_file_has_error(s->file)) { + if (qemu_file_get_error(s->file)) { return -1; } if (s->freeze_output) @@ -213,9 +213,9 @@ static int buffered_rate_limit(void *opaque) static int64_t buffered_set_rate_limit(void *opaque, int64_t new_rate) { QEMUFileBuffered *s = opaque; - if (qemu_file_has_error(s->file)) + if (qemu_file_get_error(s->file)) { goto out; - + } if (new_rate > SIZE_MAX) { new_rate = SIZE_MAX; } @@ -237,7 +237,7 @@ static void buffered_rate_tick(void *opaque) { QEMUFileBuffered *s = opaque; - if (qemu_file_has_error(s->file)) { + if (qemu_file_get_error(s->file)) { buffered_close(s); return; } diff --git a/hw/hw.h b/hw/hw.h index 6cf8cd205..ed20f5a27 100644 --- a/hw/hw.h +++ b/hw/hw.h @@ -85,7 +85,7 @@ uint64_t qemu_get_be64(QEMUFile *f); int qemu_file_rate_limit(QEMUFile *f); int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate); int64_t qemu_file_get_rate_limit(QEMUFile *f); -int qemu_file_has_error(QEMUFile *f); +int qemu_file_get_error(QEMUFile *f); void qemu_file_set_error(QEMUFile *f, int error); /* Try to send any outstanding data. This function is useful when output is diff --git a/migration.c b/migration.c index c1d647c10..c233b522f 100644 --- a/migration.c +++ b/migration.c @@ -313,7 +313,7 @@ void migrate_fd_put_notify(void *opaque) qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); qemu_file_put_notify(s->file); - if (qemu_file_has_error(s->file)) { + if (qemu_file_get_error(s->file)) { migrate_fd_error(s); } } diff --git a/savevm.c b/savevm.c index b2f22bdc8..819a6f791 100644 --- a/savevm.c +++ b/savevm.c @@ -425,7 +425,7 @@ QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, return f; } -int qemu_file_has_error(QEMUFile *f) +int qemu_file_get_error(QEMUFile *f) { return f->has_error; } @@ -1536,7 +1536,7 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable, se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque); } - ret = qemu_file_has_error(f); + ret = qemu_file_get_error(f); if (ret != 0) { qemu_savevm_state_cancel(mon, f); } @@ -1576,7 +1576,7 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f) if (ret != 0) { return ret; } - ret = qemu_file_has_error(f); + ret = qemu_file_get_error(f); if (ret != 0) { qemu_savevm_state_cancel(mon, f); } @@ -1623,7 +1623,7 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f) qemu_put_byte(f, QEMU_VM_EOF); - return qemu_file_has_error(f); + return qemu_file_get_error(f); } void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f) @@ -1664,7 +1664,7 @@ static int qemu_savevm_state(Monitor *mon, QEMUFile *f) out: if (ret == 0) { - ret = qemu_file_has_error(f); + ret = qemu_file_get_error(f); } if (!ret && saved_vm_running) @@ -1885,8 +1885,9 @@ out: g_free(le); } - if (qemu_file_has_error(f)) + if (qemu_file_get_error(f)) { ret = -EIO; + } return ret; } From 3961b4dd0e72ae70e612be1097176d8910fc3f5e Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 5 Oct 2011 01:05:21 +0200 Subject: [PATCH 18/42] savevm: Rename has_error to last_error field Now the field contains the last error name, so rename acordingly. Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- savevm.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/savevm.c b/savevm.c index 819a6f791..89147a690 100644 --- a/savevm.c +++ b/savevm.c @@ -173,7 +173,7 @@ struct QEMUFile { int buf_size; /* 0 when writing */ uint8_t buf[IO_BUF_SIZE]; - int has_error; + int last_error; }; typedef struct QEMUFileStdio @@ -427,12 +427,12 @@ QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer, int qemu_file_get_error(QEMUFile *f) { - return f->has_error; + return f->last_error; } void qemu_file_set_error(QEMUFile *f, int ret) { - f->has_error = ret; + f->last_error = ret; } void qemu_fflush(QEMUFile *f) @@ -447,7 +447,7 @@ void qemu_fflush(QEMUFile *f) if (len > 0) f->buf_offset += f->buf_index; else - f->has_error = -EINVAL; + f->last_error = -EINVAL; f->buf_index = 0; } } @@ -476,7 +476,7 @@ static void qemu_fill_buffer(QEMUFile *f) f->buf_size += len; f->buf_offset += len; } else if (len != -EAGAIN) - f->has_error = len; + f->last_error = len; } int qemu_fclose(QEMUFile *f) @@ -498,13 +498,13 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) { int l; - if (!f->has_error && f->is_write == 0 && f->buf_index > 0) { + if (!f->last_error && f->is_write == 0 && f->buf_index > 0) { fprintf(stderr, "Attempted to write to buffer while read buffer is not empty\n"); abort(); } - while (!f->has_error && size > 0) { + while (!f->last_error && size > 0) { l = IO_BUF_SIZE - f->buf_index; if (l > size) l = size; @@ -520,7 +520,7 @@ void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size) void qemu_put_byte(QEMUFile *f, int v) { - if (!f->has_error && f->is_write == 0 && f->buf_index > 0) { + if (!f->last_error && f->is_write == 0 && f->buf_index > 0) { fprintf(stderr, "Attempted to write to buffer while read buffer is not empty\n"); abort(); From 42802d47dd09c6e70763676bb2ba59136427ec6a Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 5 Oct 2011 01:14:46 +0200 Subject: [PATCH 19/42] migration: use qemu_file_get_error() return value when possible Signed-off-by: Juan Quintela --- arch_init.c | 6 ++++-- block-migration.c | 7 ++++--- buffered_file.c | 23 ++++++++++++++--------- savevm.c | 4 ++-- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/arch_init.c b/arch_init.c index 9128be0b0..98daaf318 100644 --- a/arch_init.c +++ b/arch_init.c @@ -371,6 +371,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id) { ram_addr_t addr; int flags; + int error; if (version_id < 3 || version_id > 4) { return -EINVAL; @@ -451,8 +452,9 @@ int ram_load(QEMUFile *f, void *opaque, int version_id) qemu_get_buffer(f, host, TARGET_PAGE_SIZE); } - if (qemu_file_get_error(f)) { - return -EIO; + error = qemu_file_get_error(f); + if (error) { + return error; } } while (!(flags & RAM_SAVE_FLAG_EOS)); diff --git a/block-migration.c b/block-migration.c index 56907a664..b8d19a115 100644 --- a/block-migration.c +++ b/block-migration.c @@ -647,6 +647,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id) uint8_t *buf; int64_t total_sectors = 0; int nr_sectors; + int ret; do { addr = qemu_get_be64(f); @@ -655,7 +656,6 @@ static int block_load(QEMUFile *f, void *opaque, int version_id) addr >>= BDRV_SECTOR_BITS; if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) { - int ret; /* get device name */ len = qemu_get_byte(f); qemu_get_buffer(f, (uint8_t *)device_name, len); @@ -705,8 +705,9 @@ static int block_load(QEMUFile *f, void *opaque, int version_id) fprintf(stderr, "Unknown flags\n"); return -EINVAL; } - if (qemu_file_get_error(f)) { - return -EIO; + ret = qemu_file_get_error(f); + if (ret != 0) { + return ret; } } while (!(flags & BLK_MIG_FLAG_EOS)); diff --git a/buffered_file.c b/buffered_file.c index 41c659cbd..fed9a227b 100644 --- a/buffered_file.c +++ b/buffered_file.c @@ -71,9 +71,11 @@ static void buffered_append(QEMUFileBuffered *s, static void buffered_flush(QEMUFileBuffered *s) { size_t offset = 0; + int error; - if (qemu_file_get_error(s->file)) { - DPRINTF("flush when error, bailing\n"); + error = qemu_file_get_error(s->file); + if (error != 0) { + DPRINTF("flush when error, bailing: %s\n", strerror(-error)); return; } @@ -108,14 +110,15 @@ static void buffered_flush(QEMUFileBuffered *s) static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size) { QEMUFileBuffered *s = opaque; - int offset = 0; + int offset = 0, error; ssize_t ret; DPRINTF("putting %d bytes at %" PRId64 "\n", size, pos); - if (qemu_file_get_error(s->file)) { - DPRINTF("flush when error, bailing\n"); - return -EINVAL; + error = qemu_file_get_error(s->file); + if (error) { + DPRINTF("flush when error, bailing: %s\n", strerror(-error)); + return error; } DPRINTF("unfreezing output\n"); @@ -192,14 +195,16 @@ static int buffered_close(void *opaque) * The meaning of the return values is: * 0: We can continue sending * 1: Time to stop - * -1: There has been an error + * negative: There has been an error */ static int buffered_rate_limit(void *opaque) { QEMUFileBuffered *s = opaque; + int ret; - if (qemu_file_get_error(s->file)) { - return -1; + ret = qemu_file_get_error(s->file); + if (ret) { + return ret; } if (s->freeze_output) return 1; diff --git a/savevm.c b/savevm.c index 89147a690..5b340b695 100644 --- a/savevm.c +++ b/savevm.c @@ -1885,8 +1885,8 @@ out: g_free(le); } - if (qemu_file_get_error(f)) { - ret = -EIO; + if (ret == 0) { + ret = qemu_file_get_error(f); } return ret; From 2975725f6b3d634dbe924ea9d9f4d86b8a5b217d Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 19 Oct 2011 15:22:18 +0200 Subject: [PATCH 20/42] migration: make *save_live return errors Make *save_live() return negative values when there is one error, and updates all callers to check for the error. Signed-off-by: Juan Quintela --- arch_init.c | 9 +++++++-- block-migration.c | 17 +++++++++++------ savevm.c | 14 +++++++++++--- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/arch_init.c b/arch_init.c index 98daaf318..a411fdf26 100644 --- a/arch_init.c +++ b/arch_init.c @@ -256,6 +256,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) uint64_t bytes_transferred_last; double bwidth = 0; uint64_t expected_time = 0; + int ret; if (stage < 0) { cpu_physical_memory_set_dirty_tracking(0); @@ -264,7 +265,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) if (cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX) != 0) { qemu_file_set_error(f, -EINVAL); - return 0; + return -EINVAL; } if (stage == 1) { @@ -300,7 +301,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) bytes_transferred_last = bytes_transferred; bwidth = qemu_get_clock_ns(rt_clock); - while (!qemu_file_rate_limit(f)) { + while ((ret = qemu_file_rate_limit(f)) == 0) { int bytes_sent; bytes_sent = ram_save_block(f); @@ -310,6 +311,10 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) } } + if (ret < 0) { + return ret; + } + bwidth = qemu_get_clock_ns(rt_clock) - bwidth; bwidth = (bytes_transferred - bytes_transferred_last) / bwidth; diff --git a/block-migration.c b/block-migration.c index b8d19a115..0bff07538 100644 --- a/block-migration.c +++ b/block-migration.c @@ -557,6 +557,8 @@ static void blk_mig_cleanup(Monitor *mon) static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) { + int ret; + DPRINTF("Enter save live stage %d submitted %d transferred %d\n", stage, block_mig_state.submitted, block_mig_state.transferred); @@ -580,9 +582,10 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) flush_blks(f); - if (qemu_file_get_error(f)) { + ret = qemu_file_get_error(f); + if (ret) { blk_mig_cleanup(mon); - return 0; + return ret; } blk_mig_reset_dirty_cursor(); @@ -608,9 +611,10 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) flush_blks(f); - if (qemu_file_get_error(f)) { + ret = qemu_file_get_error(f); + if (ret) { blk_mig_cleanup(mon); - return 0; + return ret; } } @@ -625,8 +629,9 @@ static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque) /* report completion */ qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS); - if (qemu_file_get_error(f)) { - return 0; + ret = qemu_file_get_error(f); + if (ret) { + return ret; } monitor_printf(mon, "Block migration completed\n"); diff --git a/savevm.c b/savevm.c index 5b340b695..9e9c7835a 100644 --- a/savevm.c +++ b/savevm.c @@ -1534,7 +1534,11 @@ int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable, qemu_put_be32(f, se->instance_id); qemu_put_be32(f, se->version_id); - se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque); + ret = se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque); + if (ret < 0) { + qemu_savevm_state_cancel(mon, f); + return ret; + } } ret = qemu_file_get_error(f); if (ret != 0) { @@ -1565,7 +1569,7 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f) qemu_put_be32(f, se->section_id); ret = se->save_live_state(mon, f, QEMU_VM_SECTION_PART, se->opaque); - if (!ret) { + if (ret <= 0) { /* Do not proceed to the next vmstate before this one reported completion of the current stage. This serializes the migration and reduces the probability that a faster changing state is @@ -1586,6 +1590,7 @@ int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f) int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f) { SaveStateEntry *se; + int ret; cpu_synchronize_all_states(); @@ -1597,7 +1602,10 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f) qemu_put_byte(f, QEMU_VM_SECTION_END); qemu_put_be32(f, se->section_id); - se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque); + ret = se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque); + if (ret < 0) { + return ret; + } } QTAILQ_FOREACH(se, &savevm_handlers, entry) { From 7be4363a2828021fd486f7f45e792aecaf909454 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 11 May 2010 15:18:38 +0200 Subject: [PATCH 21/42] migration: Make *start_outgoing_migration return FdMigrationState Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration-exec.c | 4 ++-- migration-fd.c | 4 ++-- migration-tcp.c | 4 ++-- migration-unix.c | 4 ++-- migration.c | 4 ++-- migration.h | 8 ++++---- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/migration-exec.c b/migration-exec.c index 2cfb6f232..759aa7999 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -61,7 +61,7 @@ static int exec_close(FdMigrationState *s) return ret; } -MigrationState *exec_start_outgoing_migration(Monitor *mon, +FdMigrationState *exec_start_outgoing_migration(Monitor *mon, const char *command, int64_t bandwidth_limit, int detach, @@ -108,7 +108,7 @@ MigrationState *exec_start_outgoing_migration(Monitor *mon, } migrate_fd_connect(s); - return &s->mig_state; + return s; err_after_open: pclose(f); diff --git a/migration-fd.c b/migration-fd.c index aee690aae..8036a27d2 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -50,7 +50,7 @@ static int fd_close(FdMigrationState *s) return 0; } -MigrationState *fd_start_outgoing_migration(Monitor *mon, +FdMigrationState *fd_start_outgoing_migration(Monitor *mon, const char *fdname, int64_t bandwidth_limit, int detach, @@ -91,7 +91,7 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon, } migrate_fd_connect(s); - return &s->mig_state; + return s; err_after_open: close(s->fd); diff --git a/migration-tcp.c b/migration-tcp.c index c431e03a4..05a121f1d 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -75,7 +75,7 @@ static void tcp_wait_for_connect(void *opaque) } } -MigrationState *tcp_start_outgoing_migration(Monitor *mon, +FdMigrationState *tcp_start_outgoing_migration(Monitor *mon, const char *host_port, int64_t bandwidth_limit, int detach, @@ -131,7 +131,7 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon, } else if (ret >= 0) migrate_fd_connect(s); - return &s->mig_state; + return s; } static void tcp_accept_incoming_migration(void *opaque) diff --git a/migration-unix.c b/migration-unix.c index 6dc985d42..0eeedde9b 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -74,7 +74,7 @@ static void unix_wait_for_connect(void *opaque) } } -MigrationState *unix_start_outgoing_migration(Monitor *mon, +FdMigrationState *unix_start_outgoing_migration(Monitor *mon, const char *path, int64_t bandwidth_limit, int detach, @@ -132,7 +132,7 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon, if (ret >= 0) migrate_fd_connect(s); - return &s->mig_state; + return s; err_after_open: close(s->fd); diff --git a/migration.c b/migration.c index c233b522f..1d0c76064 100644 --- a/migration.c +++ b/migration.c @@ -79,7 +79,7 @@ void process_incoming_migration(QEMUFile *f) int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) { - MigrationState *s = NULL; + FdMigrationState *s = NULL; const char *p; int detach = qdict_get_try_bool(qdict, "detach", 0); int blk = qdict_get_try_bool(qdict, "blk", 0); @@ -124,7 +124,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) current_migration->release(current_migration); } - current_migration = s; + current_migration = &s->mig_state; notifier_list_notify(&migration_state_notifiers, NULL); return 0; } diff --git a/migration.h b/migration.h index 050c56c5a..58354c744 100644 --- a/migration.h +++ b/migration.h @@ -72,7 +72,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data); int exec_start_incoming_migration(const char *host_port); -MigrationState *exec_start_outgoing_migration(Monitor *mon, +FdMigrationState *exec_start_outgoing_migration(Monitor *mon, const char *host_port, int64_t bandwidth_limit, int detach, @@ -81,7 +81,7 @@ MigrationState *exec_start_outgoing_migration(Monitor *mon, int tcp_start_incoming_migration(const char *host_port); -MigrationState *tcp_start_outgoing_migration(Monitor *mon, +FdMigrationState *tcp_start_outgoing_migration(Monitor *mon, const char *host_port, int64_t bandwidth_limit, int detach, @@ -90,7 +90,7 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon, int unix_start_incoming_migration(const char *path); -MigrationState *unix_start_outgoing_migration(Monitor *mon, +FdMigrationState *unix_start_outgoing_migration(Monitor *mon, const char *path, int64_t bandwidth_limit, int detach, @@ -99,7 +99,7 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon, int fd_start_incoming_migration(const char *path); -MigrationState *fd_start_outgoing_migration(Monitor *mon, +FdMigrationState *fd_start_outgoing_migration(Monitor *mon, const char *fdname, int64_t bandwidth_limit, int detach, From dc7acc61b67a49ce56f6a7c93692f72a3fe0759f Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 11 May 2010 15:46:39 +0200 Subject: [PATCH 22/42] migration: Use FdMigrationState instead of MigrationState when possible Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration.c | 34 ++++++++++++++++------------------ migration.h | 16 ++++++++-------- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/migration.c b/migration.c index 1d0c76064..e3362b76d 100644 --- a/migration.c +++ b/migration.c @@ -34,7 +34,7 @@ /* Migration speed throttling */ static int64_t max_throttle = (32 << 20); -static MigrationState *current_migration; +static FdMigrationState *current_migration; static NotifierList migration_state_notifiers = NOTIFIER_LIST_INITIALIZER(migration_state_notifiers); @@ -87,7 +87,8 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) const char *uri = qdict_get_str(qdict, "uri"); if (current_migration && - current_migration->get_status(current_migration) == MIG_STATE_ACTIVE) { + current_migration->mig_state.get_status(current_migration) == + MIG_STATE_ACTIVE) { monitor_printf(mon, "migration already in progress\n"); return -1; } @@ -121,20 +122,20 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) } if (current_migration) { - current_migration->release(current_migration); + current_migration->mig_state.release(current_migration); } - current_migration = &s->mig_state; + current_migration = s; notifier_list_notify(&migration_state_notifiers, NULL); return 0; } int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data) { - MigrationState *s = current_migration; + FdMigrationState *s = current_migration; - if (s && s->get_status(s) == MIG_STATE_ACTIVE) { - s->cancel(s); + if (s && s->mig_state.get_status(s) == MIG_STATE_ACTIVE) { + s->mig_state.cancel(s); } return 0; } @@ -150,7 +151,7 @@ int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data) } max_throttle = d; - s = migrate_to_fms(current_migration); + s = current_migration; if (s && s->file) { qemu_file_set_rate_limit(s->file, max_throttle); } @@ -228,10 +229,11 @@ static void migrate_put_status(QDict *qdict, const char *name, void do_info_migrate(Monitor *mon, QObject **ret_data) { QDict *qdict; - MigrationState *s = current_migration; - if (s) { - switch (s->get_status(s)) { + if (current_migration) { + MigrationState *s = ¤t_migration->mig_state; + + switch (s->get_status(current_migration)) { case MIG_STATE_ACTIVE: qdict = qdict_new(); qdict_put(qdict, "status", qstring_from_str("active")); @@ -404,16 +406,13 @@ void migrate_fd_put_ready(void *opaque) } } -int migrate_fd_get_status(MigrationState *mig_state) +int migrate_fd_get_status(FdMigrationState *s) { - FdMigrationState *s = migrate_to_fms(mig_state); return s->state; } -void migrate_fd_cancel(MigrationState *mig_state) +void migrate_fd_cancel(FdMigrationState *s) { - FdMigrationState *s = migrate_to_fms(mig_state); - if (s->state != MIG_STATE_ACTIVE) return; @@ -426,9 +425,8 @@ void migrate_fd_cancel(MigrationState *mig_state) migrate_fd_cleanup(s); } -void migrate_fd_release(MigrationState *mig_state) +void migrate_fd_release(FdMigrationState *s) { - FdMigrationState *s = migrate_to_fms(mig_state); DPRINTF("releasing state\n"); diff --git a/migration.h b/migration.h index 58354c744..b10bb6e79 100644 --- a/migration.h +++ b/migration.h @@ -25,18 +25,18 @@ typedef struct MigrationState MigrationState; +typedef struct FdMigrationState FdMigrationState; + struct MigrationState { /* FIXME: add more accessors to print migration info */ - void (*cancel)(MigrationState *s); - int (*get_status)(MigrationState *s); - void (*release)(MigrationState *s); + void (*cancel)(FdMigrationState *s); + int (*get_status)(FdMigrationState *s); + void (*release)(FdMigrationState *s); int blk; int shared; }; -typedef struct FdMigrationState FdMigrationState; - struct FdMigrationState { MigrationState mig_state; @@ -120,11 +120,11 @@ void migrate_fd_connect(FdMigrationState *s); void migrate_fd_put_ready(void *opaque); -int migrate_fd_get_status(MigrationState *mig_state); +int migrate_fd_get_status(FdMigrationState *mig_state); -void migrate_fd_cancel(MigrationState *mig_state); +void migrate_fd_cancel(FdMigrationState *mig_state); -void migrate_fd_release(MigrationState *mig_state); +void migrate_fd_release(FdMigrationState *mig_state); void migrate_fd_wait_for_unfreeze(void *opaque); From 3f77fc557e3e1cb8aab72ca0ca91aac67d478118 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 11 May 2010 15:51:36 +0200 Subject: [PATCH 23/42] migration: Fold MigrationState into FdMigrationState Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration-exec.c | 10 +++++----- migration-fd.c | 10 +++++----- migration-tcp.c | 10 +++++----- migration-unix.c | 10 +++++----- migration.c | 14 ++++++-------- migration.h | 23 +++++------------------ 6 files changed, 31 insertions(+), 46 deletions(-) diff --git a/migration-exec.c b/migration-exec.c index 759aa7999..39fd416e8 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -92,12 +92,12 @@ FdMigrationState *exec_start_outgoing_migration(Monitor *mon, s->close = exec_close; s->get_error = file_errno; s->write = file_write; - s->mig_state.cancel = migrate_fd_cancel; - s->mig_state.get_status = migrate_fd_get_status; - s->mig_state.release = migrate_fd_release; + s->cancel = migrate_fd_cancel; + s->get_status = migrate_fd_get_status; + s->release = migrate_fd_release; - s->mig_state.blk = blk; - s->mig_state.shared = inc; + s->blk = blk; + s->shared = inc; s->state = MIG_STATE_ACTIVE; s->mon = NULL; diff --git a/migration-fd.c b/migration-fd.c index 8036a27d2..c3c7b0eec 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -75,12 +75,12 @@ FdMigrationState *fd_start_outgoing_migration(Monitor *mon, s->get_error = fd_errno; s->write = fd_write; s->close = fd_close; - s->mig_state.cancel = migrate_fd_cancel; - s->mig_state.get_status = migrate_fd_get_status; - s->mig_state.release = migrate_fd_release; + s->cancel = migrate_fd_cancel; + s->get_status = migrate_fd_get_status; + s->release = migrate_fd_release; - s->mig_state.blk = blk; - s->mig_state.shared = inc; + s->blk = blk; + s->shared = inc; s->state = MIG_STATE_ACTIVE; s->mon = NULL; diff --git a/migration-tcp.c b/migration-tcp.c index 05a121f1d..5ce93d986 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -94,12 +94,12 @@ FdMigrationState *tcp_start_outgoing_migration(Monitor *mon, s->get_error = socket_errno; s->write = socket_write; s->close = tcp_close; - s->mig_state.cancel = migrate_fd_cancel; - s->mig_state.get_status = migrate_fd_get_status; - s->mig_state.release = migrate_fd_release; + s->cancel = migrate_fd_cancel; + s->get_status = migrate_fd_get_status; + s->release = migrate_fd_release; - s->mig_state.blk = blk; - s->mig_state.shared = inc; + s->blk = blk; + s->shared = inc; s->state = MIG_STATE_ACTIVE; s->mon = NULL; diff --git a/migration-unix.c b/migration-unix.c index 0eeedde9b..00a6ed576 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -93,12 +93,12 @@ FdMigrationState *unix_start_outgoing_migration(Monitor *mon, s->get_error = unix_errno; s->write = unix_write; s->close = unix_close; - s->mig_state.cancel = migrate_fd_cancel; - s->mig_state.get_status = migrate_fd_get_status; - s->mig_state.release = migrate_fd_release; + s->cancel = migrate_fd_cancel; + s->get_status = migrate_fd_get_status; + s->release = migrate_fd_release; - s->mig_state.blk = blk; - s->mig_state.shared = inc; + s->blk = blk; + s->shared = inc; s->state = MIG_STATE_ACTIVE; s->mon = NULL; diff --git a/migration.c b/migration.c index e3362b76d..caa9e03dd 100644 --- a/migration.c +++ b/migration.c @@ -87,8 +87,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) const char *uri = qdict_get_str(qdict, "uri"); if (current_migration && - current_migration->mig_state.get_status(current_migration) == - MIG_STATE_ACTIVE) { + current_migration->get_status(current_migration) == MIG_STATE_ACTIVE) { monitor_printf(mon, "migration already in progress\n"); return -1; } @@ -122,7 +121,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) } if (current_migration) { - current_migration->mig_state.release(current_migration); + current_migration->release(current_migration); } current_migration = s; @@ -134,8 +133,8 @@ int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data) { FdMigrationState *s = current_migration; - if (s && s->mig_state.get_status(s) == MIG_STATE_ACTIVE) { - s->mig_state.cancel(s); + if (s && s->get_status(s) == MIG_STATE_ACTIVE) { + s->cancel(s); } return 0; } @@ -231,7 +230,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data) QDict *qdict; if (current_migration) { - MigrationState *s = ¤t_migration->mig_state; + FdMigrationState *s = current_migration; switch (s->get_status(current_migration)) { case MIG_STATE_ACTIVE: @@ -355,8 +354,7 @@ void migrate_fd_connect(FdMigrationState *s) migrate_fd_close); DPRINTF("beginning savevm\n"); - ret = qemu_savevm_state_begin(s->mon, s->file, s->mig_state.blk, - s->mig_state.shared); + ret = qemu_savevm_state_begin(s->mon, s->file, s->blk, s->shared); if (ret < 0) { DPRINTF("failed, %d\n", ret); migrate_fd_error(s); diff --git a/migration.h b/migration.h index b10bb6e79..f0caf7b26 100644 --- a/migration.h +++ b/migration.h @@ -23,23 +23,10 @@ #define MIG_STATE_CANCELLED 1 #define MIG_STATE_ACTIVE 2 -typedef struct MigrationState MigrationState; - typedef struct FdMigrationState FdMigrationState; -struct MigrationState -{ - /* FIXME: add more accessors to print migration info */ - void (*cancel)(FdMigrationState *s); - int (*get_status)(FdMigrationState *s); - void (*release)(FdMigrationState *s); - int blk; - int shared; -}; - struct FdMigrationState { - MigrationState mig_state; int64_t bandwidth_limit; QEMUFile *file; int fd; @@ -48,7 +35,12 @@ struct FdMigrationState int (*get_error)(struct FdMigrationState*); int (*close)(struct FdMigrationState*); int (*write)(struct FdMigrationState*, const void *, size_t); + void (*cancel)(FdMigrationState *s); + int (*get_status)(FdMigrationState *s); + void (*release)(FdMigrationState *s); void *opaque; + int blk; + int shared; }; void process_incoming_migration(QEMUFile *f); @@ -130,11 +122,6 @@ void migrate_fd_wait_for_unfreeze(void *opaque); int migrate_fd_close(void *opaque); -static inline FdMigrationState *migrate_to_fms(MigrationState *mig_state) -{ - return container_of(mig_state, FdMigrationState, mig_state); -} - void add_migration_state_change_notifier(Notifier *notify); void remove_migration_state_change_notifier(Notifier *notify); int get_migration_state(void); From 22f00a4445fac68b10d1cb669836eeb8d32af56d Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 11 May 2010 15:56:35 +0200 Subject: [PATCH 24/42] migration: Rename FdMigrationState MigrationState Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration-exec.c | 10 +++++----- migration-fd.c | 10 +++++----- migration-tcp.c | 12 ++++++------ migration-unix.c | 12 ++++++------ migration.c | 34 +++++++++++++++++----------------- migration.h | 38 +++++++++++++++++++------------------- 6 files changed, 58 insertions(+), 58 deletions(-) diff --git a/migration-exec.c b/migration-exec.c index 39fd416e8..0ed597669 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -32,17 +32,17 @@ do { } while (0) #endif -static int file_errno(FdMigrationState *s) +static int file_errno(MigrationState *s) { return errno; } -static int file_write(FdMigrationState *s, const void * buf, size_t size) +static int file_write(MigrationState *s, const void * buf, size_t size) { return write(s->fd, buf, size); } -static int exec_close(FdMigrationState *s) +static int exec_close(MigrationState *s) { int ret = 0; DPRINTF("exec_close\n"); @@ -61,14 +61,14 @@ static int exec_close(FdMigrationState *s) return ret; } -FdMigrationState *exec_start_outgoing_migration(Monitor *mon, +MigrationState *exec_start_outgoing_migration(Monitor *mon, const char *command, int64_t bandwidth_limit, int detach, int blk, int inc) { - FdMigrationState *s; + MigrationState *s; FILE *f; s = g_malloc0(sizeof(*s)); diff --git a/migration-fd.c b/migration-fd.c index c3c7b0eec..e78fd4e9e 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -30,17 +30,17 @@ do { } while (0) #endif -static int fd_errno(FdMigrationState *s) +static int fd_errno(MigrationState *s) { return errno; } -static int fd_write(FdMigrationState *s, const void * buf, size_t size) +static int fd_write(MigrationState *s, const void * buf, size_t size) { return write(s->fd, buf, size); } -static int fd_close(FdMigrationState *s) +static int fd_close(MigrationState *s) { DPRINTF("fd_close\n"); if (s->fd != -1) { @@ -50,14 +50,14 @@ static int fd_close(FdMigrationState *s) return 0; } -FdMigrationState *fd_start_outgoing_migration(Monitor *mon, +MigrationState *fd_start_outgoing_migration(Monitor *mon, const char *fdname, int64_t bandwidth_limit, int detach, int blk, int inc) { - FdMigrationState *s; + MigrationState *s; s = g_malloc0(sizeof(*s)); diff --git a/migration-tcp.c b/migration-tcp.c index 5ce93d986..d6feb237e 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -28,17 +28,17 @@ do { } while (0) #endif -static int socket_errno(FdMigrationState *s) +static int socket_errno(MigrationState *s) { return socket_error(); } -static int socket_write(FdMigrationState *s, const void * buf, size_t size) +static int socket_write(MigrationState *s, const void * buf, size_t size) { return send(s->fd, buf, size, 0); } -static int tcp_close(FdMigrationState *s) +static int tcp_close(MigrationState *s) { DPRINTF("tcp_close\n"); if (s->fd != -1) { @@ -51,7 +51,7 @@ static int tcp_close(FdMigrationState *s) static void tcp_wait_for_connect(void *opaque) { - FdMigrationState *s = opaque; + MigrationState *s = opaque; int val, ret; socklen_t valsize = sizeof(val); @@ -75,7 +75,7 @@ static void tcp_wait_for_connect(void *opaque) } } -FdMigrationState *tcp_start_outgoing_migration(Monitor *mon, +MigrationState *tcp_start_outgoing_migration(Monitor *mon, const char *host_port, int64_t bandwidth_limit, int detach, @@ -83,7 +83,7 @@ FdMigrationState *tcp_start_outgoing_migration(Monitor *mon, int inc) { struct sockaddr_in addr; - FdMigrationState *s; + MigrationState *s; int ret; if (parse_host_port(&addr, host_port) < 0) diff --git a/migration-unix.c b/migration-unix.c index 00a6ed576..3b9017be4 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -28,17 +28,17 @@ do { } while (0) #endif -static int unix_errno(FdMigrationState *s) +static int unix_errno(MigrationState *s) { return errno; } -static int unix_write(FdMigrationState *s, const void * buf, size_t size) +static int unix_write(MigrationState *s, const void * buf, size_t size) { return write(s->fd, buf, size); } -static int unix_close(FdMigrationState *s) +static int unix_close(MigrationState *s) { DPRINTF("unix_close\n"); if (s->fd != -1) { @@ -50,7 +50,7 @@ static int unix_close(FdMigrationState *s) static void unix_wait_for_connect(void *opaque) { - FdMigrationState *s = opaque; + MigrationState *s = opaque; int val, ret; socklen_t valsize = sizeof(val); @@ -74,14 +74,14 @@ static void unix_wait_for_connect(void *opaque) } } -FdMigrationState *unix_start_outgoing_migration(Monitor *mon, +MigrationState *unix_start_outgoing_migration(Monitor *mon, const char *path, int64_t bandwidth_limit, int detach, int blk, int inc) { - FdMigrationState *s; + MigrationState *s; struct sockaddr_un addr; int ret; diff --git a/migration.c b/migration.c index caa9e03dd..daf3ef632 100644 --- a/migration.c +++ b/migration.c @@ -34,7 +34,7 @@ /* Migration speed throttling */ static int64_t max_throttle = (32 << 20); -static FdMigrationState *current_migration; +static MigrationState *current_migration; static NotifierList migration_state_notifiers = NOTIFIER_LIST_INITIALIZER(migration_state_notifiers); @@ -79,7 +79,7 @@ void process_incoming_migration(QEMUFile *f) int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) { - FdMigrationState *s = NULL; + MigrationState *s = NULL; const char *p; int detach = qdict_get_try_bool(qdict, "detach", 0); int blk = qdict_get_try_bool(qdict, "blk", 0); @@ -131,7 +131,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data) { - FdMigrationState *s = current_migration; + MigrationState *s = current_migration; if (s && s->get_status(s) == MIG_STATE_ACTIVE) { s->cancel(s); @@ -142,7 +142,7 @@ int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data) int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data) { int64_t d; - FdMigrationState *s; + MigrationState *s; d = qdict_get_int(qdict, "value"); if (d < 0) { @@ -230,7 +230,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data) QDict *qdict; if (current_migration) { - FdMigrationState *s = current_migration; + MigrationState *s = current_migration; switch (s->get_status(current_migration)) { case MIG_STATE_ACTIVE: @@ -263,7 +263,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data) /* shared migration helpers */ -void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon) +void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon) { s->mon = mon; if (monitor_suspend(mon) == 0) { @@ -274,7 +274,7 @@ void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon) } } -void migrate_fd_error(FdMigrationState *s) +void migrate_fd_error(MigrationState *s) { DPRINTF("setting error state\n"); s->state = MIG_STATE_ERROR; @@ -282,7 +282,7 @@ void migrate_fd_error(FdMigrationState *s) migrate_fd_cleanup(s); } -int migrate_fd_cleanup(FdMigrationState *s) +int migrate_fd_cleanup(MigrationState *s) { int ret = 0; @@ -310,7 +310,7 @@ int migrate_fd_cleanup(FdMigrationState *s) void migrate_fd_put_notify(void *opaque) { - FdMigrationState *s = opaque; + MigrationState *s = opaque; qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); qemu_file_put_notify(s->file); @@ -321,7 +321,7 @@ void migrate_fd_put_notify(void *opaque) ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) { - FdMigrationState *s = opaque; + MigrationState *s = opaque; ssize_t ret; if (s->state != MIG_STATE_ACTIVE) { @@ -342,7 +342,7 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) return ret; } -void migrate_fd_connect(FdMigrationState *s) +void migrate_fd_connect(MigrationState *s) { int ret; @@ -366,7 +366,7 @@ void migrate_fd_connect(FdMigrationState *s) void migrate_fd_put_ready(void *opaque) { - FdMigrationState *s = opaque; + MigrationState *s = opaque; int ret; if (s->state != MIG_STATE_ACTIVE) { @@ -404,12 +404,12 @@ void migrate_fd_put_ready(void *opaque) } } -int migrate_fd_get_status(FdMigrationState *s) +int migrate_fd_get_status(MigrationState *s) { return s->state; } -void migrate_fd_cancel(FdMigrationState *s) +void migrate_fd_cancel(MigrationState *s) { if (s->state != MIG_STATE_ACTIVE) return; @@ -423,7 +423,7 @@ void migrate_fd_cancel(FdMigrationState *s) migrate_fd_cleanup(s); } -void migrate_fd_release(FdMigrationState *s) +void migrate_fd_release(MigrationState *s) { DPRINTF("releasing state\n"); @@ -438,7 +438,7 @@ void migrate_fd_release(FdMigrationState *s) void migrate_fd_wait_for_unfreeze(void *opaque) { - FdMigrationState *s = opaque; + MigrationState *s = opaque; int ret; DPRINTF("wait for unfreeze\n"); @@ -461,7 +461,7 @@ void migrate_fd_wait_for_unfreeze(void *opaque) int migrate_fd_close(void *opaque) { - FdMigrationState *s = opaque; + MigrationState *s = opaque; if (s->mon) { monitor_resume(s->mon); diff --git a/migration.h b/migration.h index f0caf7b26..e24efedef 100644 --- a/migration.h +++ b/migration.h @@ -23,21 +23,21 @@ #define MIG_STATE_CANCELLED 1 #define MIG_STATE_ACTIVE 2 -typedef struct FdMigrationState FdMigrationState; +typedef struct MigrationState MigrationState; -struct FdMigrationState +struct MigrationState { int64_t bandwidth_limit; QEMUFile *file; int fd; Monitor *mon; int state; - int (*get_error)(struct FdMigrationState*); - int (*close)(struct FdMigrationState*); - int (*write)(struct FdMigrationState*, const void *, size_t); - void (*cancel)(FdMigrationState *s); - int (*get_status)(FdMigrationState *s); - void (*release)(FdMigrationState *s); + int (*get_error)(MigrationState *s); + int (*close)(MigrationState *s); + int (*write)(MigrationState *s, const void *buff, size_t size); + void (*cancel)(MigrationState *s); + int (*get_status)(MigrationState *s); + void (*release)(MigrationState *s); void *opaque; int blk; int shared; @@ -64,7 +64,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data); int exec_start_incoming_migration(const char *host_port); -FdMigrationState *exec_start_outgoing_migration(Monitor *mon, +MigrationState *exec_start_outgoing_migration(Monitor *mon, const char *host_port, int64_t bandwidth_limit, int detach, @@ -73,7 +73,7 @@ FdMigrationState *exec_start_outgoing_migration(Monitor *mon, int tcp_start_incoming_migration(const char *host_port); -FdMigrationState *tcp_start_outgoing_migration(Monitor *mon, +MigrationState *tcp_start_outgoing_migration(Monitor *mon, const char *host_port, int64_t bandwidth_limit, int detach, @@ -82,7 +82,7 @@ FdMigrationState *tcp_start_outgoing_migration(Monitor *mon, int unix_start_incoming_migration(const char *path); -FdMigrationState *unix_start_outgoing_migration(Monitor *mon, +MigrationState *unix_start_outgoing_migration(Monitor *mon, const char *path, int64_t bandwidth_limit, int detach, @@ -91,32 +91,32 @@ FdMigrationState *unix_start_outgoing_migration(Monitor *mon, int fd_start_incoming_migration(const char *path); -FdMigrationState *fd_start_outgoing_migration(Monitor *mon, +MigrationState *fd_start_outgoing_migration(Monitor *mon, const char *fdname, int64_t bandwidth_limit, int detach, int blk, int inc); -void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon); +void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon); -void migrate_fd_error(FdMigrationState *s); +void migrate_fd_error(MigrationState *s); -int migrate_fd_cleanup(FdMigrationState *s); +int migrate_fd_cleanup(MigrationState *s); void migrate_fd_put_notify(void *opaque); ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size); -void migrate_fd_connect(FdMigrationState *s); +void migrate_fd_connect(MigrationState *s); void migrate_fd_put_ready(void *opaque); -int migrate_fd_get_status(FdMigrationState *mig_state); +int migrate_fd_get_status(MigrationState *mig_state); -void migrate_fd_cancel(FdMigrationState *mig_state); +void migrate_fd_cancel(MigrationState *mig_state); -void migrate_fd_release(FdMigrationState *mig_state); +void migrate_fd_release(MigrationState *mig_state); void migrate_fd_wait_for_unfreeze(void *opaque); From 0edda1c42aa49dd3207f3c76bf25fd53ac16345d Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 11 May 2010 16:28:39 +0200 Subject: [PATCH 25/42] migration: Refactor MigrationState creation Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration-exec.c | 16 +--------------- migration-fd.c | 16 +--------------- migration-tcp.c | 15 +-------------- migration-unix.c | 15 +-------------- migration.c | 29 +++++++++++++++++++++++++---- migration.h | 11 +++-------- 6 files changed, 32 insertions(+), 70 deletions(-) diff --git a/migration-exec.c b/migration-exec.c index 0ed597669..d0119c67d 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -71,7 +71,7 @@ MigrationState *exec_start_outgoing_migration(Monitor *mon, MigrationState *s; FILE *f; - s = g_malloc0(sizeof(*s)); + s = migrate_new(mon, bandwidth_limit, detach, blk, inc); f = popen(command, "w"); if (f == NULL) { @@ -92,20 +92,6 @@ MigrationState *exec_start_outgoing_migration(Monitor *mon, s->close = exec_close; s->get_error = file_errno; s->write = file_write; - s->cancel = migrate_fd_cancel; - s->get_status = migrate_fd_get_status; - s->release = migrate_fd_release; - - s->blk = blk; - s->shared = inc; - - s->state = MIG_STATE_ACTIVE; - s->mon = NULL; - s->bandwidth_limit = bandwidth_limit; - - if (!detach) { - migrate_fd_monitor_suspend(s, mon); - } migrate_fd_connect(s); return s; diff --git a/migration-fd.c b/migration-fd.c index e78fd4e9e..9d3ca420e 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -59,7 +59,7 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon, { MigrationState *s; - s = g_malloc0(sizeof(*s)); + s = migrate_new(mon, bandwidth_limit, detach, blk, inc); s->fd = monitor_get_fd(mon, fdname); if (s->fd == -1) { @@ -75,20 +75,6 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon, s->get_error = fd_errno; s->write = fd_write; s->close = fd_close; - s->cancel = migrate_fd_cancel; - s->get_status = migrate_fd_get_status; - s->release = migrate_fd_release; - - s->blk = blk; - s->shared = inc; - - s->state = MIG_STATE_ACTIVE; - s->mon = NULL; - s->bandwidth_limit = bandwidth_limit; - - if (!detach) { - migrate_fd_monitor_suspend(s, mon); - } migrate_fd_connect(s); return s; diff --git a/migration-tcp.c b/migration-tcp.c index d6feb237e..999d4c9aa 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -89,21 +89,12 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon, if (parse_host_port(&addr, host_port) < 0) return NULL; - s = g_malloc0(sizeof(*s)); + s = migrate_new(mon, bandwidth_limit, detach, blk, inc); s->get_error = socket_errno; s->write = socket_write; s->close = tcp_close; - s->cancel = migrate_fd_cancel; - s->get_status = migrate_fd_get_status; - s->release = migrate_fd_release; - s->blk = blk; - s->shared = inc; - - s->state = MIG_STATE_ACTIVE; - s->mon = NULL; - s->bandwidth_limit = bandwidth_limit; s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (s->fd == -1) { g_free(s); @@ -112,10 +103,6 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon, socket_set_nonblock(s->fd); - if (!detach) { - migrate_fd_monitor_suspend(s, mon); - } - do { ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr)); if (ret == -1) diff --git a/migration-unix.c b/migration-unix.c index 3b9017be4..bee71d966 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -88,21 +88,12 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon, addr.sun_family = AF_UNIX; snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path); - s = g_malloc0(sizeof(*s)); + s = migrate_new(mon, bandwidth_limit, detach, blk, inc); s->get_error = unix_errno; s->write = unix_write; s->close = unix_close; - s->cancel = migrate_fd_cancel; - s->get_status = migrate_fd_get_status; - s->release = migrate_fd_release; - s->blk = blk; - s->shared = inc; - - s->state = MIG_STATE_ACTIVE; - s->mon = NULL; - s->bandwidth_limit = bandwidth_limit; s->fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0); if (s->fd < 0) { DPRINTF("Unable to open socket"); @@ -125,10 +116,6 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon, goto err_after_open; } - if (!detach) { - migrate_fd_monitor_suspend(s, mon); - } - if (ret >= 0) migrate_fd_connect(s); diff --git a/migration.c b/migration.c index daf3ef632..78d0f6116 100644 --- a/migration.c +++ b/migration.c @@ -263,7 +263,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data) /* shared migration helpers */ -void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon) +static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon) { s->mon = mon; if (monitor_suspend(mon) == 0) { @@ -404,12 +404,12 @@ void migrate_fd_put_ready(void *opaque) } } -int migrate_fd_get_status(MigrationState *s) +static int migrate_fd_get_status(MigrationState *s) { return s->state; } -void migrate_fd_cancel(MigrationState *s) +static void migrate_fd_cancel(MigrationState *s) { if (s->state != MIG_STATE_ACTIVE) return; @@ -423,7 +423,7 @@ void migrate_fd_cancel(MigrationState *s) migrate_fd_cleanup(s); } -void migrate_fd_release(MigrationState *s) +static void migrate_fd_release(MigrationState *s) { DPRINTF("releasing state\n"); @@ -488,3 +488,24 @@ int get_migration_state(void) return MIG_STATE_ERROR; } } + +MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, + int detach, int blk, int inc) +{ + MigrationState *s = g_malloc0(sizeof(*s)); + + s->cancel = migrate_fd_cancel; + s->get_status = migrate_fd_get_status; + s->release = migrate_fd_release; + s->blk = blk; + s->shared = inc; + s->mon = NULL; + s->bandwidth_limit = bandwidth_limit; + s->state = MIG_STATE_ACTIVE; + + if (!detach) { + migrate_fd_monitor_suspend(s, mon); + } + + return s; +} diff --git a/migration.h b/migration.h index e24efedef..5f933e865 100644 --- a/migration.h +++ b/migration.h @@ -98,8 +98,6 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon, int blk, int inc); -void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon); - void migrate_fd_error(MigrationState *s); int migrate_fd_cleanup(MigrationState *s); @@ -112,16 +110,13 @@ void migrate_fd_connect(MigrationState *s); void migrate_fd_put_ready(void *opaque); -int migrate_fd_get_status(MigrationState *mig_state); - -void migrate_fd_cancel(MigrationState *mig_state); - -void migrate_fd_release(MigrationState *mig_state); - void migrate_fd_wait_for_unfreeze(void *opaque); int migrate_fd_close(void *opaque); +MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, + int detach, int blk, int inc); + void add_migration_state_change_notifier(Notifier *notify); void remove_migration_state_change_notifier(Notifier *notify); int get_migration_state(void); From 8b6b99b3561b8da3b15da1871e1bb3d4ac7770ca Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Sun, 11 Sep 2011 20:28:22 +0200 Subject: [PATCH 26/42] migration: Make all posible migration functions static I have to move two functions postions to avoid forward declarations Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration.c | 72 ++++++++++++++++++++++++++--------------------------- migration.h | 12 --------- 2 files changed, 36 insertions(+), 48 deletions(-) diff --git a/migration.c b/migration.c index 78d0f6116..117bdb2a4 100644 --- a/migration.c +++ b/migration.c @@ -274,15 +274,7 @@ static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon) } } -void migrate_fd_error(MigrationState *s) -{ - DPRINTF("setting error state\n"); - s->state = MIG_STATE_ERROR; - notifier_list_notify(&migration_state_notifiers, NULL); - migrate_fd_cleanup(s); -} - -int migrate_fd_cleanup(MigrationState *s) +static int migrate_fd_cleanup(MigrationState *s) { int ret = 0; @@ -308,7 +300,15 @@ int migrate_fd_cleanup(MigrationState *s) return ret; } -void migrate_fd_put_notify(void *opaque) +void migrate_fd_error(MigrationState *s) +{ + DPRINTF("setting error state\n"); + s->state = MIG_STATE_ERROR; + notifier_list_notify(&migration_state_notifiers, NULL); + migrate_fd_cleanup(s); +} + +static void migrate_fd_put_notify(void *opaque) { MigrationState *s = opaque; @@ -319,7 +319,8 @@ void migrate_fd_put_notify(void *opaque) } } -ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) +static ssize_t migrate_fd_put_buffer(void *opaque, const void *data, + size_t size) { MigrationState *s = opaque; ssize_t ret; @@ -342,29 +343,7 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) return ret; } -void migrate_fd_connect(MigrationState *s) -{ - int ret; - - s->file = qemu_fopen_ops_buffered(s, - s->bandwidth_limit, - migrate_fd_put_buffer, - migrate_fd_put_ready, - migrate_fd_wait_for_unfreeze, - migrate_fd_close); - - DPRINTF("beginning savevm\n"); - ret = qemu_savevm_state_begin(s->mon, s->file, s->blk, s->shared); - if (ret < 0) { - DPRINTF("failed, %d\n", ret); - migrate_fd_error(s); - return; - } - - migrate_fd_put_ready(s); -} - -void migrate_fd_put_ready(void *opaque) +static void migrate_fd_put_ready(void *opaque) { MigrationState *s = opaque; int ret; @@ -436,7 +415,7 @@ static void migrate_fd_release(MigrationState *s) g_free(s); } -void migrate_fd_wait_for_unfreeze(void *opaque) +static void migrate_fd_wait_for_unfreeze(void *opaque) { MigrationState *s = opaque; int ret; @@ -459,7 +438,7 @@ void migrate_fd_wait_for_unfreeze(void *opaque) } } -int migrate_fd_close(void *opaque) +static int migrate_fd_close(void *opaque) { MigrationState *s = opaque; @@ -489,6 +468,27 @@ int get_migration_state(void) } } +void migrate_fd_connect(MigrationState *s) +{ + int ret; + + s->file = qemu_fopen_ops_buffered(s, + s->bandwidth_limit, + migrate_fd_put_buffer, + migrate_fd_put_ready, + migrate_fd_wait_for_unfreeze, + migrate_fd_close); + + DPRINTF("beginning savevm\n"); + ret = qemu_savevm_state_begin(s->mon, s->file, s->blk, s->shared); + if (ret < 0) { + DPRINTF("failed, %d\n", ret); + migrate_fd_error(s); + return; + } + migrate_fd_put_ready(s); +} + MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, int detach, int blk, int inc) { diff --git a/migration.h b/migration.h index 5f933e865..892b63650 100644 --- a/migration.h +++ b/migration.h @@ -100,20 +100,8 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon, void migrate_fd_error(MigrationState *s); -int migrate_fd_cleanup(MigrationState *s); - -void migrate_fd_put_notify(void *opaque); - -ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size); - void migrate_fd_connect(MigrationState *s); -void migrate_fd_put_ready(void *opaque); - -void migrate_fd_wait_for_unfreeze(void *opaque); - -int migrate_fd_close(void *opaque); - MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, int detach, int blk, int inc); From 07af4452919fddc6dca6462828b457aad62f6387 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 11 May 2010 22:27:45 +0200 Subject: [PATCH 27/42] migration: move migrate_new to do_migrate Once there, remove all parameters that don't need to be passed to *start_outgoing_migration() functions Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration-exec.c | 19 +++++-------------- migration-fd.c | 22 ++++++---------------- migration-tcp.c | 22 +++++++--------------- migration-unix.c | 20 +++++--------------- migration.c | 32 +++++++++++++++++++------------- migration.h | 31 ++++--------------------------- 6 files changed, 46 insertions(+), 100 deletions(-) diff --git a/migration-exec.c b/migration-exec.c index d0119c67d..b7b1055e8 100644 --- a/migration-exec.c +++ b/migration-exec.c @@ -61,22 +61,14 @@ static int exec_close(MigrationState *s) return ret; } -MigrationState *exec_start_outgoing_migration(Monitor *mon, - const char *command, - int64_t bandwidth_limit, - int detach, - int blk, - int inc) +int exec_start_outgoing_migration(MigrationState *s, const char *command) { - MigrationState *s; FILE *f; - s = migrate_new(mon, bandwidth_limit, detach, blk, inc); - f = popen(command, "w"); if (f == NULL) { DPRINTF("Unable to popen exec target\n"); - goto err_after_alloc; + goto err_after_popen; } s->fd = fileno(f); @@ -94,13 +86,12 @@ MigrationState *exec_start_outgoing_migration(Monitor *mon, s->write = file_write; migrate_fd_connect(s); - return s; + return 0; err_after_open: pclose(f); -err_after_alloc: - g_free(s); - return NULL; +err_after_popen: + return -1; } static void exec_accept_incoming_migration(void *opaque) diff --git a/migration-fd.c b/migration-fd.c index 9d3ca420e..d0aec89e8 100644 --- a/migration-fd.c +++ b/migration-fd.c @@ -50,21 +50,12 @@ static int fd_close(MigrationState *s) return 0; } -MigrationState *fd_start_outgoing_migration(Monitor *mon, - const char *fdname, - int64_t bandwidth_limit, - int detach, - int blk, - int inc) +int fd_start_outgoing_migration(MigrationState *s, const char *fdname) { - MigrationState *s; - - s = migrate_new(mon, bandwidth_limit, detach, blk, inc); - - s->fd = monitor_get_fd(mon, fdname); + s->fd = monitor_get_fd(s->mon, fdname); if (s->fd == -1) { DPRINTF("fd_migration: invalid file descriptor identifier\n"); - goto err_after_alloc; + goto err_after_get_fd; } if (fcntl(s->fd, F_SETFL, O_NONBLOCK) == -1) { @@ -77,13 +68,12 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon, s->close = fd_close; migrate_fd_connect(s); - return s; + return 0; err_after_open: close(s->fd); -err_after_alloc: - g_free(s); - return NULL; +err_after_get_fd: + return -1; } static void fd_accept_incoming_migration(void *opaque) diff --git a/migration-tcp.c b/migration-tcp.c index 999d4c9aa..f6b228820 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -75,30 +75,22 @@ static void tcp_wait_for_connect(void *opaque) } } -MigrationState *tcp_start_outgoing_migration(Monitor *mon, - const char *host_port, - int64_t bandwidth_limit, - int detach, - int blk, - int inc) +int tcp_start_outgoing_migration(MigrationState *s, const char *host_port) { struct sockaddr_in addr; - MigrationState *s; int ret; - if (parse_host_port(&addr, host_port) < 0) - return NULL; - - s = migrate_new(mon, bandwidth_limit, detach, blk, inc); - + ret = parse_host_port(&addr, host_port); + if (ret < 0) { + return ret; + } s->get_error = socket_errno; s->write = socket_write; s->close = tcp_close; s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (s->fd == -1) { - g_free(s); - return NULL; + return -1; } socket_set_nonblock(s->fd); @@ -118,7 +110,7 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon, } else if (ret >= 0) migrate_fd_connect(s); - return s; + return 0; } static void tcp_accept_incoming_migration(void *opaque) diff --git a/migration-unix.c b/migration-unix.c index bee71d966..bd8d40fe7 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -74,22 +74,13 @@ static void unix_wait_for_connect(void *opaque) } } -MigrationState *unix_start_outgoing_migration(Monitor *mon, - const char *path, - int64_t bandwidth_limit, - int detach, - int blk, - int inc) +int unix_start_outgoing_migration(MigrationState *s, const char *path) { - MigrationState *s; struct sockaddr_un addr; int ret; addr.sun_family = AF_UNIX; snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path); - - s = migrate_new(mon, bandwidth_limit, detach, blk, inc); - s->get_error = unix_errno; s->write = unix_write; s->close = unix_close; @@ -97,7 +88,7 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon, s->fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0); if (s->fd < 0) { DPRINTF("Unable to open socket"); - goto err_after_alloc; + goto err_after_socket; } socket_set_nonblock(s->fd); @@ -119,14 +110,13 @@ MigrationState *unix_start_outgoing_migration(Monitor *mon, if (ret >= 0) migrate_fd_connect(s); - return s; + return 0; err_after_open: close(s->fd); -err_after_alloc: - g_free(s); - return NULL; +err_after_socket: + return -1; } static void unix_accept_incoming_migration(void *opaque) diff --git a/migration.c b/migration.c index 117bdb2a4..ca038ec8d 100644 --- a/migration.c +++ b/migration.c @@ -77,6 +77,9 @@ void process_incoming_migration(QEMUFile *f) } } +static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, + int detach, int blk, int inc); + int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) { MigrationState *s = NULL; @@ -85,6 +88,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) int blk = qdict_get_try_bool(qdict, "blk", 0); int inc = qdict_get_try_bool(qdict, "inc", 0); const char *uri = qdict_get_str(qdict, "uri"); + int ret; if (current_migration && current_migration->get_status(current_migration) == MIG_STATE_ACTIVE) { @@ -96,28 +100,27 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) return -1; } + s = migrate_new(mon, max_throttle, detach, blk, inc); + if (strstart(uri, "tcp:", &p)) { - s = tcp_start_outgoing_migration(mon, p, max_throttle, detach, - blk, inc); + ret = tcp_start_outgoing_migration(s, p); #if !defined(WIN32) } else if (strstart(uri, "exec:", &p)) { - s = exec_start_outgoing_migration(mon, p, max_throttle, detach, - blk, inc); + ret = exec_start_outgoing_migration(s, p); } else if (strstart(uri, "unix:", &p)) { - s = unix_start_outgoing_migration(mon, p, max_throttle, detach, - blk, inc); + ret = unix_start_outgoing_migration(s, p); } else if (strstart(uri, "fd:", &p)) { - s = fd_start_outgoing_migration(mon, p, max_throttle, detach, - blk, inc); + ret = fd_start_outgoing_migration(s, p); #endif } else { monitor_printf(mon, "unknown migration protocol: %s\n", uri); - return -1; + ret = -EINVAL; + goto free_migrate_state; } - if (s == NULL) { + if (ret < 0) { monitor_printf(mon, "migration failed\n"); - return -1; + goto free_migrate_state; } if (current_migration) { @@ -127,6 +130,9 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) current_migration = s; notifier_list_notify(&migration_state_notifiers, NULL); return 0; +free_migrate_state: + g_free(s); + return -1; } int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data) @@ -489,8 +495,8 @@ void migrate_fd_connect(MigrationState *s) migrate_fd_put_ready(s); } -MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, - int detach, int blk, int inc) +static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, + int detach, int blk, int inc) { MigrationState *s = g_malloc0(sizeof(*s)); diff --git a/migration.h b/migration.h index 892b63650..14c3ebccd 100644 --- a/migration.h +++ b/migration.h @@ -64,47 +64,24 @@ void do_info_migrate(Monitor *mon, QObject **ret_data); int exec_start_incoming_migration(const char *host_port); -MigrationState *exec_start_outgoing_migration(Monitor *mon, - const char *host_port, - int64_t bandwidth_limit, - int detach, - int blk, - int inc); +int exec_start_outgoing_migration(MigrationState *s, const char *host_port); int tcp_start_incoming_migration(const char *host_port); -MigrationState *tcp_start_outgoing_migration(Monitor *mon, - const char *host_port, - int64_t bandwidth_limit, - int detach, - int blk, - int inc); +int tcp_start_outgoing_migration(MigrationState *s, const char *host_port); int unix_start_incoming_migration(const char *path); -MigrationState *unix_start_outgoing_migration(Monitor *mon, - const char *path, - int64_t bandwidth_limit, - int detach, - int blk, - int inc); +int unix_start_outgoing_migration(MigrationState *s, const char *path); int fd_start_incoming_migration(const char *path); -MigrationState *fd_start_outgoing_migration(Monitor *mon, - const char *fdname, - int64_t bandwidth_limit, - int detach, - int blk, - int inc); +int fd_start_outgoing_migration(MigrationState *s, const char *fdname); void migrate_fd_error(MigrationState *s); void migrate_fd_connect(MigrationState *s); -MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, - int detach, int blk, int inc); - void add_migration_state_change_notifier(Notifier *notify); void remove_migration_state_change_notifier(Notifier *notify); int get_migration_state(void); From d5934dde1cc47306800558a8c8619dc6a976c11c Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 11 May 2010 23:01:53 +0200 Subject: [PATCH 28/42] migration: Introduce MIG_STATE_SETUP Use MIG_STATE_ACTIVE only when migration has really started. Use this new state to setup migration parameters. Change defines for an anonymous struct. Signed-off-by: Juan Quintela --- migration.c | 6 +++++- migration.h | 11 +++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/migration.c b/migration.c index ca038ec8d..281fbaefd 100644 --- a/migration.c +++ b/migration.c @@ -239,6 +239,9 @@ void do_info_migrate(Monitor *mon, QObject **ret_data) MigrationState *s = current_migration; switch (s->get_status(current_migration)) { + case MIG_STATE_SETUP: + /* no migration has happened ever */ + break; case MIG_STATE_ACTIVE: qdict = qdict_new(); qdict_put(qdict, "status", qstring_from_str("active")); @@ -478,6 +481,7 @@ void migrate_fd_connect(MigrationState *s) { int ret; + s->state = MIG_STATE_ACTIVE; s->file = qemu_fopen_ops_buffered(s, s->bandwidth_limit, migrate_fd_put_buffer, @@ -507,7 +511,7 @@ static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, s->shared = inc; s->mon = NULL; s->bandwidth_limit = bandwidth_limit; - s->state = MIG_STATE_ACTIVE; + s->state = MIG_STATE_SETUP; if (!detach) { migrate_fd_monitor_suspend(s, mon); diff --git a/migration.h b/migration.h index 14c3ebccd..fed1cf133 100644 --- a/migration.h +++ b/migration.h @@ -18,10 +18,13 @@ #include "qemu-common.h" #include "notify.h" -#define MIG_STATE_ERROR -1 -#define MIG_STATE_COMPLETED 0 -#define MIG_STATE_CANCELLED 1 -#define MIG_STATE_ACTIVE 2 +enum { + MIG_STATE_ERROR, + MIG_STATE_SETUP, + MIG_STATE_CANCELLED, + MIG_STATE_ACTIVE, + MIG_STATE_COMPLETED, +}; typedef struct MigrationState MigrationState; From 67afff79111f0ce1ae20010c27a30b5ec61f362c Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 22 Feb 2011 23:18:20 +0100 Subject: [PATCH 29/42] migration: Refactor and simplify error checking in migrate_fd_put_ready Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/migration.c b/migration.c index 281fbaefd..ee4ef4ba6 100644 --- a/migration.c +++ b/migration.c @@ -372,23 +372,22 @@ static void migrate_fd_put_ready(void *opaque) DPRINTF("done iterating\n"); vm_stop(RUN_STATE_FINISH_MIGRATE); - if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) { + if (qemu_savevm_state_complete(s->mon, s->file) < 0) { + migrate_fd_error(s); + } else { + if (migrate_fd_cleanup(s) < 0) { + migrate_fd_error(s); + } else { + s->state = MIG_STATE_COMPLETED; + runstate_set(RUN_STATE_POSTMIGRATE); + notifier_list_notify(&migration_state_notifiers, NULL); + } + } + if (s->get_status(s) != MIG_STATE_COMPLETED) { if (old_vm_running) { vm_start(); } - s->state = MIG_STATE_ERROR; } - if (migrate_fd_cleanup(s) < 0) { - if (old_vm_running) { - vm_start(); - } - s->state = MIG_STATE_ERROR; - } - if (s->state == MIG_STATE_ACTIVE) { - s->state = MIG_STATE_COMPLETED; - runstate_set(RUN_STATE_POSTMIGRATE); - } - notifier_list_notify(&migration_state_notifiers, NULL); } } From 458cf28e6b01ff9b87a20d199d42b1c1c904cd29 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 22 Feb 2011 23:32:54 +0100 Subject: [PATCH 30/42] migration: Introduce migrate_fd_completed() for consistency This function is a bit different of the others that change the state, in the sense that if migrate_fd_cleanup() returns an error, it set the status to error, not completed. Signed-off-by: Juan Quintela --- migration.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/migration.c b/migration.c index ee4ef4ba6..a7c7b41b6 100644 --- a/migration.c +++ b/migration.c @@ -317,6 +317,18 @@ void migrate_fd_error(MigrationState *s) migrate_fd_cleanup(s); } +static void migrate_fd_completed(MigrationState *s) +{ + DPRINTF("setting completed state\n"); + if (migrate_fd_cleanup(s) < 0) { + s->state = MIG_STATE_ERROR; + } else { + s->state = MIG_STATE_COMPLETED; + runstate_set(RUN_STATE_POSTMIGRATE); + } + notifier_list_notify(&migration_state_notifiers, NULL); +} + static void migrate_fd_put_notify(void *opaque) { MigrationState *s = opaque; @@ -375,13 +387,7 @@ static void migrate_fd_put_ready(void *opaque) if (qemu_savevm_state_complete(s->mon, s->file) < 0) { migrate_fd_error(s); } else { - if (migrate_fd_cleanup(s) < 0) { - migrate_fd_error(s); - } else { - s->state = MIG_STATE_COMPLETED; - runstate_set(RUN_STATE_POSTMIGRATE); - notifier_list_notify(&migration_state_notifiers, NULL); - } + migrate_fd_completed(s); } if (s->get_status(s) != MIG_STATE_COMPLETED) { if (old_vm_running) { From 92920cd782d3b36bea64d79f162567c873882c4e Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 11 May 2010 23:18:34 +0200 Subject: [PATCH 31/42] migration: Our release callback was just free We called it from a single place, and always with state != MIG_STATE_ACTIVE. Just remove the whole callback. For users of the notifier, notice that this is exactly the case where they don't care, we are just freeing the state from previous failed migration (it can't be a sucessful one, otherwise we would not be running on that machine in the first place). Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration.c | 19 +------------------ migration.h | 1 - 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/migration.c b/migration.c index a7c7b41b6..400ffb789 100644 --- a/migration.c +++ b/migration.c @@ -123,10 +123,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) goto free_migrate_state; } - if (current_migration) { - current_migration->release(current_migration); - } - + g_free(current_migration); current_migration = s; notifier_list_notify(&migration_state_notifiers, NULL); return 0; @@ -416,19 +413,6 @@ static void migrate_fd_cancel(MigrationState *s) migrate_fd_cleanup(s); } -static void migrate_fd_release(MigrationState *s) -{ - - DPRINTF("releasing state\n"); - - if (s->state == MIG_STATE_ACTIVE) { - s->state = MIG_STATE_CANCELLED; - notifier_list_notify(&migration_state_notifiers, NULL); - migrate_fd_cleanup(s); - } - g_free(s); -} - static void migrate_fd_wait_for_unfreeze(void *opaque) { MigrationState *s = opaque; @@ -511,7 +495,6 @@ static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, s->cancel = migrate_fd_cancel; s->get_status = migrate_fd_get_status; - s->release = migrate_fd_release; s->blk = blk; s->shared = inc; s->mon = NULL; diff --git a/migration.h b/migration.h index fed1cf133..347f3217f 100644 --- a/migration.h +++ b/migration.h @@ -40,7 +40,6 @@ struct MigrationState int (*write)(MigrationState *s, const void *buff, size_t size); void (*cancel)(MigrationState *s); int (*get_status)(MigrationState *s); - void (*release)(MigrationState *s); void *opaque; int blk; int shared; From 48a2f4d6c567275b93f6d6ef7da555ab158b12d4 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 11 May 2010 23:28:53 +0200 Subject: [PATCH 32/42] migration: Remove get_status() accessor It is only used inside migration.c, and fields on that struct are accessed all around the place on that file. Signed-off-by: Juan Quintela --- migration.c | 16 +++++----------- migration.h | 1 - 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/migration.c b/migration.c index 400ffb789..8dbe8df10 100644 --- a/migration.c +++ b/migration.c @@ -91,7 +91,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) int ret; if (current_migration && - current_migration->get_status(current_migration) == MIG_STATE_ACTIVE) { + current_migration->state == MIG_STATE_ACTIVE) { monitor_printf(mon, "migration already in progress\n"); return -1; } @@ -136,7 +136,7 @@ int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data) { MigrationState *s = current_migration; - if (s && s->get_status(s) == MIG_STATE_ACTIVE) { + if (s && s->state == MIG_STATE_ACTIVE) { s->cancel(s); } return 0; @@ -235,7 +235,7 @@ void do_info_migrate(Monitor *mon, QObject **ret_data) if (current_migration) { MigrationState *s = current_migration; - switch (s->get_status(current_migration)) { + switch (s->state) { case MIG_STATE_SETUP: /* no migration has happened ever */ break; @@ -386,7 +386,7 @@ static void migrate_fd_put_ready(void *opaque) } else { migrate_fd_completed(s); } - if (s->get_status(s) != MIG_STATE_COMPLETED) { + if (s->state != MIG_STATE_COMPLETED) { if (old_vm_running) { vm_start(); } @@ -394,11 +394,6 @@ static void migrate_fd_put_ready(void *opaque) } } -static int migrate_fd_get_status(MigrationState *s) -{ - return s->state; -} - static void migrate_fd_cancel(MigrationState *s) { if (s->state != MIG_STATE_ACTIVE) @@ -460,7 +455,7 @@ void remove_migration_state_change_notifier(Notifier *notify) int get_migration_state(void) { if (current_migration) { - return migrate_fd_get_status(current_migration); + return current_migration->state; } else { return MIG_STATE_ERROR; } @@ -494,7 +489,6 @@ static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, MigrationState *s = g_malloc0(sizeof(*s)); s->cancel = migrate_fd_cancel; - s->get_status = migrate_fd_get_status; s->blk = blk; s->shared = inc; s->mon = NULL; diff --git a/migration.h b/migration.h index 347f3217f..6be3623ba 100644 --- a/migration.h +++ b/migration.h @@ -39,7 +39,6 @@ struct MigrationState int (*close)(MigrationState *s); int (*write)(MigrationState *s, const void *buff, size_t size); void (*cancel)(MigrationState *s); - int (*get_status)(MigrationState *s); void *opaque; int blk; int shared; From 767de722589c1e6e6926a421d1a8e110ad9b059f Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 11 May 2010 23:38:23 +0200 Subject: [PATCH 33/42] migration: Remove migration cancel() callback It is used only in one place Signed-off-by: Juan Quintela --- migration.c | 9 ++++----- migration.h | 1 - 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/migration.c b/migration.c index 8dbe8df10..31b6741c7 100644 --- a/migration.c +++ b/migration.c @@ -132,12 +132,12 @@ free_migrate_state: return -1; } +static void migrate_fd_cancel(MigrationState *s); + int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data) { - MigrationState *s = current_migration; - - if (s && s->state == MIG_STATE_ACTIVE) { - s->cancel(s); + if (current_migration) { + migrate_fd_cancel(current_migration); } return 0; } @@ -488,7 +488,6 @@ static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, { MigrationState *s = g_malloc0(sizeof(*s)); - s->cancel = migrate_fd_cancel; s->blk = blk; s->shared = inc; s->mon = NULL; diff --git a/migration.h b/migration.h index 6be3623ba..e1299b942 100644 --- a/migration.h +++ b/migration.h @@ -38,7 +38,6 @@ struct MigrationState int (*get_error)(MigrationState *s); int (*close)(MigrationState *s); int (*write)(MigrationState *s, const void *buff, size_t size); - void (*cancel)(MigrationState *s); void *opaque; int blk; int shared; From cab30143337c16881973a5ceda6476153bf98360 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 22 Feb 2011 23:54:21 +0100 Subject: [PATCH 34/42] migration: Move exported functions to the end of the file This means we can remove the two forward declarations. Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration.c | 187 +++++++++++++++++++++++++--------------------------- 1 file changed, 91 insertions(+), 96 deletions(-) diff --git a/migration.c b/migration.c index 31b6741c7..c852f2e9d 100644 --- a/migration.c +++ b/migration.c @@ -77,90 +77,6 @@ void process_incoming_migration(QEMUFile *f) } } -static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, - int detach, int blk, int inc); - -int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) -{ - MigrationState *s = NULL; - const char *p; - int detach = qdict_get_try_bool(qdict, "detach", 0); - int blk = qdict_get_try_bool(qdict, "blk", 0); - int inc = qdict_get_try_bool(qdict, "inc", 0); - const char *uri = qdict_get_str(qdict, "uri"); - int ret; - - if (current_migration && - current_migration->state == MIG_STATE_ACTIVE) { - monitor_printf(mon, "migration already in progress\n"); - return -1; - } - - if (qemu_savevm_state_blocked(mon)) { - return -1; - } - - s = migrate_new(mon, max_throttle, detach, blk, inc); - - if (strstart(uri, "tcp:", &p)) { - ret = tcp_start_outgoing_migration(s, p); -#if !defined(WIN32) - } else if (strstart(uri, "exec:", &p)) { - ret = exec_start_outgoing_migration(s, p); - } else if (strstart(uri, "unix:", &p)) { - ret = unix_start_outgoing_migration(s, p); - } else if (strstart(uri, "fd:", &p)) { - ret = fd_start_outgoing_migration(s, p); -#endif - } else { - monitor_printf(mon, "unknown migration protocol: %s\n", uri); - ret = -EINVAL; - goto free_migrate_state; - } - - if (ret < 0) { - monitor_printf(mon, "migration failed\n"); - goto free_migrate_state; - } - - g_free(current_migration); - current_migration = s; - notifier_list_notify(&migration_state_notifiers, NULL); - return 0; -free_migrate_state: - g_free(s); - return -1; -} - -static void migrate_fd_cancel(MigrationState *s); - -int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data) -{ - if (current_migration) { - migrate_fd_cancel(current_migration); - } - return 0; -} - -int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data) -{ - int64_t d; - MigrationState *s; - - d = qdict_get_int(qdict, "value"); - if (d < 0) { - d = 0; - } - max_throttle = d; - - s = current_migration; - if (s && s->file) { - qemu_file_set_rate_limit(s->file, max_throttle); - } - - return 0; -} - /* amount of nanoseconds we are willing to wait for migration to be down. * the choice of nanoseconds is because it is the maximum resolution that * get_clock() can achieve. It is an internal measure. All user-visible @@ -172,18 +88,6 @@ uint64_t migrate_max_downtime(void) return max_downtime; } -int do_migrate_set_downtime(Monitor *mon, const QDict *qdict, - QObject **ret_data) -{ - double d; - - d = qdict_get_double(qdict, "value") * 1e9; - d = MAX(0, MIN(UINT64_MAX, d)); - max_downtime = (uint64_t)d; - - return 0; -} - static void migrate_print_status(Monitor *mon, const char *name, const QDict *status_dict) { @@ -500,3 +404,94 @@ static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, return s; } + +int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + MigrationState *s = NULL; + const char *p; + int detach = qdict_get_try_bool(qdict, "detach", 0); + int blk = qdict_get_try_bool(qdict, "blk", 0); + int inc = qdict_get_try_bool(qdict, "inc", 0); + const char *uri = qdict_get_str(qdict, "uri"); + int ret; + + if (current_migration && + current_migration->state == MIG_STATE_ACTIVE) { + monitor_printf(mon, "migration already in progress\n"); + return -1; + } + + if (qemu_savevm_state_blocked(mon)) { + return -1; + } + + s = migrate_new(mon, max_throttle, detach, blk, inc); + + if (strstart(uri, "tcp:", &p)) { + ret = tcp_start_outgoing_migration(s, p); +#if !defined(WIN32) + } else if (strstart(uri, "exec:", &p)) { + ret = exec_start_outgoing_migration(s, p); + } else if (strstart(uri, "unix:", &p)) { + ret = unix_start_outgoing_migration(s, p); + } else if (strstart(uri, "fd:", &p)) { + ret = fd_start_outgoing_migration(s, p); +#endif + } else { + monitor_printf(mon, "unknown migration protocol: %s\n", uri); + ret = -EINVAL; + goto free_migrate_state; + } + + if (ret < 0) { + monitor_printf(mon, "migration failed\n"); + goto free_migrate_state; + } + + g_free(current_migration); + current_migration = s; + notifier_list_notify(&migration_state_notifiers, NULL); + return 0; +free_migrate_state: + g_free(s); + return -1; +} + +int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + if (current_migration) { + migrate_fd_cancel(current_migration); + } + return 0; +} + +int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + int64_t d; + MigrationState *s; + + d = qdict_get_int(qdict, "value"); + if (d < 0) { + d = 0; + } + max_throttle = d; + + s = current_migration; + if (s && s->file) { + qemu_file_set_rate_limit(s->file, max_throttle); + } + + return 0; +} + +int do_migrate_set_downtime(Monitor *mon, const QDict *qdict, + QObject **ret_data) +{ + double d; + + d = qdict_get_double(qdict, "value") * 1e9; + d = MAX(0, MIN(UINT64_MAX, d)); + max_downtime = (uint64_t)d; + + return 0; +} From 17549e84e0cccebf405a1994d70b0e0e5438fd8f Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 5 Oct 2011 13:50:43 +0200 Subject: [PATCH 35/42] migration: create accessor for current_migration Signed-off-by: Juan Quintela --- migration.c | 110 +++++++++++++++++++++++++--------------------------- 1 file changed, 52 insertions(+), 58 deletions(-) diff --git a/migration.c b/migration.c index c852f2e9d..bcc71b4fb 100644 --- a/migration.c +++ b/migration.c @@ -34,11 +34,22 @@ /* Migration speed throttling */ static int64_t max_throttle = (32 << 20); -static MigrationState *current_migration; - static NotifierList migration_state_notifiers = NOTIFIER_LIST_INITIALIZER(migration_state_notifiers); +/* When we add fault tolerance, we could have several + migrations at once. For now we don't need to add + dynamic creation of migration */ + +static MigrationState *migrate_get_current(void) +{ + static MigrationState current_migration = { + .state = MIG_STATE_SETUP, + }; + + return ¤t_migration; +} + int qemu_start_incoming_migration(const char *uri) { const char *p; @@ -135,39 +146,36 @@ static void migrate_put_status(QDict *qdict, const char *name, void do_info_migrate(Monitor *mon, QObject **ret_data) { QDict *qdict; + MigrationState *s = migrate_get_current(); - if (current_migration) { - MigrationState *s = current_migration; + switch (s->state) { + case MIG_STATE_SETUP: + /* no migration has happened ever */ + break; + case MIG_STATE_ACTIVE: + qdict = qdict_new(); + qdict_put(qdict, "status", qstring_from_str("active")); - switch (s->state) { - case MIG_STATE_SETUP: - /* no migration has happened ever */ - break; - case MIG_STATE_ACTIVE: - qdict = qdict_new(); - qdict_put(qdict, "status", qstring_from_str("active")); + migrate_put_status(qdict, "ram", ram_bytes_transferred(), + ram_bytes_remaining(), ram_bytes_total()); - migrate_put_status(qdict, "ram", ram_bytes_transferred(), - ram_bytes_remaining(), ram_bytes_total()); - - if (blk_mig_active()) { - migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(), - blk_mig_bytes_remaining(), - blk_mig_bytes_total()); - } - - *ret_data = QOBJECT(qdict); - break; - case MIG_STATE_COMPLETED: - *ret_data = qobject_from_jsonf("{ 'status': 'completed' }"); - break; - case MIG_STATE_ERROR: - *ret_data = qobject_from_jsonf("{ 'status': 'failed' }"); - break; - case MIG_STATE_CANCELLED: - *ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }"); - break; + if (blk_mig_active()) { + migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(), + blk_mig_bytes_remaining(), + blk_mig_bytes_total()); } + + *ret_data = QOBJECT(qdict); + break; + case MIG_STATE_COMPLETED: + *ret_data = qobject_from_jsonf("{ 'status': 'completed' }"); + break; + case MIG_STATE_ERROR: + *ret_data = qobject_from_jsonf("{ 'status': 'failed' }"); + break; + case MIG_STATE_CANCELLED: + *ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }"); + break; } } @@ -358,11 +366,7 @@ void remove_migration_state_change_notifier(Notifier *notify) int get_migration_state(void) { - if (current_migration) { - return current_migration->state; - } else { - return MIG_STATE_ERROR; - } + return migrate_get_current()->state; } void migrate_fd_connect(MigrationState *s) @@ -387,11 +391,12 @@ void migrate_fd_connect(MigrationState *s) migrate_fd_put_ready(s); } -static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, - int detach, int blk, int inc) +static MigrationState *migrate_init(Monitor *mon, int64_t bandwidth_limit, + int detach, int blk, int inc) { - MigrationState *s = g_malloc0(sizeof(*s)); + MigrationState *s = migrate_get_current(); + memset(s, 0, sizeof(*s)); s->blk = blk; s->shared = inc; s->mon = NULL; @@ -407,7 +412,7 @@ static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit, int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) { - MigrationState *s = NULL; + MigrationState *s = migrate_get_current(); const char *p; int detach = qdict_get_try_bool(qdict, "detach", 0); int blk = qdict_get_try_bool(qdict, "blk", 0); @@ -415,8 +420,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) const char *uri = qdict_get_str(qdict, "uri"); int ret; - if (current_migration && - current_migration->state == MIG_STATE_ACTIVE) { + if (s->state == MIG_STATE_ACTIVE) { monitor_printf(mon, "migration already in progress\n"); return -1; } @@ -425,7 +429,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) return -1; } - s = migrate_new(mon, max_throttle, detach, blk, inc); + s = migrate_init(mon, max_throttle, detach, blk, inc); if (strstart(uri, "tcp:", &p)) { ret = tcp_start_outgoing_migration(s, p); @@ -440,28 +444,20 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) } else { monitor_printf(mon, "unknown migration protocol: %s\n", uri); ret = -EINVAL; - goto free_migrate_state; } if (ret < 0) { - monitor_printf(mon, "migration failed\n"); - goto free_migrate_state; + monitor_printf(mon, "migration failed: %s\n", strerror(-ret)); + return ret; } - g_free(current_migration); - current_migration = s; notifier_list_notify(&migration_state_notifiers, NULL); return 0; -free_migrate_state: - g_free(s); - return -1; } int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data) { - if (current_migration) { - migrate_fd_cancel(current_migration); - } + migrate_fd_cancel(migrate_get_current()); return 0; } @@ -476,10 +472,8 @@ int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data) } max_throttle = d; - s = current_migration; - if (s && s->file) { - qemu_file_set_rate_limit(s->file, max_throttle); - } + s = migrate_get_current(); + qemu_file_set_rate_limit(s->file, max_throttle); return 0; } From d0ae46c1979ab3046d7ef748340ef736e47c088e Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 23 Feb 2011 00:33:19 +0100 Subject: [PATCH 36/42] migration: Use bandwidth_limit directly Now that current_migration always exist, there is no reason for max_throotle variable. Signed-off-by: Juan Quintela --- migration.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/migration.c b/migration.c index bcc71b4fb..3c989ad77 100644 --- a/migration.c +++ b/migration.c @@ -31,8 +31,7 @@ do { } while (0) #endif -/* Migration speed throttling */ -static int64_t max_throttle = (32 << 20); +#define MAX_THROTTLE (32 << 20) /* Migration speed throttling */ static NotifierList migration_state_notifiers = NOTIFIER_LIST_INITIALIZER(migration_state_notifiers); @@ -45,6 +44,7 @@ static MigrationState *migrate_get_current(void) { static MigrationState current_migration = { .state = MIG_STATE_SETUP, + .bandwidth_limit = MAX_THROTTLE, }; return ¤t_migration; @@ -391,12 +391,13 @@ void migrate_fd_connect(MigrationState *s) migrate_fd_put_ready(s); } -static MigrationState *migrate_init(Monitor *mon, int64_t bandwidth_limit, - int detach, int blk, int inc) +static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc) { MigrationState *s = migrate_get_current(); + int64_t bandwidth_limit = s->bandwidth_limit; memset(s, 0, sizeof(*s)); + s->bandwidth_limit = bandwidth_limit; s->blk = blk; s->shared = inc; s->mon = NULL; @@ -429,7 +430,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) return -1; } - s = migrate_init(mon, max_throttle, detach, blk, inc); + s = migrate_init(mon, detach, blk, inc); if (strstart(uri, "tcp:", &p)) { ret = tcp_start_outgoing_migration(s, p); @@ -470,10 +471,10 @@ int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data) if (d < 0) { d = 0; } - max_throttle = d; s = migrate_get_current(); - qemu_file_set_rate_limit(s->file, max_throttle); + s->bandwidth_limit = d; + qemu_file_set_rate_limit(s->file, s->bandwidth_limit); return 0; } From e0eb7390b02228d44e873a2071593af9ce7cac82 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 5 Oct 2011 14:27:52 +0200 Subject: [PATCH 37/42] migration: Pass MigrationState in migration notifiers Signed-off-by: Juan Quintela --- migration.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/migration.c b/migration.c index 3c989ad77..46db37b19 100644 --- a/migration.c +++ b/migration.c @@ -222,7 +222,7 @@ void migrate_fd_error(MigrationState *s) { DPRINTF("setting error state\n"); s->state = MIG_STATE_ERROR; - notifier_list_notify(&migration_state_notifiers, NULL); + notifier_list_notify(&migration_state_notifiers, s); migrate_fd_cleanup(s); } @@ -235,7 +235,7 @@ static void migrate_fd_completed(MigrationState *s) s->state = MIG_STATE_COMPLETED; runstate_set(RUN_STATE_POSTMIGRATE); } - notifier_list_notify(&migration_state_notifiers, NULL); + notifier_list_notify(&migration_state_notifiers, s); } static void migrate_fd_put_notify(void *opaque) @@ -314,7 +314,7 @@ static void migrate_fd_cancel(MigrationState *s) DPRINTF("cancelling migration\n"); s->state = MIG_STATE_CANCELLED; - notifier_list_notify(&migration_state_notifiers, NULL); + notifier_list_notify(&migration_state_notifiers, s); qemu_savevm_state_cancel(s->mon, s->file); migrate_fd_cleanup(s); @@ -452,7 +452,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) return ret; } - notifier_list_notify(&migration_state_notifiers, NULL); + notifier_list_notify(&migration_state_notifiers, s); return 0; } From 7073693bfbde541eca0cc778e1b2c30d43a65c4b Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 23 Feb 2011 00:43:59 +0100 Subject: [PATCH 38/42] migration: Export a function that tells if the migration has finished correctly This will allow us to hide the state values. Signed-off-by: Juan Quintela --- migration.c | 4 ++-- migration.h | 2 +- ui/spice-core.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/migration.c b/migration.c index 46db37b19..b5929db7e 100644 --- a/migration.c +++ b/migration.c @@ -364,9 +364,9 @@ void remove_migration_state_change_notifier(Notifier *notify) notifier_list_remove(&migration_state_notifiers, notify); } -int get_migration_state(void) +bool migration_has_finished(MigrationState *s) { - return migrate_get_current()->state; + return s->state == MIG_STATE_COMPLETED; } void migrate_fd_connect(MigrationState *s) diff --git a/migration.h b/migration.h index e1299b942..23d347ae9 100644 --- a/migration.h +++ b/migration.h @@ -84,7 +84,7 @@ void migrate_fd_connect(MigrationState *s); void add_migration_state_change_notifier(Notifier *notify); void remove_migration_state_change_notifier(Notifier *notify); -int get_migration_state(void); +bool migration_has_finished(MigrationState *); uint64_t ram_bytes_remaining(void); uint64_t ram_bytes_transferred(void); diff --git a/ui/spice-core.c b/ui/spice-core.c index 3cbc721ee..b33366e5d 100644 --- a/ui/spice-core.c +++ b/ui/spice-core.c @@ -447,9 +447,9 @@ void do_info_spice(Monitor *mon, QObject **ret_data) static void migration_state_notifier(Notifier *notifier, void *data) { - int state = get_migration_state(); + MigrationState *s = data; - if (state == MIG_STATE_COMPLETED) { + if (migration_has_finished(s)) { #if SPICE_SERVER_VERSION >= 0x000701 /* 0.7.1 */ spice_server_migrate_switch(spice_server); #endif From 7dc688ed71ff7b8509d4bf8bdc4c4cb6c25a9917 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 23 Feb 2011 00:48:46 +0100 Subject: [PATCH 39/42] migration: Make state definitions local Signed-off-by: Juan Quintela --- migration.c | 8 ++++++++ migration.h | 8 -------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/migration.c b/migration.c index b5929db7e..3db12ef11 100644 --- a/migration.c +++ b/migration.c @@ -31,6 +31,14 @@ do { } while (0) #endif +enum { + MIG_STATE_ERROR, + MIG_STATE_SETUP, + MIG_STATE_CANCELLED, + MIG_STATE_ACTIVE, + MIG_STATE_COMPLETED, +}; + #define MAX_THROTTLE (32 << 20) /* Migration speed throttling */ static NotifierList migration_state_notifiers = diff --git a/migration.h b/migration.h index 23d347ae9..a1f80d072 100644 --- a/migration.h +++ b/migration.h @@ -18,14 +18,6 @@ #include "qemu-common.h" #include "notify.h" -enum { - MIG_STATE_ERROR, - MIG_STATE_SETUP, - MIG_STATE_CANCELLED, - MIG_STATE_ACTIVE, - MIG_STATE_COMPLETED, -}; - typedef struct MigrationState MigrationState; struct MigrationState From efab4718f4203132244758fbc76b8b0676b9d85d Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 23 Feb 2011 11:52:12 +0100 Subject: [PATCH 40/42] migration: Don't use callback on file defining it Signed-off-by: Juan Quintela --- migration-tcp.c | 4 ++-- migration-unix.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/migration-tcp.c b/migration-tcp.c index f6b228820..bd3aa3a4a 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -58,7 +58,7 @@ static void tcp_wait_for_connect(void *opaque) DPRINTF("connect completed\n"); do { ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize); - } while (ret == -1 && (s->get_error(s)) == EINTR); + } while (ret == -1 && (socket_error()) == EINTR); if (ret < 0) { migrate_fd_error(s); @@ -98,7 +98,7 @@ int tcp_start_outgoing_migration(MigrationState *s, const char *host_port) do { ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr)); if (ret == -1) - ret = -(s->get_error(s)); + ret = -(socket_error()); if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s); diff --git a/migration-unix.c b/migration-unix.c index bd8d40fe7..ca6685101 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -57,7 +57,7 @@ static void unix_wait_for_connect(void *opaque) DPRINTF("connect completed\n"); do { ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, (void *) &val, &valsize); - } while (ret == -1 && (s->get_error(s)) == EINTR); + } while (ret == -1 && errno == EINTR); if (ret < 0) { migrate_fd_error(s); @@ -96,7 +96,7 @@ int unix_start_outgoing_migration(MigrationState *s, const char *path) do { ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr)); if (ret == -1) - ret = -(s->get_error(s)); + ret = -errno; if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) qemu_set_fd_handler2(s->fd, NULL, NULL, unix_wait_for_connect, s); @@ -129,7 +129,7 @@ static void unix_accept_incoming_migration(void *opaque) do { c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen); - } while (c == -1 && socket_error() == EINTR); + } while (c == -1 && errno == EINTR); DPRINTF("accepted migration\n"); From 8414ff3bd8bfafbcb632c670f4d81c8e4f15e703 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 23 Feb 2011 19:56:52 +0100 Subject: [PATCH 41/42] migration: propagate error correctly unix and tcp outgoing migration have error values, but didn't returned it. Make them return the error. Notice that EINPROGRESS & EWOULDBLOCK are not considered errors as call will be retry later. Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration-tcp.c | 20 +++++++++++--------- migration-unix.c | 26 ++++++++++---------------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/migration-tcp.c b/migration-tcp.c index bd3aa3a4a..619df2108 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -90,26 +90,28 @@ int tcp_start_outgoing_migration(MigrationState *s, const char *host_port) s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (s->fd == -1) { - return -1; + return -socket_error(); } socket_set_nonblock(s->fd); do { ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr)); - if (ret == -1) - ret = -(socket_error()); - - if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) + if (ret == -1) { + ret = -socket_error(); + } + if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) { qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s); + return 0; + } } while (ret == -EINTR); - if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) { + if (ret < 0) { DPRINTF("connect failed\n"); migrate_fd_error(s); - } else if (ret >= 0) - migrate_fd_connect(s); - + return ret; + } + migrate_fd_connect(s); return 0; } diff --git a/migration-unix.c b/migration-unix.c index ca6685101..f979b5fb9 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -88,35 +88,29 @@ int unix_start_outgoing_migration(MigrationState *s, const char *path) s->fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0); if (s->fd < 0) { DPRINTF("Unable to open socket"); - goto err_after_socket; + return -errno; } socket_set_nonblock(s->fd); do { ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr)); - if (ret == -1) + if (ret == -1) { ret = -errno; - - if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) + } + if (ret == -EINPROGRESS || ret == -EWOULDBLOCK) { qemu_set_fd_handler2(s->fd, NULL, NULL, unix_wait_for_connect, s); + return 0; + } } while (ret == -EINTR); - if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) { + if (ret < 0) { DPRINTF("connect failed\n"); - goto err_after_open; + migrate_fd_error(s); + return ret; } - - if (ret >= 0) - migrate_fd_connect(s); - + migrate_fd_connect(s); return 0; - -err_after_open: - close(s->fd); - -err_after_socket: - return -1; } static void unix_accept_incoming_migration(void *opaque) From ee86c61f285042386c0a27edf69300627a1987b4 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Wed, 23 Feb 2011 20:44:29 +0100 Subject: [PATCH 42/42] migration: make migration-{tcp,unix} consistent Files are almost identical in functionality, just remove the differences that make no sense. Signed-off-by: Juan Quintela Reviewed-by: Anthony Liguori --- migration-tcp.c | 15 ++++++++++----- migration-unix.c | 46 +++++++++++++++++++++++++--------------------- 2 files changed, 35 insertions(+), 26 deletions(-) diff --git a/migration-tcp.c b/migration-tcp.c index 619df2108..5aa742c34 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -48,7 +48,6 @@ static int tcp_close(MigrationState *s) return 0; } - static void tcp_wait_for_connect(void *opaque) { MigrationState *s = opaque; @@ -84,12 +83,14 @@ int tcp_start_outgoing_migration(MigrationState *s, const char *host_port) if (ret < 0) { return ret; } + s->get_error = socket_errno; s->write = socket_write; s->close = tcp_close; s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0); if (s->fd == -1) { + DPRINTF("Unable to open socket"); return -socket_error(); } @@ -155,23 +156,27 @@ int tcp_start_incoming_migration(const char *host_port) int val; int s; + DPRINTF("Attempting to start an incoming migration\n"); + if (parse_host_port(&addr, host_port) < 0) { fprintf(stderr, "invalid host/port combination: %s\n", host_port); return -EINVAL; } s = qemu_socket(PF_INET, SOCK_STREAM, 0); - if (s == -1) + if (s == -1) { return -socket_error(); + } val = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); - if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) + if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) { goto err; - - if (listen(s, 1) == -1) + } + if (listen(s, 1) == -1) { goto err; + } qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL, (void *)(intptr_t)s); diff --git a/migration-unix.c b/migration-unix.c index f979b5fb9..8596353d7 100644 --- a/migration-unix.c +++ b/migration-unix.c @@ -86,7 +86,7 @@ int unix_start_outgoing_migration(MigrationState *s, const char *path) s->close = unix_close; s->fd = qemu_socket(PF_UNIX, SOCK_STREAM, 0); - if (s->fd < 0) { + if (s->fd == -1) { DPRINTF("Unable to open socket"); return -errno; } @@ -129,7 +129,7 @@ static void unix_accept_incoming_migration(void *opaque) if (c == -1) { fprintf(stderr, "could not accept migration connection\n"); - return; + goto out2; } f = qemu_fopen_socket(c); @@ -141,45 +141,49 @@ static void unix_accept_incoming_migration(void *opaque) process_incoming_migration(f); qemu_fclose(f); out: + close(c); +out2: qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL); close(s); - close(c); } int unix_start_incoming_migration(const char *path) { - struct sockaddr_un un; - int sock; + struct sockaddr_un addr; + int s; + int ret; DPRINTF("Attempting to start an incoming migration\n"); - sock = qemu_socket(PF_UNIX, SOCK_STREAM, 0); - if (sock < 0) { + s = qemu_socket(PF_UNIX, SOCK_STREAM, 0); + if (s == -1) { fprintf(stderr, "Could not open unix socket: %s\n", strerror(errno)); - return -EINVAL; + return -errno; } - memset(&un, 0, sizeof(un)); - un.sun_family = AF_UNIX; - snprintf(un.sun_path, sizeof(un.sun_path), "%s", path); + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path); - unlink(un.sun_path); - if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) { - fprintf(stderr, "bind(unix:%s): %s\n", un.sun_path, strerror(errno)); + unlink(addr.sun_path); + if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) { + ret = -errno; + fprintf(stderr, "bind(unix:%s): %s\n", addr.sun_path, strerror(errno)); goto err; } - if (listen(sock, 1) < 0) { - fprintf(stderr, "listen(unix:%s): %s\n", un.sun_path, strerror(errno)); + if (listen(s, 1) == -1) { + fprintf(stderr, "listen(unix:%s): %s\n", addr.sun_path, + strerror(errno)); + ret = -errno; goto err; } - qemu_set_fd_handler2(sock, NULL, unix_accept_incoming_migration, NULL, - (void *)(intptr_t)sock); + qemu_set_fd_handler2(s, NULL, unix_accept_incoming_migration, NULL, + (void *)(intptr_t)s); return 0; err: - close(sock); - - return -EINVAL; + close(s); + return ret; }