[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