Migration Pull request (take 2)

Remove the two atomic patches that broke mips32.
 
 Please, apply.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEGJn/jt6/WMzuA0uC9IfvGFhy1yMFAmRGYTkACgkQ9IfvGFhy
 1yMD5RAApL8bJTMpmkZ8afxG124/CID7fvg/WMp3vOTG/6923XZHfosUwqrCCvzN
 8qfSfOl4P5Gtv1dOU+ZBcgoFS3tj00Ud2YhcZiSVUy5LZPJNJEfv4YzIErDTJq3I
 wcv/CgHvK1CKJ5DZ1g9hqnRvw9qYiodDEHS7UxvhGzckFExHps2oWt9nDuEZefKV
 XptOX7YDFYmWE87fp8+rQMYGZEN/6Cc7p4HmSt9I11CgLbeaqTpmKuwTv89PU9qV
 7/X9kfoHNsKsVKw5WosEdRvEqhVQbvcCCxq+TGpeQz6d5U2mY7RVxQSNJxXNdD3P
 uz7uannx+UhESgzf5GnwOMIcxWD6UMAcDt349IAWFbq5d1QGaXJ9fVVHVJDV1Irl
 XHqxkugNMxRVZ8hQy5gSE6UTpeIjkIpSoZGnGS7E/iLMZHZBgv7s5VK21mYxn/QF
 F9g3Ewo2lF+kpQ/ZEnQ9mFyCYtqOHOAOLAUa7/6WdGnUMuqQ47Fh+jbb+KdEyCLg
 l7yXk2gXAb8SN6957Tlvo9okOB4NzhDPDXgvewAG/1yW4zL9hA+YCMvEvy90N8Be
 rRKO7H9YlsW4wKjA//i2YNAbtaZN5+zeAS39m0exYmXA54AMufjWq/a7Ya/ix5Jo
 452LEz5hA4ckXXtP715pKQjqafxWXbHSS1qw9LBfMYr5TEEWC6c=
 =JTxg
 -----END PGP SIGNATURE-----

Merge tag 'migration-20230420-pull-request' of https://gitlab.com/juan.quintela/qemu into staging

Migration Pull request (take 2)

Remove the two atomic patches that broke mips32.

Please, apply.

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCAAdFiEEGJn/jt6/WMzuA0uC9IfvGFhy1yMFAmRGYTkACgkQ9IfvGFhy
# 1yMD5RAApL8bJTMpmkZ8afxG124/CID7fvg/WMp3vOTG/6923XZHfosUwqrCCvzN
# 8qfSfOl4P5Gtv1dOU+ZBcgoFS3tj00Ud2YhcZiSVUy5LZPJNJEfv4YzIErDTJq3I
# wcv/CgHvK1CKJ5DZ1g9hqnRvw9qYiodDEHS7UxvhGzckFExHps2oWt9nDuEZefKV
# XptOX7YDFYmWE87fp8+rQMYGZEN/6Cc7p4HmSt9I11CgLbeaqTpmKuwTv89PU9qV
# 7/X9kfoHNsKsVKw5WosEdRvEqhVQbvcCCxq+TGpeQz6d5U2mY7RVxQSNJxXNdD3P
# uz7uannx+UhESgzf5GnwOMIcxWD6UMAcDt349IAWFbq5d1QGaXJ9fVVHVJDV1Irl
# XHqxkugNMxRVZ8hQy5gSE6UTpeIjkIpSoZGnGS7E/iLMZHZBgv7s5VK21mYxn/QF
# F9g3Ewo2lF+kpQ/ZEnQ9mFyCYtqOHOAOLAUa7/6WdGnUMuqQ47Fh+jbb+KdEyCLg
# l7yXk2gXAb8SN6957Tlvo9okOB4NzhDPDXgvewAG/1yW4zL9hA+YCMvEvy90N8Be
# rRKO7H9YlsW4wKjA//i2YNAbtaZN5+zeAS39m0exYmXA54AMufjWq/a7Ya/ix5Jo
# 452LEz5hA4ckXXtP715pKQjqafxWXbHSS1qw9LBfMYr5TEEWC6c=
# =JTxg
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 24 Apr 2023 12:00:09 PM BST
# 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-20230420-pull-request' of https://gitlab.com/juan.quintela/qemu:
  migration: Pass migrate_caps_check() the old and new caps
  migration: rename enabled_capabilities to capabilities
  migration/postcopy: Detect file system on dest host
  vl.c: Create late backends before migration object
  util/mmap-alloc: qemu_fd_getfs()
  migration: Handle block device inactivation failures better
  migration: Rename normal to normal_pages
  migration: Rename duplicate to zero_pages
  migration: Make postcopy_requests atomic
  migration: Make dirty_sync_count atomic
  migration: Make downtime_bytes atomic
  migration: Make precopy_bytes atomic
  migration: Make dirty_sync_missed_zero_copy atomic
  migration: Make multifd_bytes atomic
  migration: Update atomic stats out of the mutex
  migration: Merge ram_counters and ram_atomic_counters
  migration: remove extra whitespace character for code style

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2023-04-24 12:06:17 +01:00
commit 81072abf15
11 changed files with 196 additions and 160 deletions

