From 81d5674f22493a8b380b652c5a8cd3fb695c7910 Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Thu, 18 Dec 2025 16:07:19 +0100 Subject: [PATCH] libvirt-11.10.0-2.el10 - tests: add test for a single per-device smmuv3 (RHEL-74200) - qemu: Use pci_bus to identify multi-smmuv3 model (RHEL-74200) - qemu: tpm: Account for possible migration without actually sharing storage (RHEL-132534) - tests: Test virFileIsSharedFSOverride (RHEL-102925) - util: Fix race condition in virFileIsSharedFSType (RHEL-102925) - util: Fix race condition in virFileIsSharedFSOverride (RHEL-102925) - util: Rework virFileIsSharedFSOverride using virFileCheckParents (RHEL-102925) Resolves: RHEL-102925, RHEL-132534, RHEL-74200 --- ...i_bus-to-identify-multi-smmuv3-model.patch | 69 ++++++ ...ion-without-actually-sharing-storage.patch | 119 +++++++++++ ...tests-Test-virFileIsSharedFSOverride.patch | 111 ++++++++++ ...-test-for-a-single-per-device-smmuv3.patch | 201 ++++++++++++++++++ ...ndition-in-virFileIsSharedFSOverride.patch | 114 ++++++++++ ...e-condition-in-virFileIsSharedFSType.patch | 144 +++++++++++++ ...FSOverride-using-virFileCheckParents.patch | 84 ++++++++ libvirt.spec | 22 +- 8 files changed, 863 insertions(+), 1 deletion(-) create mode 100644 libvirt-qemu-Use-pci_bus-to-identify-multi-smmuv3-model.patch create mode 100644 libvirt-qemu-tpm-Account-for-possible-migration-without-actually-sharing-storage.patch create mode 100644 libvirt-tests-Test-virFileIsSharedFSOverride.patch create mode 100644 libvirt-tests-add-test-for-a-single-per-device-smmuv3.patch create mode 100644 libvirt-util-Fix-race-condition-in-virFileIsSharedFSOverride.patch create mode 100644 libvirt-util-Fix-race-condition-in-virFileIsSharedFSType.patch create mode 100644 libvirt-util-Rework-virFileIsSharedFSOverride-using-virFileCheckParents.patch diff --git a/libvirt-qemu-Use-pci_bus-to-identify-multi-smmuv3-model.patch b/libvirt-qemu-Use-pci_bus-to-identify-multi-smmuv3-model.patch new file mode 100644 index 0000000..17ab1ad --- /dev/null +++ b/libvirt-qemu-Use-pci_bus-to-identify-multi-smmuv3-model.patch @@ -0,0 +1,69 @@ +From 933524784d813b24aa0970992b820698f1e03180 Mon Sep 17 00:00:00 2001 +Message-ID: <933524784d813b24aa0970992b820698f1e03180.1766070439.git.jdenemar@redhat.com> +From: Nathan Chen via Devel +Date: Tue, 2 Dec 2025 11:59:47 -0800 +Subject: [PATCH] qemu: Use pci_bus to identify multi-smmuv3 model +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Use presence of non-negative pci_bus to identify multi-smmuv3 +IOMMU model, instead of the niommus attribute. This allows for +specifying a single arm-smmuv3 on the qemu command line, +instead of both the virt-machine smmuv3 and arm-smmuv3 +being specified at the same time. + +Signed-off-by: Nathan Chen +Fixes: e70c4d54d365 conf: Support multiple device-pluggable smmuv3 IOMMUs +Reviewed-by: Ján Tomko +(cherry picked from commit da4305b7bc8d3bd52c60db1905db88e43ebd9868) + +https://issues.redhat.com/browse/RHEL-74200 +Signed-off-by: Ján Tomko +--- + src/qemu/qemu_command.c | 2 +- + src/qemu/qemu_postparse.c | 2 +- + .../iommu-smmuv3-pci-bus-single.aarch64-latest.args | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c +index b69fe23236..fb89dbec27 100644 +--- a/src/qemu/qemu_command.c ++++ b/src/qemu/qemu_command.c +@@ -7192,7 +7192,7 @@ qemuBuildMachineCommandLine(virCommand *cmd, + if (qemuAppendDomainFeaturesMachineParam(&buf, def, qemuCaps) < 0) + return -1; + +- if (def->niommus == 1) { ++ if (def->iommus && def->iommus[0]->pci_bus < 0) { + switch (def->iommus[0]->model) { + case VIR_DOMAIN_IOMMU_MODEL_SMMUV3: + virBufferAddLit(&buf, ",iommu=smmuv3"); +diff --git a/src/qemu/qemu_postparse.c b/src/qemu/qemu_postparse.c +index dc5ade829a..840d6a1174 100644 +--- a/src/qemu/qemu_postparse.c ++++ b/src/qemu/qemu_postparse.c +@@ -1559,7 +1559,7 @@ qemuDomainDefEnableDefaultFeatures(virDomainDef *def, + * domain already has IOMMU without inremap. This will be fixed in + * qemuDomainIOMMUDefPostParse() but there domain definition can't be + * modified so change it now. */ +- if (def->iommus && def->niommus == 1 && ++ if (def->iommus && def->iommus[0]->pci_bus < 0 && + (def->iommus[0]->intremap == VIR_TRISTATE_SWITCH_ON || + qemuDomainNeedsIOMMUWithEIM(def)) && + def->features[VIR_DOMAIN_FEATURE_IOAPIC] == VIR_DOMAIN_IOAPIC_NONE) { +diff --git a/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.args b/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.args +index 976467e641..34e7bda1c5 100644 +--- a/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.args ++++ b/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.args +@@ -10,7 +10,7 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ + -name guest=guest,debug-threads=on \ + -S \ + -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \ +--machine virt,usb=off,gic-version=2,iommu=smmuv3,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=off \ ++-machine virt,usb=off,gic-version=2,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=off \ + -accel tcg \ + -cpu cortex-a15 \ + -m size=1048576k \ +-- +2.52.0 diff --git a/libvirt-qemu-tpm-Account-for-possible-migration-without-actually-sharing-storage.patch b/libvirt-qemu-tpm-Account-for-possible-migration-without-actually-sharing-storage.patch new file mode 100644 index 0000000..d51a8c1 --- /dev/null +++ b/libvirt-qemu-tpm-Account-for-possible-migration-without-actually-sharing-storage.patch @@ -0,0 +1,119 @@ +From 8e9dc8aed52c98c3683949dfe1127061bd9df47a Mon Sep 17 00:00:00 2001 +Message-ID: <8e9dc8aed52c98c3683949dfe1127061bd9df47a.1766070439.git.jdenemar@redhat.com> +From: Peter Krempa +Date: Mon, 1 Dec 2025 11:35:32 +0100 +Subject: [PATCH] qemu: tpm: Account for possible migration without actually + sharing storage + +The current logic in 'qemuTPMEmulatorBuildCommand' skips all setup if +the *location* of the data is on what we'd consider shared storage. + +This means that if the location is not actually shared (e.g. it's shared +betweeh some other hosts than the two doing the migration) and the path +wasn't ever used (e.g. by migrating out) from the host where we're +migrating into the complete setup of the location would be skipped even +when it doesn't exist. + +Fix the logic by skipping only some of the setup steps so that +'qemuTPMEmulatorCreateStorage' can still create the storage if it +doesn't exist. + +The rest of the code then needs to take the 'created' flag returned from +'qemuTPMEmulatorCreateStorage' into account. + +Fixes: 68103e9daf633b789428fedef56f816c92f6ee75 +Signed-off-by: Peter Krempa +Reviewed-by: Michal Privoznik +(cherry picked from commit d56d0560946770d4364a4918cc289e6a7fe5d15c) +https://issues.redhat.com/browse/RHEL-132534 +--- + src/qemu/qemu_tpm.c | 29 ++++++++++++++++++++--------- + 1 file changed, 20 insertions(+), 9 deletions(-) + +diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c +index 4c9445d72c..660410bcba 100644 +--- a/src/qemu/qemu_tpm.c ++++ b/src/qemu/qemu_tpm.c +@@ -158,6 +158,7 @@ qemuTPMEmulatorGetPid(const char *swtpmStateDir, + /** + * qemuTPMEmulatorCreateStorage: + * @tpm: TPM definition for an emulator type ++ * @sharedStorageMigration: VM is being migrated with possibly shared storage + * @created: a pointer to a bool that will be set to true if the + * storage was created because it did not exist yet + * @swtpm_user: The uid that needs to be able to access the directory +@@ -169,6 +170,7 @@ qemuTPMEmulatorGetPid(const char *swtpmStateDir, + */ + static int + qemuTPMEmulatorCreateStorage(virDomainTPMDef *tpm, ++ bool sharedStorageMigration, + bool *created, + uid_t swtpm_user, + gid_t swtpm_group) +@@ -187,8 +189,17 @@ qemuTPMEmulatorCreateStorage(virDomainTPMDef *tpm, + *created = false; + + if (!virFileExists(source_path) || +- virDirIsEmpty(source_path, true) > 0) ++ virDirIsEmpty(source_path, true) > 0) { + *created = true; ++ } else { ++ /* If the location exists and is shared, we don't need to create it ++ * during migration */ ++ if (sharedStorageMigration) { ++ VIR_DEBUG("Skipping TPM storage creation. Path '%s' already exists and is on shared storage.", ++ source_path); ++ return 0; ++ } ++ } + + if (virDirCreate(source_path, 0700, swtpm_user, swtpm_group, + VIR_DIR_CREATE_ALLOW_EXIST) < 0) { +@@ -809,16 +820,13 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm, + run_setup = true; + } + +- /* Do not create storage and run swtpm_setup on incoming migration over +- * shared storage +- */ + on_shared_storage = virFileIsSharedFS(tpm->data.emulator.source_path, + cfg->sharedFilesystems) == 1; +- if (incomingMigration && on_shared_storage) +- create_storage = false; + + if (create_storage) { +- if (qemuTPMEmulatorCreateStorage(tpm, &created, ++ if (qemuTPMEmulatorCreateStorage(tpm, ++ incomingMigration && on_shared_storage, ++ &created, + cfg->swtpm_user, cfg->swtpm_group) < 0) + return NULL; + run_setup = created; +@@ -885,6 +893,9 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm, + /* If swtpm supports it and the TPM state is stored on shared storage, + * start swtpm with --migration release-lock-outgoing so it can migrate + * across shared storage if needed. ++ * ++ * Note that if 'created' is true, the location didn't exist so the storage ++ * is not actually shared. + */ + QEMU_DOMAIN_TPM_PRIVATE(tpm)->swtpm.can_migrate_shared_storage = false; + if (on_shared_storage && +@@ -892,13 +903,13 @@ qemuTPMEmulatorBuildCommand(virDomainTPMDef *tpm, + + virCommandAddArg(cmd, "--migration"); + virCommandAddArgFormat(cmd, "release-lock-outgoing%s", +- incomingMigration ? ",incoming": ""); ++ incomingMigration && !created ? ",incoming": ""); + QEMU_DOMAIN_TPM_PRIVATE(tpm)->swtpm.can_migrate_shared_storage = true; + } else { + /* Report an error if there's an incoming migration across shared + * storage and swtpm does not support the --migration option. + */ +- if (incomingMigration && on_shared_storage) { ++ if (incomingMigration && on_shared_storage && !created) { + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, + _("%1$s (on destination side) does not support the --migration option needed for migration with shared storage"), + swtpm); +-- +2.52.0 diff --git a/libvirt-tests-Test-virFileIsSharedFSOverride.patch b/libvirt-tests-Test-virFileIsSharedFSOverride.patch new file mode 100644 index 0000000..d247e7d --- /dev/null +++ b/libvirt-tests-Test-virFileIsSharedFSOverride.patch @@ -0,0 +1,111 @@ +From 0bb3bb84670dbd45c6eca2d108b2d4d5a7754ef4 Mon Sep 17 00:00:00 2001 +Message-ID: <0bb3bb84670dbd45c6eca2d108b2d4d5a7754ef4.1766070439.git.jdenemar@redhat.com> +From: Jiri Denemark +Date: Fri, 5 Dec 2025 15:09:15 +0100 +Subject: [PATCH] tests: Test virFileIsSharedFSOverride + +Technically virFileIsSharedFSOverride is available on any OS, but we +need a mocked realpath() to test it. Because the virfilemock library +also mocks statfs() which is only available on Linux, we don't even try +to load the library anywhere else. Thus we need to skip testing +virFileIsSharedFSOverride on non-Linux too. + +Signed-off-by: Jiri Denemark +(cherry picked from commit 121d179e068b584f62ea2c029d89a44e67c909c0) + +https://issues.redhat.com/browse/RHEL-102925 + +Signed-off-by: Jiri Denemark +--- + tests/virfiletest.c | 69 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 69 insertions(+) + +diff --git a/tests/virfiletest.c b/tests/virfiletest.c +index e05925a321..ccd76a3fac 100644 +--- a/tests/virfiletest.c ++++ b/tests/virfiletest.c +@@ -329,6 +329,55 @@ testFileIsSharedFSType(const void *opaque G_GNUC_UNUSED) + } + + ++static const char *shared_filesystems[] = { ++ "/run/user/501/gvfs", ++ "/nfs", ++ "/gluster", ++ "/ceph/multi", ++ "/gpfs/data/blaf", ++ "/quobyte", ++ NULL, ++}; ++ ++static int ++testFileIsSharedFSOverride(const void *opaque G_GNUC_UNUSED) ++{ ++#ifndef __linux__ ++ return EXIT_AM_SKIP; ++#else ++ const struct testFileIsSharedFSType *data = opaque; ++ g_autofree char *mtabFile = NULL; ++ bool actual; ++ int ret = -1; ++ ++ /* mtab is used by mocked realpath to decide whether a given path exists */ ++ mtabFile = g_strdup_printf(abs_srcdir "/virfiledata/%s", data->mtabFile); ++ ++ if (!g_setenv("LIBVIRT_MTAB", mtabFile, true)) { ++ fprintf(stderr, "Unable to set env variable\n"); ++ goto cleanup; ++ } ++ ++ actual = virFileIsSharedFSOverride(data->filename, ++ (char * const *) shared_filesystems); ++ ++ if (actual != data->expected) { ++ fprintf(stderr, "FS of '%s' is %s. Expected: %s\n", ++ data->filename, ++ actual ? "shared" : "not shared", ++ data->expected ? "shared" : "not shared"); ++ goto cleanup; ++ } ++ ++ ret = 0; ++ ++ cleanup: ++ g_unsetenv("LIBVIRT_MTAB"); ++ return ret; ++#endif ++} ++ ++ + static int + mymain(void) + { +@@ -439,6 +488,26 @@ mymain(void) + DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/gpfs/data", true); + DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/quobyte", true); + ++#define DO_TEST_FILE_IS_SHARED_FS_OVERRIDE(mtab, file, exp) \ ++ do { \ ++ struct testFileIsSharedFSType data = { \ ++ .mtabFile = mtab, .filename = file, .expected = exp \ ++ }; \ ++ if (virTestRun(virTestCounterNext(), testFileIsSharedFSOverride, &data) < 0) \ ++ ret = -1; \ ++ } while (0) ++ ++ virTestCounterReset("testFileIsSharedFSOverride "); ++ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts2.txt", "/boot/vmlinuz", false); ++ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts2.txt", "/run/user/501/gvfs/some/file", true); ++ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/nfs/file", true); ++ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/gluster/file", true); ++ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/some/symlink/file", true); ++ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/ceph/file", false); ++ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/ceph/multi/file", true); ++ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/gpfs/data", false); ++ DO_TEST_FILE_IS_SHARED_FS_OVERRIDE("mounts3.txt", "/quobyte", true); ++ + return ret != 0 ? EXIT_FAILURE : EXIT_SUCCESS; + } + +-- +2.52.0 diff --git a/libvirt-tests-add-test-for-a-single-per-device-smmuv3.patch b/libvirt-tests-add-test-for-a-single-per-device-smmuv3.patch new file mode 100644 index 0000000..2941140 --- /dev/null +++ b/libvirt-tests-add-test-for-a-single-per-device-smmuv3.patch @@ -0,0 +1,201 @@ +From d30c21439f3847ecc229db9355eb802f0256a3f0 Mon Sep 17 00:00:00 2001 +Message-ID: +From: =?UTF-8?q?J=C3=A1n=20Tomko?= +Date: Fri, 5 Dec 2025 08:50:51 +0100 +Subject: [PATCH] tests: add test for a single per-device smmuv3 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Ján Tomko +(cherry picked from commit 45ff1c002629dadd9d94b91742ffb985b0fe027f) + +https://issues.redhat.com/browse/RHEL-74200 +Signed-off-by: Ján Tomko +--- + ...-smmuv3-pci-bus-single.aarch64-latest.args | 40 +++++++++++++ + ...u-smmuv3-pci-bus-single.aarch64-latest.xml | 59 +++++++++++++++++++ + .../iommu-smmuv3-pci-bus-single.xml | 46 +++++++++++++++ + tests/qemuxmlconftest.c | 1 + + 4 files changed, 146 insertions(+) + create mode 100644 tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.args + create mode 100644 tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.xml + create mode 100644 tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.xml + +diff --git a/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.args b/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.args +new file mode 100644 +index 0000000000..976467e641 +--- /dev/null ++++ b/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.args +@@ -0,0 +1,40 @@ ++LC_ALL=C \ ++PATH=/bin \ ++HOME=/var/lib/libvirt/qemu/domain--1-guest \ ++USER=test \ ++LOGNAME=test \ ++XDG_DATA_HOME=/var/lib/libvirt/qemu/domain--1-guest/.local/share \ ++XDG_CACHE_HOME=/var/lib/libvirt/qemu/domain--1-guest/.cache \ ++XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-guest/.config \ ++/usr/bin/qemu-system-aarch64 \ ++-name guest=guest,debug-threads=on \ ++-S \ ++-object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/lib/libvirt/qemu/domain--1-guest/master-key.aes"}' \ ++-machine virt,usb=off,gic-version=2,iommu=smmuv3,dump-guest-core=off,memory-backend=mach-virt.ram,acpi=off \ ++-accel tcg \ ++-cpu cortex-a15 \ ++-m size=1048576k \ ++-object '{"qom-type":"memory-backend-ram","id":"mach-virt.ram","size":1073741824}' \ ++-overcommit mem-lock=off \ ++-smp 1,sockets=1,cores=1,threads=1 \ ++-uuid 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 \ ++-display none \ ++-no-user-config \ ++-nodefaults \ ++-chardev socket,id=charmonitor,fd=1729,server=on,wait=off \ ++-mon chardev=charmonitor,id=monitor,mode=control \ ++-rtc base=utc \ ++-no-shutdown \ ++-boot strict=on \ ++-device '{"driver":"pxb-pcie","bus_nr":252,"id":"pci.1","bus":"pcie.0","addr":"0x1"}' \ ++-device '{"driver":"pxb-pcie","bus_nr":248,"id":"pci.2","bus":"pcie.0","addr":"0x2"}' \ ++-device '{"driver":"pcie-root-port","port":0,"chassis":21,"id":"pci.3","bus":"pci.1","addr":"0x0"}' \ ++-device '{"driver":"pcie-root-port","port":168,"chassis":22,"id":"pci.4","bus":"pci.2","addr":"0x0"}' \ ++-device '{"driver":"arm-smmuv3","primary-bus":"pci.1","id":"iommu0"}' \ ++-audiodev '{"id":"audio1","driver":"none"}' \ ++-object '{"qom-type":"rng-random","id":"objrng0","filename":"/dev/urandom"}' \ ++-device '{"driver":"virtio-rng-pci","rng":"objrng0","id":"rng0","bus":"pci.3","addr":"0x0"}' \ ++-object '{"qom-type":"rng-random","id":"objrng1","filename":"/dev/urandom"}' \ ++-device '{"driver":"virtio-rng-pci","rng":"objrng1","id":"rng1","bus":"pci.4","addr":"0x0"}' \ ++-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \ ++-msg timestamp=on +diff --git a/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.xml b/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.xml +new file mode 100644 +index 0000000000..e6071fd71b +--- /dev/null ++++ b/tests/qemuxmlconfdata/iommu-smmuv3-pci-bus-single.aarch64-latest.xml +@@ -0,0 +1,59 @@ ++ ++ guest ++ 1ccfd97d-5eb4-478a-bbe6-88d254c16db7 ++ 1048576 ++ 1048576 ++ 1 ++ ++ hvm ++ ++ ++ ++ ++ ++ ++ cortex-a15 ++ ++ ++ destroy ++ restart ++ destroy ++ ++ /usr/bin/qemu-system-aarch64 ++ ++ ++ ++ ++ ++
++ ++ ++ ++ ++
++ ++ ++ ++ ++
++ ++ ++ ++ ++
++ ++