[lxc-devel] [PATCH 1/1] lxc/conf.c Heuristic determination of autodev condition...

Michael H. Warfield mhw at WittsEnd.com
Thu Oct 3 18:07:38 UTC 2013


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 <mhw at 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 |  mhw at 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!
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 482 bytes
Desc: This is a digitally signed message part
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20131003/ee0b5214/attachment.pgp>


More information about the lxc-devel mailing list