aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--exec.c5
-rw-r--r--include/exec/cpu-common.h1
-rw-r--r--include/exec/ram_addr.h5
-rw-r--r--migration/block.c3
-rw-r--r--migration/migration.c4
-rw-r--r--migration/postcopy-ram.c18
-rw-r--r--migration/ram.c12
-rw-r--r--migration/tls.c2
-rw-r--r--migration/vmstate.c8
-rw-r--r--qapi-schema.json4
10 files changed, 49 insertions, 13 deletions
diff --git a/exec.c b/exec.c
index a22f5a0..e57a8a2 100644
--- a/exec.c
+++ b/exec.c
@@ -1561,6 +1561,11 @@ const char *qemu_ram_get_idstr(RAMBlock *rb)
return rb->idstr;
}
+bool qemu_ram_is_shared(RAMBlock *rb)
+{
+ return rb->flags & RAM_SHARED;
+}
+
/* Called with iothread lock held. */
void qemu_ram_set_idstr(RAMBlock *new_block, const char *name, DeviceState *dev)
{
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index b62f0d8..4d45a72 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -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_unset_idstr(RAMBlock *block);
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_largest(void);
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h
index cd432e7..b05dc84 100644
--- a/include/exec/ram_addr.h
+++ b/include/exec/ram_addr.h
@@ -355,7 +355,8 @@ static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start,
static inline
uint64_t cpu_physical_memory_sync_dirty_bitmap(unsigned long *dest,
ram_addr_t start,
- ram_addr_t length)
+ ram_addr_t length,
+ int64_t *real_dirty_pages)
{
ram_addr_t addr;
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]) {
unsigned long bits = atomic_xchg(&src[idx][offset], 0);
unsigned long new_dirty;
+ *real_dirty_pages += ctpopl(bits);
new_dirty = ~dest[k];
dest[k] |= bits;
new_dirty &= bits;
@@ -398,6 +400,7 @@ uint64_t cpu_physical_memory_sync_dirty_bitmap(unsigned long *dest,
start + addr,
TARGET_PAGE_SIZE,
DIRTY_MEMORY_MIGRATION)) {
+ *real_dirty_pages += 1;
long k = (start + addr) >> TARGET_PAGE_BITS;
if (!test_and_set_bit(k, dest)) {
num_dirty++;
diff --git a/migration/block.c b/migration/block.c
index 6741228..7734ff7 100644
--- a/migration/block.c
+++ b/migration/block.c
@@ -576,6 +576,9 @@ static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
}
bdrv_reset_dirty_bitmap(bmds->dirty_bitmap, sector, nr_sectors);
+ sector += nr_sectors;
+ bmds->cur_dirty = sector;
+
break;
}
sector += BDRV_SECTORS_PER_DIRTY_CHUNK;
diff --git a/migration/migration.c b/migration/migration.c
index 3dab684..54060f7 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -110,6 +110,8 @@ MigrationState *migrate_get_current(void)
if (!once) {
qemu_mutex_init(&current_migration.src_page_req_mutex);
+ current_migration.parameters.tls_creds = g_strdup("");
+ current_migration.parameters.tls_hostname = g_strdup("");
once = true;
}
return &current_migration;
@@ -458,6 +460,7 @@ void migration_channel_process_incoming(MigrationState *s,
ioc, object_get_typename(OBJECT(ioc)));
if (s->parameters.tls_creds &&
+ *s->parameters.tls_creds &&
!object_dynamic_cast(OBJECT(ioc),
TYPE_QIO_CHANNEL_TLS)) {
Error *local_err = NULL;
@@ -480,6 +483,7 @@ void migration_channel_connect(MigrationState *s,
ioc, object_get_typename(OBJECT(ioc)), hostname);
if (s->parameters.tls_creds &&
+ *s->parameters.tls_creds &&
!object_dynamic_cast(OBJECT(ioc),
TYPE_QIO_CHANNEL_TLS)) {
Error *local_err = NULL;
diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c
index effbeb6..dc80dbb 100644
--- a/migration/postcopy-ram.c
+++ b/migration/postcopy-ram.c
@@ -95,6 +95,19 @@ static bool ufd_version_check(int ufd)
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
* 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;
}
+ /* 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
* it was enabled.
diff --git a/migration/ram.c b/migration/ram.c
index 719425b..de1e0a3 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -576,18 +576,18 @@ static inline bool migration_bitmap_clear_dirty(ram_addr_t addr)
return ret;
}
+static int64_t num_dirty_pages_period;
static void migration_bitmap_sync_range(ram_addr_t start, ram_addr_t length)
{
unsigned long *bitmap;
bitmap = atomic_rcu_read(&migration_bitmap_rcu)->bmap;
- migration_dirty_pages +=
- cpu_physical_memory_sync_dirty_bitmap(bitmap, start, length);
+ migration_dirty_pages += cpu_physical_memory_sync_dirty_bitmap(bitmap,
+ start, length, &num_dirty_pages_period);
}
/* Fix me: there are too many global variables used in migration process. */
static int64_t start_time;
static int64_t bytes_xfer_prev;
-static int64_t num_dirty_pages_period;
static uint64_t xbzrle_cache_miss_prev;
static uint64_t iterations_prev;
@@ -620,7 +620,6 @@ uint64_t ram_pagesize_summary(void)
static void migration_bitmap_sync(void)
{
RAMBlock *block;
- uint64_t num_dirty_pages_init = migration_dirty_pages;
MigrationState *s = migrate_get_current();
int64_t end_time;
int64_t bytes_xfer_now;
@@ -646,9 +645,8 @@ static void migration_bitmap_sync(void)
rcu_read_unlock();
qemu_mutex_unlock(&migration_bitmap_mutex);
- trace_migration_bitmap_sync_end(migration_dirty_pages
- - num_dirty_pages_init);
- num_dirty_pages_period += migration_dirty_pages - num_dirty_pages_init;
+ trace_migration_bitmap_sync_end(num_dirty_pages_period);
+
end_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
/* more than 1 second = 1000 millisecons */
diff --git a/migration/tls.c b/migration/tls.c
index 203c11d..45bec44 100644
--- a/migration/tls.c
+++ b/migration/tls.c
@@ -141,7 +141,7 @@ void migration_tls_channel_connect(MigrationState *s,
return;
}
- if (s->parameters.tls_hostname) {
+ if (s->parameters.tls_hostname && *s->parameters.tls_hostname) {
hostname = s->parameters.tls_hostname;
}
if (!hostname) {
diff --git a/migration/vmstate.c b/migration/vmstate.c
index 78b3cd4..7b4a607 100644
--- a/migration/vmstate.c
+++ b/migration/vmstate.c
@@ -109,7 +109,7 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
vmstate_handle_alloc(first_elem, field, opaque);
if (field->flags & VMS_POINTER) {
first_elem = *(void **)first_elem;
- assert(first_elem || !n_elems);
+ assert(first_elem || !n_elems || !size);
}
for (i = 0; i < n_elems; 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) {
curr_elem = *(void **)curr_elem;
}
- if (!curr_elem) {
+ if (!curr_elem && size) {
/* if null pointer check placeholder and do not follow */
assert(field->flags & VMS_ARRAY_OF_POINTER);
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);
if (field->flags & VMS_POINTER) {
first_elem = *(void **)first_elem;
- assert(first_elem || !n_elems);
+ assert(first_elem || !n_elems || !size);
}
for (i = 0; i < n_elems; i++) {
void *curr_elem = first_elem + size * i;
@@ -336,7 +336,7 @@ void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
assert(curr_elem);
curr_elem = *(void **)curr_elem;
}
- if (!curr_elem) {
+ if (!curr_elem && size) {
/* if null pointer write placeholder and do not follow */
assert(field->flags & VMS_ARRAY_OF_POINTER);
vmstate_info_nullptr.put(f, curr_elem, size, NULL, NULL);
diff --git a/qapi-schema.json b/qapi-schema.json
index 1d7b1cd..68a4327 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1059,6 +1059,8 @@
# credentials must be for a 'server' endpoint. Setting this
# will enable TLS for all migrations. The default is unset,
# 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
# is required when using x509 based TLS credentials and the
@@ -1066,6 +1068,8 @@
# example if using fd: or exec: based migration, the
# hostname must be provided so that the server's x509
# 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
# bytes per second. (Since 2.8)