virDomainMigrate: Introduce VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES flag

Non-shared storage migration of guests which are disk I/O intensive and
have fast local storage may actually never converge if the guest happens
to dirty the disk faster than it can be copied.

This patch introduces a new flag
'VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES' which will instruct
hypervisors to synchronize local I/O writes with the writes to remote
storage used for migration so that the guest can't overwhelm the
migration. This comes at a cost of decreased local I/O performance for
guests which behave well on average.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Peter Krempa 2021-12-01 16:21:29 +01:00
parent 21a9be4412
commit 51d1c08fe9
4 changed files with 48 additions and 1 deletions

View File

@ -3180,7 +3180,7 @@ migrate
[--postcopy-bandwidth bandwidth] [--postcopy-bandwidth bandwidth]
[--parallel [--parallel-connections connections]] [--parallel [--parallel-connections connections]]
[--bandwidth bandwidth] [--tls-destination hostname] [--bandwidth bandwidth] [--tls-destination hostname]
[--disks-uri URI] [--disks-uri URI] [--copy-storage-synchronous-writes]
Migrate domain to another host. Add *--live* for live migration; <--p2p> Migrate domain to another host. Add *--live* for live migration; <--p2p>
for peer-2-peer migration; *--direct* for direct migration; or *--tunnelled* for peer-2-peer migration; *--direct* for direct migration; or *--tunnelled*
@ -3202,6 +3202,10 @@ images on source host to the images found at the same place on the destination
host. By default only non-shared non-readonly images are transferred. Use host. By default only non-shared non-readonly images are transferred. Use
*--migrate-disks* to explicitly specify a list of disk targets to *--migrate-disks* to explicitly specify a list of disk targets to
transfer via the comma separated ``disk-list`` argument. transfer via the comma separated ``disk-list`` argument.
With *--copy-storage-synchronous-writes* flag used the disk data migration will
synchronously handle guest disk writes to both the original soure and the
destination to ensure that the disk migration converges at the price of possibly
decreased burst performance.
*--change-protection* enforces that no incompatible configuration changes will *--change-protection* enforces that no incompatible configuration changes will
be made to the domain while the migration is underway; this flag is implicitly be made to the domain while the migration is underway; this flag is implicitly

View File

@ -850,6 +850,16 @@ typedef enum {
*/ */
VIR_MIGRATE_PARALLEL = (1 << 17), VIR_MIGRATE_PARALLEL = (1 << 17),
/* Force the guest writes which happen when copying disk images for
* non-shared storage migration to be synchronously written to the
* destination. This ensures the storage migration converges for VMs
* doing heavy I/O on fast local storage and slow mirror.
*
* Requires one of VIR_MIGRATE_NON_SHARED_DISK, VIR_MIGRATE_NON_SHARED_INC
* to be present as well.
*/
VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES = (1 << 18),
} virDomainMigrateFlags; } virDomainMigrateFlags;

View File

@ -3567,6 +3567,10 @@ virDomainMigrate(virDomainPtr domain,
VIR_MIGRATE_PARALLEL, VIR_MIGRATE_PARALLEL,
error); error);
VIR_REQUIRE_FLAG_GOTO(VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES,
VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC,
error);
if (flags & VIR_MIGRATE_OFFLINE) { if (flags & VIR_MIGRATE_OFFLINE) {
rc = VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn, rc = VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn,
VIR_DRV_FEATURE_MIGRATION_OFFLINE); VIR_DRV_FEATURE_MIGRATION_OFFLINE);
@ -3760,6 +3764,10 @@ virDomainMigrate2(virDomainPtr domain,
VIR_MIGRATE_PARALLEL, VIR_MIGRATE_PARALLEL,
error); error);
VIR_REQUIRE_FLAG_GOTO(VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES,
VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC,
error);
if (flags & VIR_MIGRATE_OFFLINE) { if (flags & VIR_MIGRATE_OFFLINE) {
rc = VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn, rc = VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn,
VIR_DRV_FEATURE_MIGRATION_OFFLINE); VIR_DRV_FEATURE_MIGRATION_OFFLINE);
@ -3966,6 +3974,14 @@ virDomainMigrate3(virDomainPtr domain,
VIR_MIGRATE_NON_SHARED_INC, VIR_MIGRATE_NON_SHARED_INC,
error); error);
VIR_REQUIRE_FLAG_GOTO(VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES,
VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC,
error);
VIR_REQUIRE_FLAG_GOTO(VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES,
VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC,
error);
if (flags & VIR_MIGRATE_PEER2PEER) { if (flags & VIR_MIGRATE_PEER2PEER) {
virReportInvalidArg(flags, "%s", virReportInvalidArg(flags, "%s",
_("use virDomainMigrateToURI3 for peer-to-peer " _("use virDomainMigrateToURI3 for peer-to-peer "
@ -4137,6 +4153,10 @@ int virDomainMigrateUnmanagedCheckCompat(virDomainPtr domain,
VIR_MIGRATE_NON_SHARED_INC, VIR_MIGRATE_NON_SHARED_INC,
-1); -1);
VIR_REQUIRE_FLAG_RET(VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES,
VIR_MIGRATE_NON_SHARED_DISK | VIR_MIGRATE_NON_SHARED_INC,
-1);
if (flags & VIR_MIGRATE_OFFLINE) { if (flags & VIR_MIGRATE_OFFLINE) {
rc = VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn, rc = VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn,
VIR_DRV_FEATURE_MIGRATION_OFFLINE); VIR_DRV_FEATURE_MIGRATION_OFFLINE);

View File

@ -10543,6 +10543,10 @@ static const vshCmdOptDef opts_migrate[] = {
.type = VSH_OT_BOOL, .type = VSH_OT_BOOL,
.help = N_("migration with non-shared storage with incremental copy (same base image shared between source and destination)") .help = N_("migration with non-shared storage with incremental copy (same base image shared between source and destination)")
}, },
{.name = "copy-storage-synchronous-writes",
.type = VSH_OT_BOOL,
.help = N_("force guest disk writes to be synchronously written to the destination to improve storage migration convergence")
},
{.name = "change-protection", {.name = "change-protection",
.type = VSH_OT_BOOL, .type = VSH_OT_BOOL,
.help = N_("prevent any configuration changes to domain until migration ends") .help = N_("prevent any configuration changes to domain until migration ends")
@ -10949,6 +10953,15 @@ doMigrate(void *opaque)
if (vshCommandOptBool(cmd, "copy-storage-inc")) if (vshCommandOptBool(cmd, "copy-storage-inc"))
flags |= VIR_MIGRATE_NON_SHARED_INC; flags |= VIR_MIGRATE_NON_SHARED_INC;
if (vshCommandOptBool(cmd, "copy-storage-synchronous-writes")) {
if (!(flags & VIR_MIGRATE_NON_SHARED_DISK) &&
!(flags & VIR_MIGRATE_NON_SHARED_INC)) {
vshError(ctl, "'--copy-storage-synchronous-writes' requires one of '--copy-storage-all', 'copy-storage-inc'");
goto out;
}
flags |= VIR_MIGRATE_NON_SHARED_SYNCHRONOUS_WRITES;
}
if (vshCommandOptBool(cmd, "change-protection")) if (vshCommandOptBool(cmd, "change-protection"))
flags |= VIR_MIGRATE_CHANGE_PROTECTION; flags |= VIR_MIGRATE_CHANGE_PROTECTION;