Skip to content

Commit

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

Migration Pull request

Hi

Based on latest reviewed parts of migration:
- Disable colo (vladimir)
- Migration atomic counters (juan)

Please apply.

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEGJn/jt6/WMzuA0uC9IfvGFhy1yMFAmRmXJUACgkQ9IfvGFhy
# 1yNRAxAAjDYJELL34Qovt/WE9qKhYJEvIUGTl1IMWJ22YMFnqIFKRdka57dWoU3P
# 7EK1BHmokEEtzGT7Fe1ecERXsOwQIJDIkDTJ5g8Oc8Jt1iqY1AC8h5T+LghijCar
# mbZ6qWHaSjsg2lmek/xc9quymzFGGK36PSyB5WkaLRviKQn4RIkEDpUaWny7nDbA
# Q8zJJpBqNFqKfC5/DN0ePa3QQscXQJhey3nxqFd8hYp8RFNIV5UJVW5Lf6ombtK7
# atgdWC4ckkfO2z3OsghKeo/UiMFWpPktgBVVMhDLmk+P/E6czc2gfzD6SCvrPKTj
# XowI8hro22HVmq9bEY8PtbjMOfpxrAxer+tM2KR/0O9l3UzUacFsi7KGqCJ1/trQ
# 1tSDjlgyczb8GOgLwwxj8XE+jPHPfVrzCNfDqrBKBNxz6nnZSdZUwhV5mG8FdVtm
# oVVV96BIrNXLl/lIxYIFD/Zyvl8/lrSWQdLkEHTzihYQeXaQfyvPVbV/dOLT4sii
# YUuGCuEhF+DW/qz43G1krwq5/bfxsiZoQzrMV/Odtf0wYQKkabA3KNBIda/vxBCR
# dsLQ7QtmOwKmCzjqw4LUov9vDNYOYr98o7ZqwJ3qeKL4QgFwtEZUFO3VW6UR8fnF
# arVXiTn9wVlkTpu4sT5hLm9400iadhX4Fppji7Ce0tUpLbWbghA=
# =3x32
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 18 May 2023 10:12:53 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-20230518-pull-request' of https://gitlab.com/juan.quintela/qemu:
  migration: Fix duplicated included in meson.build
  migration/multifd: Compute transferred bytes correctly
  migration: We don't need the field rate_limit_used anymore
  migration: Use migration_transferred_bytes() to calculate rate_limit
  migration: Add a trace for migration_transferred_bytes
  migration: Move migration_total_bytes() to migration-stats.c
  migration: Move rate_limit_max and rate_limit_used to migration_stats
  qemu-file: Account for rate_limit usage on qemu_fflush()
  migration: Don't use INT64_MAX for unlimited rate
  migration: process_incoming_migration_co(): move colo part to colo
  migration: split migration_incoming_co
  configure: add --disable-colo-proxy option

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
  • Loading branch information
rth7680 committed May 18, 2023
2 parents 297e818 + ba9d2cb commit 146f515
Show file tree
Hide file tree
Showing 27 changed files with 242 additions and 148 deletions.
4 changes: 2 additions & 2 deletions hw/ppc/spapr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2166,7 +2166,7 @@ static void htab_save_first_pass(QEMUFile *f, SpaprMachineState *spapr,
break;
}
}
} while ((index < htabslots) && !qemu_file_rate_limit(f));
} while ((index < htabslots) && !migration_rate_exceeded(f));

if (index >= htabslots) {
assert(index == htabslots);
Expand Down Expand Up @@ -2237,7 +2237,7 @@ static int htab_save_later_pass(QEMUFile *f, SpaprMachineState *spapr,
assert(index == htabslots);
index = 0;
}
} while ((examined < htabslots) && (!qemu_file_rate_limit(f) || final));
} while ((examined < htabslots) && (!migration_rate_exceeded(f) || final));

if (index >= htabslots) {
assert(index == htabslots);
Expand Down
2 changes: 1 addition & 1 deletion hw/s390x/s390-stattrib.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ static int cmma_save(QEMUFile *f, void *opaque, int final)
return -ENOMEM;
}

