From 0ca45005d7d45311b062a61805c1049c32b0b9db Mon Sep 17 00:00:00 2001 From: Peter Krempa Date: Mon, 8 Sep 2025 17:50:22 +0200 Subject: [PATCH] qemuMigrationSrcIsSafeDisk: Extract safe migration checks for one storage source MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Further split up the code originally in 'qemuMigrationSrcIsSafe' to separate checks concerning a single storage source. The code will then be reused to check the safe migration state also for the data file (qcow2 feature that allows store of data separated from the qcow2 metadata). Signed-off-by: Peter Krempa Reviewed-by: Ján Tomko --- src/qemu/qemu_migration.c | 71 ++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c index 96709dfcdd..ae26f74f8c 100644 --- a/src/qemu/qemu_migration.c +++ b/src/qemu/qemu_migration.c @@ -1733,40 +1733,34 @@ qemuMigrationSrcIsAllowed(virDomainObj *vm, } -static bool -qemuMigrationSrcIsSafeDisk(virDomainDiskDef *disk, - virQEMUCaps *qemuCaps, - virQEMUDriverConfig *cfg) +static int +qemuMigrationSrcCheckStorageSourceSafety(virStorageSource *src, + virQEMUDriverConfig *cfg, + bool *unsafe_storage, + bool *requires_safe_cache) { - virStorageType actualType = virStorageSourceGetActualType(disk->src); - bool unsafe = false; - int rc; + switch (virStorageSourceGetActualType(src)) { + case VIR_STORAGE_TYPE_FILE: { + int rc_cluster = virFileIsClusterFS(src->path); + int rc_shared = virFileIsSharedFS(src->path, cfg->sharedFilesystems); - /* Disks without any source (i.e. floppies and CD-ROMs) OR readonly are safe. */ - if (virStorageSourceIsEmpty(disk->src) || - disk->src->readonly) - return true; + if (rc_cluster < 0 || rc_shared < 0) + return -1; - /* However, disks on local FS (e.g. ext4) are not safe. */ - switch (actualType) { - case VIR_STORAGE_TYPE_FILE: - if ((rc = virFileIsSharedFS(disk->src->path, cfg->sharedFilesystems)) < 0) { - return false; - } else if (rc == 0) { - unsafe = true; - } + if (rc_cluster == 0) { + *requires_safe_cache = true; - if ((rc = virFileIsClusterFS(disk->src->path)) < 0) - return false; - else if (rc == 1) - return true; + if (rc_shared == 0) + *unsafe_storage = true; + } + } break; case VIR_STORAGE_TYPE_NETWORK: - return true; + break; case VIR_STORAGE_TYPE_NVME: - unsafe = true; + *unsafe_storage = true; break; case VIR_STORAGE_TYPE_VHOST_USER: @@ -1776,10 +1770,32 @@ qemuMigrationSrcIsSafeDisk(virDomainDiskDef *disk, case VIR_STORAGE_TYPE_DIR: case VIR_STORAGE_TYPE_VOLUME: case VIR_STORAGE_TYPE_LAST: + *requires_safe_cache = true; break; } - if (unsafe) { + return 0; +} + + +static bool +qemuMigrationSrcIsSafeDisk(virDomainDiskDef *disk, + virQEMUCaps *qemuCaps, + virQEMUDriverConfig *cfg) +{ + bool unsafe_storage = false; + bool requires_safe_cache = false; + + /* Disks without any source (i.e. floppies and CD-ROMs) OR readonly are safe. */ + if (virStorageSourceIsEmpty(disk->src) || + disk->src->readonly) + return true; + + if (qemuMigrationSrcCheckStorageSourceSafety(disk->src, cfg, &unsafe_storage, + &requires_safe_cache) < 0) + return false; + + if (unsafe_storage) { virReportError(VIR_ERR_MIGRATE_UNSAFE, "%s", _("Migration without shared storage is unsafe")); return false; @@ -1787,7 +1803,8 @@ qemuMigrationSrcIsSafeDisk(virDomainDiskDef *disk, /* Our code elsewhere guarantees shared disks are either readonly (in * which case cache mode doesn't matter) or used with cache=none or used with cache=directsync */ - if (!(disk->src->shared || + if (requires_safe_cache && + !(disk->src->shared || disk->cachemode == VIR_DOMAIN_DISK_CACHE_DISABLE || disk->cachemode == VIR_DOMAIN_DISK_CACHE_DIRECTSYNC || virQEMUCapsGet(qemuCaps, QEMU_CAPS_MIGRATION_FILE_DROP_CACHE))) { -- 2.47.3