[libvirt] [PATCH 11/23] Add support for storage host device passthrough with LXC

Daniel P. Berrange berrange at redhat.com
Fri Nov 30 20:26:25 UTC 2012


From: "Daniel P. Berrange" <berrange at redhat.com>

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 at redhat.com>
---
 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




More information about the libvir-list mailing list