while (final ? 1 : qemu_file_rate_limit(f) == 0) {
while (final ? 1 : migration_rate_exceeded(f) == 0) {
reallen = sac->get_stattr(sas, &start_gfn, buflen, buf);
if (reallen < 0) {
g_free(buf);
Expand Down
9 changes: 8 additions & 1 deletion include/migration/colo.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ bool migration_in_colo_state(void);
int migration_incoming_enable_colo(void);
void migration_incoming_disable_colo(void);
bool migration_incoming_colo_enabled(void);
void *colo_process_incoming_thread(void *opaque);
bool migration_incoming_in_colo_state(void);

COLOMode get_colo_mode(void);
Expand All @@ -44,5 +43,13 @@ void colo_do_failover(void);
*/
void colo_checkpoint_delay_set(void);

/*
* Starts COLO incoming process. Called from process_incoming_migration_co()
* after loading the state.
*
* Called with BQL locked, may temporary release BQL.
*/
int coroutine_fn colo_incoming_co(void);

void colo_shutdown(void);
#endif
12 changes: 11 additions & 1 deletion include/migration/qemu-file-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,16 @@ size_t coroutine_mixed_fn qemu_get_counted_string(QEMUFile *f, char buf[256]);

void qemu_put_counted_string(QEMUFile *f, const char *name);

int qemu_file_rate_limit(QEMUFile *f);
/**
* migration_rate_exceeded: Check if we have exceeded rate for this interval
*
* Checks if we have already transferred more data that we are allowed
* in the current interval.
*
* @f: QEMUFile used for main migration channel
*
* Returns if we should stop sending data for this interval.
*/
bool migration_rate_exceeded(QEMUFile *f);

#endif
2 changes: 2 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ option('live_block_migration', type: 'feature', value: 'auto',
description: 'block migration in the main migration stream')
option('replication', type: 'feature', value: 'auto',
description: 'replication support')
option('colo_proxy', type: 'feature', value: 'auto',
description: 'colo-proxy support')
option('bochs', type: 'feature', value: 'auto',
description: 'bochs image format support')
option('cloop', type: 'feature', value: 'auto',
Expand Down
2 changes: 1 addition & 1 deletion migration/block-dirty-bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ static void bulk_phase(QEMUFile *f, DBMSaveState *s, bool limit)
QSIMPLEQ_FOREACH(dbms, &s->dbms_list, entry) {
while (!dbms->bulk_completed) {
bulk_phase_send_chunk(f, s, dbms);
if (limit && qemu_file_rate_limit(f)) {
if (limit && migration_rate_exceeded(f)) {
return;
}
}
Expand Down
5 changes: 3 additions & 2 deletions migration/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "block/dirty-bitmap.h"
#include "migration/misc.h"
#include "migration.h"
#include "migration-stats.h"
#include "migration/register.h"
#include "qemu-file.h"
#include "migration/vmstate.h"
Expand Down Expand Up @@ -625,7 +626,7 @@ static int flush_blks(QEMUFile *f)

blk_mig_lock();
while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
if (qemu_file_rate_limit(f)) {
if (migration_rate_exceeded(f)) {
break;
}
if (blk->ret < 0) {
Expand Down Expand Up @@ -762,7 +763,7 @@ static int block_save_iterate(QEMUFile *f, void *opaque)
/* control the rate of transfer */
blk_mig_lock();
while (block_mig_state.read_done * BLK_MIG_BLOCK_SIZE <
qemu_file_get_rate_limit(f) &&
migration_rate_get() &&
block_mig_state.submitted < MAX_PARALLEL_IO &&
(block_mig_state.submitted + block_mig_state.read_done) <
MAX_IO_BUFFERS) {
Expand Down
43 changes: 40 additions & 3 deletions migration/colo.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ static void secondary_vm_do_failover(void)
qemu_sem_post(&mis->colo_incoming_sem);

/* For Secondary VM, jump to incoming co */
if (mis->migration_incoming_co) {
qemu_coroutine_enter(mis->migration_incoming_co);
if (mis->colo_incoming_co) {
qemu_coroutine_enter(mis->colo_incoming_co);
}
}

Expand Down Expand Up @@ -817,7 +817,7 @@ void colo_shutdown(void)
}
}

void *colo_process_incoming_thread(void *opaque)
static void *colo_process_incoming_thread(void *opaque)
{
MigrationIncomingState *mis = opaque;
QEMUFile *fb = NULL;
Expand Down Expand Up @@ -918,3 +918,40 @@ void *colo_process_incoming_thread(void *opaque)
rcu_unregister_thread();
return NULL;
}

int coroutine_fn colo_incoming_co(void)
{
MigrationIncomingState *mis = migration_incoming_get_current();
Error *local_err = NULL;
QemuThread th;

assert(qemu_mutex_iothread_locked());

if (!migration_incoming_colo_enabled()) {
return 0;
}

/* Make sure all file formats throw away their mutable metadata */
bdrv_activate_all(&local_err);
if (local_err) {
error_report_err(local_err);
return -EINVAL;
}

qemu_thread_create(&th, "COLO incoming", colo_process_incoming_thread,
mis, QEMU_THREAD_JOINABLE);

mis->colo_incoming_co = qemu_coroutine_self();
qemu_coroutine_yield();
mis->colo_incoming_co = NULL;

qemu_mutex_unlock_iothread();
/* Wait checkpoint incoming thread exit before free resource */
qemu_thread_join(&th);
qemu_mutex_lock_iothread();

/* We hold the global iothread lock, so it is safe here */
colo_release_ram_cache();

return 0;
}
3 changes: 1 addition & 2 deletions migration/meson.build
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Files needed by unit tests
migration_files = files(
'migration-stats.c',
'page_cache.c',
'xbzrle.c',
'vmstate-types.c',
Expand All @@ -18,11 +19,9 @@ softmmu_ss.add(files(
'fd.c',
'global_state.c',
'migration-hmp-cmds.c',
'migration-stats.c',
'migration.c',
'multifd.c',
'multifd-zlib.c',
'multifd-zlib.c',
'ram-compress.c',
'options.c',
'postcopy-ram.c',
Expand Down
51 changes: 51 additions & 0 deletions migration/migration-stats.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,57 @@

#include "qemu/osdep.h"
#include "qemu/stats64.h"
#include "qemu-file.h"
#include "trace.h"
#include "migration-stats.h"

MigrationAtomicStats mig_stats;

bool migration_rate_exceeded(QEMUFile *f)
{
if (qemu_file_get_error(f)) {
return true;
}

uint64_t rate_limit_start = stat64_get(&mig_stats.rate_limit_start);
uint64_t rate_limit_current = migration_transferred_bytes(f);
uint64_t rate_limit_used = rate_limit_current - rate_limit_start;
uint64_t rate_limit_max = stat64_get(&mig_stats.rate_limit_max);

if (rate_limit_max == RATE_LIMIT_DISABLED) {
return false;
}
if (rate_limit_max > 0 && rate_limit_used > rate_limit_max) {
return true;
}
return false;
}

uint64_t migration_rate_get(void)
{
return stat64_get(&mig_stats.rate_limit_max);
}

#define XFER_LIMIT_RATIO (1000 / BUFFER_DELAY)

void migration_rate_set(uint64_t limit)
{
/*
* 'limit' is per second. But we check it each BUFER_DELAY miliseconds.
*/
stat64_set(&mig_stats.rate_limit_max, limit / XFER_LIMIT_RATIO);
}

void migration_rate_reset(QEMUFile *f)
{
stat64_set(&mig_stats.rate_limit_start, migration_transferred_bytes(f));
}

uint64_t migration_transferred_bytes(QEMUFile *f)
{
uint64_t multifd = stat64_get(&mig_stats.multifd_bytes);
uint64_t qemu_file = qemu_file_transferred(f);

trace_migration_transferred_bytes(qemu_file, multifd);
return qemu_file + multifd;
}
55 changes: 55 additions & 0 deletions migration/migration-stats.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,18 @@

#include "qemu/stats64.h"

/*
* Amount of time to allocate to each "chunk" of bandwidth-throttled
* data.
*/
#define BUFFER_DELAY 100

/*
* If rate_limit_max is 0, there is special code to remove the rate
* limit.
*/
#define RATE_LIMIT_DISABLED 0

/*
* These are the ram migration statistic counters. It is loosely
* based on MigrationStats. We change to Stat64 any counter that
Expand Down Expand Up @@ -69,6 +81,14 @@ typedef struct {
* Number of bytes sent during precopy stage.
*/
Stat64 precopy_bytes;
/*
* Amount of transferred data at the start of current cycle.
*/
Stat64 rate_limit_start;
/*
* Maximum amount of data we can send in a cycle.
*/
Stat64 rate_limit_max;
/*
* Total number of bytes transferred.
*/
Expand All @@ -81,4 +101,39 @@ typedef struct {

extern MigrationAtomicStats mig_stats;

/**
* migration_rate_get: Get the maximum amount that can be transferred.
*
* Returns the maximum number of bytes that can be transferred in a cycle.
*/
uint64_t migration_rate_get(void);

/**
* migration_rate_reset: Reset the rate limit counter.
*
* This is called when we know we start a new transfer cycle.
*
* @f: QEMUFile used for main migration channel
*/
void migration_rate_reset(QEMUFile *f);

/**
* migration_rate_set: Set the maximum amount that can be transferred.
*
* Sets the maximum amount of bytes that can be transferred in one cycle.
*
* @new_rate: new maximum amount
*/
void migration_rate_set(uint64_t new_rate);

/**
* migration_transferred_bytes: Return number of bytes transferred
*
* @f: QEMUFile used for main migration channel
*
* Returns how many bytes have we transferred since the beginning of
* the migration. It accounts for bytes sent through any migration
* channel, multifd, qemu_file, rdma, ....
*/
uint64_t migration_transferred_bytes(QEMUFile *f);
#endif

0 comments on commit 146f515

Please sign in to comment.