]>
Commit | Line | Data |
---|---|---|
d6c9574f | 1 | /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
ab35fb1b LP |
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 General Public License as published by | |
10 | the Free Software Foundation; either version 2 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 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU 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> | |
fa776d8e LP |
24 | #include <dirent.h> |
25 | #include <errno.h> | |
ab35fb1b LP |
26 | |
27 | #include "util.h" | |
28 | #include "macro.h" | |
c6c18be3 | 29 | #include "cgroup-util.h" |
ab35fb1b LP |
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 | ||
fa776d8e LP |
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 | ||
1e5678d0 | 53 | static int show_cgroup_one_by_path(const char *path, const char *prefix, unsigned n_columns, bool more, bool kernel_threads) { |
ab35fb1b LP |
54 | char *fn; |
55 | FILE *f; | |
56 | size_t n = 0, n_allocated = 0; | |
57 | pid_t *pids = NULL; | |
fa776d8e | 58 | char *p; |
c6c18be3 | 59 | pid_t pid, biggest = 0; |
fa776d8e | 60 | int r; |
ab35fb1b | 61 | |
fa776d8e LP |
62 | if (n_columns <= 0) |
63 | n_columns = columns(); | |
ab35fb1b | 64 | |
fa776d8e LP |
65 | if (!prefix) |
66 | prefix = ""; | |
67 | ||
35d2e7ec LP |
68 | if ((r = cg_fix_path(path, &p)) < 0) |
69 | return r; | |
ab35fb1b | 70 | |
fa776d8e LP |
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"); | |
ab35fb1b LP |
78 | free(fn); |
79 | ||
80 | if (!f) | |
fa776d8e | 81 | return -errno; |
ab35fb1b | 82 | |
c6c18be3 | 83 | while ((r = cg_read_pid(f, &pid)) > 0) { |
ab35fb1b | 84 | |
1e5678d0 LP |
85 | if (!kernel_threads && is_kernel_thread(pid) > 0) |
86 | continue; | |
87 | ||
ab35fb1b LP |
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))) { | |
fa776d8e | 94 | r = -ENOMEM; |
ab35fb1b LP |
95 | goto finish; |
96 | } | |
97 | ||
98 | pids = npids; | |
99 | } | |
100 | ||
101 | assert(n < n_allocated); | |
c6c18be3 | 102 | pids[n++] = pid; |
fa776d8e | 103 | |
c6c18be3 LP |
104 | if (pid > biggest) |
105 | biggest = pid; | |
ab35fb1b LP |
106 | } |
107 | ||
c6c18be3 LP |
108 | if (r < 0) |
109 | goto finish; | |
110 | ||
ab35fb1b LP |
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 | ||
fa776d8e LP |
131 | if (n_columns > 8) |
132 | n_columns -= 8; | |
ab35fb1b | 133 | else |
fa776d8e | 134 | n_columns = 20; |
ab35fb1b LP |
135 | |
136 | for (i = 0; i < n; i++) { | |
137 | char *t = NULL; | |
138 | ||
87d2c1ff | 139 | get_process_cmdline(pids[i], n_columns, true, &t); |
ab35fb1b | 140 | |
fa776d8e | 141 | printf("%s%s %*lu %s\n", |
ab35fb1b | 142 | prefix, |
fa776d8e | 143 | (more || i < n-1) ? "\342\224\234" : "\342\224\224", |
e364ad06 | 144 | (int) ilog10(biggest), |
fa776d8e LP |
145 | (unsigned long) pids[i], |
146 | strna(t)); | |
ab35fb1b LP |
147 | |
148 | free(t); | |
149 | } | |
150 | } | |
151 | ||
fa776d8e LP |
152 | r = 0; |
153 | ||
ab35fb1b LP |
154 | finish: |
155 | free(pids); | |
156 | ||
157 | if (f) | |
158 | fclose(f); | |
fa776d8e LP |
159 | |
160 | return r; | |
161 | } | |
162 | ||
1e5678d0 | 163 | int show_cgroup_by_path(const char *path, const char *prefix, unsigned n_columns, bool kernel_threads) { |
fa776d8e LP |
164 | DIR *d; |
165 | char *last = NULL; | |
35d2e7ec | 166 | char *p1 = NULL, *p2 = NULL, *fn = NULL, *gn = NULL; |
fa776d8e LP |
167 | bool shown_pids = false; |
168 | int r; | |
169 | ||
fa776d8e LP |
170 | if (n_columns <= 0) |
171 | n_columns = columns(); | |
172 | ||
173 | if (!prefix) | |
174 | prefix = ""; | |
175 | ||
35d2e7ec LP |
176 | if ((r = cg_fix_path(path, &fn)) < 0) |
177 | return r; | |
fa776d8e LP |
178 | |
179 | if (!(d = opendir(fn))) { | |
180 | free(fn); | |
181 | return -errno; | |
182 | } | |
183 | ||
35d2e7ec | 184 | while ((r = cg_read_subgroup(d, &gn)) > 0) { |
fa776d8e LP |
185 | |
186 | if (!shown_pids) { | |
1e5678d0 | 187 | show_cgroup_one_by_path(path, prefix, n_columns, true, kernel_threads); |
fa776d8e LP |
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 | ||
1e5678d0 | 200 | show_cgroup_by_path(last, p1, n_columns-2, kernel_threads); |
fa776d8e LP |
201 | |
202 | free(last); | |
203 | last = NULL; | |
204 | } | |
205 | ||
35d2e7ec LP |
206 | r = asprintf(&last, "%s/%s", fn, gn); |
207 | free(gn); | |
208 | ||
209 | if (r < 0) { | |
e34b6159 | 210 | r = -ENOMEM; |
fa776d8e LP |
211 | goto finish; |
212 | } | |
213 | } | |
214 | ||
35d2e7ec LP |
215 | if (r < 0) |
216 | goto finish; | |
217 | ||
fa776d8e | 218 | if (!shown_pids) |
1e5678d0 | 219 | show_cgroup_one_by_path(path, prefix, n_columns, !!last, kernel_threads); |
fa776d8e LP |
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 | ||
1e5678d0 | 230 | show_cgroup_by_path(last, p2, n_columns-2, kernel_threads); |
fa776d8e LP |
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; | |
ab35fb1b | 244 | } |
35d2e7ec | 245 | |
1e5678d0 | 246 | int show_cgroup(const char *controller, const char *path, const char *prefix, unsigned n_columns, bool kernel_threads) { |
35d2e7ec LP |
247 | char *p; |
248 | int r; | |
249 | ||
250 | assert(controller); | |
251 | assert(path); | |
252 | ||
1e5678d0 LP |
253 | r = cg_get_path(controller, path, NULL, &p); |
254 | if (r < 0) | |
35d2e7ec LP |
255 | return r; |
256 | ||
1e5678d0 | 257 | r = show_cgroup_by_path(p, prefix, n_columns, kernel_threads); |
35d2e7ec LP |
258 | free(p); |
259 | ||
260 | return r; | |
261 | } |