[lxc-devel] [PATCH] Add lxc.autodev (v2)

Stéphane Graber stgraber at ubuntu.com
Mon Nov 26 16:44:38 UTC 2012


On 11/23/2012 03:16 PM, Serge Hallyn wrote:
> Add a container config option to mount and populate /dev in a container.
> 
> We might want to add options to specify a max size for /dev other than
> the default 100k, and to specify other devices to create.  And maybe
> someone can think of a better name than autodev.
> 
> Changelog: Don't error out if we couldn't mknod a /dev/ttyN.
> Changelog: Describe the option in lxc.conf manpage.
> 
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>

Acked-by: Stéphane Graber <stgraber at ubuntu.com>

I'll push the fix I highlighted below too.

This change is now in the staging branch.

Thanks

> ---
>  doc/lxc.conf.sgml.in |   25 ++++++++++++++++
>  src/lxc/conf.c       |   77 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  src/lxc/conf.h       |    1 +
>  src/lxc/confile.c    |   12 ++++++++
>  4 files changed, 115 insertions(+)
> 
> diff --git a/doc/lxc.conf.sgml.in b/doc/lxc.conf.sgml.in
> index 6c3d7b2..eed07fc 100644
> --- a/doc/lxc.conf.sgml.in
> +++ b/doc/lxc.conf.sgml.in
> @@ -502,6 +502,31 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
>      </refsect2>
>  
>      <refsect2>
> +      <title>/dev directory</title>
> +      <para>
> +	By default, lxc does nothing with the container's
> +	<filename>/dev</filename>.  This allows the container's
> +	<filename>/dev</filename> to be set up as needed in the container
> +	rootfs.  If lxc.autodev is to 1, then after mounting the container's

Should be "If lxc.autodev is set to 1"

> +	rootfs LXC will mount a fresh tmpfs under <filename>/dev</filename>
> +	(limited to 100k) and fill in a minimal set of initial devices.
> +      </para>
> +      <variablelist>
> +	<varlistentry>
> +	  <term>
> +	    <option>lxc.autodev</option>
> +	  </term>
> +	  <listitem>
> +	    <para>
> +	      Set this to 1 to have LXC mount and populate a minimal
> +	      <filename>/dev</filename> when starting the container.
> +	    </para>
> +	  </listitem>
> +	</varlistentry>
> +      </variablelist>
> +    </refsect2>
> +
> +    <refsect2>
>        <title>Mount points</title>
>        <para>
>  	The mount points section specifies the different places to be
> diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> index fe574ac..f1c41f1 100644
> --- a/src/lxc/conf.c
> +++ b/src/lxc/conf.c
> @@ -653,6 +653,15 @@ static int setup_tty(const struct lxc_rootfs *rootfs,
>  				return -1;
>  			}
>  		} else {
> +			/* If we populated /dev, then we need to create /dev/ttyN */
> +			if (access(path, F_OK)) {
> +				ret = creat(path, 0660);
> +				if (ret==-1) {
> +					SYSERROR("error creating %s\n", path);
> +					/* this isn't fatal, continue */
> +				} else
> +					close(ret);
> +			}
>  			if (mount(pty_info->name, path, "none", MS_BIND, 0)) {
>  				WARN("failed to mount '%s'->'%s'",
>  						pty_info->name, path);
> @@ -860,6 +869,67 @@ static int setup_rootfs_pivot_root(const char *rootfs, const char *pivotdir)
>  	return 0;
>  }
>  
> +struct lxc_devs {
> +	char *name;
> +	mode_t mode;
> +	int maj;
> +	int min;
> +};
> +
> +struct lxc_devs lxc_devs[] = {
> +	{ "null",	S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 3	},
> +	{ "zero",	S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 5	},
> +	{ "full",	S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 7	},
> +	{ "urandom",	S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 9	},
> +	{ "random",	S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 1, 8	},
> +	{ "tty",	S_IFCHR | S_IRWXU | S_IRWXG | S_IRWXO, 5, 0	},
> +	{ "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;
> +	struct lxc_devs *d;
> +	char path[MAXPATHLEN];
> +	int i;
> +
> +	INFO("Creating and populating /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;
> +	}
> +	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) {
> +			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;
> +}
> +
>  static int setup_rootfs(const struct lxc_rootfs *rootfs)
>  {
>  	if (!rootfs->path)
> @@ -2265,6 +2335,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 set up /dev in the container");
> +			return -1;
> +		}
> +	}
> +
>  	if (setup_mount(&lxc_conf->rootfs, lxc_conf->fstab, name)) {
>  		ERROR("failed to setup the mounts for '%s'", name);
>  		return -1;
> diff --git a/src/lxc/conf.h b/src/lxc/conf.h
> index dccc176..76bf19d 100644
> --- a/src/lxc/conf.h
> +++ b/src/lxc/conf.h
> @@ -237,6 +237,7 @@ struct lxc_conf {
>  #endif
>  	char *seccomp;  // filename with the seccomp rules
>  	int maincmd_fd;
> +	int autodev;  // if 1, mount and fill a /dev at start
>  };
>  
>  int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf);
> diff --git a/src/lxc/confile.c b/src/lxc/confile.c
> index cf1c891..3d9f36e 100644
> --- a/src/lxc/confile.c
> +++ b/src/lxc/confile.c
> @@ -79,6 +79,7 @@ static int config_console(const char *, char *, struct lxc_conf *);
>  static int config_seccomp(const char *, char *, struct lxc_conf *);
>  static int config_includefile(const char *, char *, struct lxc_conf *);
>  static int config_network_nic(const char *, char *, struct lxc_conf *);
> +static int config_autodev(const char *, char *, struct lxc_conf *);
>  
>  static struct lxc_config_t config[] = {
>  
> @@ -121,6 +122,7 @@ static struct lxc_config_t config[] = {
>  	{ "lxc.console",              config_console              },
>  	{ "lxc.seccomp",              config_seccomp              },
>  	{ "lxc.include",              config_includefile          },
> +	{ "lxc.autodev",              config_autodev              },
>  };
>  
>  static const size_t config_size = sizeof(config)/sizeof(struct lxc_config_t);
> @@ -881,6 +883,16 @@ static int config_aa_profile(const char *key, char *value, struct lxc_conf *lxc_
>  }
>  #endif
>  
> +static int config_autodev(const char *key, char *value,
> +			  struct lxc_conf *lxc_conf)
> +{
> +	int v = atoi(value);
> +
> +	lxc_conf->autodev = v;
> +
> +	return 0;
> +}
> +
>  static int config_cgroup(const char *key, char *value, struct lxc_conf *lxc_conf)
>  {
>  	char *token = "lxc.cgroup.";
> 


-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 899 bytes
Desc: OpenPGP digital signature
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20121126/140f704a/attachment.pgp>


More information about the lxc-devel mailing list