summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-10-01 15:55:37 +0200
committerLennart Poettering <lennart@poettering.net>2021-10-07 11:59:23 +0200
commit8e5aba7acadcfbb95c9131947199c863e58a882b (patch)
treefd802ca1941c283f52991ed23daf66ab671e53a0
parentkmod-setup: port from nftw() to recurse_dir() (diff)
downloadsystemd-8e5aba7acadcfbb95c9131947199c863e58a882b.tar.xz
systemd-8e5aba7acadcfbb95c9131947199c863e58a882b.zip
cgroup-util: port from nftw() to recurse_dir()
-rw-r--r--src/shared/cgroup-setup.c83
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;
}