From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> This extends support for host device passthrough with LXC to cover storage devices. In this case all we need todo is a mknod in the container's /dev and whitelist the device in cgroups Signed-off-by: Daniel P. Berrange <berrange@xxxxxxxxxx> --- src/lxc/lxc_cgroup.c | 46 ++++++++++++++++++---------- src/lxc/lxc_container.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 15 deletions(-) diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index 14c840a..0c3d5dd 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -414,21 +414,37 @@ static int virLXCCgroupSetupDeviceACL(virDomainDefPtr def, virDomainHostdevDefPtr hostdev = def->hostdevs[i]; usbDevice *usb; - if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) - continue; - if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) - continue; - if (hostdev->missing) - continue; - - if ((usb = usbGetDevice(hostdev->source.subsys.u.usb.bus, - hostdev->source.subsys.u.usb.device, - NULL)) == NULL) - goto cleanup; - - if (usbDeviceFileIterate(usb, virLXCSetupHostUsbDeviceCgroup, - cgroup) < 0) - goto cleanup; + switch (hostdev->mode) { + case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: + if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) + continue; + if (hostdev->missing) + continue; + + if ((usb = usbGetDevice(hostdev->source.subsys.u.usb.bus, + hostdev->source.subsys.u.usb.device, + NULL)) == NULL) + goto cleanup; + + if (usbDeviceFileIterate(usb, virLXCSetupHostUsbDeviceCgroup, + cgroup) < 0) + goto cleanup; + break; + case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES: + switch (hostdev->source.caps.type) { + case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE: + if (virCgroupAllowDevicePath(cgroup, + hostdev->source.caps.u.storage.block, + VIR_CGROUP_DEVICE_RW | + VIR_CGROUP_DEVICE_MKNOD) < 0) + goto cleanup; + break; + default: + break; + } + default: + break; + } } rc = virCgroupAllowDeviceMajor(cgroup, 'c', LXC_DEV_MAJ_PTY, diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 0a407bf..19c5702 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -1384,6 +1384,64 @@ cleanup: } +static int lxcContainerSetupHostdevCapsStorage(virDomainDefPtr vmDef ATTRIBUTE_UNUSED, + virDomainHostdevDefPtr def ATTRIBUTE_UNUSED, + const char *dstprefix ATTRIBUTE_UNUSED, + virSecurityManagerPtr securityDriver ATTRIBUTE_UNUSED) +{ + char *src = NULL; + int ret = -1; + struct stat sb; + mode_t mode; + + if (def->source.caps.u.storage.block == NULL) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Missing storage host block path")); + goto cleanup; + } + + if (virAsprintf(&src, "%s/%s", dstprefix, def->source.caps.u.storage.block) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (stat(src, &sb) < 0) { + virReportSystemError(errno, + _("Unable to access %s"), + src); + goto cleanup; + } + + if (!S_ISBLK(sb.st_mode)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Storage source %s must be a block device"), + def->source.caps.u.storage.block); + goto cleanup; + } + + mode = 0700 | S_IFBLK; + + VIR_DEBUG("Creating dev %s (%d,%d)", + def->source.caps.u.storage.block, + major(sb.st_rdev), minor(sb.st_rdev)); + if (mknod(def->source.caps.u.storage.block, mode, sb.st_rdev) < 0) { + virReportSystemError(errno, + _("Unable to create device %s"), + def->source.caps.u.storage.block); + goto cleanup; + } + + if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0) + goto cleanup; + + ret = 0; + +cleanup: + VIR_FREE(src); + return ret; +} + + static int lxcContainerSetupHostdevSubsys(virDomainDefPtr vmDef, virDomainHostdevDefPtr def, const char *dstprefix, @@ -1402,6 +1460,24 @@ static int lxcContainerSetupHostdevSubsys(virDomainDefPtr vmDef, } +static int lxcContainerSetupHostdevCaps(virDomainDefPtr vmDef, + virDomainHostdevDefPtr def, + const char *dstprefix, + virSecurityManagerPtr securityDriver) +{ + switch (def->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE: + return lxcContainerSetupHostdevCapsStorage(vmDef, def, dstprefix, securityDriver); + + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unsupported host device mode %s"), + virDomainHostdevCapsTypeToString(def->source.subsys.type)); + return -1; + } +} + + static int lxcContainerSetupAllHostdevs(virDomainDefPtr vmDef, const char *dstprefix, virSecurityManagerPtr securityDriver) @@ -1416,6 +1492,10 @@ static int lxcContainerSetupAllHostdevs(virDomainDefPtr vmDef, if (lxcContainerSetupHostdevSubsys(vmDef, def, dstprefix, securityDriver) < 0) return -1; break; + case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES: + if (lxcContainerSetupHostdevCaps(vmDef, def, dstprefix, securityDriver) < 0) + return -1; + break; default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Unsupported host device mode %s"), -- 1.8.0.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list