View File

@ -1,8 +1,15 @@
#ifndef QEMU_MMAP_ALLOC_H
#define QEMU_MMAP_ALLOC_H
typedef enum {
QEMU_FS_TYPE_UNKNOWN = 0,
QEMU_FS_TYPE_TMPFS,
QEMU_FS_TYPE_HUGETLBFS,
QEMU_FS_TYPE_NUM,
} QemuFsType;
size_t qemu_fd_getpagesize(int fd);
QemuFsType qemu_fd_getfs(int fd);
/**
* qemu_ram_mmap: mmap anonymous memory, the specified file or device.

View File

@ -364,8 +364,7 @@ static bool migrate_late_block_activate(void)
s = migrate_get_current();
return s->enabled_capabilities[
MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
return s->capabilities[MIGRATION_CAPABILITY_LATE_BLOCK_ACTIVATE];
}
/*
@ -944,7 +943,7 @@ MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp)
#endif
caps = g_malloc0(sizeof(*caps));
caps->capability = i;
caps->state = s->enabled_capabilities[i];
caps->state = s->capabilities[i];
QAPI_LIST_APPEND(tail, caps);
}
@ -1140,24 +1139,26 @@ static void populate_ram_info(MigrationInfo *info, MigrationState *s)
size_t page_size = qemu_target_page_size();
info->ram = g_malloc0(sizeof(*info->ram));
info->ram->transferred = stat64_get(&ram_atomic_counters.transferred);
info->ram->transferred = stat64_get(&ram_counters.transferred);
info->ram->total = ram_bytes_total();
info->ram->duplicate = stat64_get(&ram_atomic_counters.duplicate);
info->ram->duplicate = stat64_get(&ram_counters.zero_pages);
/* legacy value. It is not used anymore */
info->ram->skipped = 0;
info->ram->normal = stat64_get(&ram_atomic_counters.normal);
info->ram->normal = stat64_get(&ram_counters.normal_pages);
info->ram->normal_bytes = info->ram->normal * page_size;
info->ram->mbps = s->mbps;
info->ram->dirty_sync_count = ram_counters.dirty_sync_count;
info->ram->dirty_sync_count =
stat64_get(&ram_counters.dirty_sync_count);
info->ram->dirty_sync_missed_zero_copy =
ram_counters.dirty_sync_missed_zero_copy;
info->ram->postcopy_requests = ram_counters.postcopy_requests;
stat64_get(&ram_counters.dirty_sync_missed_zero_copy);
info->ram->postcopy_requests =
stat64_get(&ram_counters.postcopy_requests);
info->ram->page_size = page_size;
info->ram->multifd_bytes = ram_counters.multifd_bytes;
info->ram->multifd_bytes = stat64_get(&ram_counters.multifd_bytes);
info->ram->pages_per_second = s->pages_per_second;
info->ram->precopy_bytes = ram_counters.precopy_bytes;
info->ram->downtime_bytes = ram_counters.downtime_bytes;
info->ram->postcopy_bytes = stat64_get(&ram_atomic_counters.postcopy_bytes);
info->ram->precopy_bytes = stat64_get(&ram_counters.precopy_bytes);
info->ram->downtime_bytes = stat64_get(&ram_counters.downtime_bytes);
info->ram->postcopy_bytes = stat64_get(&ram_counters.postcopy_bytes);
if (migrate_use_xbzrle()) {
info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
@ -1298,30 +1299,20 @@ WriteTrackingSupport migrate_query_write_tracking(void)
}
/**
* @migration_caps_check - check capability validity
* @migration_caps_check - check capability compatibility
*
* @cap_list: old capability list, array of bool
* @params: new capabilities to be applied soon
* @old_caps: old capability list
* @new_caps: new capability list
* @errp: set *errp if the check failed, with reason
*
* Returns true if check passed, otherwise false.
*/
static bool migrate_caps_check(bool *cap_list,
MigrationCapabilityStatusList *params,
Error **errp)
static bool migrate_caps_check(bool *old_caps, bool *new_caps, Error **errp)
{
MigrationCapabilityStatusList *cap;
bool old_postcopy_cap;
MigrationIncomingState *mis = migration_incoming_get_current();
old_postcopy_cap = cap_list[MIGRATION_CAPABILITY_POSTCOPY_RAM];
for (cap = params; cap; cap = cap->next) {
cap_list[cap->value->capability] = cap->value->state;
}
#ifndef CONFIG_LIVE_BLOCK_MIGRATION
if (cap_list[MIGRATION_CAPABILITY_BLOCK]) {
if (new_caps[MIGRATION_CAPABILITY_BLOCK]) {
error_setg(errp, "QEMU compiled without old-style (blk/-b, inc/-i) "
"block migration");
error_append_hint(errp, "Use drive_mirror+NBD instead.\n");
@ -1330,7 +1321,7 @@ static bool migrate_caps_check(bool *cap_list,
#endif
#ifndef CONFIG_REPLICATION
if (cap_list[MIGRATION_CAPABILITY_X_COLO]) {
if (new_caps[MIGRATION_CAPABILITY_X_COLO]) {
error_setg(errp, "QEMU compiled without replication module"
" can't enable COLO");
error_append_hint(errp, "Please enable replication before COLO.\n");
@ -1338,12 +1329,13 @@ static bool migrate_caps_check(bool *cap_list,
}
#endif
if (cap_list[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
/* This check is reasonably expensive, so only when it's being
* set the first time, also it's only the destination that needs
* special support.
*/
if (!old_postcopy_cap && runstate_check(RUN_STATE_INMIGRATE) &&
if (!old_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM] &&
runstate_check(RUN_STATE_INMIGRATE) &&
!postcopy_ram_supported_by_host(mis)) {
/* postcopy_ram_supported_by_host will have emitted a more
* detailed message
@ -1352,13 +1344,13 @@ static bool migrate_caps_check(bool *cap_list,
return false;
}
if (cap_list[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) {
if (new_caps[MIGRATION_CAPABILITY_X_IGNORE_SHARED]) {
error_setg(errp, "Postcopy is not compatible with ignore-shared");
return false;
}
}
if (cap_list[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) {
if (new_caps[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT]) {
WriteTrackingSupport wt_support;
int idx;
/*
@ -1382,7 +1374,7 @@ static bool migrate_caps_check(bool *cap_list,
*/
for (idx = 0; idx < check_caps_background_snapshot.size; idx++) {
int incomp_cap = check_caps_background_snapshot.caps[idx];
if (cap_list[incomp_cap]) {
if (new_caps[incomp_cap]) {
error_setg(errp,
"Background-snapshot is not compatible with %s",
MigrationCapability_str(incomp_cap));
@ -1392,10 +1384,10 @@ static bool migrate_caps_check(bool *cap_list,
}
#ifdef CONFIG_LINUX
if (cap_list[MIGRATION_CAPABILITY_ZERO_COPY_SEND] &&
(!cap_list[MIGRATION_CAPABILITY_MULTIFD] ||
cap_list[MIGRATION_CAPABILITY_COMPRESS] ||
cap_list[MIGRATION_CAPABILITY_XBZRLE] ||
if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND] &&
(!new_caps[MIGRATION_CAPABILITY_MULTIFD] ||
new_caps[MIGRATION_CAPABILITY_COMPRESS] ||
new_caps[MIGRATION_CAPABILITY_XBZRLE] ||
migrate_multifd_compression() ||
migrate_use_tls())) {
error_setg(errp,
@ -1403,15 +1395,15 @@ static bool migrate_caps_check(bool *cap_list,
return false;
}
#else
if (cap_list[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) {
if (new_caps[MIGRATION_CAPABILITY_ZERO_COPY_SEND]) {
error_setg(errp,
"Zero copy currently only available on Linux");
return false;
}
#endif
if (cap_list[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) {
if (!cap_list[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
if (new_caps[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT]) {
if (!new_caps[MIGRATION_CAPABILITY_POSTCOPY_RAM]) {
error_setg(errp, "Postcopy preempt requires postcopy-ram");
return false;
}
@ -1422,14 +1414,14 @@ static bool migrate_caps_check(bool *cap_list,
* different compression channels, which is not compatible with the
* preempt assumptions on channel assignments.
*/
if (cap_list[MIGRATION_CAPABILITY_COMPRESS]) {
if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
error_setg(errp, "Postcopy preempt not compatible with compress");
return false;
}
}
if (cap_list[MIGRATION_CAPABILITY_MULTIFD]) {
if (cap_list[MIGRATION_CAPABILITY_COMPRESS]) {
if (new_caps[MIGRATION_CAPABILITY_MULTIFD]) {
if (new_caps[MIGRATION_CAPABILITY_COMPRESS]) {
error_setg(errp, "Multifd is not compatible with compress");
return false;
}
@ -1485,20 +1477,24 @@ void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
{
MigrationState *s = migrate_get_current();
MigrationCapabilityStatusList *cap;
bool cap_list[MIGRATION_CAPABILITY__MAX];
bool new_caps[MIGRATION_CAPABILITY__MAX];
if (migration_is_running(s->state)) {
error_setg(errp, QERR_MIGRATION_ACTIVE);
return;
}
memcpy(cap_list, s->enabled_capabilities, sizeof(cap_list));
if (!migrate_caps_check(cap_list, params, errp)) {
memcpy(new_caps, s->capabilities, sizeof(new_caps));
for (cap = params; cap; cap = cap->next) {
new_caps[cap->value->capability] = cap->value->state;
}
if (!migrate_caps_check(s->capabilities, new_caps, errp)) {
return;
}
for (cap = params; cap; cap = cap->next) {
s->enabled_capabilities[cap->value->capability] = cap->value->state;
s->capabilities[cap->value->capability] = cap->value->state;
}
}
@ -2567,7 +2563,7 @@ bool migrate_release_ram(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_RELEASE_RAM];
return s->capabilities[MIGRATION_CAPABILITY_RELEASE_RAM];
}
bool migrate_postcopy_ram(void)
@ -2576,7 +2572,7 @@ bool migrate_postcopy_ram(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM];
return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_RAM];
}
bool migrate_postcopy(void)
@ -2590,7 +2586,7 @@ bool migrate_auto_converge(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE];
return s->capabilities[MIGRATION_CAPABILITY_AUTO_CONVERGE];
}
bool migrate_zero_blocks(void)
@ -2599,7 +2595,7 @@ bool migrate_zero_blocks(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS];
return s->capabilities[MIGRATION_CAPABILITY_ZERO_BLOCKS];
}
bool migrate_postcopy_blocktime(void)
@ -2608,7 +2604,7 @@ bool migrate_postcopy_blocktime(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME];
return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_BLOCKTIME];
}
bool migrate_use_compression(void)
@ -2617,7 +2613,7 @@ bool migrate_use_compression(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_COMPRESS];
return s->capabilities[MIGRATION_CAPABILITY_COMPRESS];
}
int migrate_compress_level(void)
@ -2662,7 +2658,7 @@ bool migrate_dirty_bitmaps(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS];
return s->capabilities[MIGRATION_CAPABILITY_DIRTY_BITMAPS];
}
bool migrate_ignore_shared(void)
@ -2671,7 +2667,7 @@ bool migrate_ignore_shared(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
return s->capabilities[MIGRATION_CAPABILITY_X_IGNORE_SHARED];
}
bool migrate_validate_uuid(void)
@ -2680,7 +2676,7 @@ bool migrate_validate_uuid(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
return s->capabilities[MIGRATION_CAPABILITY_VALIDATE_UUID];
}
bool migrate_use_events(void)
@ -2689,7 +2685,7 @@ bool migrate_use_events(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_EVENTS];
return s->capabilities[MIGRATION_CAPABILITY_EVENTS];
}
bool migrate_use_multifd(void)
@ -2698,7 +2694,7 @@ bool migrate_use_multifd(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_MULTIFD];
return s->capabilities[MIGRATION_CAPABILITY_MULTIFD];
}
bool migrate_pause_before_switchover(void)
@ -2707,8 +2703,7 @@ bool migrate_pause_before_switchover(void)
s = migrate_get_current();
return s->enabled_capabilities[
MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER];
return s->capabilities[MIGRATION_CAPABILITY_PAUSE_BEFORE_SWITCHOVER];
}
int migrate_multifd_channels(void)
@ -2755,7 +2750,7 @@ bool migrate_use_zero_copy_send(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND];
return s->capabilities[MIGRATION_CAPABILITY_ZERO_COPY_SEND];
}
#endif
@ -2774,7 +2769,7 @@ int migrate_use_xbzrle(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_XBZRLE];
return s->capabilities[MIGRATION_CAPABILITY_XBZRLE];
}
uint64_t migrate_xbzrle_cache_size(void)
@ -2801,7 +2796,7 @@ bool migrate_use_block(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_BLOCK];
return s->capabilities[MIGRATION_CAPABILITY_BLOCK];
}
bool migrate_use_return_path(void)
@ -2810,7 +2805,7 @@ bool migrate_use_return_path(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_RETURN_PATH];
return s->capabilities[MIGRATION_CAPABILITY_RETURN_PATH];
}
bool migrate_use_block_incremental(void)
@ -2828,7 +2823,7 @@ bool migrate_background_snapshot(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT];
return s->capabilities[MIGRATION_CAPABILITY_BACKGROUND_SNAPSHOT];
}
bool migrate_postcopy_preempt(void)
@ -2837,7 +2832,7 @@ bool migrate_postcopy_preempt(void)
s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT];
return s->capabilities[MIGRATION_CAPABILITY_POSTCOPY_PREEMPT];
}
/* migration thread support */
@ -3444,13 +3439,11 @@ static void migration_completion(MigrationState *s)
MIGRATION_STATUS_DEVICE);
}
if (ret >= 0) {
s->block_inactive = inactivate;
qemu_file_set_rate_limit(s->to_dst_file, INT64_MAX);
ret = qemu_savevm_state_complete_precopy(s->to_dst_file, false,
inactivate);
}
if (inactivate && ret >= 0) {
s->block_inactive = true;
}
}
qemu_mutex_unlock_iothread();
@ -3522,6 +3515,7 @@ fail_invalidate:
bdrv_activate_all(&local_err);
if (local_err) {
error_report_err(local_err);
s->block_inactive = true;
} else {
s->block_inactive = false;
}
@ -3580,7 +3574,7 @@ fail:
bool migrate_colo_enabled(void)
{
MigrationState *s = migrate_get_current();
return s->enabled_capabilities[MIGRATION_CAPABILITY_X_COLO];
return s->capabilities[MIGRATION_CAPABILITY_X_COLO];
}
typedef enum MigThrError {
@ -3778,7 +3772,7 @@ static MigThrError migration_detect_error(MigrationState *s)
static uint64_t migration_total_bytes(MigrationState *s)
{
return qemu_file_total_transferred(s->to_dst_file) +
ram_counters.multifd_bytes;
stat64_get(&ram_counters.multifd_bytes);
}
static void migration_calculate_complete(MigrationState *s)
@ -4443,7 +4437,7 @@ void migration_global_dump(Monitor *mon)
}
#define DEFINE_PROP_MIG_CAP(name, x) \
DEFINE_PROP_BOOL(name, MigrationState, enabled_capabilities[x], false)
DEFINE_PROP_BOOL(name, MigrationState, capabilities[x], false)
static Property migration_properties[] = {
DEFINE_PROP_BOOL("store-global-state", MigrationState,
@ -4632,27 +4626,14 @@ static void migration_instance_init(Object *obj)
*/
static bool migration_object_check(MigrationState *ms, Error **errp)
{
MigrationCapabilityStatusList *head = NULL;
/* Assuming all off */
bool cap_list[MIGRATION_CAPABILITY__MAX] = { 0 }, ret;
int i;
bool old_caps[MIGRATION_CAPABILITY__MAX] = { 0 };
if (!migrate_params_check(&ms->parameters, errp)) {
return false;
}
for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
if (ms->enabled_capabilities[i]) {
QAPI_LIST_PREPEND(head, migrate_cap_add(i, true));
}
}
ret = migrate_caps_check(cap_list, head, errp);
/* It works with head == NULL */
qapi_free_MigrationCapabilityStatusList(head);
return ret;
return migrate_caps_check(old_caps, ms->capabilities, errp);
}
static const TypeInfo migration_type = {

View File

@ -310,7 +310,7 @@ struct MigrationState {
int64_t downtime_start;
int64_t downtime;
int64_t expected_downtime;
bool enabled_capabilities[MIGRATION_CAPABILITY__MAX];
bool capabilities[MIGRATION_CAPABILITY__MAX];
int64_t setup_time;
/*
* Whether guest was running when we enter the completion stage.

View File

@ -432,9 +432,9 @@ static int multifd_send_pages(QEMUFile *f)
p->pages = pages;
transferred = ((uint64_t) pages->num) * p->page_size + p->packet_len;
qemu_file_acct_rate_limit(f, transferred);
ram_counters.multifd_bytes += transferred;
stat64_add(&ram_atomic_counters.transferred, transferred);
qemu_mutex_unlock(&p->mutex);
stat64_add(&ram_counters.transferred, transferred);
stat64_add(&ram_counters.multifd_bytes, transferred);
qemu_sem_post(&p->sem);
return 1;
@ -576,7 +576,7 @@ static int multifd_zero_copy_flush(QIOChannel *c)
return -1;
}
if (ret == 1) {
dirty_sync_missed_zero_copy();
stat64_add(&ram_counters.dirty_sync_missed_zero_copy, 1);
}
return ret;
@ -627,9 +627,9 @@ int multifd_send_sync_main(QEMUFile *f)
p->flags |= MULTIFD_FLAG_SYNC;
p->pending_job++;
qemu_file_acct_rate_limit(f, p->packet_len);
ram_counters.multifd_bytes += p->packet_len;
stat64_add(&ram_atomic_counters.transferred, p->packet_len);
qemu_mutex_unlock(&p->mutex);
stat64_add(&ram_counters.transferred, p->packet_len);
stat64_add(&ram_counters.multifd_bytes, p->packet_len);
qemu_sem_post(&p->sem);
}
for (i = 0; i < migrate_multifd_channels(); i++) {

View File

@ -36,6 +36,7 @@
#include "yank_functions.h"
#include "tls.h"
#include "qemu/userfaultfd.h"
#include "qemu/mmap-alloc.h"
/* Arbitrary limit on size of each discard command,
* keeps them around ~200 bytes
@ -336,11 +337,12 @@ static bool ufd_check_and_apply(int ufd, MigrationIncomingState *mis)
/* Callback from postcopy_ram_supported_by_host block iterator.
*/
static int test_ramblock_postcopiable(RAMBlock *rb, void *opaque)
static int test_ramblock_postcopiable(RAMBlock *rb)
{
const char *block_name = qemu_ram_get_idstr(rb);
ram_addr_t length = qemu_ram_get_used_length(rb);
size_t pagesize = qemu_ram_pagesize(rb);
QemuFsType fs;
if (length % pagesize) {
error_report("Postcopy requires RAM blocks to be a page size multiple,"
@ -348,6 +350,15 @@ static int test_ramblock_postcopiable(RAMBlock *rb, void *opaque)
"page size of 0x%zx", block_name, length, pagesize);
return 1;
}
if (rb->fd >= 0) {
fs = qemu_fd_getfs(rb->fd);
if (fs != QEMU_FS_TYPE_TMPFS && fs != QEMU_FS_TYPE_HUGETLBFS) {
error_report("Host backend files need to be TMPFS or HUGETLBFS only");
return 1;
}
}
return 0;
}
@ -366,6 +377,7 @@ bool postcopy_ram_supported_by_host(MigrationIncomingState *mis)
struct uffdio_range range_struct;
uint64_t feature_mask;
Error *local_err = NULL;
RAMBlock *block;
if (qemu_target_page_size() > pagesize) {
error_report("Target page size bigger than host page size");
@ -390,9 +402,23 @@ bool postcopy_ram_supported_by_host(MigrationIncomingState *mis)
goto out;
}
/* We don't support postcopy with shared RAM yet */
if (foreach_not_ignored_block(test_ramblock_postcopiable, NULL)) {
goto out;
/*
* We don't support postcopy with some type of ramblocks.
*
* NOTE: we explicitly ignored ramblock_is_ignored() instead we checked
* all possible ramblocks. This is because this function can be called
* when creating the migration object, during the phase RAM_MIGRATABLE
* is not even properly set for all the ramblocks.
*
* A side effect of this is we'll also check against RAM_SHARED
* ramblocks even if migrate_ignore_shared() is set (in which case
* we'll never migrate RAM_SHARED at all), but normally this shouldn't
* affect in reality, or we can revisit.
*/
RAMBLOCK_FOREACH(block) {
if (test_ramblock_postcopiable(block)) {
goto out;
}
}
/*

View File

@ -458,30 +458,18 @@ uint64_t ram_bytes_remaining(void)
0;
}
/*
* NOTE: not all stats in ram_counters are used in reality. See comments
* for struct MigrationAtomicStats. The ultimate result of ram migration
* counters will be a merged version with both ram_counters and the atomic
* fields in ram_atomic_counters.
*/
MigrationStats ram_counters;
MigrationAtomicStats ram_atomic_counters;
RAMStats ram_counters;
void ram_transferred_add(uint64_t bytes)
{
if (runstate_is_running()) {
ram_counters.precopy_bytes += bytes;
stat64_add(&ram_counters.precopy_bytes, bytes);
} else if (migration_in_postcopy()) {
stat64_add(&ram_atomic_counters.postcopy_bytes, bytes);
stat64_add(&ram_counters.postcopy_bytes, bytes);
} else {
ram_counters.downtime_bytes += bytes;
stat64_add(&ram_counters.downtime_bytes, bytes);
}
stat64_add(&ram_atomic_counters.transferred, bytes);
}
void dirty_sync_missed_zero_copy(void)
{
ram_counters.dirty_sync_missed_zero_copy++;
stat64_add(&ram_counters.transferred, bytes);
}
struct MigrationOps {
@ -756,7 +744,7 @@ void mig_throttle_counter_reset(void)
rs->time_last_bitmap_sync = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
rs->num_dirty_pages_period = 0;
rs->bytes_xfer_prev = stat64_get(&ram_atomic_counters.transferred);
rs->bytes_xfer_prev = stat64_get(&ram_counters.transferred);
}
/**
@ -776,7 +764,7 @@ static void xbzrle_cache_zero_page(RAMState *rs, ram_addr_t current_addr)
/* We don't care if this fails to allocate a new cache page
* as long as it updated an old one */
cache_insert(XBZRLE.cache, current_addr, XBZRLE.zero_target_page,
ram_counters.dirty_sync_count);
stat64_get(&ram_counters.dirty_sync_count));
}
#define ENCODING_FLAG_XBZRLE 0x1
@ -802,13 +790,13 @@ static int save_xbzrle_page(RAMState *rs, PageSearchStatus *pss,
int encoded_len = 0, bytes_xbzrle;
uint8_t *prev_cached_page;
QEMUFile *file = pss->pss_channel;
uint64_t generation = stat64_get(&ram_counters.dirty_sync_count);
if (!cache_is_cached(XBZRLE.cache, current_addr,
ram_counters.dirty_sync_count)) {
if (!cache_is_cached(XBZRLE.cache, current_addr, generation)) {
xbzrle_counters.cache_miss++;
if (!rs->last_stage) {
if (cache_insert(XBZRLE.cache, current_addr, *current_data,
ram_counters.dirty_sync_count) == -1) {
generation) == -1) {
return -1;
} else {
/* update *current_data when the page has been
@ -1130,8 +1118,8 @@ uint64_t ram_pagesize_summary(void)
uint64_t ram_get_total_transferred_pages(void)
{
return stat64_get(&ram_atomic_counters.normal) +
stat64_get(&ram_atomic_counters.duplicate) +
return stat64_get(&ram_counters.normal_pages) +
stat64_get(&ram_counters.zero_pages) +
compression_counters.pages + xbzrle_counters.pages;
}
@ -1192,7 +1180,7 @@ static void migration_trigger_throttle(RAMState *rs)
MigrationState *s = migrate_get_current();
uint64_t threshold = s->parameters.throttle_trigger_threshold;
uint64_t bytes_xfer_period =
stat64_get(&ram_atomic_counters.transferred) - rs->bytes_xfer_prev;
stat64_get(&ram_counters.transferred) - rs->bytes_xfer_prev;
uint64_t bytes_dirty_period = rs->num_dirty_pages_period * TARGET_PAGE_SIZE;
uint64_t bytes_dirty_threshold = bytes_xfer_period * threshold / 100;
@ -1221,7 +1209,7 @@ static void migration_bitmap_sync(RAMState *rs)
RAMBlock *block;
int64_t end_time;
ram_counters.dirty_sync_count++;
stat64_add(&ram_counters.dirty_sync_count, 1);
if (!rs->time_last_bitmap_sync) {
rs->time_last_bitmap_sync = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
@ -1255,10 +1243,11 @@ static void migration_bitmap_sync(RAMState *rs)
/* reset period counters */
rs->time_last_bitmap_sync = end_time;
rs->num_dirty_pages_period = 0;
rs->bytes_xfer_prev = stat64_get(&ram_atomic_counters.transferred);
rs->bytes_xfer_prev = stat64_get(&ram_counters.transferred);
}
if (migrate_use_events()) {
qapi_event_send_migration_pass(ram_counters.dirty_sync_count);
uint64_t generation = stat64_get(&ram_counters.dirty_sync_count);
qapi_event_send_migration_pass(generation);
}
}
@ -1331,7 +1320,7 @@ static int save_zero_page(PageSearchStatus *pss, QEMUFile *f, RAMBlock *block,
int len = save_zero_page_to_file(pss, f, block, offset);
if (len) {
stat64_add(&ram_atomic_counters.duplicate, 1);
stat64_add(&ram_counters.zero_pages, 1);
ram_transferred_add(len);
return 1;
}
@ -1368,9 +1357,9 @@ static bool control_save_page(PageSearchStatus *pss, RAMBlock *block,
}
if (bytes_xmit > 0) {
stat64_add(&ram_atomic_counters.normal, 1);
stat64_add(&ram_counters.normal_pages, 1);
} else if (bytes_xmit == 0) {
stat64_add(&ram_atomic_counters.duplicate, 1);
stat64_add(&ram_counters.zero_pages, 1);
}
return true;
@ -1402,7 +1391,7 @@ static int save_normal_page(PageSearchStatus *pss, RAMBlock *block,
qemu_put_buffer(file, buf, TARGET_PAGE_SIZE);
}
ram_transferred_add(TARGET_PAGE_SIZE);
stat64_add(&ram_atomic_counters.normal, 1);
stat64_add(&ram_counters.normal_pages, 1);
return 1;
}
@ -1458,7 +1447,7 @@ static int ram_save_multifd_page(QEMUFile *file, RAMBlock *block,
if (multifd_queue_page(file, block, offset) < 0) {
return -1;
}
stat64_add(&ram_atomic_counters.normal, 1);
stat64_add(&ram_counters.normal_pages, 1);
return 1;
}
@ -1497,7 +1486,7 @@ update_compress_thread_counts(const CompressParam *param, int bytes_xmit)
ram_transferred_add(bytes_xmit);
if (param->zero_page) {
stat64_add(&ram_atomic_counters.duplicate, 1);
stat64_add(&ram_counters.zero_pages, 1);
return;
}
@ -2180,7 +2169,7 @@ int ram_save_queue_pages(const char *rbname, ram_addr_t start, ram_addr_t len)
RAMBlock *ramblock;
RAMState *rs = ram_state;
ram_counters.postcopy_requests++;
stat64_add(&ram_counters.postcopy_requests, 1);
RCU_READ_LOCK_GUARD();
if (!rbname) {
@ -2632,9 +2621,9 @@ void acct_update_position(QEMUFile *f, size_t size, bool zero)
uint64_t pages = size / TARGET_PAGE_SIZE;
if (zero) {
stat64_add(&ram_atomic_counters.duplicate, pages);
stat64_add(&ram_counters.zero_pages, pages);
} else {
stat64_add(&ram_atomic_counters.normal, pages);
stat64_add(&ram_counters.normal_pages, pages);
ram_transferred_add(size);
qemu_file_credit_transfer(f, size);
}
@ -3293,7 +3282,7 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
migration_ops = g_malloc0(sizeof(MigrationOps));
migration_ops->ram_save_target_page = ram_save_target_page_legacy;
ret = multifd_send_sync_main(f);
ret = multifd_send_sync_main(f);
if (ret < 0) {
return ret;
}

View File

@ -35,25 +35,27 @@
#include "qemu/stats64.h"
/*
* These are the migration statistic counters that need to be updated using
* atomic ops (can be accessed by more than one thread). Here since we
* cannot modify MigrationStats directly to use Stat64 as it was defined in
* the QAPI scheme, we define an internal structure to hold them, and we
* propagate the real values when QMP queries happen.
*
* IOW, the corresponding fields within ram_counters on these specific
* fields will be always zero and not being used at all; they're just
* placeholders to make it QAPI-compatible.
* These are the ram migration statistic counters. It is loosely
* based on MigrationStats. We change to Stat64 any counter that
* needs to be updated using atomic ops (can be accessed by more than
* one thread).
*/
typedef struct {
Stat64 transferred;
Stat64 duplicate;
Stat64 normal;
int64_t dirty_pages_rate;
Stat64 dirty_sync_count;
Stat64 dirty_sync_missed_zero_copy;
Stat64 downtime_bytes;
Stat64 zero_pages;
Stat64 multifd_bytes;
Stat64 normal_pages;
Stat64 postcopy_bytes;
} MigrationAtomicStats;
Stat64 postcopy_requests;
Stat64 precopy_bytes;
int64_t remaining;
Stat64 transferred;
} RAMStats;
extern MigrationAtomicStats ram_atomic_counters;
extern MigrationStats ram_counters;
extern RAMStats ram_counters;
extern XBZRLECacheStats xbzrle_counters;
extern CompressionStats compression_counters;
@ -112,6 +114,4 @@ void ram_write_tracking_prepare(void);
int ram_write_tracking_start(void);
void ram_write_tracking_stop(void);
void dirty_sync_missed_zero_copy(void);
#endif

View File

@ -4179,7 +4179,7 @@ void rdma_start_outgoing_migration(void *opaque,
}
ret = qemu_rdma_source_init(rdma,
s->enabled_capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL], errp);
s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL], errp);
if (ret) {
goto err;
@ -4201,7 +4201,7 @@ void rdma_start_outgoing_migration(void *opaque,
}
ret = qemu_rdma_source_init(rdma_return_path,
s->enabled_capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL], errp);
s->capabilities[MIGRATION_CAPABILITY_RDMA_PIN_ALL], errp);
if (ret) {
goto return_path_err;

View File

@ -253,7 +253,7 @@ static uint32_t get_validatable_capabilities_count(void)
uint32_t result = 0;
int i;
for (i = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
if (should_validate_capability(i) && s->enabled_capabilities[i]) {
if (should_validate_capability(i) && s->capabilities[i]) {
result++;
}
}
@ -275,7 +275,7 @@ static int configuration_pre_save(void *opaque)
state->capabilities = g_renew(MigrationCapability, state->capabilities,
state->caps_count);
for (i = j = 0; i < MIGRATION_CAPABILITY__MAX; i++) {
if (should_validate_capability(i) && s->enabled_capabilities[i]) {
if (should_validate_capability(i) && s->capabilities[i]) {
state->capabilities[j++] = i;
}
}
@ -325,7 +325,7 @@ static bool configuration_validate_capabilities(SaveState *state)
continue;
}
source_state = test_bit(i, source_caps_bm);
target_state = s->enabled_capabilities[i];
target_state = s->capabilities[i];
if (source_state != target_state) {
error_report("Capability %s is %s, but received capability is %s",
MigrationCapability_str(i),

View File

@ -3583,14 +3583,19 @@ void qemu_init(int argc, char **argv)
machine_class->name, machine_class->deprecation_reason);
}
/*
* Create backends before creating migration objects, so that it can
* check against compatibilities on the backend memories (e.g. postcopy
* over memory-backend-file objects).
*/
qemu_create_late_backends();
/*
* Note: creates a QOM object, must run only after global and
* compat properties have been set up.
*/
migration_object_init();
qemu_create_late_backends();
/* parse features once if machine provides default cpu_type */
current_machine->cpu_type = machine_class->default_cpu_type;
if (cpu_option) {

View File

@ -27,8 +27,36 @@
#ifdef CONFIG_LINUX
#include <sys/vfs.h>
#include <linux/magic.h>
#endif
QemuFsType qemu_fd_getfs(int fd)
{
#ifdef CONFIG_LINUX
struct statfs fs;
int ret;
if (fd < 0) {
return QEMU_FS_TYPE_UNKNOWN;
}
do {
ret = fstatfs(fd, &fs);
} while (ret != 0 && errno == EINTR);
switch (fs.f_type) {
case TMPFS_MAGIC:
return QEMU_FS_TYPE_TMPFS;
case HUGETLBFS_MAGIC:
return QEMU_FS_TYPE_HUGETLBFS;
default:
return QEMU_FS_TYPE_UNKNOWN;
}
#else
return QEMU_FS_TYPE_UNKNOWN;
#endif
}
size_t qemu_fd_getpagesize(int fd)
{
#ifdef CONFIG_LINUX