1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "cgroup-util.h"
30 #include "cgroup-show.h"
32 static int compare(const void *a, const void *b) {
33 const pid_t *p = a, *q = b;
42 static unsigned ilog10(unsigned long ul) {
53 static void show_pid_array(int pids[], unsigned n_pids, const char *prefix, unsigned n_columns, bool extra, bool more, bool kernel_threads) {
57 /* Filter duplicates */
59 for (i = 0; i < n_pids; i++) {
62 if (pids[i] > biggest)
65 for (j = i+1; j < n_pids; j++)
66 if (pids[i] == pids[j])
75 qsort(pids, n_pids, sizeof(pid_t), compare);
82 for (i = 0; i < n_pids; i++) {
85 get_process_cmdline(pids[i], n_columns, true, &t);
87 printf("%s%s %*lu %s\n",
89 extra ? "\342\200\243" : ((more || i < n_pids-1) ? "\342\224\234" : "\342\224\224"),
90 (int) ilog10(biggest),
91 (unsigned long) pids[i],
99 static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigned n_columns, bool more, bool kernel_threads) {
102 size_t n = 0, n_allocated = 0;
108 r = cg_fix_path(path, &p);
112 r = asprintf(&fn, "%s/cgroup.procs", p);
122 while ((r = cg_read_pid(f, &pid)) > 0) {
124 if (!kernel_threads && is_kernel_thread(pid) > 0)
127 if (n >= n_allocated) {
130 n_allocated = MAX(16U, n*2U);
132 npids = realloc(pids, sizeof(pid_t) * n_allocated);
141 assert(n < n_allocated);
149 show_pid_array(pids, n, prefix, n_columns, false, more, kernel_threads);
162 int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, bool all) {
165 char *p1 = NULL, *p2 = NULL, *fn = NULL, *gn = NULL;
166 bool shown_pids = false;
172 n_columns = columns();
177 r = cg_fix_path(path, &fn);
187 while ((r = cg_read_subgroup(d, &gn)) > 0) {
190 r = asprintf(&k, "%s/%s", fn, gn);
197 if (!all && cg_is_empty_recursive(NULL, k, false) > 0) {
203 show_cgroup_one_by_path(path, prefix, n_columns, true, kernel_threads);
208 printf("%s\342\224\234 %s\n", prefix, file_name_from_path(last));
211 p1 = strappend(prefix, "\342\224\202 ");
219 show_cgroup_by_path(last, p1, n_columns-2, kernel_threads, all);
230 show_cgroup_one_by_path(path, prefix, n_columns, !!last, kernel_threads);
233 printf("%s\342\224\224 %s\n", prefix, file_name_from_path(last));
236 p2 = strappend(prefix, " ");
243 show_cgroup_by_path(last, p2, n_columns-2, kernel_threads, all);
259 int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, bool all) {
266 r = cg_get_path(controller, path, NULL, &p);
270 r = show_cgroup_by_path(p, prefix, n_columns, kernel_threads, all);
276 static int show_extra_pids(const char *controller, const char *path, const char *prefix, unsigned n_columns, const pid_t pids[], unsigned n_pids) {
288 n_columns = columns();
293 copy = new(pid_t, n_pids);
297 for (i = 0, j = 0; i < n_pids; i++) {
300 r = cg_get_by_pid(controller, pids[i], &k);
306 if (path_startswith(k, path))
312 show_pid_array(copy, j, prefix, n_columns, true, false, false);
318 int show_cgroup_and_extra(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads, bool all, const pid_t extra_pids[], unsigned n_extra_pids) {
324 r = show_cgroup(controller, path, prefix, n_columns, kernel_threads, all);
328 return show_extra_pids(controller, path, prefix, n_columns, extra_pids, n_extra_pids);
331 int show_cgroup_and_extra_by_spec(const char *spec, const char *prefix, unsigned n_columns, bool kernel_threads, bool all, const pid_t extra_pids[], unsigned n_extra_pids) {
333 char *controller, *path;
337 r = cg_split_spec(spec, &controller, &path);
341 r = show_cgroup_and_extra(controller, path, prefix, n_columns, kernel_threads, all, extra_pids, n_extra_pids);