cgtop: tweak root cgroup detection a bit

Inside a cgroup-namespaced container we shouldn't assume that "/" is
really the root cgroup, because it generally is not.
This commit is contained in:
Lennart Poettering 2018-02-09 17:25:30 +01:00
parent ad078b4181
commit ba4b1544f2

View file

@ -46,6 +46,7 @@
#include "terminal-util.h"
#include "unit-name.h"
#include "util.h"
#include "virt.h"
typedef struct Group {
char *path;
@ -126,6 +127,26 @@ static const char *maybe_format_bytes(char *buf, size_t l, bool is_valid, uint64
}
static bool is_root_cgroup(const char *path) {
/* Returns true if the specified path belongs to the root cgroup. The root cgroup is special on cgroupsv2 as it
* carries only very few attributes in order not to export multiple truth about system state as most
* information is available elsewhere in /proc anyway. We need to be able to deal with that, and need to get
* our data from different sources in that case.
*
* There's one extra complication in all of this, though 😣: if the path to the cgroup indicates we are in the
* root cgroup this might actually not be the case, because cgroup namespacing might be in effect
* (CLONE_NEWCGROUP). Since there's no nice way to distuingish a real cgroup root from a fake namespaced one we
* do an explicit container check here, under the assumption that CLONE_NEWCGROUP is generally used when
* container managers are used too.
*
* Note that checking for a container environment is kinda ugly, since in theory people could use cgtop from
* inside a container where cgroup namespacing is turned off to watch the host system. However, that's mostly a
* theoretic usecase, and if people actually try all they'll lose is accounting for the top-level cgroup. Which
* isn't too bad. */
if (detect_container() > 0)
return false;
return isempty(path) || path_equal(path, "/");
}
@ -176,7 +197,8 @@ static int process(
}
}
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) && IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES)) {
if (streq(controller, SYSTEMD_CGROUP_CONTROLLER) &&
IN_SET(arg_count, COUNT_ALL_PROCESSES, COUNT_USERSPACE_PROCESSES)) {
_cleanup_fclose_ FILE *f = NULL;
pid_t pid;