migration/next for 20170316
-----BEGIN PGP SIGNATURE----- iQIcBAABCAAGBQJYyksfAAoJEPSH7xhYctcjC2EP/RitHPcaOhaP54TR0SJOgsVa eVZ2kqXsy641hL85eVVlXV/lNfCko7nACieGEk/Xo6mZoM3r+ta6gafraUR3fzSJ HVCeI9S2UDFO9lc4L3cOSNPJ7+UHae0SfeRikyB/zmltDRda7QIh3SOQ2wTkSoEE UoRmnAGkjXVplaktpaqgrPrh/W/SDH+++lDB46yH6XddMAaVfddoMqG84g6qmhHN 3nwsxzW5VD1dLjdeiDZ5ksSaV0RgJQbsQKOu7+9bmjnIVHH5jdA7usg/AZnarCKl obIMuWz5hxt6uUX98fV6rt9mfBeIyTDi6kP9k16aGqJfWWNSG4g9XwYr2v87R8Io P3Mvjq4WXKnKw/nYgTI48kzmNMgj0FXXYRX90RTSCz1moaAWgDxM0Qgmxe1JwLmP hZXYCmVkXdc6se2N/IAjqXLPw9eJYfPozZTY4CAn1FhCN3gqi8pbaVw3X2tvgdMp VVEBrMzfyTpTsZobndUklIHa6HllCGg5OpZS7WSmKSOy3e+wOFP8KbdBAd6Ir0mQ QL7t0MCS8TZH7+h2Hh84DFcZvhcGFyHcLsOK6+caq9EMwZFnMELp5niUiZ5oI0XH PeWbaaKPt7ra40/Y4JUfkaHuerchO89KiORVooCDc1Ntx2I0LpGCStXJde8MF8qb b117+BQeS/S20S8n5btz =hzT9 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/juanquintela/tags/migration/20170316' into staging migration/next for 20170316 # gpg: Signature made Thu 16 Mar 2017 08:21:51 GMT # gpg: using RSA key 0xF487EF185872D723 # gpg: Good signature from "Juan Quintela <quintela@redhat.com>" # gpg: aka "Juan Quintela <quintela@trasno.org>" # Primary key fingerprint: 1899 FF8E DEBF 58CC EE03 4B82 F487 EF18 5872 D723 * remotes/juanquintela/tags/migration/20170316: postcopy: Check for shared memory RAMBlocks: qemu_ram_is_shared vmstate: fix failed iotests case 68 and 91 migration/block: Avoid invoking blk_drain too frequently migration: use "" as the default for tls-creds/hostname Change the method to calculate dirty-pages-rate Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
c5e737e5fb
5
exec.c
5
exec.c
@ -1561,6 +1561,11 @@ const char *qemu_ram_get_idstr(RAMBlock *rb)
|
|||||||
return rb->idstr;
|
return rb->idstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool qemu_ram_is_shared(RAMBlock *rb)
|
||||||
|
{
|
||||||
|
return rb->flags & RAM_SHARED;
|
||||||
|
}
|
||||||
|
|
||||||
/* Called with iothread lock held. */
|
/* Called with iothread lock held. */
|
||||||
void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev)
|
void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev)
|
||||||
{
|
{
|
||||||
|
@ -69,6 +69,7 @@ RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset,
|
|||||||
void qemu_ram_set_idstr(RAMBlock *block, const char *name, DeviceState *dev);
|
void qemu_ram_set_idstr(RAMBlock *block, const char *name, DeviceState *dev);
|
||||||
void qemu_ram_unset_idstr(RAMBlock *block);
|
void qemu_ram_unset_idstr(RAMBlock *block);
|
||||||
const char *qemu_ram_get_idstr(RAMBlock *rb);
|
const char *qemu_ram_get_idstr(RAMBlock *rb);
|
||||||
|
bool qemu_ram_is_shared(RAMBlock *rb);
|
||||||
size_t qemu_ram_pagesize(RAMBlock *block);
|
size_t qemu_ram_pagesize(RAMBlock *block);
|
||||||
size_t qemu_ram_pagesize_largest(void);
|
size_t qemu_ram_pagesize_largest(void);
|
||||||
|
|
||||||
|
@ -355,7 +355,8 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
|
|||||||
static inline
|
static inline
|
||||||
uint64_t cpu_physical_memory_sync_dirty_bitmap(unsigned long *dest,
|
uint64_t cpu_physical_memory_sync_dirty_bitmap(unsigned long *dest,
|
||||||
ram_addr_t start,
|
ram_addr_t start,
|
||||||
ram_addr_t length)
|
ram_addr_t length,
|
||||||
|
int64_t *real_dirty_pages)
|
||||||
{
|
{
|
||||||
ram_addr_t addr;
|
ram_addr_t addr;
|
||||||
unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS);
|
unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS);
|
||||||
@ -379,6 +380,7 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(unsigned long *dest,
|
|||||||
if (src[idx][offset]) {
|
if (src[idx][offset]) {
|
||||||
unsigned long bits = atomic_xchg(&src[idx][offset], 0);
|
unsigned long bits = atomic_xchg(&src[idx][offset], 0);
|
||||||
unsigned long new_dirty;
|
unsigned long new_dirty;
|
||||||
|
*real_dirty_pages += ctpopl(bits);
|
||||||
new_dirty = ~dest[k];
|
new_dirty = ~dest[k];
|
||||||
dest[k] |= bits;
|
dest[k] |= bits;
|
||||||
new_dirty &= bits;
|
new_dirty &= bits;
|
||||||
@ -398,6 +400,7 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(unsigned long *dest,
|
|||||||
start + addr,
|
start + addr,
|
||||||
TARGET_PAGE_SIZE,
|
TARGET_PAGE_SIZE,
|
||||||
DIRTY_MEMORY_MIGRATION)) {
|
DIRTY_MEMORY_MIGRATION)) {
|
||||||
|
*real_dirty_pages += 1;
|
||||||
long k = (start + addr) >> TARGET_PAGE_BITS;
|
long k = (start + addr) >> TARGET_PAGE_BITS;
|
||||||
if (!test_and_set_bit(k, dest)) {
|
if (!test_and_set_bit(k, dest)) {
|
||||||
num_dirty++;
|
num_dirty++;
|
||||||
|
@ -576,6 +576,9 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bdrv_reset_dirty_bitmap(bmds->dirty_bitmap, sector, nr_sectors);
|
bdrv_reset_dirty_bitmap(bmds->dirty_bitmap, sector, nr_sectors);
|
||||||
|
sector += nr_sectors;
|
||||||
|
bmds->cur_dirty = sector;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sector += BDRV_SECTORS_PER_DIRTY_CHUNK;
|
sector += BDRV_SECTORS_PER_DIRTY_CHUNK;
|
||||||
|
@ -110,6 +110,8 @@ MigrationState *migrate_get_current(void)
|
|||||||
|
|
||||||
if (!once) {
|
if (!once) {
|
||||||
qemu_mutex_init(¤t_migration.src_page_req_mutex);
|
qemu_mutex_init(¤t_migration.src_page_req_mutex);
|
||||||
|
current_migration.parameters.tls_creds = g_strdup("");
|
||||||
|
current_migration.parameters.tls_hostname = g_strdup("");
|
||||||
once = true;
|
once = true;
|
||||||
}
|
}
|
||||||
return ¤t_migration;
|
return ¤t_migration;
|
||||||
@ -458,6 +460,7 @@ void migration_channel_process_incoming(MigrationState *s,
|
|||||||
ioc, object_get_typename(OBJECT(ioc)));
|
ioc, object_get_typename(OBJECT(ioc)));
|
||||||
|
|
||||||
if (s->parameters.tls_creds &&
|
if (s->parameters.tls_creds &&
|
||||||
|
*s->parameters.tls_creds &&
|
||||||
!object_dynamic_cast(OBJECT(ioc),
|
!object_dynamic_cast(OBJECT(ioc),
|
||||||
TYPE_QIO_CHANNEL_TLS)) {
|
TYPE_QIO_CHANNEL_TLS)) {
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
@ -480,6 +483,7 @@ void migration_channel_connect(MigrationState *s,
|
|||||||
ioc, object_get_typename(OBJECT(ioc)), hostname);
|
ioc, object_get_typename(OBJECT(ioc)), hostname);
|
||||||
|
|
||||||
if (s->parameters.tls_creds &&
|
if (s->parameters.tls_creds &&
|
||||||
|
*s->parameters.tls_creds &&
|
||||||
!object_dynamic_cast(OBJECT(ioc),
|
!object_dynamic_cast(OBJECT(ioc),
|
||||||
TYPE_QIO_CHANNEL_TLS)) {
|
TYPE_QIO_CHANNEL_TLS)) {
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
@ -95,6 +95,19 @@ static bool ufd_version_check(int ufd)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Callback from postcopy_ram_supported_by_host block iterator.
|
||||||
|
*/
|
||||||
|
static int test_range_shared(const char *block_name, void *host_addr,
|
||||||
|
ram_addr_t offset, ram_addr_t length, void *opaque)
|
||||||
|
{
|
||||||
|
if (qemu_ram_is_shared(qemu_ram_block_by_name(block_name))) {
|
||||||
|
error_report("Postcopy on shared RAM (%s) is not yet supported",
|
||||||
|
block_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Note: This has the side effect of munlock'ing all of RAM, that's
|
* Note: This has the side effect of munlock'ing all of RAM, that's
|
||||||
* normally fine since if the postcopy succeeds it gets turned back on at the
|
* normally fine since if the postcopy succeeds it gets turned back on at the
|
||||||
@ -127,6 +140,11 @@ bool postcopy_ram_supported_by_host(void)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We don't support postcopy with shared RAM yet */
|
||||||
|
if (qemu_ram_foreach_block(test_range_shared, NULL)) {
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* userfault and mlock don't go together; we'll put it back later if
|
* userfault and mlock don't go together; we'll put it back later if
|
||||||
* it was enabled.
|
* it was enabled.
|
||||||
|
@ -576,18 +576,18 @@ static inline bool migration_bitmap_clear_dirty(ram_addr_t addr)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int64_t num_dirty_pages_period;
|
||||||
static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length)
|
static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length)
|
||||||
{
|
{
|
||||||
unsigned long *bitmap;
|
unsigned long *bitmap;
|
||||||
bitmap = atomic_rcu_read(&migration_bitmap_rcu)->bmap;
|
bitmap = atomic_rcu_read(&migration_bitmap_rcu)->bmap;
|
||||||
migration_dirty_pages +=
|
migration_dirty_pages += cpu_physical_memory_sync_dirty_bitmap(bitmap,
|
||||||
cpu_physical_memory_sync_dirty_bitmap(bitmap, start, length);
|
start, length, &num_dirty_pages_period);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix me: there are too many global variables used in migration process. */
|
/* Fix me: there are too many global variables used in migration process. */
|
||||||
static int64_t start_time;
|
static int64_t start_time;
|
||||||
static int64_t bytes_xfer_prev;
|
static int64_t bytes_xfer_prev;
|
||||||
static int64_t num_dirty_pages_period;
|
|
||||||
static uint64_t xbzrle_cache_miss_prev;
|
static uint64_t xbzrle_cache_miss_prev;
|
||||||
static uint64_t iterations_prev;
|
static uint64_t iterations_prev;
|
||||||
|
|
||||||
@ -620,7 +620,6 @@ uint64_t ram_pagesize_summary(void)
|
|||||||
static void migration_bitmap_sync(void)
|
static void migration_bitmap_sync(void)
|
||||||
{
|
{
|
||||||
RAMBlock *block;
|
RAMBlock *block;
|
||||||
uint64_t num_dirty_pages_init = migration_dirty_pages;
|
|
||||||
MigrationState *s = migrate_get_current();
|
MigrationState *s = migrate_get_current();
|
||||||
int64_t end_time;
|
int64_t end_time;
|
||||||
int64_t bytes_xfer_now;
|
int64_t bytes_xfer_now;
|
||||||
@ -646,9 +645,8 @@ static void migration_bitmap_sync(void)
|
|||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
qemu_mutex_unlock(&migration_bitmap_mutex);
|
qemu_mutex_unlock(&migration_bitmap_mutex);
|
||||||
|
|
||||||
trace_migration_bitmap_sync_end(migration_dirty_pages
|
trace_migration_bitmap_sync_end(num_dirty_pages_period);
|
||||||
- num_dirty_pages_init);
|
|
||||||
num_dirty_pages_period += migration_dirty_pages - num_dirty_pages_init;
|
|
||||||
end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
||||||
|
|
||||||
/* more than 1 second = 1000 millisecons */
|
/* more than 1 second = 1000 millisecons */
|
||||||
|
@ -141,7 +141,7 @@ void migration_tls_channel_connect(MigrationState *s,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->parameters.tls_hostname) {
|
if (s->parameters.tls_hostname && *s->parameters.tls_hostname) {
|
||||||
hostname = s->parameters.tls_hostname;
|
hostname = s->parameters.tls_hostname;
|
||||||
}
|
}
|
||||||
if (!hostname) {
|
if (!hostname) {
|
||||||
|
@ -109,7 +109,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
|
|||||||
vmstate_handle_alloc(first_elem, field, opaque);
|
vmstate_handle_alloc(first_elem, field, opaque);
|
||||||
if (field->flags & VMS_POINTER) {
|
if (field->flags & VMS_POINTER) {
|
||||||
first_elem = *(void **)first_elem;
|
first_elem = *(void **)first_elem;
|
||||||
assert(first_elem || !n_elems);
|
assert(first_elem || !n_elems || !size);
|
||||||
}
|
}
|
||||||
for (i = 0; i < n_elems; i++) {
|
for (i = 0; i < n_elems; i++) {
|
||||||
void *curr_elem = first_elem + size * i;
|
void *curr_elem = first_elem + size * i;
|
||||||
@ -117,7 +117,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
|
|||||||
if (field->flags & VMS_ARRAY_OF_POINTER) {
|
if (field->flags & VMS_ARRAY_OF_POINTER) {
|
||||||
curr_elem = *(void **)curr_elem;
|
curr_elem = *(void **)curr_elem;
|
||||||
}
|
}
|
||||||
if (!curr_elem) {
|
if (!curr_elem && size) {
|
||||||
/* if null pointer check placeholder and do not follow */
|
/* if null pointer check placeholder and do not follow */
|
||||||
assert(field->flags & VMS_ARRAY_OF_POINTER);
|
assert(field->flags & VMS_ARRAY_OF_POINTER);
|
||||||
ret = vmstate_info_nullptr.get(f, curr_elem, size, NULL);
|
ret = vmstate_info_nullptr.get(f, curr_elem, size, NULL);
|
||||||
@ -325,7 +325,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
|
|||||||
trace_vmstate_save_state_loop(vmsd->name, field->name, n_elems);
|
trace_vmstate_save_state_loop(vmsd->name, field->name, n_elems);
|
||||||
if (field->flags & VMS_POINTER) {
|
if (field->flags & VMS_POINTER) {
|
||||||
first_elem = *(void **)first_elem;
|
first_elem = *(void **)first_elem;
|
||||||
assert(first_elem || !n_elems);
|
assert(first_elem || !n_elems || !size);
|
||||||
}
|
}
|
||||||
for (i = 0; i < n_elems; i++) {
|
for (i = 0; i < n_elems; i++) {
|
||||||
void *curr_elem = first_elem + size * i;
|
void *curr_elem = first_elem + size * i;
|
||||||
@ -336,7 +336,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
|
|||||||
assert(curr_elem);
|
assert(curr_elem);
|
||||||
curr_elem = *(void **)curr_elem;
|
curr_elem = *(void **)curr_elem;
|
||||||
}
|
}
|
||||||
if (!curr_elem) {
|
if (!curr_elem && size) {
|
||||||
/* if null pointer write placeholder and do not follow */
|
/* if null pointer write placeholder and do not follow */
|
||||||
assert(field->flags & VMS_ARRAY_OF_POINTER);
|
assert(field->flags & VMS_ARRAY_OF_POINTER);
|
||||||
vmstate_info_nullptr.put(f, curr_elem, size, NULL, NULL);
|
vmstate_info_nullptr.put(f, curr_elem, size, NULL, NULL);
|
||||||
|
@ -1059,6 +1059,8 @@
|
|||||||
# credentials must be for a 'server' endpoint. Setting this
|
# credentials must be for a 'server' endpoint. Setting this
|
||||||
# will enable TLS for all migrations. The default is unset,
|
# will enable TLS for all migrations. The default is unset,
|
||||||
# resulting in unsecured migration at the QEMU level. (Since 2.7)
|
# resulting in unsecured migration at the QEMU level. (Since 2.7)
|
||||||
|
# An empty string means that QEMU will use plain text mode for
|
||||||
|
# migration, rather than TLS (Since 2.9)
|
||||||
#
|
#
|
||||||
# @tls-hostname: hostname of the target host for the migration. This
|
# @tls-hostname: hostname of the target host for the migration. This
|
||||||
# is required when using x509 based TLS credentials and the
|
# is required when using x509 based TLS credentials and the
|
||||||
@ -1066,6 +1068,8 @@
|
|||||||
# example if using fd: or exec: based migration, the
|
# example if using fd: or exec: based migration, the
|
||||||
# hostname must be provided so that the server's x509
|
# hostname must be provided so that the server's x509
|
||||||
# certificate identity can be validated. (Since 2.7)
|
# certificate identity can be validated. (Since 2.7)
|
||||||
|
# An empty string means that QEMU will use the hostname
|
||||||
|
# associated with the migration URI, if any. (Since 2.9)
|
||||||
#
|
#
|
||||||
# @max-bandwidth: to set maximum speed for migration. maximum speed in
|
# @max-bandwidth: to set maximum speed for migration. maximum speed in
|
||||||
# bytes per second. (Since 2.8)
|
# bytes per second. (Since 2.8)
|
||||||
|
Loading…
Reference in New Issue
Block a user