]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-cgroup.c
core: add support for the "pids" cgroup controller
[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
db785129
LP
136static int property_get_ulong_as_u64(
137 sd_bus *bus,
138 const char *path,
139 const char *interface,
140 const char *property,
141 sd_bus_message *reply,
142 void *userdata,
143 sd_bus_error *error) {
144
145 unsigned long *ul = userdata;
146
147 assert(bus);
148 assert(reply);
149 assert(ul);
150
151 return sd_bus_message_append(reply, "t", *ul == (unsigned long) -1 ? (uint64_t) -1 : (uint64_t) *ul);
152}
153
718db961
LP
154const sd_bus_vtable bus_cgroup_vtable[] = {
155 SD_BUS_VTABLE_START(0),
a931ad47 156 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
610f780c 157 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
db785129
LP
158 SD_BUS_PROPERTY("CPUShares", "t", property_get_ulong_as_u64, offsetof(CGroupContext, cpu_shares), 0),
159 SD_BUS_PROPERTY("StartupCPUShares", "t", property_get_ulong_as_u64, offsetof(CGroupContext, startup_cpu_shares), 0),
ee26bcc0 160 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
610f780c 161 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
db785129
LP
162 SD_BUS_PROPERTY("BlockIOWeight", "t", property_get_ulong_as_u64, offsetof(CGroupContext, blockio_weight), 0),
163 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", property_get_ulong_as_u64, offsetof(CGroupContext, startup_blockio_weight), 0),
610f780c
LP
164 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
165 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
166 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
167 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
168 SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
169 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
170 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
03a7b521
LP
171 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0),
172 SD_BUS_PROPERTY("TasksMax", "t", NULL, offsetof(CGroupContext, tasks_max), 0),
718db961 173 SD_BUS_VTABLE_END
4ad49000 174};
8e2af478 175
a931ad47
LP
176static int bus_cgroup_set_transient_property(
177 Unit *u,
178 CGroupContext *c,
179 const char *name,
180 sd_bus_message *message,
181 UnitSetPropertiesMode mode,
182 sd_bus_error *error) {
183
184 int r;
185
186 assert(u);
187 assert(c);
188 assert(name);
189 assert(message);
190
191 if (streq(name, "Delegate")) {
192 int b;
193
194 r = sd_bus_message_read(message, "b", &b);
195 if (r < 0)
196 return r;
197
198 if (mode != UNIT_CHECK) {
199 c->delegate = b;
200 unit_write_drop_in_private(u, mode, name, b ? "Delegate=yes" : "Delegate=no");
201 }
202
203 return 1;
204 }
205
206 return 0;
207}
208
8e2af478
LP
209int bus_cgroup_set_property(
210 Unit *u,
211 CGroupContext *c,
212 const char *name,
718db961 213 sd_bus_message *message,
8e2af478 214 UnitSetPropertiesMode mode,
718db961
LP
215 sd_bus_error *error) {
216
217 int r;
8e2af478 218
8e2af478
LP
219 assert(u);
220 assert(c);
718db961
LP
221 assert(name);
222 assert(message);
8e2af478
LP
223
224 if (streq(name, "CPUAccounting")) {
718db961 225 int b;
8e2af478 226
718db961
LP
227 r = sd_bus_message_read(message, "b", &b);
228 if (r < 0)
229 return r;
8e2af478
LP
230
231 if (mode != UNIT_CHECK) {
8e2af478 232 c->cpu_accounting = b;
efdb0237 233 u->cgroup_realized_mask &= ~CGROUP_MASK_CPUACCT;
b9ec9359 234 unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no");
b42defe3
LP
235 }
236
237 return 1;
238
239 } else if (streq(name, "CPUShares")) {
240 uint64_t u64;
241 unsigned long ul;
242
718db961
LP
243 r = sd_bus_message_read(message, "t", &u64);
244 if (r < 0)
245 return r;
b42defe3 246
db785129
LP
247 if (u64 == (uint64_t) -1)
248 ul = (unsigned long) -1;
249 else {
250 ul = (unsigned long) u64;
251 if (ul <= 0 || (uint64_t) ul != u64)
252 return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range");
253 }
b42defe3
LP
254
255 if (mode != UNIT_CHECK) {
b42defe3 256 c->cpu_shares = ul;
efdb0237 257 u->cgroup_realized_mask &= ~CGROUP_MASK_CPU;
b9ec9359 258 unit_write_drop_in_private_format(u, mode, name, "CPUShares=%lu", ul);
8e2af478
LP
259 }
260
261 return 1;
262
95ae05c0
WC
263 } else if (streq(name, "StartupCPUShares")) {
264 uint64_t u64;
265 unsigned long ul;
266
267 r = sd_bus_message_read(message, "t", &u64);
268 if (r < 0)
269 return r;
270
db785129
LP
271 if (u64 == (uint64_t) -1)
272 ul = (unsigned long) -1;
273 else {
274 ul = (unsigned long) u64;
275 if (ul <= 0 || (uint64_t) ul != u64)
276 return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range");
277 }
95ae05c0
WC
278
279 if (mode != UNIT_CHECK) {
280 c->startup_cpu_shares = ul;
efdb0237 281 u->cgroup_realized_mask &= ~CGROUP_MASK_CPU;
95ae05c0
WC
282 unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%lu", ul);
283 }
284
285 return 1;
286
b2f8b02e
LP
287 } else if (streq(name, "CPUQuotaPerSecUSec")) {
288 uint64_t u64;
289
290 r = sd_bus_message_read(message, "t", &u64);
291 if (r < 0)
292 return r;
293
294 if (u64 <= 0)
295 return sd_bus_error_set_errnof(error, EINVAL, "CPUQuotaPerSecUSec value out of range");
296
297 if (mode != UNIT_CHECK) {
298 c->cpu_quota_per_sec_usec = u64;
efdb0237 299 u->cgroup_realized_mask &= ~CGROUP_MASK_CPU;
b2f8b02e
LP
300 unit_write_drop_in_private_format(u, mode, "CPUQuota", "CPUQuota=%0.f%%", (double) (c->cpu_quota_per_sec_usec / 10000));
301 }
302
303 return 1;
304
8e2af478 305 } else if (streq(name, "BlockIOAccounting")) {
718db961 306 int b;
8e2af478 307
718db961
LP
308 r = sd_bus_message_read(message, "b", &b);
309 if (r < 0)
310 return r;
8e2af478
LP
311
312 if (mode != UNIT_CHECK) {
8e2af478 313 c->blockio_accounting = b;
efdb0237 314 u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO;
b9ec9359 315 unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
8e2af478
LP
316 }
317
318 return 1;
b42defe3
LP
319
320 } else if (streq(name, "BlockIOWeight")) {
321 uint64_t u64;
322 unsigned long ul;
323
718db961
LP
324 r = sd_bus_message_read(message, "t", &u64);
325 if (r < 0)
326 return r;
b42defe3 327
db785129
LP
328 if (u64 == (uint64_t) -1)
329 ul = (unsigned long) -1;
330 else {
331 ul = (unsigned long) u64;
332 if (ul < 10 || ul > 1000)
333 return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range");
334 }
b42defe3
LP
335
336 if (mode != UNIT_CHECK) {
f2369103 337 c->blockio_weight = ul;
efdb0237 338 u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO;
b9ec9359 339 unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%lu", ul);
b42defe3
LP
340 }
341
342 return 1;
95ae05c0
WC
343
344 } else if (streq(name, "StartupBlockIOWeight")) {
345 uint64_t u64;
346 unsigned long ul;
347
348 r = sd_bus_message_read(message, "t", &u64);
349 if (r < 0)
350 return r;
351
db785129
LP
352 if (u64 == (uint64_t) -1)
353 ul = (unsigned long) -1;
354 else {
355 ul = (unsigned long) u64;
356 if (ul < 10 || ul > 1000)
357 return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range");
358 }
95ae05c0
WC
359
360 if (mode != UNIT_CHECK) {
361 c->startup_blockio_weight = ul;
efdb0237 362 u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO;
95ae05c0
WC
363 unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%lu", ul);
364 }
365
366 return 1;
b42defe3 367
f004c2ca 368 } else if (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth")) {
718db961 369 const char *path;
f004c2ca 370 bool read = true;
718db961
LP
371 unsigned n = 0;
372 uint64_t u64;
f004c2ca
G
373
374 if (streq(name, "BlockIOWriteBandwidth"))
375 read = false;
376
718db961
LP
377 r = sd_bus_message_enter_container(message, 'a', "(st)");
378 if (r < 0)
379 return r;
f004c2ca 380
718db961 381 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
f004c2ca
G
382
383 if (mode != UNIT_CHECK) {
718db961 384 CGroupBlockIODeviceBandwidth *a = NULL, *b;
f004c2ca
G
385
386 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
387 if (path_equal(path, b->path) && read == b->read) {
388 a = b;
f004c2ca
G
389 break;
390 }
391 }
392
718db961 393 if (!a) {
f004c2ca
G
394 a = new0(CGroupBlockIODeviceBandwidth, 1);
395 if (!a)
396 return -ENOMEM;
397
398 a->read = read;
399 a->path = strdup(path);
400 if (!a->path) {
401 free(a);
402 return -ENOMEM;
403 }
718db961
LP
404
405 LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
f004c2ca
G
406 }
407
408 a->bandwidth = u64;
f004c2ca
G
409 }
410
411 n++;
f004c2ca 412 }
718db961
LP
413 if (r < 0)
414 return r;
f004c2ca 415
9c96019d
LP
416 r = sd_bus_message_exit_container(message);
417 if (r < 0)
418 return r;
419
f004c2ca 420 if (mode != UNIT_CHECK) {
718db961 421 CGroupBlockIODeviceBandwidth *a, *next;
f004c2ca
G
422 _cleanup_free_ char *buf = NULL;
423 _cleanup_fclose_ FILE *f = NULL;
f004c2ca
G
424 size_t size = 0;
425
426 if (n == 0) {
427 LIST_FOREACH_SAFE(device_bandwidths, a, next, c->blockio_device_bandwidths)
428 if (a->read == read)
429 cgroup_context_free_blockio_device_bandwidth(c, a);
430 }
431
efdb0237 432 u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO;
3051f187 433
f004c2ca
G
434 f = open_memstream(&buf, &size);
435 if (!f)
436 return -ENOMEM;
437
7d6884b6 438 if (read) {
f004c2ca 439 fputs("BlockIOReadBandwidth=\n", f);
7d6884b6 440 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
f004c2ca
G
441 if (a->read)
442 fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth);
443 } else {
444 fputs("BlockIOWriteBandwidth=\n", f);
445 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
446 if (!a->read)
447 fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth);
448 }
449
6f68ecb4
G
450 fflush(f);
451 unit_write_drop_in_private(u, mode, name, buf);
452 }
453
454 return 1;
455
456 } else if (streq(name, "BlockIODeviceWeight")) {
718db961
LP
457 const char *path;
458 uint64_t u64;
6f68ecb4
G
459 unsigned n = 0;
460
718db961
LP
461 r = sd_bus_message_enter_container(message, 'a', "(st)");
462 if (r < 0)
463 return r;
6f68ecb4 464
ccd06097
ZJS
465 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
466 unsigned long ul = u64;
6f68ecb4 467
6f68ecb4 468 if (ul < 10 || ul > 1000)
718db961 469 return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range");
6f68ecb4
G
470
471 if (mode != UNIT_CHECK) {
718db961 472 CGroupBlockIODeviceWeight *a = NULL, *b;
6f68ecb4
G
473
474 LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
475 if (path_equal(b->path, path)) {
476 a = b;
6f68ecb4
G
477 break;
478 }
479 }
480
718db961 481 if (!a) {
6f68ecb4
G
482 a = new0(CGroupBlockIODeviceWeight, 1);
483 if (!a)
484 return -ENOMEM;
485
486 a->path = strdup(path);
487 if (!a->path) {
488 free(a);
489 return -ENOMEM;
490 }
718db961 491 LIST_PREPEND(device_weights,c->blockio_device_weights, a);
6f68ecb4
G
492 }
493
494 a->weight = ul;
6f68ecb4
G
495 }
496
497 n++;
6f68ecb4
G
498 }
499
9c96019d
LP
500 r = sd_bus_message_exit_container(message);
501 if (r < 0)
502 return r;
503
6f68ecb4
G
504 if (mode != UNIT_CHECK) {
505 _cleanup_free_ char *buf = NULL;
506 _cleanup_fclose_ FILE *f = NULL;
507 CGroupBlockIODeviceWeight *a;
508 size_t size = 0;
509
510 if (n == 0) {
511 while (c->blockio_device_weights)
512 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
513 }
514
efdb0237 515 u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO;
3051f187 516
6f68ecb4
G
517 f = open_memstream(&buf, &size);
518 if (!f)
519 return -ENOMEM;
520
521 fputs("BlockIODeviceWeight=\n", f);
522 LIST_FOREACH(device_weights, a, c->blockio_device_weights)
523 fprintf(f, "BlockIODeviceWeight=%s %lu\n", a->path, a->weight);
524
f004c2ca
G
525 fflush(f);
526 unit_write_drop_in_private(u, mode, name, buf);
527 }
528
529 return 1;
530
8e2af478 531 } else if (streq(name, "MemoryAccounting")) {
718db961 532 int b;
8e2af478 533
718db961
LP
534 r = sd_bus_message_read(message, "b", &b);
535 if (r < 0)
536 return r;
8e2af478
LP
537
538 if (mode != UNIT_CHECK) {
b42defe3 539 c->memory_accounting = b;
efdb0237 540 u->cgroup_realized_mask &= ~CGROUP_MASK_MEMORY;
b9ec9359 541 unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
8e2af478
LP
542 }
543
544 return 1;
8e2af478 545
ddca82ac 546 } else if (streq(name, "MemoryLimit")) {
718db961 547 uint64_t limit;
b42defe3 548
718db961
LP
549 r = sd_bus_message_read(message, "t", &limit);
550 if (r < 0)
551 return r;
b42defe3
LP
552
553 if (mode != UNIT_CHECK) {
ddca82ac 554 c->memory_limit = limit;
efdb0237 555 u->cgroup_realized_mask &= ~CGROUP_MASK_MEMORY;
03a7b521
LP
556
557 if (limit == (uint64_t) -1)
558 unit_write_drop_in_private(u, mode, name, "MemoryLimit=infinity");
559 else
560 unit_write_drop_in_private_format(u, mode, name, "MemoryLimit=%" PRIu64, limit);
b42defe3
LP
561 }
562
7041efe9
LP
563 return 1;
564
565 } else if (streq(name, "DevicePolicy")) {
566 const char *policy;
567 CGroupDevicePolicy p;
568
718db961
LP
569 r = sd_bus_message_read(message, "s", &policy);
570 if (r < 0)
571 return r;
7041efe9 572
7041efe9
LP
573 p = cgroup_device_policy_from_string(policy);
574 if (p < 0)
575 return -EINVAL;
576
577 if (mode != UNIT_CHECK) {
578 char *buf;
579
580 c->device_policy = p;
3905f127 581 u->cgroup_realized_mask &= ~CGROUP_MASK_DEVICES;
7041efe9 582
63c372cb 583 buf = strjoina("DevicePolicy=", policy);
b9ec9359 584 unit_write_drop_in_private(u, mode, name, buf);
7041efe9
LP
585 }
586
587 return 1;
588
589 } else if (streq(name, "DeviceAllow")) {
718db961 590 const char *path, *rwm;
7041efe9
LP
591 unsigned n = 0;
592
718db961
LP
593 r = sd_bus_message_enter_container(message, 'a', "(ss)");
594 if (r < 0)
595 return r;
7041efe9 596
718db961 597 while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
7041efe9 598
90060676
LP
599 if ((!startswith(path, "/dev/") &&
600 !startswith(path, "block-") &&
601 !startswith(path, "char-")) ||
602 strpbrk(path, WHITESPACE))
603 return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node");
7041efe9
LP
604
605 if (isempty(rwm))
606 rwm = "rwm";
607
718db961
LP
608 if (!in_charset(rwm, "rwm"))
609 return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires combination of rwm flags");
7041efe9 610
7041efe9 611 if (mode != UNIT_CHECK) {
718db961 612 CGroupDeviceAllow *a = NULL, *b;
ad7bfffd
G
613
614 LIST_FOREACH(device_allow, b, c->device_allow) {
06eb4e3b 615 if (path_equal(b->path, path)) {
ad7bfffd 616 a = b;
ad7bfffd
G
617 break;
618 }
619 }
620
718db961 621 if (!a) {
ad7bfffd
G
622 a = new0(CGroupDeviceAllow, 1);
623 if (!a)
624 return -ENOMEM;
625
626 a->path = strdup(path);
627 if (!a->path) {
628 free(a);
629 return -ENOMEM;
630 }
718db961
LP
631
632 LIST_PREPEND(device_allow, c->device_allow, a);
7041efe9
LP
633 }
634
635 a->r = !!strchr(rwm, 'r');
636 a->w = !!strchr(rwm, 'w');
637 a->m = !!strchr(rwm, 'm');
7041efe9
LP
638 }
639
c2756a68 640 n++;
7041efe9 641 }
43a99a7a
LP
642 if (r < 0)
643 return r;
7041efe9 644
9c96019d
LP
645 r = sd_bus_message_exit_container(message);
646 if (r < 0)
647 return r;
648
7041efe9
LP
649 if (mode != UNIT_CHECK) {
650 _cleanup_free_ char *buf = NULL;
651 _cleanup_fclose_ FILE *f = NULL;
652 CGroupDeviceAllow *a;
653 size_t size = 0;
654
655 if (n == 0) {
656 while (c->device_allow)
657 cgroup_context_free_device_allow(c, c->device_allow);
658 }
659
3905f127 660 u->cgroup_realized_mask &= ~CGROUP_MASK_DEVICES;
3051f187 661
7041efe9
LP
662 f = open_memstream(&buf, &size);
663 if (!f)
664 return -ENOMEM;
665
666 fputs("DeviceAllow=\n", f);
667 LIST_FOREACH(device_allow, a, c->device_allow)
668 fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
669
670 fflush(f);
b9ec9359 671 unit_write_drop_in_private(u, mode, name, buf);
7041efe9
LP
672 }
673
b42defe3 674 return 1;
a931ad47 675
03a7b521
LP
676 } else if (streq(name, "TasksAccounting")) {
677 int b;
678
679 r = sd_bus_message_read(message, "b", &b);
680 if (r < 0)
681 return r;
682
683 if (mode != UNIT_CHECK) {
684 c->tasks_accounting = b;
685 u->cgroup_realized_mask &= ~CGROUP_MASK_PIDS;
686 unit_write_drop_in_private(u, mode, name, b ? "TasksAccounting=yes" : "TasksAccounting=no");
687 }
688
689 return 1;
690
691 } else if (streq(name, "TasksMax")) {
692 uint64_t limit;
693
694 r = sd_bus_message_read(message, "t", &limit);
695 if (r < 0)
696 return r;
697
698 if (mode != UNIT_CHECK) {
699 c->tasks_max = limit;
700 u->cgroup_realized_mask &= ~CGROUP_MASK_PIDS;
701
702 if (limit == (uint64_t) -1)
703 unit_write_drop_in_private(u, mode, name, "TasksMax=infinity");
704 else
705 unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu64, limit);
706 }
707
708 return 1;
a931ad47
LP
709 }
710
711 if (u->transient && u->load_state == UNIT_STUB) {
712 r = bus_cgroup_set_transient_property(u, c, name, message, mode, error);
713 if (r != 0)
714 return r;
715
b42defe3 716 }
8e2af478
LP
717
718 return 0;
719}