Unverified Commit f947066a by Christian Brauner Committed by GitHub

Merge pull request #2092 from lifeng68/modify_console_create

Create console when the rootfs is NULL
parents a346335e 86530b0a
...@@ -1565,11 +1565,12 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, ...@@ -1565,11 +1565,12 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
{ {
char path[MAXPATHLEN]; char path[MAXPATHLEN];
int ret, fd; int ret, fd;
char *rootfs_path = rootfs->path ? rootfs->mount : "";
if (console->path && !strcmp(console->path, "none")) if (console->path && !strcmp(console->path, "none"))
return 0; return 0;
ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount); ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs_path);
if (ret < 0 || (size_t)ret >= sizeof(path)) if (ret < 0 || (size_t)ret >= sizeof(path))
return -1; return -1;
...@@ -1579,16 +1580,10 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, ...@@ -1579,16 +1580,10 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
if (file_exists(path)) { if (file_exists(path)) {
ret = lxc_unstack_mountpoint(path, false); ret = lxc_unstack_mountpoint(path, false);
if (ret < 0) { if (ret < 0) {
ERROR("failed to unmount \"%s\": %s", path, strerror(errno)); ERROR("Failed to unmount \"%s\": %s", path, strerror(errno));
return -ret; return -ret;
} else { } else {
DEBUG("cleared all (%d) mounts from \"%s\"", ret, path); DEBUG("Cleared all (%d) mounts from \"%s\"", ret, path);
}
ret = unlink(path);
if (ret < 0) {
SYSERROR("error unlinking %s", path);
return -errno;
} }
} }
...@@ -1598,24 +1593,26 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs, ...@@ -1598,24 +1593,26 @@ static int lxc_setup_dev_console(const struct lxc_rootfs *rootfs,
fd = open(path, O_CREAT | O_EXCL, S_IXUSR | S_IXGRP | S_IXOTH); fd = open(path, O_CREAT | O_EXCL, S_IXUSR | S_IXGRP | S_IXOTH);
if (fd < 0) { if (fd < 0) {
if (errno != EEXIST) { if (errno != EEXIST) {
SYSERROR("failed to create console"); SYSERROR("Failed to create console");
return -errno; return -errno;
} }
} else { } else {
close(fd); close(fd);
} }
if (chmod(console->name, S_IXUSR | S_IXGRP | S_IXOTH)) { ret = chmod(console->name, S_IXUSR | S_IXGRP | S_IXOTH);
SYSERROR("failed to set mode '0%o' to '%s'", S_IXUSR | S_IXGRP | S_IXOTH, console->name); if (ret < 0) {
SYSERROR("Failed to set mode '0%o' to '%s'", S_IXUSR | S_IXGRP | S_IXOTH, console->name);
return -errno; return -errno;
} }
if (safe_mount(console->name, path, "none", MS_BIND, 0, rootfs->mount) < 0) { ret = safe_mount(console->name, path, "none", MS_BIND, 0, rootfs_path);
ERROR("failed to mount '%s' on '%s'", console->name, path); if (ret < 0) {
ERROR("Failed to mount '%s' on '%s'", console->name, path);
return -1; return -1;
} }
DEBUG("mounted pts device \"%s\" onto \"%s\"", console->name, path); DEBUG("Mounted pts device \"%s\" onto \"%s\"", console->name, path);
return 0; return 0;
} }
...@@ -1623,137 +1620,91 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs, ...@@ -1623,137 +1620,91 @@ static int lxc_setup_ttydir_console(const struct lxc_rootfs *rootfs,
const struct lxc_console *console, const struct lxc_console *console,
char *ttydir) char *ttydir)
{ {
int ret; int ret, fd;
char path[MAXPATHLEN], lxcpath[MAXPATHLEN]; char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
char *rootfs_path = rootfs->path ? rootfs->mount : "";
if (console->path && !strcmp(console->path, "none"))
return 0;
/* create rootfs/dev/<ttydir> directory */ /* create rootfs/dev/<ttydir> directory */
ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->mount, ttydir); ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs_path, ttydir);
if (ret < 0 || (size_t)ret >= sizeof(path)) if (ret < 0 || (size_t)ret >= sizeof(path))
return -1; return -1;
ret = mkdir(path, 0755); ret = mkdir(path, 0755);
if (ret && errno != EEXIST) { if (ret && errno != EEXIST) {
SYSERROR("failed with errno %d to create %s", errno, path); SYSERROR("Failed with errno %d to create %s", errno, path);
return -errno; return -errno;
} }
DEBUG("Created directory for console and tty devices at \"%s\"", path); DEBUG("Created directory for console and tty devices at \"%s\"", path);
ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console", rootfs->mount, ttydir); ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console", rootfs_path, ttydir);
if (ret < 0 || (size_t)ret >= sizeof(lxcpath)) if (ret < 0 || (size_t)ret >= sizeof(lxcpath))
return -1; return -1;
ret = creat(lxcpath, 0660); ret = creat(lxcpath, 0660);
if (ret == -1 && errno != EEXIST) { if (ret == -1 && errno != EEXIST) {
SYSERROR("error %d creating %s", errno, lxcpath); SYSERROR("Error %d creating %s", errno, lxcpath);
return -errno; return -errno;
} }
if (ret >= 0) if (ret >= 0)
close(ret); close(ret);
ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount); ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs_path);
if (ret < 0 || (size_t)ret >= sizeof(lxcpath)) if (ret < 0 || (size_t)ret >= sizeof(path))
return -1; return -1;
/* When we are asked to setup a console we remove any previous
* /dev/console bind-mounts.
*/
if (console->path && !strcmp(console->path, "none")) {
struct stat st;
ret = stat(path, &st);
if (ret < 0) {
if (errno == ENOENT)
return 0;
SYSERROR("failed stat() \"%s\"", path);
return -errno;
}
/* /dev/console must be character device with major number 5 and
* minor number 1. If not, give benefit of the doubt and assume
* the user has mounted something else right there on purpose.
*/
if (((st.st_mode & S_IFMT) != S_IFCHR) || major(st.st_rdev) != 5 || minor(st.st_rdev) != 1)
return 0;
/* In case the user requested a bind-mount for /dev/console and
* requests a ttydir we move the mount to the
* /dev/<ttydir/console.
* Note, we only move the uppermost mount and clear all other
* mounts underneath for safety.
* If it is a character device created via mknod() we simply
* rename it.
*/
ret = safe_mount(path, lxcpath, "none", MS_MOVE, NULL, rootfs->mount);
if (ret < 0) {
if (errno != EINVAL) {
ERROR("failed to MS_MOVE \"%s\" to \"%s\": %s", path, lxcpath, strerror(errno));
return -errno;
}
/* path was not a mountpoint */
ret = rename(path, lxcpath);
if (ret < 0) {
ERROR("failed to rename \"%s\" to \"%s\": %s", path, lxcpath, strerror(errno));
return -errno;
}
DEBUG("renamed \"%s\" to \"%s\"", path, lxcpath);
} else {
DEBUG("moved mount \"%s\" to \"%s\"", path, lxcpath);
}
/* Clear all remaining bind-mounts. */
ret = lxc_unstack_mountpoint(path, false);
if (ret < 0) {
ERROR("failed to unmount \"%s\": %s", path, strerror(errno));
return -ret;
} else {
DEBUG("cleared all (%d) mounts from \"%s\"", ret, path);
}
} else {
if (file_exists(path)) { if (file_exists(path)) {
ret = lxc_unstack_mountpoint(path, false); ret = lxc_unstack_mountpoint(path, false);
if (ret < 0) { if (ret < 0) {
ERROR("failed to unmount \"%s\": %s", path, strerror(errno)); ERROR("Failed to unmount \"%s\": %s", path, strerror(errno));
return -ret; return -ret;
} else { } else {
DEBUG("cleared all (%d) mounts from \"%s\"", ret, path); DEBUG("Cleared all (%d) mounts from \"%s\"", ret, path);
} }
} }
if (safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs->mount) < 0) { fd = open(path, O_CREAT | O_EXCL, S_IXUSR | S_IXGRP | S_IXOTH);
ERROR("failed to mount '%s' on '%s'", console->name, lxcpath); if (fd < 0) {
return -1; if (errno != EEXIST) {
SYSERROR("Failed to create console");
return -errno;
} }
DEBUG("mounted \"%s\" onto \"%s\"", console->name, lxcpath); } else {
close(fd);
} }
/* create symlink from rootfs /dev/console to '<ttydir>/console' */ ret = chmod(console->name, S_IXUSR | S_IXGRP | S_IXOTH);
ret = snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir); if (ret < 0) {
if (ret < 0 || (size_t)ret >= sizeof(lxcpath)) SYSERROR("Failed to set mode '0%o' to '%s'", S_IXUSR | S_IXGRP | S_IXOTH, console->name);
return -1;
ret = unlink(path);
if (ret && errno != ENOENT) {
SYSERROR("error unlinking %s", path);
return -errno; return -errno;
} }
ret = symlink(lxcpath, path); /* bind mount console->name to '/dev/<ttydir>/console' */
ret = safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs_path);
if (ret < 0) { if (ret < 0) {
SYSERROR("failed to create symlink for console from \"%s\" to \"%s\"", lxcpath, path); ERROR("Failed to mount '%s' on '%s'", console->name, lxcpath);
return -1; return -1;
} }
DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath);
/* bind mount '/dev/<ttydir>/console' to '/dev/console' */
ret = safe_mount(lxcpath, path, "none", MS_BIND, 0, rootfs_path);
if (ret < 0) {
ERROR("Failed to mount '%s' on '%s'", console->name, lxcpath);
return -1;
}
DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath);
DEBUG("Console has been setup under \"%s\" and mounted to \"%s\"", lxcpath, path);
DEBUG("console has been setup under \"%s\" and symlinked to \"%s\"", lxcpath, path);
return 0; return 0;
} }
static int lxc_setup_console(const struct lxc_rootfs *rootfs, static int lxc_setup_console(const struct lxc_rootfs *rootfs,
const struct lxc_console *console, char *ttydir) const struct lxc_console *console, char *ttydir)
{ {
/* We don't have a rootfs, /dev/console will be shared. */
if (!rootfs->path) {
DEBUG("/dev/console will be shared with the host");
return 0;
}
if (!ttydir) if (!ttydir)
return lxc_setup_dev_console(rootfs, console); return lxc_setup_dev_console(rootfs, console);
......
...@@ -747,12 +747,6 @@ int lxc_console_create(struct lxc_conf *conf) ...@@ -747,12 +747,6 @@ int lxc_console_create(struct lxc_conf *conf)
int ret; int ret;
struct lxc_console *console = &conf->console; struct lxc_console *console = &conf->console;
if (!conf->rootfs.path) {
INFO("Container does not have a rootfs. The console will be "
"shared with the host");
return 0;
}
if (console->path && !strcmp(console->path, "none")) { if (console->path && !strcmp(console->path, "none")) {
INFO("No console was requested"); INFO("No console was requested");
return 0; return 0;
......
...@@ -494,9 +494,12 @@ int lxc_set_state(const char *name, struct lxc_handler *handler, ...@@ -494,9 +494,12 @@ int lxc_set_state(const char *name, struct lxc_handler *handler,
int lxc_poll(const char *name, struct lxc_handler *handler) int lxc_poll(const char *name, struct lxc_handler *handler)
{ {
int ret; int ret;
bool has_console = (handler->conf->rootfs.path != NULL); bool has_console = true;
struct lxc_epoll_descr descr, descr_console; struct lxc_epoll_descr descr, descr_console;
if (handler->conf->console.path && !strcmp(handler->conf->console.path, "none"))
has_console = false;
ret = lxc_mainloop_open(&descr); ret = lxc_mainloop_open(&descr);
if (ret < 0) { if (ret < 0) {
ERROR("Failed to create mainloop"); ERROR("Failed to create mainloop");
......
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