V2 migration+virtiofs fixes pull 2021-04-07

A seg fix in virtiofsd, a bunch of fixes for background snapshots, and
 a migration test fix.
 
 Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
 
 v2
   Fix for !linux build
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEERfXHG0oMt/uXep+pBRYzHrxb/ecFAmBt8YkACgkQBRYzHrxb
 /efHNBAAismdo7L9iU8hUpvIuFbdLzREoYH3vqbZT6K1zjbmabpqbmMkcPQvj9Oo
 St9uSdq+6oOMrMi3r0oDpkb2F2csbIdPLQ7a2Y3hZTbzsUJXmI6eoYuSLUNRkvP1
 57MoUienK5TsATGFFPd3MuAvwHVOIBZGgg8aeYkC5RiltlQx42IQ4SEtc7yXSrnp
 TbjS45kd5I13crH4RxNG4X2/cG8McVYCSzEUMPBqbvNFiw2dJTOWr2kzza0jh4tP
 0VsgjeqPIoYa4n7LZEs7BgSiXcFcOPbUXvZ/ho7wHOLckhKlbdhJgklBUOom5aqO
 RZcN1XyPdzcKoxpch3T5d0h/YdEXEQSS7zdLBJDx4bUfb1ZhjEq0RhXqdYJ9YFEG
 dZTtxaxzW4u8UhPom4Eu0/HNyaqvjyqGrTxCpnS5fHH6pJKtdVhH7WfdEyYHj4lp
 PkEoKuTPZClk7Fjdsc329vHtIv0+rrWxBWtzFmrPgj13Xy8CkOOmKlYO2BhwI5zb
 j76s+y3IGNas4pJqhksNBE8AaODZ2IB8hq5dnqb9EsX4gtbOwhXYlA6aZY0EokiS
 VPbQ76emdE79A/vjArBkfiHsDzUkNe+sBSmreHBxzij/mmaXMP4mcVGew5dNfCFm
 TQrG9C1oH445yopZIXukcOOZofS3met90m6bbZO0DfAX+wXAAQM=
 =FKJ4
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/dgilbert/tags/pull-migration-20210407b' into staging

V2 migration+virtiofs fixes pull 2021-04-07

A seg fix in virtiofsd, a bunch of fixes for background snapshots, and
a migration test fix.

Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>

v2
  Fix for !linux build

# gpg: Signature made Wed 07 Apr 2021 18:53:13 BST
# gpg:                using RSA key 45F5C71B4A0CB7FB977A9FA90516331EBC5BFDE7
# gpg: Good signature from "Dr. David Alan Gilbert (RH2) <dgilbert@redhat.com>" [full]
# Primary key fingerprint: 45F5 C71B 4A0C B7FB 977A  9FA9 0516 331E BC5B FDE7

* remotes/dgilbert/tags/pull-migration-20210407b:
  tests/migration: fix parameter of auto-converge migration
  migration: Rename 'bs' to 'block' in background snapshot code
  migration: Pre-fault memory before starting background snasphot
  migration: Inhibit virtio-balloon for the duration of background snapshot
  migration: Fix missing qemu_fflush() on buffer file in bg_migration_thread
  virtiofsd: Fix security.capability comparison

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-04-08 14:00:57 +01:00
commit d8724020dd
7 changed files with 121 additions and 40 deletions

View File

@ -66,8 +66,12 @@ static bool virtio_balloon_pbp_matches(PartiallyBalloonedPage *pbp,
static bool virtio_balloon_inhibited(void)
{
/* Postcopy cannot deal with concurrent discards, so it's special. */
return ram_block_discard_is_disabled() || migration_in_incoming_postcopy();
/*
* Postcopy cannot deal with concurrent discards,
* so it's special, as well as background snapshots.
*/
return ram_block_discard_is_disabled() || migration_in_incoming_postcopy() ||
migration_in_bg_snapshot();
}
static void balloon_inflate_page(VirtIOBalloon *balloon,

View File

@ -70,6 +70,8 @@ bool migration_in_postcopy_after_devices(MigrationState *);
void migration_global_dump(Monitor *mon);
/* True if incomming migration entered POSTCOPY_INCOMING_DISCARD */
bool migration_in_incoming_postcopy(void);
/* True if background snapshot is active */
bool migration_in_bg_snapshot(void);
/* migration/block-dirty-bitmap.c */
void dirty_bitmap_mig_init(void);

View File

@ -1976,6 +1976,14 @@ bool migration_in_incoming_postcopy(void)
return ps >= POSTCOPY_INCOMING_DISCARD && ps < POSTCOPY_INCOMING_END;
}
bool migration_in_bg_snapshot(void)
{
MigrationState *s = migrate_get_current();
return migrate_background_snapshot() &&
migration_is_setup_or_active(s->state);
}
bool migration_is_idle(void)
{
MigrationState *s = current_migration;
@ -3812,13 +3820,21 @@ static void *bg_migration_thread(void *opaque)
* with vCPUs running and, finally, write stashed non-RAM part of
* the vmstate from the buffer to the migration stream.
*/
s->bioc = qio_channel_buffer_new(128 * 1024);
s->bioc = qio_channel_buffer_new(512 * 1024);
qio_channel_set_name(QIO_CHANNEL(s->bioc), "vmstate-buffer");
fb = qemu_fopen_channel_output(QIO_CHANNEL(s->bioc));
object_unref(OBJECT(s->bioc));
update_iteration_initial_status(s);
/*
* Prepare for tracking memory writes with UFFD-WP - populate
* RAM pages before protecting.
*/
#ifdef __linux__
ram_write_tracking_prepare();
#endif
qemu_savevm_state_header(s->to_dst_file);
qemu_savevm_state_setup(s->to_dst_file);
@ -3866,6 +3882,12 @@ static void *bg_migration_thread(void *opaque)
if (qemu_savevm_state_complete_precopy_non_iterable(fb, false, false)) {
goto fail;
}
/*
* Since we are going to get non-iterable state data directly
* from s->bioc->data, explicit flush is needed here.
*/
qemu_fflush(fb);
/* Now initialize UFFD context and start tracking RAM writes */
if (ram_write_tracking_start()) {
goto fail;

View File

@ -1455,7 +1455,7 @@ static RAMBlock *poll_fault_page(RAMState *rs, ram_addr_t *offset)
{
struct uffd_msg uffd_msg;
void *page_address;
RAMBlock *bs;
RAMBlock *block;
int res;
if (!migrate_background_snapshot()) {
@ -1468,9 +1468,9 @@ static RAMBlock *poll_fault_page(RAMState *rs, ram_addr_t *offset)
}
page_address = (void *)(uintptr_t) uffd_msg.arg.pagefault.address;
bs = qemu_ram_block_from_host(page_address, false, offset);
assert(bs && (bs->flags & RAM_UF_WRITEPROTECT) != 0);
return bs;
block = qemu_ram_block_from_host(page_address, false, offset);
assert(block && (block->flags & RAM_UF_WRITEPROTECT) != 0);
return block;
}
/**
@ -1526,7 +1526,7 @@ bool ram_write_tracking_compatible(void)
{
const uint64_t uffd_ioctls_mask = BIT(_UFFDIO_WRITEPROTECT);
int uffd_fd;
RAMBlock *bs;
RAMBlock *block;
bool ret = false;
/* Open UFFD file descriptor */
@ -1537,15 +1537,15 @@ bool ram_write_tracking_compatible(void)
RCU_READ_LOCK_GUARD();
RAMBLOCK_FOREACH_NOT_IGNORED(bs) {
RAMBLOCK_FOREACH_NOT_IGNORED(block) {
uint64_t uffd_ioctls;
/* Nothing to do with read-only and MMIO-writable regions */
if (bs->mr->readonly || bs->mr->rom_device) {
if (block->mr->readonly || block->mr->rom_device) {
continue;
}
/* Try to register block memory via UFFD-IO to track writes */
if (uffd_register_memory(uffd_fd, bs->host, bs->max_length,
if (uffd_register_memory(uffd_fd, block->host, block->max_length,
UFFDIO_REGISTER_MODE_WP, &uffd_ioctls)) {
goto out;
}
@ -1560,6 +1560,55 @@ out:
return ret;
}
/*
* ram_block_populate_pages: populate memory in the RAM block by reading
* an integer from the beginning of each page.
*
* Since it's solely used for userfault_fd WP feature, here we just
* hardcode page size to qemu_real_host_page_size.
*
* @block: RAM block to populate
*/
static void ram_block_populate_pages(RAMBlock *block)
{
char *ptr = (char *) block->host;
for (ram_addr_t offset = 0; offset < block->used_length;
offset += qemu_real_host_page_size) {
char tmp = *(ptr + offset);
/* Don't optimize the read out */
asm volatile("" : "+r" (tmp));
}
}
/*
* ram_write_tracking_prepare: prepare for UFFD-WP memory tracking
*/
void ram_write_tracking_prepare(void)
{
RAMBlock *block;
RCU_READ_LOCK_GUARD();
RAMBLOCK_FOREACH_NOT_IGNORED(block) {
/* Nothing to do with read-only and MMIO-writable regions */
if (block->mr->readonly || block->mr->rom_device) {
continue;
}
/*
* Populate pages of the RAM block before enabling userfault_fd
* write protection.
*
* This stage is required since ioctl(UFFDIO_WRITEPROTECT) with
* UFFDIO_WRITEPROTECT_MODE_WP mode setting would silently skip
* pages with pte_none() entries in page table.
*/
ram_block_populate_pages(block);
}
}
/*
* ram_write_tracking_start: start UFFD-WP memory tracking
*
@ -1569,7 +1618,7 @@ int ram_write_tracking_start(void)
{
int uffd_fd;
RAMState *rs = ram_state;
RAMBlock *bs;
RAMBlock *block;
/* Open UFFD file descriptor */
uffd_fd = uffd_create_fd(UFFD_FEATURE_PAGEFAULT_FLAG_WP, true);
@ -1580,27 +1629,27 @@ int ram_write_tracking_start(void)
RCU_READ_LOCK_GUARD();
RAMBLOCK_FOREACH_NOT_IGNORED(bs) {
RAMBLOCK_FOREACH_NOT_IGNORED(block) {
/* Nothing to do with read-only and MMIO-writable regions */
if (bs->mr->readonly || bs->mr->rom_device) {
if (block->mr->readonly || block->mr->rom_device) {
continue;
}
/* Register block memory with UFFD to track writes */
if (uffd_register_memory(rs->uffdio_fd, bs->host,
bs->max_length, UFFDIO_REGISTER_MODE_WP, NULL)) {
if (uffd_register_memory(rs->uffdio_fd, block->host,
block->max_length, UFFDIO_REGISTER_MODE_WP, NULL)) {
goto fail;
}
/* Apply UFFD write protection to the block memory range */
if (uffd_change_protection(rs->uffdio_fd, bs->host,
bs->max_length, true, false)) {
if (uffd_change_protection(rs->uffdio_fd, block->host,
block->max_length, true, false)) {
goto fail;
}
bs->flags |= RAM_UF_WRITEPROTECT;
memory_region_ref(bs->mr);
block->flags |= RAM_UF_WRITEPROTECT;
memory_region_ref(block->mr);
trace_ram_write_tracking_ramblock_start(bs->idstr, bs->page_size,
bs->host, bs->max_length);
trace_ram_write_tracking_ramblock_start(block->idstr, block->page_size,
block->host, block->max_length);
}
return 0;
@ -1608,19 +1657,20 @@ int ram_write_tracking_start(void)
fail:
error_report("ram_write_tracking_start() failed: restoring initial memory state");
RAMBLOCK_FOREACH_NOT_IGNORED(bs) {
if ((bs->flags & RAM_UF_WRITEPROTECT) == 0) {
RAMBLOCK_FOREACH_NOT_IGNORED(block) {
if ((block->flags & RAM_UF_WRITEPROTECT) == 0) {
continue;
}
/*
* In case some memory block failed to be write-protected
* remove protection and unregister all succeeded RAM blocks
*/
uffd_change_protection(rs->uffdio_fd, bs->host, bs->max_length, false, false);
uffd_unregister_memory(rs->uffdio_fd, bs->host, bs->max_length);
uffd_change_protection(rs->uffdio_fd, block->host, block->max_length,
false, false);
uffd_unregister_memory(rs->uffdio_fd, block->host, block->max_length);
/* Cleanup flags and remove reference */
bs->flags &= ~RAM_UF_WRITEPROTECT;
memory_region_unref(bs->mr);
block->flags &= ~RAM_UF_WRITEPROTECT;
memory_region_unref(block->mr);
}
uffd_close_fd(uffd_fd);
@ -1634,24 +1684,25 @@ fail:
void ram_write_tracking_stop(void)
{
RAMState *rs = ram_state;
RAMBlock *bs;
RAMBlock *block;
RCU_READ_LOCK_GUARD();
RAMBLOCK_FOREACH_NOT_IGNORED(bs) {
if ((bs->flags & RAM_UF_WRITEPROTECT) == 0) {
RAMBLOCK_FOREACH_NOT_IGNORED(block) {
if ((block->flags & RAM_UF_WRITEPROTECT) == 0) {
continue;
}
/* Remove protection and unregister all affected RAM blocks */
uffd_change_protection(rs->uffdio_fd, bs->host, bs->max_length, false, false);
uffd_unregister_memory(rs->uffdio_fd, bs->host, bs->max_length);
uffd_change_protection(rs->uffdio_fd, block->host, block->max_length,
false, false);
uffd_unregister_memory(rs->uffdio_fd, block->host, block->max_length);
trace_ram_write_tracking_ramblock_stop(bs->idstr, bs->page_size,
bs->host, bs->max_length);
trace_ram_write_tracking_ramblock_stop(block->idstr, block->page_size,
block->host, block->max_length);
/* Cleanup flags and remove reference */
bs->flags &= ~RAM_UF_WRITEPROTECT;
memory_region_unref(bs->mr);
block->flags &= ~RAM_UF_WRITEPROTECT;
memory_region_unref(block->mr);
}
/* Finally close UFFD file descriptor */

View File

@ -82,6 +82,7 @@ void colo_incoming_start_dirty_log(void);
/* Background snapshot */
bool ram_write_tracking_available(void);
bool ram_write_tracking_compatible(void);
void ram_write_tracking_prepare(void);
int ram_write_tracking_start(void);
void ram_write_tracking_stop(void);

View File

@ -102,7 +102,7 @@ class Engine(object):
info.get("downtime", 0),
info.get("expected-downtime", 0),
info.get("setup-time", 0),
info.get("x-cpu-throttle-percentage", 0),
info.get("cpu-throttle-percentage", 0),
)
def _migrate(self, hardware, scenario, src, dst, connect_uri):
@ -135,7 +135,7 @@ class Engine(object):
"state": True }
])
resp = src.command("migrate-set-parameters",
x_cpu_throttle_increment=scenario._auto_converge_step)
cpu_throttle_increment=scenario._auto_converge_step)
if scenario._post_copy:
resp = src.command("migrate-set-capabilities",

View File

@ -2636,7 +2636,8 @@ static void parse_xattrmap(struct lo_data *lo)
strerror(ret));
exit(1);
}
if (!strcmp(lo->xattr_security_capability, "security.capability")) {
if (!lo->xattr_security_capability ||
!strcmp(lo->xattr_security_capability, "security.capability")) {
/* 1-1 mapping, don't need to do anything */
free(lo->xattr_security_capability);
lo->xattr_security_capability = NULL;