]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/cgroup-show.c
relicense to LGPLv2.1 (with exceptions)
[thirdparty/systemd.git] / src / cgroup-show.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <dirent.h>
25 #include <errno.h>
26
27 #include "util.h"
28 #include "macro.h"
29 #include "cgroup-util.h"
30 #include "cgroup-show.h"
31
32 static int compare(const void *a, const void *b) {
33 const pid_t *p = a, *q = b;
34
35 if (*p < *q)
36 return -1;
37 if (*p > *q)
38 return 1;
39 return 0;
40 }
41
42 static unsigned ilog10(unsigned long ul) {
43 int n = 0;
44
45 while (ul > 0) {
46 n++;
47 ul /= 10;
48 }
49
50 return n;
51 }
52
53 static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigned n_columns, bool more, bool kernel_threads) {
54 char *fn;
55 FILE *f;
56 size_t n = 0, n_allocated = 0;
57 pid_t *pids = NULL;
58 char *p;
59 pid_t pid, biggest = 0;
60 int r;
61
62 if (n_columns <= 0)
63 n_columns = columns();
64
65 if (!prefix)
66 prefix = "";
67
68 if ((r = cg_fix_path(path, &p)) < 0)
69 return r;
70
71 r = asprintf(&fn, "%s/cgroup.procs", p);
72 free(p);
73
74 if (r < 0)
75 return -ENOMEM;
76
77 f = fopen(fn, "re");
78 free(fn);
79
80 if (!f)
81 return -errno;
82
83 while ((r = cg_read_pid(f, &pid)) > 0) {
84
85 if (!kernel_threads && is_kernel_thread(pid) > 0)
86 continue;
87
88 if (n >= n_allocated) {
89 pid_t *npids;
90
91 n_allocated = MAX(16U, n*2U);
92
93 if (!(npids = realloc(pids, sizeof(pid_t) * n_allocated))) {
94 r = -ENOMEM;
95 goto finish;
96 }
97
98 pids = npids;
99 }
100
101 assert(n < n_allocated);
102 pids[n++] = pid;
103
104 if (pid > biggest)
105 biggest = pid;
106 }
107
108 if (r < 0)
109 goto finish;
110
111 if (n > 0) {
112 unsigned i, m;
113
114 /* Filter duplicates */
115 m = 0;
116 for (i = 0; i < n; i++) {
117 unsigned j;
118
119 for (j = i+1; j < n; j++)
120 if (pids[i] == pids[j])
121 break;
122
123 if (j >= n)
124 pids[m++] = pids[i];
125 }
126 n = m;
127
128 /* And sort */
129 qsort(pids, n, sizeof(pid_t), compare);
130
131 if (n_columns > 8)
132 n_columns -= 8;
133 else
134 n_columns = 20;
135
136 for (i = 0; i < n; i++) {
137 char *t = NULL;
138
139 get_process_cmdline(pids[i], n_columns, true, &t);
140
141 printf("%s%s %*lu %s\n",
142 prefix,
143 (more || i < n-1) ? "\342\224\234" : "\342\224\224",
144 (int) ilog10(biggest),
145 (unsigned long) pids[i],
146 strna(t));
147
148 free(t);
149 }
150 }
151
152 r = 0;
153
154 finish:
155 free(pids);
156
157 if (f)
158 fclose(f);
159
160 return r;
161 }
162
163 int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns, bool kernel_threads) {
164 DIR *d;
165 char *last = NULL;
166 char *p1 = NULL, *p2 = NULL, *fn = NULL, *gn = NULL;
167 bool shown_pids = false;
168 int r;
169
170 if (n_columns <= 0)
171 n_columns = columns();
172
173 if (!prefix)
174 prefix = "";
175
176 if ((r = cg_fix_path(path, &fn)) < 0)
177 return r;
178
179 if (!(d = opendir(fn))) {
180 free(fn);
181 return -errno;
182 }
183
184 while ((r = cg_read_subgroup(d, &gn)) > 0) {
185
186 if (!shown_pids) {
187 show_cgroup_one_by_path(path, prefix, n_columns, true, kernel_threads);
188 shown_pids = true;
189 }
190
191 if (last) {
192 printf("%s\342\224\234 %s\n", prefix, file_name_from_path(last));
193
194 if (!p1)
195 if (!(p1 = strappend(prefix, "\342\224\202 "))) {
196 r = -ENOMEM;
197 goto finish;
198 }
199
200 show_cgroup_by_path(last, p1, n_columns-2, kernel_threads);
201
202 free(last);
203 last = NULL;
204 }
205
206 r = asprintf(&last, "%s/%s", fn, gn);
207 free(gn);
208
209 if (r < 0) {
210 r = -ENOMEM;
211 goto finish;
212 }
213 }
214
215 if (r < 0)
216 goto finish;
217
218 if (!shown_pids)
219 show_cgroup_one_by_path(path, prefix, n_columns, !!last, kernel_threads);
220
221 if (last) {
222 printf("%s\342\224\224 %s\n", prefix, file_name_from_path(last));
223
224 if (!p2)
225 if (!(p2 = strappend(prefix, " "))) {
226 r = -ENOMEM;
227 goto finish;
228 }
229
230 show_cgroup_by_path(last, p2, n_columns-2, kernel_threads);
231 }
232
233 r = 0;
234
235 finish:
236 free(p1);
237 free(p2);
238 free(last);
239 free(fn);
240
241 closedir(d);
242
243 return r;
244 }
245
246 int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads) {
247 char *p;
248 int r;
249
250 assert(controller);
251 assert(path);
252
253 r = cg_get_path(controller, path, NULL, &p);
254 if (r < 0)
255 return r;
256
257 r = show_cgroup_by_path(p, prefix, n_columns, kernel_threads);
258 free(p);
259
260 return r;
261 }