Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge tag 'migration-20230530-pull-request' of https://gitlab.com/jua…
…n.quintela/qemu into staging

Migration 20230530 Pull request

Hi

On this PULL request:

- Set vmstate migration failure right (vladimir)
- Migration QEMUFileHook removal (juan)
- Migration Atomic counters (juan)

Please apply.

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEGJn/jt6/WMzuA0uC9IfvGFhy1yMFAmR14+wACgkQ9IfvGFhy
# 1yNNCg/9EjKE4RGPdHxSxNudnLCkR2M3+XAJ0REw88+K2rbJgEU2iok3Ya+BzBes
# 6dbzCJ6mEFnGGmtAWCoPvrWdlaXCwiGzHMGTrrS2tHoV9REujG1nmdHhHW0M81x4
# RdWoRpOvirPYk1ZumlK8RBEBiEGvzSYxtEc+B3GW9WGs/SFhRVZPCU8rDK01U1pS
# ZjnD/Cg6IsAuJdK3nmdDpqaAqZNTtsRO3bquPSUrQqGGSAnZiuZAY2OUz04qBWA8
# DH7tmg1pLooyHyibn9XvsROKmmaEECVMUwndg3U6610weXJNtJUKcOSSRKEkxRrQ
# mYS2iRJTFhgML8E1Jzn8PK2Ojhr2i4IT6jxFOjVX30bDJamLT3uplzdeciMJnPtX
# qFDMva/hjhH4Dr385G167peIAzX3c3STeP2RWKET4iOUqqLsMa+BLB+2Ca21HixE
# tOx/W6Fj+d3OQ0K0NF57tQWV6Sc+Dr372oWGYqClqqQBzTUqYQ4t1L6HDZapF2em
# 8khrkVjDxcYK3pZa6i3eA6i120+AeT2e5Ox9Ow37pgphucZA3lT/E701e8h+VHk8
# ONp/Vmwby4troOU3LIkGFWHyEsCnf735ttXSJ3MCszPzabTh04U4tGNSUmppqEFI
# tADbIm/J2P0azf5pqONVeXVfuCYAWsEzUHq2KCtYk0OfxysMDes=
# =fdBo
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 30 May 2023 04:54:20 AM PDT
# gpg:                using RSA key 1899FF8EDEBF58CCEE034B82F487EF185872D723
# gpg: Good signature from "Juan Quintela <quintela@redhat.com>" [undefined]
# gpg:                 aka "Juan Quintela <quintela@trasno.org>" [undefined]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 1899 FF8E DEBF 58CC EE03  4B82 F487 EF18 5872 D723

* tag 'migration-20230530-pull-request' of https://gitlab.com/juan.quintela/qemu: (21 commits)
  migration/rdma: Check sooner if we are in postcopy for save_page()
  migration/rdma: Remove qemu_ prefix from exported functions
  migration/rdma: Move rdma constants from qemu-file.h to rdma.h
  qemu-file: Remove QEMUFileHooks
  migration/rdma: Create rdma_control_save_page()
  migration/rdma: Unfold hook_ram_load()
  migration/rdma: Remove all uses of RAM_CONTROL_HOOK
  migration/rdma: Unfold ram_control_after_iterate()
  migration/rdma: Unfold ram_control_before_iterate()
  migration: Create migrate_rdma()
  migration/rdma: Simplify the function that saves a page
  migration: Remove unused qemu_file_credit_transfer()
  migration/rdma: Don't use imaginary transfers
  migration/rdma: Remove QEMUFile parameter when not used
  migration/RDMA: It is accounting for zero/normal pages in two places
  migration: Don't abuse qemu_file transferred for RDMA
  migration: restore vmstate on migration failure
  migration: switch from .vm_was_running to .vm_old_state
  runstate: drop unused runstate_store()
  migration: never fail in global_state_store()
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed May 30, 2023
2 parents aa9bbd8 + d83da46 commit a4423a3
Show file tree
Hide file tree
Showing 17 changed files with 258 additions and 329 deletions.
2 changes: 1 addition & 1 deletion include/migration/global_state.h
Expand Up @@ -16,7 +16,7 @@
#include "qapi/qapi-types-run-state.h"

void register_global_state(void);
int global_state_store(void);
void global_state_store(void);
void global_state_store_running(void);
bool global_state_received(void);
RunState global_state_get_runstate(void);
Expand Down
2 changes: 1 addition & 1 deletion include/sysemu/runstate.h
Expand Up @@ -6,9 +6,9 @@

bool runstate_check(RunState state);
void runstate_set(RunState new_state);
RunState runstate_get(void);
bool runstate_is_running(void);
bool runstate_needs_reset(void);
bool runstate_store(char *str, size_t size);

typedef void VMChangeStateHandler(void *opaque, bool running, RunState state);

