提交 6e574928 编写于 作者: M Michal Privoznik

qemu: Manage /dev entry on hostdev 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: NMichal Privoznik <mprivozn@redhat.com>
上级 81df2150
...@@ -7527,6 +7527,13 @@ qemuDomainAttachDeviceMknodHelper(pid_t pid ATTRIBUTE_UNUSED, ...@@ -7527,6 +7527,13 @@ qemuDomainAttachDeviceMknodHelper(pid_t pid ATTRIBUTE_UNUSED,
def->src->path = tmpsrc; def->src->path = tmpsrc;
} break; } break;
case VIR_DOMAIN_DEVICE_HOSTDEV: {
virDomainHostdevDefPtr def = data->devDef->data.hostdev;
if (virSecurityManagerSetHostdevLabel(data->driver->securityManager,
data->vm->def, def, NULL) < 0)
goto cleanup;
} break;
case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_NONE:
case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_LEASE:
case VIR_DOMAIN_DEVICE_FS: case VIR_DOMAIN_DEVICE_FS:
...@@ -7534,7 +7541,6 @@ qemuDomainAttachDeviceMknodHelper(pid_t pid ATTRIBUTE_UNUSED, ...@@ -7534,7 +7541,6 @@ qemuDomainAttachDeviceMknodHelper(pid_t pid ATTRIBUTE_UNUSED,
case VIR_DOMAIN_DEVICE_INPUT: case VIR_DOMAIN_DEVICE_INPUT:
case VIR_DOMAIN_DEVICE_SOUND: case VIR_DOMAIN_DEVICE_SOUND:
case VIR_DOMAIN_DEVICE_VIDEO: case VIR_DOMAIN_DEVICE_VIDEO:
case VIR_DOMAIN_DEVICE_HOSTDEV:
case VIR_DOMAIN_DEVICE_WATCHDOG: case VIR_DOMAIN_DEVICE_WATCHDOG:
case VIR_DOMAIN_DEVICE_CONTROLLER: case VIR_DOMAIN_DEVICE_CONTROLLER:
case VIR_DOMAIN_DEVICE_GRAPHICS: case VIR_DOMAIN_DEVICE_GRAPHICS:
...@@ -7614,6 +7620,91 @@ qemuDomainAttachDeviceMknod(virQEMUDriverPtr driver, ...@@ -7614,6 +7620,91 @@ qemuDomainAttachDeviceMknod(virQEMUDriverPtr driver,
} }
static int
qemuDomainDetachDeviceUnlinkHelper(pid_t pid ATTRIBUTE_UNUSED,
void *opaque)
{
const char *path = opaque;
VIR_DEBUG("Unlinking %s", path);
if (unlink(path) < 0 && errno != ENOENT) {
virReportSystemError(errno,
_("Unable to remove device %s"), path);
return -1;
}
return 0;
}
static int
qemuDomainDetachDeviceUnlink(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainDeviceDefPtr dev,
const char *file)
{
/* Technically, this is not needed. Yet. But in the future
* security managers might do some reference counting over
* Set/Restore label and thus for every SetLabel() there
* should be corresponding RestoreLabel(). */
switch ((virDomainDeviceType) dev->type) {
case VIR_DOMAIN_DEVICE_DISK: {
virDomainDiskDefPtr def = dev->data.disk;
char *tmpsrc = def->src->path;
def->src->path = (char *) file;
if (virSecurityManagerRestoreDiskLabel(driver->securityManager,
vm->def, def) < 0) {
def->src->path = tmpsrc;
return -1;
}
def->src->path = tmpsrc;
} break;
case VIR_DOMAIN_DEVICE_HOSTDEV: {
virDomainHostdevDefPtr def = dev->data.hostdev;
if (virSecurityManagerRestoreHostdevLabel(driver->securityManager,
vm->def, def, NULL) < 0)
return -1;
} break;
case VIR_DOMAIN_DEVICE_NONE:
case VIR_DOMAIN_DEVICE_LEASE:
case VIR_DOMAIN_DEVICE_FS:
case VIR_DOMAIN_DEVICE_NET:
case VIR_DOMAIN_DEVICE_INPUT:
case VIR_DOMAIN_DEVICE_SOUND:
case VIR_DOMAIN_DEVICE_VIDEO:
case VIR_DOMAIN_DEVICE_WATCHDOG:
case VIR_DOMAIN_DEVICE_CONTROLLER:
case VIR_DOMAIN_DEVICE_GRAPHICS:
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:
case VIR_DOMAIN_DEVICE_SHMEM:
case VIR_DOMAIN_DEVICE_TPM:
case VIR_DOMAIN_DEVICE_PANIC:
case VIR_DOMAIN_DEVICE_MEMORY:
case VIR_DOMAIN_DEVICE_IOMMU:
case VIR_DOMAIN_DEVICE_LAST:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected device type %d"),
dev->type);
return -1;
}
if (virProcessRunInMountNamespace(vm->pid,
qemuDomainDetachDeviceUnlinkHelper,
(void *)file) < 0)
return -1;
return 0;
}
int int
qemuDomainNamespaceSetupDisk(virQEMUDriverPtr driver, qemuDomainNamespaceSetupDisk(virQEMUDriverPtr driver,
virDomainObjPtr vm, virDomainObjPtr vm,
...@@ -7674,3 +7765,67 @@ qemuDomainNamespaceTeardownDisk(virQEMUDriverPtr driver ATTRIBUTE_UNUSED, ...@@ -7674,3 +7765,67 @@ qemuDomainNamespaceTeardownDisk(virQEMUDriverPtr driver ATTRIBUTE_UNUSED,
* I don't, therefore: */ * I don't, therefore: */
return 0; return 0;
} }
int
qemuDomainNamespaceSetupHostdev(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev)
{
virDomainDeviceDef dev = {.type = VIR_DOMAIN_DEVICE_HOSTDEV, .data.hostdev = hostdev};
int ret = -1;
char *path = NULL;
if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
return 0;
if (qemuDomainGetHostdevPath(hostdev, &path) < 0)
goto cleanup;
if (!path) {
/* There's no /dev device that we need to create. Claim success. */
ret = 0;
goto cleanup;
}
if (qemuDomainAttachDeviceMknod(driver,
vm,
&dev,
path) < 0)
goto cleanup;
ret = 0;
cleanup:
VIR_FREE(path);
return ret;
}
int
qemuDomainNamespaceTeardownHostdev(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev)
{
virDomainDeviceDef dev = {.type = VIR_DOMAIN_DEVICE_HOSTDEV, .data.hostdev = hostdev};
int ret = -1;
char *path = NULL;
if (!qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT))
return 0;
if (qemuDomainGetHostdevPath(hostdev, &path) < 0)
goto cleanup;
if (!path) {
/* There's no /dev device that we need to create. Claim success. */
ret = 0;
goto cleanup;
}
if (qemuDomainDetachDeviceUnlink(driver, vm, &dev, path) < 0)
goto cleanup;
ret = 0;
cleanup:
VIR_FREE(path);
return ret;
}
...@@ -813,4 +813,12 @@ int qemuDomainNamespaceSetupDisk(virQEMUDriverPtr driver, ...@@ -813,4 +813,12 @@ int qemuDomainNamespaceSetupDisk(virQEMUDriverPtr driver,
int qemuDomainNamespaceTeardownDisk(virQEMUDriverPtr driver, int qemuDomainNamespaceTeardownDisk(virQEMUDriverPtr driver,
virDomainObjPtr vm, virDomainObjPtr vm,
virDomainDiskDefPtr disk); virDomainDiskDefPtr disk);
int qemuDomainNamespaceSetupHostdev(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev);
int qemuDomainNamespaceTeardownHostdev(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev);
#endif /* __QEMU_DOMAIN_H__ */ #endif /* __QEMU_DOMAIN_H__ */
...@@ -1391,6 +1391,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, ...@@ -1391,6 +1391,7 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
bool releaseaddr = false; bool releaseaddr = false;
bool teardowncgroup = false; bool teardowncgroup = false;
bool teardownlabel = false; bool teardownlabel = false;
bool teardowndevice = false;
int backend; int backend;
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
unsigned int flags = 0; unsigned int flags = 0;
...@@ -1442,12 +1443,15 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, ...@@ -1442,12 +1443,15 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
} }
vm->def->hostdevs[--(vm->def->nhostdevs)] = NULL; vm->def->hostdevs[--(vm->def->nhostdevs)] = NULL;
if (qemuDomainNamespaceSetupHostdev(driver, vm, hostdev) < 0)
goto error;
teardowndevice = true;
if (qemuSetupHostdevCgroup(vm, hostdev) < 0) if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
goto error; goto error;
teardowncgroup = true; teardowncgroup = true;
if (virSecurityManagerSetHostdevLabel(driver->securityManager, if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
vm->def, hostdev, NULL) < 0)
goto error; goto error;
if (backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) if (backend != VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO)
teardownlabel = true; teardownlabel = true;
...@@ -1500,9 +1504,11 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver, ...@@ -1500,9 +1504,11 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0) if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail"); VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
if (teardownlabel && if (teardownlabel &&
virSecurityManagerRestoreHostdevLabel(driver->securityManager, qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
vm->def, hostdev, NULL) < 0)
VIR_WARN("Unable to restore host device labelling on hotplug fail"); VIR_WARN("Unable to restore host device labelling on hotplug fail");
if (teardowndevice &&
qemuDomainNamespaceTeardownHostdev(driver, vm, hostdev) < 0)
VIR_WARN("Unable to remove host device from /dev");
if (releaseaddr) if (releaseaddr)
qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL); qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL);
...@@ -2283,6 +2289,7 @@ qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver, ...@@ -2283,6 +2289,7 @@ qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver,
bool added = false; bool added = false;
bool teardowncgroup = false; bool teardowncgroup = false;
bool teardownlabel = false; bool teardownlabel = false;
bool teardowndevice = false;
int ret = -1; int ret = -1;
if (priv->usbaddrs) { if (priv->usbaddrs) {
...@@ -2296,12 +2303,15 @@ qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver, ...@@ -2296,12 +2303,15 @@ qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver,
added = true; added = true;
if (qemuDomainNamespaceSetupHostdev(driver, vm, hostdev) < 0)
goto cleanup;
teardowndevice = true;
if (qemuSetupHostdevCgroup(vm, hostdev) < 0) if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
goto cleanup; goto cleanup;
teardowncgroup = true; teardowncgroup = true;
if (virSecurityManagerSetHostdevLabel(driver->securityManager, if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
vm->def, hostdev, NULL) < 0)
goto cleanup; goto cleanup;
teardownlabel = true; teardownlabel = true;
...@@ -2331,9 +2341,11 @@ qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver, ...@@ -2331,9 +2341,11 @@ qemuDomainAttachHostUSBDevice(virQEMUDriverPtr driver,
if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0) if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail"); VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
if (teardownlabel && if (teardownlabel &&
virSecurityManagerRestoreHostdevLabel(driver->securityManager, qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
vm->def, hostdev, NULL) < 0)
VIR_WARN("Unable to restore host device labelling on hotplug fail"); VIR_WARN("Unable to restore host device labelling on hotplug fail");
if (teardowndevice &&
qemuDomainNamespaceTeardownHostdev(driver, vm, hostdev) < 0)
VIR_WARN("Unable to remove host device from /dev");
if (added) if (added)
qemuHostdevReAttachUSBDevices(driver, vm->def->name, &hostdev, 1); qemuHostdevReAttachUSBDevices(driver, vm->def->name, &hostdev, 1);
if (releaseaddr) if (releaseaddr)
...@@ -2359,6 +2371,7 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn, ...@@ -2359,6 +2371,7 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn,
char *drivealias = NULL; char *drivealias = NULL;
bool teardowncgroup = false; bool teardowncgroup = false;
bool teardownlabel = false; bool teardownlabel = false;
bool teardowndevice = false;
bool driveAdded = false; bool driveAdded = false;
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_SCSI_GENERIC)) { if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE_SCSI_GENERIC)) {
...@@ -2397,12 +2410,15 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn, ...@@ -2397,12 +2410,15 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn,
return -1; return -1;
} }
if (qemuDomainNamespaceSetupHostdev(driver, vm, hostdev) < 0)
goto cleanup;
teardowndevice = true;
if (qemuSetupHostdevCgroup(vm, hostdev) < 0) if (qemuSetupHostdevCgroup(vm, hostdev) < 0)
goto cleanup; goto cleanup;
teardowncgroup = true; teardowncgroup = true;
if (virSecurityManagerSetHostdevLabel(driver->securityManager, if (qemuSecuritySetHostdevLabel(driver, vm, hostdev) < 0)
vm->def, hostdev, NULL) < 0)
goto cleanup; goto cleanup;
teardownlabel = true; teardownlabel = true;
...@@ -2449,9 +2465,11 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn, ...@@ -2449,9 +2465,11 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn,
if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0) if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail"); VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
if (teardownlabel && if (teardownlabel &&
virSecurityManagerRestoreHostdevLabel(driver->securityManager, qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
vm->def, hostdev, NULL) < 0)
VIR_WARN("Unable to restore host device labelling on hotplug fail"); VIR_WARN("Unable to restore host device labelling on hotplug fail");
if (teardowndevice &&
qemuDomainNamespaceTeardownHostdev(driver, vm, hostdev) < 0)
VIR_WARN("Unable to remove host device from /dev");
} }
VIR_FREE(drivealias); VIR_FREE(drivealias);
VIR_FREE(drvstr); VIR_FREE(drvstr);
...@@ -3782,13 +3800,15 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver, ...@@ -3782,13 +3800,15 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver,
virDomainAuditHostdev(vm, hostdev, "detach", true); virDomainAuditHostdev(vm, hostdev, "detach", true);
if (!is_vfio && if (!is_vfio &&
virSecurityManagerRestoreHostdevLabel(driver->securityManager, qemuSecurityRestoreHostdevLabel(driver, vm, hostdev) < 0)
vm->def, hostdev, NULL) < 0)
VIR_WARN("Failed to restore host device labelling"); VIR_WARN("Failed to restore host device labelling");
if (qemuTeardownHostdevCgroup(vm, hostdev) < 0) if (qemuTeardownHostdevCgroup(vm, hostdev) < 0)
VIR_WARN("Failed to remove host device cgroup ACL"); VIR_WARN("Failed to remove host device cgroup ACL");
if (qemuDomainNamespaceTeardownHostdev(driver, vm, hostdev) < 0)
VIR_WARN("Unable to remove host device from /dev");
switch ((virDomainHostdevSubsysType) hostdev->source.subsys.type) { switch ((virDomainHostdevSubsysType) hostdev->source.subsys.type) {
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
qemuDomainRemovePCIHostDevice(driver, vm, hostdev); qemuDomainRemovePCIHostDevice(driver, vm, hostdev);
......
...@@ -162,3 +162,37 @@ qemuSecurityRestoreDiskLabel(virQEMUDriverPtr driver, ...@@ -162,3 +162,37 @@ qemuSecurityRestoreDiskLabel(virQEMUDriverPtr driver,
vm->def, vm->def,
disk); disk);
} }
int
qemuSecuritySetHostdevLabel(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev)
{
if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT)) {
/* Already handled by namespace code. */
return 0;
}
return virSecurityManagerSetHostdevLabel(driver->securityManager,
vm->def,
hostdev,
NULL);
}
int
qemuSecurityRestoreHostdevLabel(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev)
{
if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT)) {
/* Already handled by namespace code. */
return 0;
}
return virSecurityManagerRestoreHostdevLabel(driver->securityManager,
vm->def,
hostdev,
NULL);
}
...@@ -44,4 +44,12 @@ int qemuSecuritySetDiskLabel(virQEMUDriverPtr driver, ...@@ -44,4 +44,12 @@ int qemuSecuritySetDiskLabel(virQEMUDriverPtr driver,
int qemuSecurityRestoreDiskLabel(virQEMUDriverPtr driver, int qemuSecurityRestoreDiskLabel(virQEMUDriverPtr driver,
virDomainObjPtr vm, virDomainObjPtr vm,
virDomainDiskDefPtr disk); virDomainDiskDefPtr disk);
int qemuSecuritySetHostdevLabel(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev);
int qemuSecurityRestoreHostdevLabel(virQEMUDriverPtr driver,
virDomainObjPtr vm,
virDomainHostdevDefPtr hostdev);
#endif /* __QEMU_SECURITY_H__ */ #endif /* __QEMU_SECURITY_H__ */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册