From: Lennart Poettering Date: Fri, 1 Oct 2021 13:55:37 +0000 (+0200) Subject: cgroup-util: port from nftw() to recurse_dir() X-Git-Tag: v250-rc1~550^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8e5aba7acadcfbb95c9131947199c863e58a882b;p=thirdparty%2Fsystemd.git cgroup-util: port from nftw() to recurse_dir() --- diff --git a/src/shared/cgroup-setup.c b/src/shared/cgroup-setup.c index f197f715c79..7dee7e95127 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 #include #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; }