Expand Down
23 changes: 11 additions & 12 deletions migration/global_state.c
Expand Up @@ -29,23 +29,22 @@ typedef struct {

static GlobalState global_state;

int global_state_store(void)
static void global_state_do_store(RunState state)
{
if (!runstate_store((char *)global_state.runstate,
sizeof(global_state.runstate))) {
error_report("runstate name too big: %s", global_state.runstate);
trace_migrate_state_too_big();
return -EINVAL;
}
return 0;
const char *state_str = RunState_str(state);
assert(strlen(state_str) < sizeof(global_state.runstate));
strpadcpy((char *)global_state.runstate, sizeof(global_state.runstate),
state_str, '\0');
}

void global_state_store(void)
{
global_state_do_store(runstate_get());
}

void global_state_store_running(void)
{
const char *state = RunState_str(RUN_STATE_RUNNING);
assert(strlen(state) < sizeof(global_state.runstate));
strpadcpy((char *)global_state.runstate, sizeof(global_state.runstate),
state, '\0');
global_state_do_store(RUN_STATE_RUNNING);
}

bool global_state_received(void)
Expand Down
5 changes: 3 additions & 2 deletions migration/migration-stats.c
Expand Up @@ -61,8 +61,9 @@ void migration_rate_reset(QEMUFile *f)
uint64_t migration_transferred_bytes(QEMUFile *f)
{
uint64_t multifd = stat64_get(&mig_stats.multifd_bytes);
uint64_t rdma = stat64_get(&mig_stats.rdma_bytes);
uint64_t qemu_file = qemu_file_transferred(f);

trace_migration_transferred_bytes(qemu_file, multifd);
return qemu_file + multifd;
trace_migration_transferred_bytes(qemu_file, multifd, rdma);
return qemu_file + multifd + rdma;
}
4 changes: 4 additions & 0 deletions migration/migration-stats.h
Expand Up @@ -89,6 +89,10 @@ typedef struct {
* Maximum amount of data we can send in a cycle.
*/
Stat64 rate_limit_max;
/*
* Number of bytes sent through RDMA.
*/
Stat64 rdma_bytes;
/*
* Total number of bytes transferred.
*/
Expand Down
57 changes: 28 additions & 29 deletions migration/migration.c
Expand Up @@ -1402,9 +1402,10 @@ void migrate_init(MigrationState *s)

s->start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
s->total_time = 0;
s->vm_was_running = false;
s->vm_old_state = -1;
s->iteration_initial_bytes = 0;
s->threshold_size = 0;
s->rdma_migration = false;
}

int migrate_add_blocker_internal(Error *reason, Error **errp)
Expand Down Expand Up @@ -2287,28 +2288,28 @@ static void migration_completion(MigrationState *s)
qemu_mutex_lock_iothread();
s->downtime_start = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
s->vm_was_running = runstate_is_running();
ret = global_state_store();

if (!ret) {
ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
trace_migration_completion_vm_stop(ret);
if (ret >= 0) {
ret = migration_maybe_pause(s, &current_active_state,
MIGRATION_STATUS_DEVICE);
}
if (ret >= 0) {
/*
* Inactivate disks except in COLO, and track that we
* have done so in order to remember to reactivate
* them if migration fails or is cancelled.
*/
s->block_inactive = !migrate_colo();
migration_rate_set(RATE_LIMIT_DISABLED);
ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false,
s->block_inactive);
}

s->vm_old_state = runstate_get();
global_state_store();

ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE);
trace_migration_completion_vm_stop(ret);
if (ret >= 0) {
ret = migration_maybe_pause(s, &current_active_state,
MIGRATION_STATUS_DEVICE);
}
if (ret >= 0) {
/*
* Inactivate disks except in COLO, and track that we
* have done so in order to remember to reactivate
* them if migration fails or is cancelled.
*/
s->block_inactive = !migrate_colo();
migration_rate_set(RATE_LIMIT_DISABLED);
ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false,
s->block_inactive);
}

qemu_mutex_unlock_iothread();

