cgroup-util: port from nftw() to recurse_dir()

This commit is contained in:
Lennart Poettering
2021-10-07 11:59:23 +02:00
parent 79a72b1bf8
commit 8e5aba7aca
+45 -32
View File
@@ -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);
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) {
if (typeflag != FTW_DP)
return 0;
/* 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);
if (ftwbuf->level < 1)
return 0;
(void) rmdir(path);
return 0;
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);
}
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 (delete_root) {
if (rmdir(fs) < 0 && errno != ENOENT)
return -errno;
/* 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;
}