
on 2012/12/01 04:26, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
This adds support for host device passthrough with the LXC driver. Since there is only a single kernel image, it doesn't make sense to pass through PCI devices, but USB devices are fine. For the latter we merely need to make the /dev/bus/usb/NNN/MMM character device exist in the container's /dev
Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/Makefile.am | 1 + src/lxc/lxc_cgroup.c | 64 ++++++++ src/lxc/lxc_cgroup.h | 12 ++ src/lxc/lxc_conf.h | 3 + src/lxc/lxc_container.c | 124 ++++++++++++++- src/lxc/lxc_driver.c | 6 + src/lxc/lxc_hostdev.c | 390 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lxc/lxc_hostdev.h | 43 ++++++ src/lxc/lxc_process.c | 11 ++ 9 files changed, 653 insertions(+), 1 deletion(-) create mode 100644 src/lxc/lxc_hostdev.c create mode 100644 src/lxc/lxc_hostdev.h
diff --git a/src/Makefile.am b/src/Makefile.am index 627dbb5..c3459a5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -411,6 +411,7 @@ LXC_DRIVER_SOURCES = \ lxc/lxc_container.c lxc/lxc_container.h \ lxc/lxc_cgroup.c lxc/lxc_cgroup.h \ lxc/lxc_domain.c lxc/lxc_domain.h \ + lxc/lxc_hostdev.c lxc/lxc_hostdev.h \ lxc/lxc_monitor.c lxc/lxc_monitor.h \ lxc/lxc_process.c lxc/lxc_process.h \ lxc/lxc_fuse.c lxc/lxc_fuse.h \ diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c index 0636869..14c840a 100644 --- a/src/lxc/lxc_cgroup.c +++ b/src/lxc/lxc_cgroup.c @@ -291,6 +291,49 @@ struct _virLXCCgroupDevicePolicy { };
+int +virLXCSetupHostUsbDeviceCgroup(usbDevice *dev ATTRIBUTE_UNUSED, + const char *path, + void *opaque) +{ + virCgroupPtr cgroup = opaque; + int rc; + + VIR_DEBUG("Process path '%s' for USB device", path); + rc = virCgroupAllowDevicePath(cgroup, path, + VIR_CGROUP_DEVICE_RW); + if (rc < 0) {
Maybe it's better to give some warning message when rc == 1,it means the path is not a device.
+ virReportSystemError(-rc, + _("Unable to allow device %s"), + path); + return -1; + } + + return 0; +} + + +int +virLXCTeardownHostUsbDeviceCgroup(usbDevice *dev ATTRIBUTE_UNUSED, + const char *path, + void *opaque) +{ + virCgroupPtr cgroup = opaque; + int rc; + + VIR_DEBUG("Process path '%s' for USB device", path); + rc = virCgroupDenyDevicePath(cgroup, path, + VIR_CGROUP_DEVICE_RW); + if (rc < 0) { + virReportSystemError(-rc, + _("Unable to deny device %s"), + path); + return -1; + } + + return 0; +} +
[...]
+static int lxcContainerSetupHostdevSubsysUSB(virDomainDefPtr vmDef ATTRIBUTE_UNUSED, + virDomainHostdevDefPtr def ATTRIBUTE_UNUSED, + const char *dstprefix ATTRIBUTE_UNUSED, + virSecurityManagerPtr securityDriver ATTRIBUTE_UNUSED)
ATTRIBUTE_UNUSED should be removed.
+{ + int ret = -1; + char *src = NULL; + char *dstdir = NULL; + char *dstfile = NULL; + struct stat sb; + mode_t mode; +
[...]
+ +int +virLXCPrepareHostdevUSBDevices(virLXCDriverPtr driver, + const char *name, + usbDeviceList *list) +{ + size_t i, j; + unsigned int count; + usbDevice *tmp; + + count = usbDeviceListCount(list); + + for (i = 0; i < count; i++) { + usbDevice *usb = usbDeviceListGet(list, i); + if ((tmp = usbDeviceListFind(driver->activeUsbHostdevs, usb))) { + const char *other_name = usbDeviceGetUsedBy(tmp); + + if (other_name) + virReportError(VIR_ERR_OPERATION_INVALID, + _("USB device %s is in use by domain %s"), + usbDeviceGetName(tmp), other_name); + else + virReportError(VIR_ERR_OPERATION_INVALID, + _("USB device %s is already in use"), + usbDeviceGetName(tmp)); + goto error; + } + + usbDeviceSetUsedBy(usb, name); + VIR_DEBUG("Adding %03d.%03d dom=%s to activeUsbHostdevs", + usbDeviceGetBus(usb), usbDeviceGetDevno(usb), name); + /* + * The caller is responsible to steal these usb devices + * from the usbDeviceList that passed in on success, + * perform rollback on failure. + */ + if (usbDeviceListAdd(driver->activeUsbHostdevs, usb) < 0) + goto error; + } + return 0; + +error: + for (j = 0; j < i; j++) { + tmp = usbDeviceListGet(list, i);
j?
+ usbDeviceListSteal(driver->activeUsbHostdevs, tmp); + } + return -1; +}
this patch looks good to me. ACK