if (ret < 0) {
Expand Down Expand Up @@ -2761,18 +2762,18 @@ static void migration_iteration_finish(MigrationState *s)
case MIGRATION_STATUS_COLO:
assert(migrate_colo());
migrate_start_colo_process(s);
s->vm_was_running = true;
s->vm_old_state = RUN_STATE_RUNNING;
/* Fallthrough */
case MIGRATION_STATUS_FAILED:
case MIGRATION_STATUS_CANCELLED:
case MIGRATION_STATUS_CANCELLING:
if (s->vm_was_running) {
if (s->vm_old_state == RUN_STATE_RUNNING) {
if (!runstate_check(RUN_STATE_SHUTDOWN)) {
vm_start();
}
} else {
if (runstate_check(RUN_STATE_FINISH_MIGRATE)) {
runstate_set(RUN_STATE_POSTMIGRATE);
runstate_set(s->vm_old_state);
}
}
break;
Expand Down Expand Up @@ -3086,11 +3087,9 @@ static void *bg_migration_thread(void *opaque)
* transition in vm_stop_force_state() we need to wakeup it up.
*/
qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, NULL);
s->vm_was_running = runstate_is_running();
s->vm_old_state = runstate_get();

if (global_state_store()) {
goto fail;
}
global_state_store();
/* Forcibly stop VM before saving state of vCPUs and devices */
if (vm_stop_force_state(RUN_STATE_PAUSED)) {
goto fail;
Expand Down
12 changes: 9 additions & 3 deletions migration/migration.h
Expand Up @@ -25,6 +25,7 @@
#include "net/announce.h"
#include "qom/object.h"
#include "postcopy-ram.h"
#include "sysemu/runstate.h"

struct PostcopyBlocktimeContext;

Expand Down Expand Up @@ -317,12 +318,14 @@ struct MigrationState {
int64_t expected_downtime;
bool capabilities[MIGRATION_CAPABILITY__MAX];
int64_t setup_time;

/*
* Whether guest was running when we enter the completion stage.
* State before stopping the vm by vm_stop_force_state().
* If migration is interrupted by any reason, we need to continue
* running the guest on source.
* running the guest on source if it was running or restore its stopped
* state.
*/
bool vm_was_running;
RunState vm_old_state;

/* Flag set once the migration has been asked to enter postcopy */
bool start_postcopy;
Expand Down Expand Up @@ -437,6 +440,9 @@ struct MigrationState {

/* QEMU_VM_VMDESCRIPTION content filled for all non-iterable devices. */
JSONWriter *vmdesc;

/* Is this a rdma migration */
bool rdma_migration;
};

void migrate_set_state(int *state, int old_state, int new_state);
Expand Down
7 changes: 7 additions & 0 deletions migration/options.c
Expand Up @@ -350,6 +350,13 @@ bool migrate_postcopy(void)
return migrate_postcopy_ram() || migrate_dirty_bitmaps();
}

bool migrate_rdma(void)
{
MigrationState *s = migrate_get_current();

return s->rdma_migration;
}

bool migrate_tls(void)
{
MigrationState *s = migrate_get_current();
Expand Down
1 change: 1 addition & 0 deletions migration/options.h
Expand Up @@ -54,6 +54,7 @@ bool migrate_zero_copy_send(void);

bool migrate_multifd_flush_after_each_section(void);
bool migrate_postcopy(void);
bool migrate_rdma(void);
bool migrate_tls(void);

/* capabilities helpers */
Expand Down
69 changes: 1 addition & 68 deletions migration/qemu-file.c
Expand Up @@ -32,12 +32,12 @@
#include "trace.h"
#include "options.h"
#include "qapi/error.h"
#include "rdma.h"

#define IO_BUF_SIZE 32768
#define MAX_IOV_SIZE MIN_CONST(IOV_MAX, 64)

struct QEMUFile {
const QEMUFileHooks *hooks;
QIOChannel *ioc;
bool is_writable;

Expand Down Expand Up @@ -146,11 +146,6 @@ QEMUFile *qemu_file_new_input(QIOChannel *ioc)
return qemu_file_new_impl(ioc, false);
}

void qemu_file_set_hooks(QEMUFile *f, const QEMUFileHooks *hooks)
{
f->hooks = hooks;
}

/*
* Get last error for stream f with optional Error*
*
Expand Down Expand Up @@ -302,63 +297,6 @@ void qemu_fflush(QEMUFile *f)
f->iovcnt = 0;
}

void ram_control_before_iterate(QEMUFile *f, uint64_t flags)
{
int ret = 0;

if (f->hooks && f->hooks->before_ram_iterate) {
ret = f->hooks->before_ram_iterate(f, flags, NULL);
if (ret < 0) {
qemu_file_set_error(f, ret);
}
}
}

void ram_control_after_iterate(QEMUFile *f, uint64_t flags)
{
int ret = 0;

if (f->hooks && f->hooks->after_ram_iterate) {
ret = f->hooks->after_ram_iterate(f, flags, NULL);
if (ret < 0) {
qemu_file_set_error(f, ret);
}
}
}

void ram_control_load_hook(QEMUFile *f, uint64_t flags, void *data)
{
if (f->hooks && f->hooks->hook_ram_load) {
int ret = f->hooks->hook_ram_load(f, flags, data);
if (ret < 0) {
qemu_file_set_error(f, ret);
}
}
}

size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
ram_addr_t offset, size_t size,
uint64_t *bytes_sent)
{
if (f->hooks && f->hooks->save_page) {
int ret = f->hooks->save_page(f, block_offset,
offset, size, bytes_sent);

if (ret != RAM_SAVE_CONTROL_DELAYED &&
ret != RAM_SAVE_CONTROL_NOT_SUPP) {
if (bytes_sent && *bytes_sent > 0) {
qemu_file_credit_transfer(f, *bytes_sent);
} else if (ret < 0) {
qemu_file_set_error(f, ret);
}
}

return ret;
}

return RAM_SAVE_CONTROL_NOT_SUPP;
}

/*
* Attempt to fill the buffer from the underlying file
* Returns the number of bytes read, or negative value for an error.
Expand Down Expand Up @@ -414,11 +352,6 @@ static ssize_t coroutine_mixed_fn qemu_fill_buffer(QEMUFile *f)
return len;
}

void qemu_file_credit_transfer(QEMUFile *f, size_t size)
{
f->total_transferred += size;
}

/** Closes the file
*
* Returns negative error value if any error happened on previous operations or
Expand Down

0 comments on commit a4423a3

Please sign in to comment.