diff --git a/migration/colo.c b/migration/colo.c index 79fa1f6619..e3b1f136f4 100644 --- a/migration/colo.c +++ b/migration/colo.c @@ -152,7 +152,7 @@ static void primary_vm_do_failover(void) * kick COLO thread which might wait at * qemu_sem_wait(&s->colo_checkpoint_sem). */ - colo_checkpoint_notify(migrate_get_current()); + colo_checkpoint_notify(s); /* * Wake up COLO thread which may blocked in recv() or send(), @@ -205,7 +205,7 @@ void colo_do_failover(void) vm_stop_force_state(RUN_STATE_COLO); } - switch (get_colo_mode()) { + switch (last_colo_mode = get_colo_mode()) { case COLO_MODE_PRIMARY: primary_vm_do_failover(); break; @@ -530,8 +530,7 @@ static void colo_process_checkpoint(MigrationState *s) Error *local_err = NULL; int ret; - last_colo_mode = get_colo_mode(); - if (last_colo_mode != COLO_MODE_PRIMARY) { + if (get_colo_mode() != COLO_MODE_PRIMARY) { error_report("COLO mode must be COLO_MODE_PRIMARY"); return; } @@ -640,6 +639,7 @@ out: */ if (s->rp_state.from_dst_file) { qemu_fclose(s->rp_state.from_dst_file); + s->rp_state.from_dst_file = NULL; } } @@ -829,8 +829,7 @@ void *colo_process_incoming_thread(void *opaque) migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE, MIGRATION_STATUS_COLO); - last_colo_mode = get_colo_mode(); - if (last_colo_mode != COLO_MODE_SECONDARY) { + if (get_colo_mode() != COLO_MODE_SECONDARY) { error_report("COLO mode must be COLO_MODE_SECONDARY"); return NULL; } @@ -918,11 +917,6 @@ out: /* Hope this not to be too long to loop here */ qemu_sem_wait(&mis->colo_incoming_sem); qemu_sem_destroy(&mis->colo_incoming_sem); - /* Must be called after failover BH is completed */ - if (mis->to_src_file) { - qemu_fclose(mis->to_src_file); - mis->to_src_file = NULL; - } rcu_unregister_thread(); return NULL; diff --git a/migration/migration.c b/migration/migration.c index 53b9a8af96..abaf6f9e3d 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -215,8 +215,11 @@ void migration_object_init(void) dirty_bitmap_mig_init(); } -void migration_cancel(void) +void migration_cancel(const Error *error) { + if (error) { + migrate_set_error(current_migration, error); + } migrate_fd_cancel(current_migration); } @@ -226,7 +229,7 @@ void migration_shutdown(void) * Cancel the current migration - that will (eventually) * stop the migration using this structure */ - migration_cancel(); + migration_cancel(NULL); object_unref(OBJECT(current_migration)); /* @@ -587,8 +590,10 @@ static void process_incoming_migration_co(void *opaque) mis->have_colo_incoming_thread = true; qemu_coroutine_yield(); + qemu_mutex_unlock_iothread(); /* Wait checkpoint incoming thread exit before free resource */ qemu_thread_join(&mis->colo_incoming_thread); + qemu_mutex_lock_iothread(); /* We hold the global iothread lock, so it is safe here */ colo_release_ram_cache(); } @@ -2268,10 +2273,11 @@ static bool migrate_prepare(MigrationState *s, bool blk, bool blk_inc, migrate_init(s); /* - * set ram_counters memory to zero for a + * set ram_counters compression_counters memory to zero for a * new migration */ memset(&ram_counters, 0, sizeof(ram_counters)); + memset(&compression_counters, 0, sizeof(compression_counters)); return true; } @@ -2334,7 +2340,7 @@ void qmp_migrate(const char *uri, bool has_blk, bool blk, void qmp_migrate_cancel(Error **errp) { - migration_cancel(); + migration_cancel(NULL); } void qmp_migrate_continue(MigrationStatus state, Error **errp) @@ -3622,7 +3628,9 @@ static void migration_iteration_finish(MigrationState *s) case MIGRATION_STATUS_CANCELLED: case MIGRATION_STATUS_CANCELLING: if (s->vm_was_running) { - vm_start(); + if (!runstate_check(RUN_STATE_SHUTDOWN)) { + vm_start(); + } } else { if (runstate_check(RUN_STATE_FINISH_MIGRATE)) { runstate_set(RUN_STATE_POSTMIGRATE); diff --git a/migration/migration.h b/migration/migration.h index 7a5aa8c2fd..8130b703eb 100644 --- a/migration/migration.h +++ b/migration/migration.h @@ -388,7 +388,7 @@ int foreach_not_ignored_block(RAMBlockIterFunc func, void *opaque); void migration_make_urgent_request(void); void migration_consume_urgent_request(void); bool migration_rate_limit(void); -void migration_cancel(void); +void migration_cancel(const Error *error); void populate_vfio_info(MigrationInfo *info); diff --git a/migration/ram.c b/migration/ram.c index 680a5158aa..847af461f2 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -56,6 +56,8 @@ #include "multifd.h" #include "sysemu/runstate.h" +#include "hw/boards.h" /* for machine_dump_guest_core() */ + #if defined(__linux__) #include "qemu/userfaultfd.h" #endif /* defined(__linux__) */ @@ -3542,6 +3544,10 @@ int colo_init_ram_cache(void) } return -errno; } + if (!machine_dump_guest_core(current_machine)) { + qemu_madvise(block->colo_cache, block->used_length, + QEMU_MADV_DONTDUMP); + } } } @@ -4323,9 +4329,8 @@ static void ram_mig_ram_block_resized(RAMBlockNotifier *n, void *host, * Abort and indicate a proper reason. */ error_setg(&err, "RAM block '%s' resized during precopy.", rb->idstr); - migrate_set_error(migrate_get_current(), err); + migration_cancel(err); error_free(err); - migration_cancel(); } switch (ps) { diff --git a/migration/savevm.c b/migration/savevm.c index 7b7b64bd13..d59e976d50 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -1567,6 +1567,7 @@ static int qemu_savevm_state(QEMUFile *f, Error **errp) migrate_init(ms); memset(&ram_counters, 0, sizeof(ram_counters)); + memset(&compression_counters, 0, sizeof(compression_counters)); ms->to_dst_file = f; qemu_mutex_unlock_iothread(); diff --git a/net/colo-compare.c b/net/colo-compare.c index b100e7b51f..b8876d7fd9 100644 --- a/net/colo-compare.c +++ b/net/colo-compare.c @@ -170,7 +170,7 @@ static bool packet_matches_str(const char *str, return false; } - return !memcmp(str, buf, strlen(str)); + return !memcmp(str, buf, packet_len); } static void notify_remote_frame(CompareState *s) @@ -264,7 +264,7 @@ static int packet_enqueue(CompareState *s, int mode, Connection **con) pkt = NULL; return -1; } - fill_connection_key(pkt, &key); + fill_connection_key(pkt, &key, false); conn = connection_get(s->connection_track_table, &key, diff --git a/net/colo.c b/net/colo.c index 3a3e6e89a0..1f8162f59f 100644 --- a/net/colo.c +++ b/net/colo.c @@ -83,19 +83,26 @@ int parse_packet_early(Packet *pkt) return 0; } -void extract_ip_and_port(uint32_t tmp_ports, ConnectionKey *key, Packet *pkt) +void extract_ip_and_port(uint32_t tmp_ports, ConnectionKey *key, + Packet *pkt, bool reverse) { + if (reverse) { + key->src = pkt->ip->ip_dst; + key->dst = pkt->ip->ip_src; + key->src_port = ntohs(tmp_ports & 0xffff); + key->dst_port = ntohs(tmp_ports >> 16); + } else { key->src = pkt->ip->ip_src; key->dst = pkt->ip->ip_dst; key->src_port = ntohs(tmp_ports >> 16); key->dst_port = ntohs(tmp_ports & 0xffff); + } } -void fill_connection_key(Packet *pkt, ConnectionKey *key) +void fill_connection_key(Packet *pkt, ConnectionKey *key, bool reverse) { - uint32_t tmp_ports; + uint32_t tmp_ports = 0; - memset(key, 0, sizeof(*key)); key->ip_proto = pkt->ip->ip_p; switch (key->ip_proto) { @@ -106,29 +113,15 @@ void fill_connection_key(Packet *pkt, ConnectionKey *key) case IPPROTO_SCTP: case IPPROTO_UDPLITE: tmp_ports = *(uint32_t *)(pkt->transport_header); - extract_ip_and_port(tmp_ports, key, pkt); break; case IPPROTO_AH: tmp_ports = *(uint32_t *)(pkt->transport_header + 4); - extract_ip_and_port(tmp_ports, key, pkt); break; default: break; } -} -void reverse_connection_key(ConnectionKey *key) -{ - struct in_addr tmp_ip; - uint16_t tmp_port; - - tmp_ip = key->src; - key->src = key->dst; - key->dst = tmp_ip; - - tmp_port = key->src_port; - key->src_port = key->dst_port; - key->dst_port = tmp_port; + extract_ip_and_port(tmp_ports, key, pkt, reverse); } Connection *connection_new(ConnectionKey *key) diff --git a/net/colo.h b/net/colo.h index d91cd245c4..8b3e8d5a83 100644 --- a/net/colo.h +++ b/net/colo.h @@ -89,9 +89,9 @@ typedef struct Connection { uint32_t connection_key_hash(const void *opaque); int connection_key_equal(const void *opaque1, const void *opaque2); int parse_packet_early(Packet *pkt); -void extract_ip_and_port(uint32_t tmp_ports, ConnectionKey *key, Packet *pkt); -void fill_connection_key(Packet *pkt, ConnectionKey *key); -void reverse_connection_key(ConnectionKey *key); +void extract_ip_and_port(uint32_t tmp_ports, ConnectionKey *key, + Packet *pkt, bool reverse); +void fill_connection_key(Packet *pkt, ConnectionKey *key, bool reverse); Connection *connection_new(ConnectionKey *key); void connection_destroy(void *opaque); Connection *connection_get(GHashTable *connection_track_table, diff --git a/net/filter-rewriter.c b/net/filter-rewriter.c index cb3a96cde1..bf05023dc3 100644 --- a/net/filter-rewriter.c +++ b/net/filter-rewriter.c @@ -279,15 +279,7 @@ static ssize_t colo_rewriter_receive_iov(NetFilterState *nf, */ if (pkt && is_tcp_packet(pkt)) { - fill_connection_key(pkt, &key); - - if (sender == nf->netdev) { - /* - * We need make tcp TX and RX packet - * into one connection. - */ - reverse_connection_key(&key); - } + fill_connection_key(pkt, &key, sender == nf->netdev); /* After failover we needn't change new TCP packet */ if (s->failover_mode &&