[libvirt] [RFC PATCH 4/6] LXC: Creating devices for container on host side

Gao feng gaofeng at cn.fujitsu.com
Mon Mar 11 06:26:50 UTC 2013


user namespace doesn't allow to create devices in
uninit userns. We should create devices on host side.

Signed-off-by: Gao feng <gaofeng at cn.fujitsu.com>
---
 src/lxc/lxc_container.c  | 47 +++++++--------------------
 src/lxc/lxc_controller.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 94 insertions(+), 36 deletions(-)

diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 92af3e5..58d6ee5 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -681,22 +681,10 @@ static int lxcContainerMountFSDevPTS(virDomainFSDefPtr root)
     return rc;
 }
 
-static int lxcContainerPopulateDevices(char **ttyPaths, size_t nttyPaths)
+static int lxcContainerSetupDevices(char **ttyPaths, size_t nttyPaths)
 {
     size_t i;
     const struct {
-        int maj;
-        int min;
-        mode_t mode;
-        const char *path;
-    } devs[] = {
-        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_NULL, 0666, "/dev/null" },
-        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_ZERO, 0666, "/dev/zero" },
-        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_FULL, 0666, "/dev/full" },
-        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_RANDOM, 0666, "/dev/random" },
-        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM, 0666, "/dev/urandom" },
-    };
-    const struct {
         const char *src;
         const char *dst;
     } links[] = {
@@ -706,18 +694,6 @@ static int lxcContainerPopulateDevices(char **ttyPaths, size_t nttyPaths)
         { "/proc/self/fd", "/dev/fd" },
     };
 
-    /* Populate /dev/ with a few important bits */
-    for (i = 0 ; i < ARRAY_CARDINALITY(devs) ; i++) {
-        dev_t dev = makedev(devs[i].maj, devs[i].min);
-        if (mknod(devs[i].path, S_IFCHR, dev) < 0 ||
-            chmod(devs[i].path, devs[i].mode)) {
-            virReportSystemError(errno,
-                                 _("Failed to make device %s"),
-                                 devs[i].path);
-            return -1;
-        }
-    }
-
     for (i = 0 ; i < ARRAY_CARDINALITY(links) ; i++) {
         if (symlink(links[i].src, links[i].dst) < 0) {
             virReportSystemError(errno,
@@ -737,15 +713,6 @@ static int lxcContainerPopulateDevices(char **ttyPaths, size_t nttyPaths)
                                  _("Failed to bind /dev/pts/ptmx on to /dev/ptmx"));
             return -1;
         }
-    } else {
-        /* Legacy devpts, so we need to just use shared one */
-        dev_t dev = makedev(LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX);
-        if (mknod("/dev/ptmx", S_IFCHR, dev) < 0 ||
-            chmod("/dev/ptmx", 0666)) {
-            virReportSystemError(errno, "%s",
-                                 _("Failed to make device /dev/ptmx"));
-            return -1;
-        }
     }
 
     for (i = 0 ; i < nttyPaths ; i++) {
@@ -1988,8 +1955,8 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
     if (lxcContainerMountFSDevPTS(root) < 0)
         goto cleanup;
 
-    /* Populates device nodes in /dev/ */
-    if (lxcContainerPopulateDevices(ttyPaths, nttyPaths) < 0)
+    /* Setup device nodes in /dev/ */
+    if (lxcContainerSetupDevices(ttyPaths, nttyPaths) < 0)
         goto cleanup;
 
     /* Sets up any non-root mounts from guest config */
@@ -2306,6 +2273,14 @@ static int lxcContainerChild(void *data)
         goto cleanup;
     }
 
+    /* Wait for controller creating devices for container */
+    if (lxcContainerWaitForContinue(argv->monitor) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Failed to read the container continue message"));
+        goto cleanup;
+    }
+    VIR_DEBUG("Received container continue message, create devices success.");
+
     ret = 0;
 cleanup:
     VIR_FREE(ttyPath);
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index f17142f..c6f8c3b 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -1092,6 +1092,79 @@ cleanup:
 }
 
 
+static int virLXCControllerPopulateDevices(virLXCControllerPtr ctrl)
+{
+    size_t i;
+    char *ptmx = NULL;
+    const struct {
+        int maj;
+        int min;
+        mode_t mode;
+        const char *path;
+    } devs[] = {
+        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_NULL, 0666, "/dev/null" },
+        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_ZERO, 0666, "/dev/zero" },
+        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_FULL, 0666, "/dev/full" },
+        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_RANDOM, 0666, "/dev/random" },
+        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM, 0666, "/dev/urandom" },
+    };
+    virDomainFSDefPtr root = virDomainGetRootFilesystem(ctrl->def);
+
+    if (root == NULL || root->src == NULL)
+        return 0;
+
+    /* Populate /dev/ with a few important bits */
+    for (i = 0 ; i < ARRAY_CARDINALITY(devs) ; i++) {
+        char *path = NULL;
+        if (virAsprintf(&path, "/proc/%llu/root/%s",
+                        (unsigned long long)ctrl->initpid,
+                        devs[i].path) < 0) {
+            virReportOOMError();
+            return -1;
+        }
+        dev_t dev = makedev(devs[i].maj, devs[i].min);
+        if (mknod(path, S_IFCHR, dev) < 0 ||
+            chmod(path, devs[i].mode)) {
+            virReportSystemError(errno,
+                                 _("Failed to make device %s"),
+                                 path);
+            VIR_FREE(path);
+            return -1;
+        }
+        VIR_FREE(path);
+    }
+
+    if (virAsprintf(&ptmx, "/proc/%llu/root/dev/pts/ptmx",
+                    (unsigned long long)ctrl->initpid) < 0) {
+        virReportOOMError();
+        return -1;
+    }
+
+    if (access(ptmx, W_OK)) {
+        char *path = NULL;
+        if (virAsprintf(&path, "/proc/%llu/root/dev/ptmx",
+                        (unsigned long long)ctrl->initpid) < 0) {
+            virReportOOMError();
+            VIR_FREE(ptmx);
+            return -1;
+        }
+        /* Legacy devpts, so we need to just use shared one */
+        dev_t dev = makedev(LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX);
+        if (mknod(path, S_IFCHR, dev) < 0 ||
+            chmod(path, 0666)) {
+            virReportSystemError(errno,
+                                 _("Failed to make device %s"), path);
+            VIR_FREE(path);
+            VIR_FREE(ptmx);
+            return -1;
+        }
+        VIR_FREE(path);
+    }
+    VIR_FREE(ptmx);
+    return 0;
+}
+
+
 /**
  * virLXCControllerMoveInterfaces
  * @nveths: number of interfaces
@@ -1535,6 +1608,16 @@ virLXCControllerRun(virLXCControllerPtr ctrl)
         goto cleanup;
     }
 
+    /* Populate devices for container */
+    if (virLXCControllerPopulateDevices(ctrl) < 0)
+        goto cleanup;
+
+    if (lxcContainerSendContinue(control[0]) < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to send container continue message"));
+        goto cleanup;
+    }
+
     /* Now the container is fully setup... */
 
     /* ...we can close the loop devices... */
-- 
1.7.11.7




More information about the libvir-list mailing list