From f5fdf23a68d5c9838890451c1c50b4ae1062d8d2 Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Fri, 18 Nov 2016 14:53:27 +0100 Subject: [PATCH] qemu: Manage /dev entry on chardev hotplug When attaching a device to a domain that's using separate mount namespace we must maintain /dev entries in order for qemu process to see them. Signed-off-by: Michal Privoznik --- src/qemu/qemu_domain.c | 64 +++++++++++++++++++++++++++++++++++++++-- src/qemu/qemu_domain.h | 8 ++++++ src/qemu/qemu_hotplug.c | 10 +++++++ 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 0d0b4a8d7b..7da3963bba 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -7534,6 +7534,10 @@ qemuDomainAttachDeviceMknodHelper(pid_t pid ATTRIBUTE_UNUSED, goto cleanup; } break; + case VIR_DOMAIN_DEVICE_CHR: + /* No labelling. */ + break; + case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_FS: @@ -7547,7 +7551,6 @@ qemuDomainAttachDeviceMknodHelper(pid_t pid ATTRIBUTE_UNUSED, case VIR_DOMAIN_DEVICE_HUB: case VIR_DOMAIN_DEVICE_REDIRDEV: case VIR_DOMAIN_DEVICE_SMARTCARD: - case VIR_DOMAIN_DEVICE_CHR: case VIR_DOMAIN_DEVICE_MEMBALLOON: case VIR_DOMAIN_DEVICE_NVRAM: case VIR_DOMAIN_DEVICE_RNG: @@ -7667,6 +7670,10 @@ qemuDomainDetachDeviceUnlink(virQEMUDriverPtr driver, return -1; } break; + case VIR_DOMAIN_DEVICE_CHR: + /* No labelling. */ + break; + case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_FS: @@ -7680,7 +7687,6 @@ qemuDomainDetachDeviceUnlink(virQEMUDriverPtr driver, case VIR_DOMAIN_DEVICE_HUB: case VIR_DOMAIN_DEVICE_REDIRDEV: case VIR_DOMAIN_DEVICE_SMARTCARD: - case VIR_DOMAIN_DEVICE_CHR: case VIR_DOMAIN_DEVICE_MEMBALLOON: case VIR_DOMAIN_DEVICE_NVRAM: case VIR_DOMAIN_DEVICE_RNG: @@ -7829,3 +7835,57 @@ qemuDomainNamespaceTeardownHostdev(virQEMUDriverPtr driver, VIR_FREE(path); return ret; } + + +int +qemuDomainNamespaceSetupChardev(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainChrDefPtr chr) +{ + virDomainDeviceDef dev = {.type = VIR_DOMAIN_DEVICE_CHR, .data.chr = chr}; + const char *path; + int ret = -1; + + if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT)) + return 0; + + if (chr->source->type != VIR_DOMAIN_CHR_TYPE_DEV) + return 0; + + path = chr->source->data.file.path; + + if (qemuDomainAttachDeviceMknod(driver, + vm, + &dev, + path) < 0) + goto cleanup; + ret = 0; + cleanup: + return ret; +} + + +int +qemuDomainNamespaceTeardownChardev(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainChrDefPtr chr) +{ + virDomainDeviceDef dev = {.type = VIR_DOMAIN_DEVICE_CHR, .data.chr = chr}; + int ret = -1; + const char *path = NULL; + + if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT)) + return 0; + + if (chr->source->type != VIR_DOMAIN_CHR_TYPE_DEV) + return 0; + + path = chr->source->data.file.path; + + if (qemuDomainDetachDeviceUnlink(driver, vm, &dev, path) < 0) + goto cleanup; + + ret = 0; + cleanup: + return ret; +} diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 7a3f31c188..7a774a543d 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -821,4 +821,12 @@ int qemuDomainNamespaceSetupHostdev(virQEMUDriverPtr driver, int qemuDomainNamespaceTeardownHostdev(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainHostdevDefPtr hostdev); + +int qemuDomainNamespaceSetupChardev(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainChrDefPtr chr); + +int qemuDomainNamespaceTeardownChardev(virQEMUDriverPtr driver, + virDomainObjPtr vm, + virDomainChrDefPtr chr); #endif /* __QEMU_DOMAIN_H__ */ diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 09aca03e0e..8b41edc560 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1851,6 +1851,7 @@ int qemuDomainAttachChrDevice(virConnectPtr conn, bool chardevAttached = false; bool tlsobjAdded = false; bool teardowncgroup = false; + bool teardowndevice = false; bool secobjAdded = false; virJSONValuePtr tlsProps = NULL; char *tlsAlias = NULL; @@ -1872,6 +1873,10 @@ int qemuDomainAttachChrDevice(virConnectPtr conn, if (rc == 1) need_release = true; + if (qemuDomainNamespaceSetupChardev(driver, vm, chr) < 0) + goto cleanup; + teardowndevice = true; + if (qemuSetupChardevCgroup(vm, chr) < 0) goto cleanup; teardowncgroup = true; @@ -1935,6 +1940,8 @@ int qemuDomainAttachChrDevice(virConnectPtr conn, qemuDomainReleaseDeviceAddress(vm, &chr->info, NULL); if (teardowncgroup && qemuTeardownChardevCgroup(vm, chr) < 0) VIR_WARN("Unable to remove chr device cgroup ACL on hotplug fail"); + if (teardowndevice && qemuDomainNamespaceTeardownChardev(driver, vm, chr) < 0) + VIR_WARN("Unable to remove chr device from /dev"); } VIR_FREE(tlsAlias); virJSONValueFree(tlsProps); @@ -4021,6 +4028,9 @@ qemuDomainRemoveChrDevice(virQEMUDriverPtr driver, if (qemuTeardownChardevCgroup(vm, chr) < 0) VIR_WARN("Failed to remove chr device cgroup ACL"); + if (qemuDomainNamespaceTeardownChardev(driver, vm, chr) < 0) + VIR_WARN("Unable to remove chr device from /dev"); + event = virDomainEventDeviceRemovedNewFromObj(vm, chr->info.alias); qemuDomainEventQueue(driver, event);