on 2012/12/01 04:26, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange(a)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(a)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