]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-cgroup.c
build-sys: minor fixes found with cppcheck
[thirdparty/systemd.git] / src / core / dbus-cgroup.c
CommitLineData
4ad49000
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 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
718db961 22#include "bus-util.h"
7041efe9 23#include "path-util.h"
718db961
LP
24#include "cgroup-util.h"
25#include "cgroup.h"
4ad49000
LP
26#include "dbus-cgroup.h"
27
718db961
LP
28static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
29
30static int property_get_blockio_device_weight(
31 sd_bus *bus,
32 const char *path,
33 const char *interface,
34 const char *property,
35 sd_bus_message *reply,
ebcf1f97
LP
36 void *userdata,
37 sd_bus_error *error) {
4ad49000 38
718db961 39 CGroupContext *c = userdata;
4ad49000 40 CGroupBlockIODeviceWeight *w;
718db961 41 int r;
4ad49000 42
718db961
LP
43 assert(bus);
44 assert(reply);
4ad49000
LP
45 assert(c);
46
718db961
LP
47 r = sd_bus_message_open_container(reply, 'a', "(st)");
48 if (r < 0)
49 return r;
4ad49000
LP
50
51 LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
718db961
LP
52 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
53 if (r < 0)
54 return r;
4ad49000
LP
55 }
56
718db961 57 return sd_bus_message_close_container(reply);
4ad49000
LP
58}
59
718db961
LP
60static int property_get_blockio_device_bandwidths(
61 sd_bus *bus,
62 const char *path,
63 const char *interface,
64 const char *property,
65 sd_bus_message *reply,
ebcf1f97
LP
66 void *userdata,
67 sd_bus_error *error) {
718db961
LP
68
69 CGroupContext *c = userdata;
4ad49000 70 CGroupBlockIODeviceBandwidth *b;
718db961 71 int r;
4ad49000 72
718db961
LP
73 assert(bus);
74 assert(reply);
4ad49000
LP
75 assert(c);
76
718db961
LP
77 r = sd_bus_message_open_container(reply, 'a', "(st)");
78 if (r < 0)
79 return r;
4ad49000
LP
80
81 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
82
83 if (streq(property, "BlockIOReadBandwidth") != b->read)
84 continue;
85
718db961
LP
86 r = sd_bus_message_append(reply, "(st)", b->path, b->bandwidth);
87 if (r < 0)
88 return r;
4ad49000
LP
89 }
90
718db961 91 return sd_bus_message_close_container(reply);
4ad49000
LP
92}
93
718db961
LP
94static int property_get_device_allow(
95 sd_bus *bus,
96 const char *path,
97 const char *interface,
98 const char *property,
99 sd_bus_message *reply,
ebcf1f97
LP
100 void *userdata,
101 sd_bus_error *error) {
718db961
LP
102
103 CGroupContext *c = userdata;
4ad49000 104 CGroupDeviceAllow *a;
718db961 105 int r;
4ad49000 106
718db961
LP
107 assert(bus);
108 assert(reply);
4ad49000
LP
109 assert(c);
110
718db961
LP
111 r = sd_bus_message_open_container(reply, 'a', "(ss)");
112 if (r < 0)
113 return r;
4ad49000
LP
114
115 LIST_FOREACH(device_allow, a, c->device_allow) {
4ad49000 116 unsigned k = 0;
718db961 117 char rwm[4];
4ad49000
LP
118
119 if (a->r)
718db961 120 rwm[k++] = 'r';
4ad49000 121 if (a->w)
718db961 122 rwm[k++] = 'w';
4ad49000 123 if (a->m)
718db961 124 rwm[k++] = 'm';
4ad49000 125
718db961 126 rwm[k] = 0;
4ad49000 127
718db961
LP
128 r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
129 if (r < 0)
130 return r;
4ad49000
LP
131 }
132
718db961 133 return sd_bus_message_close_container(reply);
4ad49000
LP
134}
135
718db961
LP
136const sd_bus_vtable bus_cgroup_vtable[] = {
137 SD_BUS_VTABLE_START(0),
610f780c
LP
138 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
139 SD_BUS_PROPERTY("CPUShares", "t", bus_property_get_ulong, offsetof(CGroupContext, cpu_shares), 0),
140 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
141 SD_BUS_PROPERTY("BlockIOWeight", "t", bus_property_get_ulong, offsetof(CGroupContext, blockio_weight), 0),
142 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
143 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
144 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
145 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
146 SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
147 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
148 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
718db961 149 SD_BUS_VTABLE_END
4ad49000 150};
8e2af478
LP
151
152int bus_cgroup_set_property(
153 Unit *u,
154 CGroupContext *c,
155 const char *name,
718db961 156 sd_bus_message *message,
8e2af478 157 UnitSetPropertiesMode mode,
718db961
LP
158 sd_bus_error *error) {
159
160 int r;
8e2af478 161
8e2af478
LP
162 assert(u);
163 assert(c);
718db961
LP
164 assert(name);
165 assert(message);
8e2af478
LP
166
167 if (streq(name, "CPUAccounting")) {
718db961 168 int b;
8e2af478 169
718db961
LP
170 r = sd_bus_message_read(message, "b", &b);
171 if (r < 0)
172 return r;
8e2af478
LP
173
174 if (mode != UNIT_CHECK) {
8e2af478 175 c->cpu_accounting = b;
b9ec9359 176 unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no");
b42defe3
LP
177 }
178
179 return 1;
180
181 } else if (streq(name, "CPUShares")) {
182 uint64_t u64;
183 unsigned long ul;
184
718db961
LP
185 r = sd_bus_message_read(message, "t", &u64);
186 if (r < 0)
187 return r;
b42defe3 188
b42defe3 189 ul = (unsigned long) u64;
718db961
LP
190 if (ul <= 0 || (uint64_t) ul != u64)
191 return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range");
b42defe3
LP
192
193 if (mode != UNIT_CHECK) {
b42defe3 194 c->cpu_shares = ul;
b9ec9359 195 unit_write_drop_in_private_format(u, mode, name, "CPUShares=%lu", ul);
8e2af478
LP
196 }
197
198 return 1;
199
200 } else if (streq(name, "BlockIOAccounting")) {
718db961 201 int b;
8e2af478 202
718db961
LP
203 r = sd_bus_message_read(message, "b", &b);
204 if (r < 0)
205 return r;
8e2af478
LP
206
207 if (mode != UNIT_CHECK) {
8e2af478 208 c->blockio_accounting = b;
b9ec9359 209 unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
8e2af478
LP
210 }
211
212 return 1;
b42defe3
LP
213
214 } else if (streq(name, "BlockIOWeight")) {
215 uint64_t u64;
216 unsigned long ul;
217
718db961
LP
218 r = sd_bus_message_read(message, "t", &u64);
219 if (r < 0)
220 return r;
b42defe3 221
b42defe3 222 ul = (unsigned long) u64;
718db961
LP
223 if (ul < 10 || ul > 1000)
224 return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range");
b42defe3
LP
225
226 if (mode != UNIT_CHECK) {
f2369103 227 c->blockio_weight = ul;
b9ec9359 228 unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%lu", ul);
b42defe3
LP
229 }
230
231 return 1;
232
f004c2ca 233 } else if (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth")) {
718db961 234 const char *path;
f004c2ca 235 bool read = true;
718db961
LP
236 unsigned n = 0;
237 uint64_t u64;
f004c2ca
G
238
239 if (streq(name, "BlockIOWriteBandwidth"))
240 read = false;
241
718db961
LP
242 r = sd_bus_message_enter_container(message, 'a', "(st)");
243 if (r < 0)
244 return r;
f004c2ca 245
718db961 246 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
f004c2ca
G
247
248 if (mode != UNIT_CHECK) {
718db961 249 CGroupBlockIODeviceBandwidth *a = NULL, *b;
f004c2ca
G
250
251 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
252 if (path_equal(path, b->path) && read == b->read) {
253 a = b;
f004c2ca
G
254 break;
255 }
256 }
257
718db961 258 if (!a) {
f004c2ca
G
259 a = new0(CGroupBlockIODeviceBandwidth, 1);
260 if (!a)
261 return -ENOMEM;
262
263 a->read = read;
264 a->path = strdup(path);
265 if (!a->path) {
266 free(a);
267 return -ENOMEM;
268 }
718db961
LP
269
270 LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
f004c2ca
G
271 }
272
273 a->bandwidth = u64;
f004c2ca
G
274 }
275
276 n++;
f004c2ca 277 }
718db961
LP
278 if (r < 0)
279 return r;
f004c2ca
G
280
281 if (mode != UNIT_CHECK) {
718db961 282 CGroupBlockIODeviceBandwidth *a, *next;
f004c2ca
G
283 _cleanup_free_ char *buf = NULL;
284 _cleanup_fclose_ FILE *f = NULL;
f004c2ca
G
285 size_t size = 0;
286
287 if (n == 0) {
288 LIST_FOREACH_SAFE(device_bandwidths, a, next, c->blockio_device_bandwidths)
289 if (a->read == read)
290 cgroup_context_free_blockio_device_bandwidth(c, a);
291 }
292
293 f = open_memstream(&buf, &size);
294 if (!f)
295 return -ENOMEM;
296
297 if (read) {
298 fputs("BlockIOReadBandwidth=\n", f);
299 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
300 if (a->read)
301 fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth);
302 } else {
303 fputs("BlockIOWriteBandwidth=\n", f);
304 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
305 if (!a->read)
306 fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth);
307 }
308
6f68ecb4
G
309 fflush(f);
310 unit_write_drop_in_private(u, mode, name, buf);
311 }
312
313 return 1;
314
315 } else if (streq(name, "BlockIODeviceWeight")) {
718db961
LP
316 const char *path;
317 uint64_t u64;
6f68ecb4
G
318 unsigned n = 0;
319
718db961
LP
320 r = sd_bus_message_enter_container(message, 'a', "(st)");
321 if (r < 0)
322 return r;
6f68ecb4 323
718db961 324 while (( r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
6f68ecb4 325 unsigned long ul;
6f68ecb4 326
6f68ecb4
G
327 ul = (unsigned long) u64;
328 if (ul < 10 || ul > 1000)
718db961 329 return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range");
6f68ecb4
G
330
331 if (mode != UNIT_CHECK) {
718db961 332 CGroupBlockIODeviceWeight *a = NULL, *b;
6f68ecb4
G
333
334 LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
335 if (path_equal(b->path, path)) {
336 a = b;
6f68ecb4
G
337 break;
338 }
339 }
340
718db961 341 if (!a) {
6f68ecb4
G
342 a = new0(CGroupBlockIODeviceWeight, 1);
343 if (!a)
344 return -ENOMEM;
345
346 a->path = strdup(path);
347 if (!a->path) {
348 free(a);
349 return -ENOMEM;
350 }
718db961 351 LIST_PREPEND(device_weights,c->blockio_device_weights, a);
6f68ecb4
G
352 }
353
354 a->weight = ul;
6f68ecb4
G
355 }
356
357 n++;
6f68ecb4
G
358 }
359
360 if (mode != UNIT_CHECK) {
361 _cleanup_free_ char *buf = NULL;
362 _cleanup_fclose_ FILE *f = NULL;
363 CGroupBlockIODeviceWeight *a;
364 size_t size = 0;
365
366 if (n == 0) {
367 while (c->blockio_device_weights)
368 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
369 }
370
371 f = open_memstream(&buf, &size);
372 if (!f)
373 return -ENOMEM;
374
375 fputs("BlockIODeviceWeight=\n", f);
376 LIST_FOREACH(device_weights, a, c->blockio_device_weights)
377 fprintf(f, "BlockIODeviceWeight=%s %lu\n", a->path, a->weight);
378
f004c2ca
G
379 fflush(f);
380 unit_write_drop_in_private(u, mode, name, buf);
381 }
382
383 return 1;
384
8e2af478 385 } else if (streq(name, "MemoryAccounting")) {
718db961 386 int b;
8e2af478 387
718db961
LP
388 r = sd_bus_message_read(message, "b", &b);
389 if (r < 0)
390 return r;
8e2af478
LP
391
392 if (mode != UNIT_CHECK) {
b42defe3 393 c->memory_accounting = b;
b9ec9359 394 unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
8e2af478
LP
395 }
396
397 return 1;
8e2af478 398
ddca82ac 399 } else if (streq(name, "MemoryLimit")) {
718db961 400 uint64_t limit;
b42defe3 401
718db961
LP
402 r = sd_bus_message_read(message, "t", &limit);
403 if (r < 0)
404 return r;
b42defe3
LP
405
406 if (mode != UNIT_CHECK) {
ddca82ac 407 c->memory_limit = limit;
b9ec9359 408 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, limit);
b42defe3
LP
409 }
410
7041efe9
LP
411 return 1;
412
413 } else if (streq(name, "DevicePolicy")) {
414 const char *policy;
415 CGroupDevicePolicy p;
416
718db961
LP
417 r = sd_bus_message_read(message, "s", &policy);
418 if (r < 0)
419 return r;
7041efe9 420
7041efe9
LP
421 p = cgroup_device_policy_from_string(policy);
422 if (p < 0)
423 return -EINVAL;
424
425 if (mode != UNIT_CHECK) {
426 char *buf;
427
428 c->device_policy = p;
429
430 buf = strappenda("DevicePolicy=", policy);
b9ec9359 431 unit_write_drop_in_private(u, mode, name, buf);
7041efe9
LP
432 }
433
434 return 1;
435
436 } else if (streq(name, "DeviceAllow")) {
718db961 437 const char *path, *rwm;
7041efe9
LP
438 unsigned n = 0;
439
718db961
LP
440 r = sd_bus_message_enter_container(message, 'a', "(ss)");
441 if (r < 0)
442 return r;
7041efe9 443
718db961 444 while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
7041efe9 445
718db961
LP
446 if (!path_startswith(path, "/dev"))
447 return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node");
7041efe9
LP
448
449 if (isempty(rwm))
450 rwm = "rwm";
451
718db961
LP
452 if (!in_charset(rwm, "rwm"))
453 return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires combination of rwm flags");
7041efe9 454
7041efe9 455 if (mode != UNIT_CHECK) {
718db961 456 CGroupDeviceAllow *a = NULL, *b;
ad7bfffd
G
457
458 LIST_FOREACH(device_allow, b, c->device_allow) {
06eb4e3b 459 if (path_equal(b->path, path)) {
ad7bfffd 460 a = b;
ad7bfffd
G
461 break;
462 }
463 }
464
718db961 465 if (!a) {
ad7bfffd
G
466 a = new0(CGroupDeviceAllow, 1);
467 if (!a)
468 return -ENOMEM;
469
470 a->path = strdup(path);
471 if (!a->path) {
472 free(a);
473 return -ENOMEM;
474 }
718db961
LP
475
476 LIST_PREPEND(device_allow, c->device_allow, a);
7041efe9
LP
477 }
478
479 a->r = !!strchr(rwm, 'r');
480 a->w = !!strchr(rwm, 'w');
481 a->m = !!strchr(rwm, 'm');
482
7041efe9
LP
483 }
484
c2756a68 485 n++;
7041efe9 486 }
43a99a7a
LP
487 if (r < 0)
488 return r;
7041efe9
LP
489
490 if (mode != UNIT_CHECK) {
491 _cleanup_free_ char *buf = NULL;
492 _cleanup_fclose_ FILE *f = NULL;
493 CGroupDeviceAllow *a;
494 size_t size = 0;
495
496 if (n == 0) {
497 while (c->device_allow)
498 cgroup_context_free_device_allow(c, c->device_allow);
499 }
500
501 f = open_memstream(&buf, &size);
502 if (!f)
503 return -ENOMEM;
504
505 fputs("DeviceAllow=\n", f);
506 LIST_FOREACH(device_allow, a, c->device_allow)
507 fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
508
509 fflush(f);
b9ec9359 510 unit_write_drop_in_private(u, mode, name, buf);
7041efe9
LP
511 }
512
b42defe3
LP
513 return 1;
514 }
8e2af478
LP
515
516 return 0;
517}