提交 117d04fb 编写于 作者: D Daniel P. Berrange

Fix handling of disk backing stores with cgroups

The cgroups ACL code was only allowing the primary disk image.
It is possible to chain images together, so we need to search
for backing stores and add them to the ACL too. Since the ACL
only handles block devices, we ignore the EINVAL we get from
plain files. In addition it was missing code to teardown the
cgroup when hot-unplugging a disk

* src/qemu/qemu_driver.c: Allow backing stores in cgroup ACLs
  and add missing teardown code in unplug path
上级 abb76942
...@@ -2929,6 +2929,102 @@ static const char *const defaultDeviceACL[] = { ...@@ -2929,6 +2929,102 @@ static const char *const defaultDeviceACL[] = {
#define DEVICE_PTY_MAJOR 136 #define DEVICE_PTY_MAJOR 136
#define DEVICE_SND_MAJOR 116 #define DEVICE_SND_MAJOR 116
static int qemuSetupDiskCgroup(virCgroupPtr cgroup,
virDomainObjPtr vm,
virDomainDiskDefPtr disk)
{
char *path = disk->src;
int ret = -1;
while (path != NULL) {
virStorageFileMetadata meta;
int rc;
VIR_DEBUG("Process path %s for disk", path);
rc = virCgroupAllowDevicePath(cgroup, path);
if (rc != 0) {
/* Get this for non-block devices */
if (rc == -EINVAL) {
VIR_DEBUG("Ignoring EINVAL for %s", path);
} else {
virReportSystemError(-rc,
_("Unable to allow device %s for %s"),
path, vm->def->name);
if (path != disk->src)
VIR_FREE(path);
goto cleanup;
}
}
memset(&meta, 0, sizeof(meta));
rc = virStorageFileGetMetadata(path, &meta);
if (path != disk->src)
VIR_FREE(path);
path = NULL;
if (rc < 0)
goto cleanup;
path = meta.backingStore;
} while (path != NULL);
ret = 0;
cleanup:
return ret;
}
static int qemuTeardownDiskCgroup(virCgroupPtr cgroup,
virDomainObjPtr vm,
virDomainDiskDefPtr disk)
{
char *path = disk->src;
int ret = -1;
while (path != NULL) {
virStorageFileMetadata meta;
int rc;
VIR_DEBUG("Process path %s for disk", path);
rc = virCgroupDenyDevicePath(cgroup, path);
if (rc != 0) {
/* Get this for non-block devices */
if (rc == -EINVAL) {
VIR_DEBUG("Ignoring EINVAL for %s", path);
} else {
virReportSystemError(-rc,
_("Unable to deny device %s for %s"),
path, vm->def->name);
if (path != disk->src)
VIR_FREE(path);
goto cleanup;
}
}
memset(&meta, 0, sizeof(meta));
rc = virStorageFileGetMetadata(path, &meta);
if (path != disk->src)
VIR_FREE(path);
path = NULL;
if (rc < 0)
goto cleanup;
path = meta.backingStore;
} while (path != NULL);
ret = 0;
cleanup:
return ret;
}
static int qemuSetupCgroup(struct qemud_driver *driver, static int qemuSetupCgroup(struct qemud_driver *driver,
virDomainObjPtr vm) virDomainObjPtr vm)
{ {
...@@ -2965,19 +3061,9 @@ static int qemuSetupCgroup(struct qemud_driver *driver, ...@@ -2965,19 +3061,9 @@ static int qemuSetupCgroup(struct qemud_driver *driver,
} }
for (i = 0; i < vm->def->ndisks ; i++) { for (i = 0; i < vm->def->ndisks ; i++) {
if (vm->def->disks[i]->type != VIR_DOMAIN_DISK_TYPE_BLOCK || if (qemuSetupDiskCgroup(cgroup, vm, vm->def->disks[i]) < 0)
vm->def->disks[i]->src == NULL)
continue;
rc = virCgroupAllowDevicePath(cgroup,
vm->def->disks[i]->src);
if (rc != 0) {
virReportSystemError(-rc,
_("Unable to allow device %s for %s"),
vm->def->disks[i]->src, vm->def->name);
goto cleanup; goto cleanup;
} }
}
rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_PTY_MAJOR); rc = virCgroupAllowDeviceMajor(cgroup, 'c', DEVICE_PTY_MAJOR);
if (rc != 0) { if (rc != 0) {
...@@ -7576,16 +7662,9 @@ static int qemudDomainAttachDevice(virDomainPtr dom, ...@@ -7576,16 +7662,9 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
vm->def->name); vm->def->name);
goto endjob; goto endjob;
} }
if (dev->data.disk->src != NULL && if (qemuSetupDiskCgroup(cgroup, vm, dev->data.disk) < 0)
dev->data.disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
virCgroupAllowDevicePath(cgroup,
dev->data.disk->src) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("unable to allow device %s"),
dev->data.disk->src);
goto endjob; goto endjob;
} }
}
switch (dev->data.disk->device) { switch (dev->data.disk->device) {
case VIR_DOMAIN_DISK_DEVICE_CDROM: case VIR_DOMAIN_DISK_DEVICE_CDROM:
...@@ -7628,8 +7707,9 @@ static int qemudDomainAttachDevice(virDomainPtr dom, ...@@ -7628,8 +7707,9 @@ static int qemudDomainAttachDevice(virDomainPtr dom,
/* Fallthrough */ /* Fallthrough */
} }
if (ret != 0 && cgroup) { if (ret != 0 && cgroup) {
virCgroupDenyDevicePath(cgroup, if (qemuTeardownDiskCgroup(cgroup, vm, dev->data.disk) < 0)
dev->data.disk->src); VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
} }
} else if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) { } else if (dev->type == VIR_DOMAIN_DEVICE_CONTROLLER) {
if (dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) { if (dev->data.controller->type == VIR_DOMAIN_CONTROLLER_TYPE_SCSI) {
...@@ -7827,16 +7907,9 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, ...@@ -7827,16 +7907,9 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
vm->def->name); vm->def->name);
goto endjob; goto endjob;
} }
if (dev->data.disk->src != NULL && if (qemuSetupDiskCgroup(cgroup, vm, dev->data.disk) < 0)
dev->data.disk->type == VIR_DOMAIN_DISK_TYPE_BLOCK &&
virCgroupAllowDevicePath(cgroup,
dev->data.disk->src) < 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("unable to allow device %s"),
dev->data.disk->src);
goto endjob; goto endjob;
} }
}
switch (dev->data.disk->device) { switch (dev->data.disk->device) {
case VIR_DOMAIN_DISK_DEVICE_CDROM: case VIR_DOMAIN_DISK_DEVICE_CDROM:
...@@ -7857,8 +7930,9 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, ...@@ -7857,8 +7930,9 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom,
} }
if (ret != 0 && cgroup) { if (ret != 0 && cgroup) {
virCgroupDenyDevicePath(cgroup, if (qemuTeardownDiskCgroup(cgroup, vm, dev->data.disk) < 0)
dev->data.disk->src); VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
} }
break; break;
...@@ -7930,6 +8004,7 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver, ...@@ -7930,6 +8004,7 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
int i, ret = -1; int i, ret = -1;
virDomainDiskDefPtr detach = NULL; virDomainDiskDefPtr detach = NULL;
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
virCgroupPtr cgroup = NULL;
i = qemudFindDisk(vm->def, dev->data.disk->dst); i = qemudFindDisk(vm->def, dev->data.disk->dst);
...@@ -7941,6 +8016,15 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver, ...@@ -7941,6 +8016,15 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
detach = vm->def->disks[i]; detach = vm->def->disks[i];
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to find cgroup for %s\n"),
vm->def->name);
goto cleanup;
}
}
if (!virDomainDeviceAddressIsValid(&detach->info, if (!virDomainDeviceAddressIsValid(&detach->info,
VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) { VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)) {
qemuReportError(VIR_ERR_OPERATION_FAILED, "%s", qemuReportError(VIR_ERR_OPERATION_FAILED, "%s",
...@@ -7965,11 +8049,19 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver, ...@@ -7965,11 +8049,19 @@ static int qemudDomainDetachPciDiskDevice(struct qemud_driver *driver,
qemudShrinkDisks(vm->def, i); qemudShrinkDisks(vm->def, i);
virDomainDiskDefFree(detach);
if (driver->securityDriver && if (driver->securityDriver &&
driver->securityDriver->domainRestoreSecurityImageLabel && driver->securityDriver->domainRestoreSecurityImageLabel &&
driver->securityDriver->domainRestoreSecurityImageLabel(vm, dev->data.disk) < 0) driver->securityDriver->domainRestoreSecurityImageLabel(vm, dev->data.disk) < 0)
VIR_WARN("Unable to restore security label on %s", dev->data.disk->src); VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
if (cgroup != NULL) {
if (qemuTeardownDiskCgroup(cgroup, vm, dev->data.disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
}
ret = 0; ret = 0;
cleanup: cleanup:
...@@ -7984,6 +8076,7 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver, ...@@ -7984,6 +8076,7 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
int i, ret = -1; int i, ret = -1;
virDomainDiskDefPtr detach = NULL; virDomainDiskDefPtr detach = NULL;
qemuDomainObjPrivatePtr priv = vm->privateData; qemuDomainObjPrivatePtr priv = vm->privateData;
virCgroupPtr cgroup = NULL;
i = qemudFindDisk(vm->def, dev->data.disk->dst); i = qemudFindDisk(vm->def, dev->data.disk->dst);
...@@ -8001,6 +8094,15 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver, ...@@ -8001,6 +8094,15 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
detach = vm->def->disks[i]; detach = vm->def->disks[i];
if (qemuCgroupControllerActive(driver, VIR_CGROUP_CONTROLLER_DEVICES)) {
if (virCgroupForDomain(driver->cgroup, vm->def->name, &cgroup, 0) != 0) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to find cgroup for %s\n"),
vm->def->name);
goto cleanup;
}
}
qemuDomainObjEnterMonitorWithDriver(driver, vm); qemuDomainObjEnterMonitorWithDriver(driver, vm);
if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
qemuDomainObjExitMonitor(vm); qemuDomainObjExitMonitor(vm);
...@@ -8017,6 +8119,12 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver, ...@@ -8017,6 +8119,12 @@ static int qemudDomainDetachSCSIDiskDevice(struct qemud_driver *driver,
driver->securityDriver->domainRestoreSecurityImageLabel(vm, dev->data.disk) < 0) driver->securityDriver->domainRestoreSecurityImageLabel(vm, dev->data.disk) < 0)
VIR_WARN("Unable to restore security label on %s", dev->data.disk->src); VIR_WARN("Unable to restore security label on %s", dev->data.disk->src);
if (cgroup != NULL) {
if (qemuTeardownDiskCgroup(cgroup, vm, dev->data.disk) < 0)
VIR_WARN("Failed to teardown cgroup for disk path %s",
NULLSTR(dev->data.disk->src));
}
ret = 0; ret = 0;
cleanup: cleanup:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册