]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
Description: run MAKEDEV console when doing lxc.autodev
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Thu, 29 Nov 2012 16:46:46 +0000 (10:46 -0600)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Thu, 29 Nov 2012 17:14:07 +0000 (11:14 -0600)
mounted-dev.conf won't be running that in container's userspace as it
previously would have, so make sure that all the devices it would have
created (other than ones which lxc later finagles) get created.
To achieve this, we have to first mount /dev, then run MAKEDEV, then
run setup_autodev to populate the rest of /dev.

Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/lxc/+bug/1075717

Changelog:
  v2: Use INFO rather than ERROR when makedev fails, since we won't stop the container boot.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
src/lxc/conf.c

index eb0c07edb51baac49a984c6ccf42f1d5f490f2cc..e3f1d53c7db38ad7a555177b4682713eb46f5c55 100644 (file)
@@ -231,12 +231,41 @@ static struct caps_opt caps_opt[] = {
 #endif
 };
 
+static int run_buffer(char *buffer)
+{
+       FILE *f;
+       char *output;
+
+       f = popen(buffer, "r");
+       if (!f) {
+               SYSERROR("popen failed");
+               return -1;
+       }
+
+       output = malloc(LXC_LOG_BUFFER_SIZE);
+       if (!output) {
+               ERROR("failed to allocate memory for script output");
+               return -1;
+       }
+
+       while(fgets(output, LXC_LOG_BUFFER_SIZE, f))
+               DEBUG("script output: %s", output);
+
+       free(output);
+
+       if (pclose(f) == -1) {
+               SYSERROR("Script exited on error");
+               return -1;
+       }
+
+       return 0;
+}
+
 static int run_script(const char *name, const char *section,
                      const char *script, ...)
 {
        int ret;
-       FILE *f;
-       char *buffer, *p, *output;
+       char *buffer, *p;
        size_t size = 0;
        va_list ap;
 
@@ -283,29 +312,7 @@ static int run_script(const char *name, const char *section,
        }
        va_end(ap);
 
-       f = popen(buffer, "r");
-       if (!f) {
-               SYSERROR("popen failed");
-               return -1;
-       }
-
-       output = malloc(LXC_LOG_BUFFER_SIZE);
-       if (!output) {
-               ERROR("failed to allocate memory for script output");
-               return -1;
-       }
-
-       while(fgets(output, LXC_LOG_BUFFER_SIZE, f))
-               DEBUG("script output: %s", output);
-
-       free(output);
-
-       if (pclose(f) == -1) {
-               SYSERROR("Script exited on error");
-               return -1;
-       }
-
-       return 0;
+       return run_buffer(buffer);
 }
 
 static int find_fstype_cb(char* buffer, void *data)
@@ -869,6 +876,62 @@ static int setup_rootfs_pivot_root(const char *rootfs, const char *pivotdir)
        return 0;
 }
 
+/*
+ * Do we want to add options for max size of /dev and a file to
+ * specify which devices to create?
+ */
+static int mount_autodev(char *root)
+{
+       int ret;
+       char path[MAXPATHLEN];
+
+       INFO("Mounting /dev under %s\n", root);
+       ret = snprintf(path, MAXPATHLEN, "%s/dev", root);
+       if (ret < 0 || ret > MAXPATHLEN)
+               return -1;
+       ret = mount("none", path, "tmpfs", 0, "size=100000");
+       if (ret) {
+               SYSERROR("Failed to mount /dev at %s\n", root);
+               return -1;
+       }
+       ret = snprintf(path, MAXPATHLEN, "%s/dev/pts", root);
+       if (ret < 0 || ret >= MAXPATHLEN)
+               return -1;
+       ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
+       if (ret) {
+               SYSERROR("Failed to create /dev/pts in container");
+               return -1;
+       }
+
+       INFO("Mounted /dev under %s\n", root);
+       return 0;
+}
+
+/*
+ * Try to run MAKEDEV console in the container.  If something fails,
+ * continue anyway as it should not be detrimental to the container.
+ * This makes sure that things like /dev/vcs* exist.
+ * (Pass devpath in to reduce stack usage)
+ */
+static void run_makedev(char *devpath)
+{
+       int curd;
+       int ret;
+
+       curd = open(".", O_RDONLY);
+       if (curd < 0)
+               return;
+       ret = chdir(devpath);
+       if (ret) {
+               close(curd);
+               return;
+       }
+       if (run_buffer("/sbin/MAKEDEV console"))
+               INFO("Error running MAKEDEV console in %s", devpath);
+       fchdir(curd);
+       close(curd);
+}
+
 struct lxc_devs {
        char *name;
        mode_t mode;
@@ -886,10 +949,6 @@ struct lxc_devs lxc_devs[] = {
        { "console",    S_IFCHR | S_IRUSR | S_IWUSR,           5, 1     },
 };
 
-/*
- * Do we want to add options for max size of /dev and a file to
- * specify which devices to create?
- */
 static int setup_autodev(char *root)
 {
        int ret;
@@ -897,34 +956,27 @@ static int setup_autodev(char *root)
        char path[MAXPATHLEN];
        int i;
 
-       INFO("Creating and populating /dev under %s\n", root);
+       INFO("Creating initial consoles under %s/dev\n", root);
+
        ret = snprintf(path, MAXPATHLEN, "%s/dev", root);
-       if (ret < 0 || ret > MAXPATHLEN)
+       if (ret < 0 || ret >= MAXPATHLEN) {
+               ERROR("Error calculating container /dev location");
                return -1;
-       ret = mount("none", path, "tmpfs", 0, "size=100000");
-       if (ret) {
-               SYSERROR("Failed to mount /dev at %s\n", root);
-               return -1;
-       }
+       } else
+               run_makedev(path);
+
+       INFO("Populating /dev under %s\n", root);
        for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) {
                d = &lxc_devs[i];
                ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", root, d->name);
                if (ret < 0 || ret >= MAXPATHLEN)
                        return -1;
                ret = mknod(path, d->mode, makedev(d->maj, d->min));
-               if (ret) {
+               if (ret && errno != EEXIST) {
                        SYSERROR("Error creating %s\n", d->name);
                        return -1;
                }
        }
-       ret = snprintf(path, MAXPATHLEN, "%s/dev/pts", root);
-       if (ret < 0 || ret >= MAXPATHLEN)
-               return -1;
-       ret = mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
-       if (ret) {
-               SYSERROR("Failed to create /dev/pts in container");
-               return -1;
-       }
 
        INFO("Populated /dev under %s\n", root);
        return 0;
@@ -2336,8 +2388,8 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
        }
 
        if (lxc_conf->autodev) {
-               if (setup_autodev(lxc_conf->rootfs.mount)) {
-                       ERROR("failed to set up /dev in the container");
+               if (mount_autodev(lxc_conf->rootfs.mount)) {
+                       ERROR("failed to mount /dev in the container");
                        return -1;
                }
        }
@@ -2357,6 +2409,13 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
                return -1;
        }
 
+       if (lxc_conf->autodev) {
+               if (setup_autodev(lxc_conf->rootfs.mount)) {
+                       ERROR("failed to populate /dev in the container");
+                       return -1;
+               }
+       }
+
        if (setup_cgroup(name, &lxc_conf->cgroup)) {
                ERROR("failed to setup the cgroups for '%s'", name);
                return -1;