Commit 91c3830e by Serge Hallyn

Description: run MAKEDEV console when doing lxc.autodev

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: 's avatarSerge Hallyn <serge.hallyn@ubuntu.com> Acked-by: 's avatarStéphane Graber <stgraber@ubuntu.com>
parent 5f29734f
...@@ -231,12 +231,41 @@ static struct caps_opt caps_opt[] = { ...@@ -231,12 +231,41 @@ static struct caps_opt caps_opt[] = {
#endif #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, static int run_script(const char *name, const char *section,
const char *script, ...) const char *script, ...)
{ {
int ret; int ret;
FILE *f; char *buffer, *p;
char *buffer, *p, *output;
size_t size = 0; size_t size = 0;
va_list ap; va_list ap;
...@@ -283,29 +312,7 @@ static int run_script(const char *name, const char *section, ...@@ -283,29 +312,7 @@ static int run_script(const char *name, const char *section,
} }
va_end(ap); va_end(ap);
f = popen(buffer, "r"); return run_buffer(buffer);
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 find_fstype_cb(char* buffer, void *data) 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) ...@@ -869,6 +876,62 @@ static int setup_rootfs_pivot_root(const char *rootfs, const char *pivotdir)
return 0; 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 { struct lxc_devs {
char *name; char *name;
mode_t mode; mode_t mode;
...@@ -886,10 +949,6 @@ struct lxc_devs lxc_devs[] = { ...@@ -886,10 +949,6 @@ struct lxc_devs lxc_devs[] = {
{ "console", S_IFCHR | S_IRUSR | S_IWUSR, 5, 1 }, { "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) static int setup_autodev(char *root)
{ {
int ret; int ret;
...@@ -897,34 +956,27 @@ static int setup_autodev(char *root) ...@@ -897,34 +956,27 @@ static int setup_autodev(char *root)
char path[MAXPATHLEN]; char path[MAXPATHLEN];
int i; 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); 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; return -1;
ret = mount("none", path, "tmpfs", 0, "size=100000"); } else
if (ret) { run_makedev(path);
SYSERROR("Failed to mount /dev at %s\n", root);
return -1; INFO("Populating /dev under %s\n", root);
}
for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) { for (i = 0; i < sizeof(lxc_devs) / sizeof(lxc_devs[0]); i++) {
d = &lxc_devs[i]; d = &lxc_devs[i];
ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", root, d->name); ret = snprintf(path, MAXPATHLEN, "%s/dev/%s", root, d->name);
if (ret < 0 || ret >= MAXPATHLEN) if (ret < 0 || ret >= MAXPATHLEN)
return -1; return -1;
ret = mknod(path, d->mode, makedev(d->maj, d->min)); ret = mknod(path, d->mode, makedev(d->maj, d->min));
if (ret) { if (ret && errno != EEXIST) {
SYSERROR("Error creating %s\n", d->name); SYSERROR("Error creating %s\n", d->name);
return -1; 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); INFO("Populated /dev under %s\n", root);
return 0; return 0;
...@@ -2336,8 +2388,8 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf) ...@@ -2336,8 +2388,8 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
} }
if (lxc_conf->autodev) { if (lxc_conf->autodev) {
if (setup_autodev(lxc_conf->rootfs.mount)) { if (mount_autodev(lxc_conf->rootfs.mount)) {
ERROR("failed to set up /dev in the container"); ERROR("failed to mount /dev in the container");
return -1; return -1;
} }
} }
...@@ -2357,6 +2409,13 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf) ...@@ -2357,6 +2409,13 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf)
return -1; 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)) { if (setup_cgroup(name, &lxc_conf->cgroup)) {
ERROR("failed to setup the cgroups for '%s'", name); ERROR("failed to setup the cgroups for '%s'", name);
return -1; return -1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment