diff options
author | Lennart Poettering <lennart@poettering.net> | 2021-10-01 15:55:37 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2021-10-07 11:59:23 +0200 |
commit | 8e5aba7acadcfbb95c9131947199c863e58a882b (patch) | |
tree | fd802ca1941c283f52991ed23daf66ab671e53a0 | |
parent | kmod-setup: port from nftw() to recurse_dir() (diff) | |
download | systemd-8e5aba7acadcfbb95c9131947199c863e58a882b.tar.xz systemd-8e5aba7acadcfbb95c9131947199c863e58a882b.zip |
cgroup-util: port from nftw() to recurse_dir()
-rw-r--r-- | src/shared/cgroup-setup.c | 83 |
1 files changed, 48 insertions, 35 deletions
diff --git a/src/shared/cgroup-setup.c b/src/shared/cgroup-setup.c index f197f715c7..7dee7e9512 100644 --- a/src/shared/cgroup-setup.c +++ b/src/shared/cgroup-setup.c @@ -1,22 +1,22 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ -#include <ftw.h> #include <unistd.h> #include "cgroup-setup.h" #include "cgroup-util.h" #include "errno-util.h" +#include "fd-util.h" +#include "fileio.h" +#include "fs-util.h" +#include "mkdir.h" #include "parse-util.h" #include "path-util.h" #include "proc-cmdline.h" +#include "process-util.h" +#include "recurse-dir.h" #include "stdio-util.h" #include "string-util.h" -#include "fs-util.h" -#include "mkdir.h" -#include "process-util.h" -#include "fileio.h" #include "user-util.h" -#include "fd-util.h" bool cg_is_unified_wanted(void) { static thread_local int wanted = -1; @@ -149,19 +149,23 @@ int cg_blkio_weight_parse(const char *s, uint64_t *ret) { return 0; } -static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { - assert(path); - assert(sb); - assert(ftwbuf); - - if (typeflag != FTW_DP) - return 0; - - if (ftwbuf->level < 1) - return 0; - - (void) rmdir(path); - return 0; +static int trim_cb( + RecurseDirEvent event, + const char *path, + int dir_fd, + int inode_fd, + const struct dirent *de, + const struct statx *sx, + void *userdata) { + + /* Failures to delete inner cgroup we ignore (but debug log in case error code is unexpected) */ + if (event == RECURSE_DIR_LEAVE && + de->d_type == DT_DIR && + unlinkat(dir_fd, de->d_name, AT_REMOVEDIR) < 0 && + !IN_SET(errno, ENOENT, ENOTEMPTY, EBUSY)) + log_debug_errno(errno, "Failed to trim inner cgroup %s, ignoring: %m", path); + + return RECURSE_DIR_CONTINUE; } int cg_trim(const char *controller, const char *path, bool delete_root) { @@ -169,32 +173,41 @@ int cg_trim(const char *controller, const char *path, bool delete_root) { int r, q; assert(path); + assert(controller); r = cg_get_path(controller, path, NULL, &fs); if (r < 0) return r; - errno = 0; - if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0) { - if (errno == ENOENT) - r = 0; - else - r = errno_or_else(EIO); - } - - if (delete_root) { - if (rmdir(fs) < 0 && errno != ENOENT) - return -errno; + r = recurse_dir_at( + AT_FDCWD, + fs, + /* statx_mask= */ 0, + /* n_depth_max= */ UINT_MAX, + RECURSE_DIR_ENSURE_TYPE, + trim_cb, + NULL); + if (r == -ENOENT) /* non-existing is the ultimate trimming, hence no error */ + r = 0; + else if (r < 0) + log_debug_errno(r, "Failed to iterate through cgroup %s: %m", path); + + /* If we shall delete the top-level cgroup, then propagate the faiure to do so (except if it is + * already gone anyway). Also, let's debug log about this failure, except if the error code is an + * expected one. */ + if (delete_root && !empty_or_root(path) && + rmdir(fs) < 0 && errno != ENOENT) { + if (!IN_SET(errno, ENOTEMPTY, EBUSY)) + log_debug_errno(errno, "Failed to trim cgroup %s: %m", path); + if (r >= 0) + r = -errno; } q = cg_hybrid_unified(); if (q < 0) return q; - if (q > 0 && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) { - q = cg_trim(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, delete_root); - if (q < 0) - log_warning_errno(q, "Failed to trim compat systemd cgroup %s: %m", path); - } + if (q > 0 && streq(controller, SYSTEMD_CGROUP_CONTROLLER)) + (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, delete_root); return r; } |