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