[libvirt] [PATCH] LXC: support block devices for container

Gao feng gaofeng at cn.fujitsu.com
Fri Apr 6 06:31:54 UTC 2012


This patch allows to config block device for container.
the disk node is used to point out source device and target device
source device is the device path in host,
and target device is the device name in container.
such as
<disk type='block' device='disk'>
    <driver name="lxc"/>
    <source dev='/dev/sda2'/>
    <target dev='sda1'/>
</disk>

Unfortunately it's no use to config readonly in disk node now.

Signed-off-by: Gao feng <gaofeng at cn.fujitsu.com>
---
 src/lxc/lxc_container.c  |   78 ++++++++++++++++++++++++++++++++++++++++++++++
 src/lxc/lxc_controller.c |   15 +++++++++
 2 files changed, 93 insertions(+), 0 deletions(-)

diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 9bb6218..062cc8f 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -581,6 +581,80 @@ static int lxcContainerMountFSDevPTS(virDomainFSDefPtr root)
     return rc;
 }
 
+static int lxcContainerAddDisk(virDomainDiskDefPtr disk,
+                               const char *srcprefix)
+{
+    char *srcPath = NULL;
+    char *dstPath = NULL;
+    struct stat sb;
+    dev_t dev;
+    int ret = -1;
+    switch (disk->device) {
+    case VIR_DOMAIN_DISK_DEVICE_DISK:
+    case VIR_DOMAIN_DISK_DEVICE_LUN:
+        if (virAsprintf(&srcPath, "%s/%s", srcprefix, disk->src) < 0) {
+            virReportOOMError();
+            return ret;
+        }
+        if (virAsprintf(&dstPath, "/dev/%s", disk->dst) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+        if (stat(srcPath, &sb) < 0) {
+            ret = -errno;
+            goto cleanup;
+        }
+        dev = makedev(major(sb.st_rdev), minor(sb.st_rdev));
+        if (mknod(dstPath, S_ISCHR(sb.st_mode) ? S_IFCHR : S_IFBLK, dev) < 0 ||
+            chmod(dstPath, sb.st_mode)) {
+            virReportSystemError(errno,
+                                 _("Failed to make device %s"),
+                                 dstPath);
+            goto cleanup;
+        }
+        ret = 0;
+        break;
+    default:
+        lxcError(VIR_ERR_CONFIG_UNSUPPORTED,
+                 _("unsupported disk device type '%s'."),
+                 virDomainDiskDeviceTypeToString(disk->device));
+        break;
+    }
+
+cleanup:
+    VIR_FREE(srcPath);
+    VIR_FREE(dstPath);
+    return ret;
+}
+static int lxcContainerAddDevices(virDomainDefPtr vmDef,
+                                 const char *srcprefix)
+{
+    int ret = -1;
+    size_t i;
+
+    for (i=0 ; i<vmDef->ndisks ; i++) {
+        virDomainDiskDefPtr disk = vmDef->disks[i];
+
+        if (disk->driverName !=NULL && !STREQ(disk->driverName, "lxc")) {
+            lxcError(VIR_ERR_CONFIG_UNSUPPORTED,
+		     _("unsupported driver name '%s' for disk '%s'"),
+		     disk->driverName, disk->src);
+            continue;
+        }
+        if (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK) {
+            lxcError(VIR_ERR_CONFIG_UNSUPPORTED,
+                     _("unsupported disk type '%s'"),
+                     virDomainDiskTypeToString(disk->type));
+            continue;
+        }
+        if (lxcContainerAddDisk(disk, srcprefix) < 0)
+            goto cleanup;
+    }
+    ret = 0;
+cleanup:
+    return ret;
+}
+
 static int lxcContainerPopulateDevices(char **ttyPaths, size_t nttyPaths)
 {
     size_t i;
@@ -1144,6 +1218,10 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
     if (lxcContainerMountFSDevPTS(root) < 0)
         return -1;
 
+    /* Create devices */
+    if (lxcContainerAddDevices(vmDef, "/.oldroot") <0)
+        return -1;
+
     /* Populates device nodes in /dev/ */
     if (lxcContainerPopulateDevices(ttyPaths, nttyPaths) < 0)
         return -1;
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index bbc9d9c..5576f99 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -545,6 +545,21 @@ static int lxcSetContainerDeviceACL(virCgroupPtr cgroup, virDomainDefPtr def)
         }
     }
 
+    for (i = 0 ; i < def->ndisks ; i++) {
+        if (def->disks[i]->type != VIR_DOMAIN_DISK_TYPE_BLOCK)
+            continue;
+
+        rc = virCgroupAllowDevicePath(cgroup,
+                                      def->disks[i]->src,
+                                      VIR_CGROUP_DEVICE_RWM);
+        if (rc != 0) {
+            virReportSystemError(-rc,
+                                 _("Unable to allow device %s for domain %s"),
+                                 def->disks[i]->src, def->name);
+            goto cleanup;
+        }
+    }
+
     rc = virCgroupAllowDeviceMajor(cgroup, 'c', LXC_DEV_MAJ_PTY,
                                    VIR_CGROUP_DEVICE_RWM);
     if (rc != 0) {
-- 
1.7.7.6




More information about the libvir-list mailing list