[lxc-devel] [PATCH] clean autodev dir on container exit

Jean-Tiare LE BIGOT jean-tiare.le-bigot at ovh.net
Fri Aug 8 16:48:25 UTC 2014



On 08/08/2014 06:41 PM, Serge Hallyn wrote:
> Quoting Stéphane Graber (stgraber at ubuntu.com):
>> Hello,
>>
>> We received this patch on github: https://github.com/lxc/lxc/pull/289.patch
>>
>> While it does appear to make sense to me that we don't want cruft piling
>> up in /dev, especially on systems creating hundreds/thousands of
>> temporary containers, Serge told me that this may have been done by
>> design.
>
> Right, I wasn't sure whether Michael wanted those to persist.  If not, then
> great let's apply as is.  If so, then how about if we have lxc check at
> start time whether the dir already existed - if so it leaves it be, else it
> removes it at shutdown?

Or maybe I can just add a check to see if the container has a valid 
configuration path. If it is not valid, container has been created via 
the API AND not persisted, hence not persistent.

>
>> So I'm forwarding this one to the list to get some feedback from Mike
>> and whoever else is involved with that autodev stuff :)
>>
>> --
>> Stéphane Graber
>> Ubuntu developer
>> http://www.ubuntu.com
>
>> Date: Sat, 2 Aug 2014 14:35:02 +0200
>> From: Jean-Tiare LE BIGOT <jean-tiare.le-bigot at ovh.net>
>> Subject: [PATCH] clean autodev dir on container exit
>>
>> When "lxc.autodev = 1", LXC creates automatically a "/dev/.lxc/<name>.<hash>"
>> folder to put container's devices in so that they are visible from both
>> the host and the container itself.
>>
>> On container exit (ne it normal or not), this folder was not cleaned
>> which made "/dev" folder grow continuously.
>>
>> We fix this by adding a new `int lxc_delete_autodev(struct lxc_handler
>> *handler)` called from `static void lxc_fini(const char *name, struct
>> lxc_handler *handler)`.
>>
>> Signed-off-by: Jean-Tiare LE BIGOT <jean-tiare.le-bigot at ovh.net>
>> ---
>>   src/lxc/conf.c  | 78 ++++++++++++++++++++++++++++++++++++++++++++++++---------
>>   src/lxc/conf.h  |  1 +
>>   src/lxc/start.c |  1 +
>>   3 files changed, 68 insertions(+), 12 deletions(-)
>>
>> diff --git a/src/lxc/conf.c b/src/lxc/conf.c
>> index 473d076..3ba118d 100644
>> --- a/src/lxc/conf.c
>> +++ b/src/lxc/conf.c
>> @@ -288,6 +288,9 @@ static struct caps_opt caps_opt[] = {
>>   static struct caps_opt caps_opt[] = {};
>>   #endif
>>
>> +const char *dev_base_path = "/dev/.lxc";
>> +const char *dev_user_path = "/dev/.lxc/user";
>> +
>>   static int run_buffer(char *buffer)
>>   {
>>   	struct lxc_popen_FILE *f;
>> @@ -1259,13 +1262,11 @@ static char *mk_devtmpfs(const char *name, char *path, const char *lxcpath)
>>   	struct stat s;
>>   	char tmp_path[MAXPATHLEN];
>>   	char fstype[MAX_FSTYPE_LEN];
>> -	char *base_path = "/dev/.lxc";
>> -	char *user_path = "/dev/.lxc/user";
>>   	uint64_t hash;
>>
>> -	if ( 0 != access(base_path, F_OK) || 0 != stat(base_path, &s) || 0 == S_ISDIR(s.st_mode) ) {
>> +	if ( 0 != access(dev_base_path, F_OK) || 0 != stat(dev_base_path, &s) || 0 == S_ISDIR(s.st_mode) ) {
>>   		/* This is just making /dev/.lxc it better work or we're done */
>> -		ret = mkdir(base_path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
>> +		ret = mkdir(dev_base_path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
>>   		if ( ret ) {
>>   			SYSERROR( "Unable to create /dev/.lxc for autodev" );
>>   			return NULL;
>> @@ -1299,19 +1300,19 @@ static char *mk_devtmpfs(const char *name, char *path, const char *lxcpath)
>>   		}
>>   	}
>>
>> -	if ( 0 != access(user_path, F_OK) || 0 != stat(user_path, &s) || 0 == S_ISDIR(s.st_mode) ) {
>> +	if ( 0 != access(dev_user_path, F_OK) || 0 != stat(dev_user_path, &s) || 0 == S_ISDIR(s.st_mode) ) {
>>   		/*
>>   		 * This is making /dev/.lxc/user path for non-priv users.
>>   		 * If this doesn't work, we'll have to fall back in the
>>   		 * case of non-priv users.  It's mode 1777 like /tmp.
>>   		 */
>> -		ret = mkdir(user_path, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
>> +		ret = mkdir(dev_user_path, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
>>   		if ( ret ) {
>>   			/* Issue an error but don't fail yet! */
>>   			ERROR("Unable to create /dev/.lxc/user");
>>   		}
>>   		/* Umask tends to screw us up here */
>> -		chmod(user_path, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
>> +		chmod(dev_user_path, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX);
>>   	}
>>
>>   	/*
>> @@ -1326,18 +1327,18 @@ static char *mk_devtmpfs(const char *name, char *path, const char *lxcpath)
>>
>>   	hash = fnv_64a_buf(tmp_path, ret, FNV1A_64_INIT);
>>
>> -	ret = snprintf(tmp_path, MAXPATHLEN, "%s/%s.%016" PRIx64, base_path, name, hash);
>> +	ret = snprintf(tmp_path, MAXPATHLEN, "%s/%s.%016" PRIx64, dev_base_path, name, hash);
>>   	if (ret < 0 || ret >= MAXPATHLEN)
>>   		return NULL;
>>
>>   	if ( 0 != access(tmp_path, F_OK) || 0 != stat(tmp_path, &s) || 0 == S_ISDIR(s.st_mode) ) {
>>   		ret = mkdir(tmp_path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
>>   		if ( ret ) {
>> -			/* Something must have failed with the base_path...
>> -			 * Maybe unpriv user.  Try user_path now... */
>> +			/* Something must have failed with the dev_base_path...
>> +			 * Maybe unpriv user.  Try dev_user_path now... */
>>   			INFO("Setup in /dev/.lxc failed.  Trying /dev/.lxc/user." );
>>
>> -			ret = snprintf(tmp_path, MAXPATHLEN, "%s/%s.%016" PRIx64, user_path, name, hash);
>> +			ret = snprintf(tmp_path, MAXPATHLEN, "%s/%s.%016" PRIx64, dev_user_path, name, hash);
>>   			if (ret < 0 || ret >= MAXPATHLEN)
>>   				return NULL;
>>
>> @@ -1355,7 +1356,6 @@ static char *mk_devtmpfs(const char *name, char *path, const char *lxcpath)
>>   	return path;
>>   }
>>
>> -
>>   /*
>>    * Do we want to add options for max size of /dev and a file to
>>    * specify which devices to create?
>> @@ -1482,6 +1482,60 @@ static int setup_autodev(const char *root)
>>   }
>>
>>   /*
>> + * Locate allocated devtmpfs mount and purge it.
>> + * path lookup mostly taken from mk_devtmpfs
>> + */
>> +int lxc_delete_autodev(struct lxc_handler *handler)
>> +{
>> +	int ret;
>> +	struct stat s;
>> +	struct lxc_conf *lxc_conf = handler->conf;
>> +	const char *name = handler->name;
>> +	const char *lxcpath = handler->lxcpath;
>> +	char tmp_path[MAXPATHLEN];
>> +	uint64_t hash;
>> +
>> +	if ( lxc_conf->autodev <= 0 )
>> +		return 0;
>> +
>> +    /*
>> +     * Use the same logic as mk_devtmpfs to compute condidate
>> +     * path for cleanup.
>> +     */
>> +
>> +	ret = snprintf(tmp_path, MAXPATHLEN, "%s/%s", lxcpath, name);
>> +	if (ret < 0 || ret >= MAXPATHLEN)
>> +		return -1;
>> +
>> +	hash = fnv_64a_buf(tmp_path, ret, FNV1A_64_INIT);
>> +
>> +	/* Probe /dev/.lxc/<container name>.<hash> */
>> +	ret = snprintf(tmp_path, MAXPATHLEN, "%s/%s.%016" PRIx64, dev_base_path, name, hash);
>> +	if (ret < 0 || ret >= MAXPATHLEN)
>> +		return -1;
>> +
>> +	if ( 0 != access(tmp_path, F_OK) || 0 != stat(tmp_path, &s) || 0 == S_ISDIR(s.st_mode) ) {
>> +		/* Probe /dev/.lxc/user/<container name>.<hash> */
>> +		ret = snprintf(tmp_path, MAXPATHLEN, "%s/%s.%016" PRIx64, dev_user_path, name, hash);
>> +		if (ret < 0 || ret >= MAXPATHLEN)
>> +			return -1;
>> +
>> +		if ( 0 != access(tmp_path, F_OK) || 0 != stat(tmp_path, &s) || 0 == S_ISDIR(s.st_mode) ) {
>> +			WARN("Failed to locate autodev /dev/.lxc and /dev/.lxc/user." );
>> +			return -1;
>> +		}
>> +    }
>> +
>> +	/* Do the cleanup */
>> +	INFO("Cleaning %s", tmp_path );
>> +	if ( 0 != lxc_rmdir_onedev(tmp_path, NULL) ) {
>> +		ERROR("Failed to cleanup autodev" );
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +/*
>>    * I'll forgive you for asking whether all of this is needed :)  The
>>    * answer is yes.
>>    * pivot_root will fail if the new root, the put_old dir, or the parent
>> diff --git a/src/lxc/conf.h b/src/lxc/conf.h
>> index 615f276..99495f8 100644
>> --- a/src/lxc/conf.h
>> +++ b/src/lxc/conf.h
>> @@ -388,6 +388,7 @@ extern int lxc_clear_hooks(struct lxc_conf *c, const char *key);
>>   extern int lxc_clear_idmaps(struct lxc_conf *c);
>>   extern int lxc_clear_groups(struct lxc_conf *c);
>>   extern int lxc_clear_environment(struct lxc_conf *c);
>> +extern int lxc_delete_autodev(struct lxc_handler *handler);
>>
>>   extern int do_rootfs_setup(struct lxc_conf *conf, const char *name,
>>   			   const char *lxcpath);
>> diff --git a/src/lxc/start.c b/src/lxc/start.c
>> index bb136af..e1ee1ca 100644
>> --- a/src/lxc/start.c
>> +++ b/src/lxc/start.c
>> @@ -477,6 +477,7 @@ static void lxc_fini(const char *name, struct lxc_handler *handler)
>>
>>   	lxc_console_delete(&handler->conf->console);
>>   	lxc_delete_tty(&handler->conf->tty_info);
>> +	lxc_delete_autodev(handler);
>>   	close(handler->conf->maincmd_fd);
>>   	handler->conf->maincmd_fd = -1;
>>   	free(handler->name);
>> --
>> 2.0.3
>
>
>
>
>> _______________________________________________
>> lxc-devel mailing list
>> lxc-devel at lists.linuxcontainers.org
>> http://lists.linuxcontainers.org/listinfo/lxc-devel
>
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel
>

-- 
Jean-Tiare, shared-hosting team


More information about the lxc-devel mailing list