My second takeaway from the Linux Plumbers conference was to do an automatic heuristic determination when we should enable autodev (mounting of something on /dev/ in the container at startup for things like systemd). If autodev is not enabled when it is required (systemd) the container can cause the host to hang or behave indeterminently due to devtmpfs being mounted in both the host and the container.
This patch turns lxc.autodev into a tristate. If it's not set or negative (default) it will try to determine if certain conditions (systemd) exist in the container. If so, it will enable autodev. If not, it will leave it disabled. The heuristics are in a single function so we can add to them as time goes on. For example, we will probably want to add the logic to enable autodev under conditions when the host has devtmpfs mounted on its /dev. This logic is not currently in there but may be necessary as we develop the fake udev / devtmpfs logic further (next takeaway from Linux Plumbers). The initial heuristic, in this case, is the existence of /etc/systemd/system in the container to enable autodev. This is the heuristic used in the lxc-fedora template but it applicable to all systemd containers, as far as I can determine. Signed-off-by: Michael H. Warfield <m...@wittsend.com> -- diff --git a/src/lxc/conf.c b/src/lxc/conf.c index ecbcf41..5f3a705 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -2369,6 +2369,7 @@ struct lxc_conf *lxc_conf_init(void) new->loglevel = LXC_LOG_PRIORITY_NOTSET; new->personality = -1; + new->autodev = -1; new->console.log_path = NULL; new->console.log_fd = -1; new->console.path = NULL; @@ -3035,6 +3036,55 @@ int uid_shift_ttys(int pid, struct lxc_conf *conf) return 0; } +/* + * This routine is called when the configuration does not already specify a value + * for autodev (mounting a file system on /dev and populating it in a container). + * If a hard override value has not be specified, then we try to apply some + * heuristics to determine if we should switch to autodev mode. + * + * For instance, if the container has an /etc/systemd/system directory then it + * is probably running systemd as the init process and it needs the autodev + * mount to prevent it from mounting devtmpfs on /dev on it's own causing conflicts + * in the host. + * + * We may also want to enable autodev if the host has devtmpfs mounted on its + * /dev as this then enable us to use subdirectories under /dev for the container + * /dev directories and we can fake udev devices. + */ +int check_autodev( const char *rootfs ) +{ + char absrootfs[MAXPATHLEN]; + int ret; + struct stat s; + char path[MAXPATHLEN]; + + INFO("Testing for systemd in %s\n", rootfs); + + if (rootfs == NULL || strlen(rootfs) == 0) + return -2; + + if (!realpath(rootfs, absrootfs)) + return -2; + + /* Note here: we could instead check for /etc/systemd/system.conf */ + ret = snprintf(path, MAXPATHLEN, "%s/etc/systemd/system", absrootfs); + if (ret < 0 || ret > MAXPATHLEN) + return -2; + + if ( 0 == access(path, F_OK) && 0 == stat(path, &s) && S_ISDIR(s.st_mode) ) + return 1; + + + /* Add future checks here. + * Return positive if we should go autodev + * Return 0 if we should NOT go autodev + * Return negative if we encounter an error or can not determine... + */ + + /* All else fails, disable autodev */ + return 0; +} + int lxc_setup(const char *name, struct lxc_conf *lxc_conf, const char *lxcpath, struct cgroup_process_info *cgroup_info) { if (setup_utsname(lxc_conf->utsname)) { @@ -3057,7 +3107,11 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf, const char *lxcpath, return -1; } - if (lxc_conf->autodev) { + if (lxc_conf->autodev < 0) { + lxc_conf->autodev = check_autodev(lxc_conf->rootfs.mount); + } + + if (lxc_conf->autodev > 0) { if (mount_autodev(lxc_conf->rootfs.mount)) { ERROR("failed to mount /dev in the container"); return -1; @@ -3096,7 +3150,7 @@ int lxc_setup(const char *name, struct lxc_conf *lxc_conf, const char *lxcpath, return -1; } - if (lxc_conf->autodev) { + if (lxc_conf->autodev > 0) { if (run_lxc_hooks(name, "autodev", lxc_conf, lxcpath, NULL)) { ERROR("failed to run autodev hooks for container '%s'.", name); return -1; -- Regards, Mike -- Michael H. Warfield (AI4NB) | (770) 985-6132 | m...@wittsend.com /\/\|=mhw=|\/\/ | (678) 463-0932 | http://www.wittsend.com/mhw/ NIC whois: MHW9 | An optimist believes we live in the best of all PGP Key: 0x674627FF | possible worlds. A pessimist is sure of it!
signature.asc
Description: This is a digitally signed message part
------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60134791&iu=/4140/ostg.clktrk
_______________________________________________ Lxc-devel mailing list Lxc-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/lxc-devel