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. 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
--- Begin Message ---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 <[email protected]> --- 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
--- End Message ---
signature.asc
Description: Digital signature
_______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
