2 This file is part of systemd.
4 Copyright 2013 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include "alloc-util.h"
22 #include "cgroup-util.h"
24 #include "dbus-cgroup.h"
27 #include "path-util.h"
29 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy
, cgroup_device_policy
, CGroupDevicePolicy
);
31 static int property_get_io_device_weight(
34 const char *interface
,
36 sd_bus_message
*reply
,
38 sd_bus_error
*error
) {
40 CGroupContext
*c
= userdata
;
41 CGroupIODeviceWeight
*w
;
48 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
52 LIST_FOREACH(device_weights
, w
, c
->io_device_weights
) {
53 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
58 return sd_bus_message_close_container(reply
);
61 static int property_get_io_device_limits(
64 const char *interface
,
66 sd_bus_message
*reply
,
68 sd_bus_error
*error
) {
70 CGroupContext
*c
= userdata
;
71 CGroupIODeviceLimit
*l
;
78 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
82 LIST_FOREACH(device_limits
, l
, c
->io_device_limits
) {
83 CGroupIOLimitType type
;
85 type
= cgroup_io_limit_type_from_string(property
);
86 if (type
< 0 || l
->limits
[type
] == cgroup_io_limit_defaults
[type
])
89 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->limits
[type
]);
94 return sd_bus_message_close_container(reply
);
97 static int property_get_blockio_device_weight(
100 const char *interface
,
101 const char *property
,
102 sd_bus_message
*reply
,
104 sd_bus_error
*error
) {
106 CGroupContext
*c
= userdata
;
107 CGroupBlockIODeviceWeight
*w
;
114 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
118 LIST_FOREACH(device_weights
, w
, c
->blockio_device_weights
) {
119 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
124 return sd_bus_message_close_container(reply
);
127 static int property_get_blockio_device_bandwidths(
130 const char *interface
,
131 const char *property
,
132 sd_bus_message
*reply
,
134 sd_bus_error
*error
) {
136 CGroupContext
*c
= userdata
;
137 CGroupBlockIODeviceBandwidth
*b
;
144 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
148 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
151 if (streq(property
, "BlockIOReadBandwidth"))
156 if (v
== CGROUP_LIMIT_MAX
)
159 r
= sd_bus_message_append(reply
, "(st)", b
->path
, v
);
164 return sd_bus_message_close_container(reply
);
167 static int property_get_device_allow(
170 const char *interface
,
171 const char *property
,
172 sd_bus_message
*reply
,
174 sd_bus_error
*error
) {
176 CGroupContext
*c
= userdata
;
177 CGroupDeviceAllow
*a
;
184 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
188 LIST_FOREACH(device_allow
, a
, c
->device_allow
) {
201 r
= sd_bus_message_append(reply
, "(ss)", a
->path
, rwm
);
206 return sd_bus_message_close_container(reply
);
209 const sd_bus_vtable bus_cgroup_vtable
[] = {
210 SD_BUS_VTABLE_START(0),
211 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool
, offsetof(CGroupContext
, delegate
), 0),
212 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, cpu_accounting
), 0),
213 SD_BUS_PROPERTY("CPUShares", "t", NULL
, offsetof(CGroupContext
, cpu_shares
), 0),
214 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL
, offsetof(CGroupContext
, startup_cpu_shares
), 0),
215 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_per_sec_usec
), 0),
216 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, io_accounting
), 0),
217 SD_BUS_PROPERTY("IOWeight", "t", NULL
, offsetof(CGroupContext
, io_weight
), 0),
218 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_io_weight
), 0),
219 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight
, 0, 0),
220 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
221 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
222 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
223 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
224 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, blockio_accounting
), 0),
225 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL
, offsetof(CGroupContext
, blockio_weight
), 0),
226 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_blockio_weight
), 0),
227 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight
, 0, 0),
228 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
229 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
230 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_accounting
), 0),
231 SD_BUS_PROPERTY("MemoryLimit", "t", NULL
, offsetof(CGroupContext
, memory_limit
), 0),
232 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
233 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
234 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
235 SD_BUS_PROPERTY("TasksMax", "t", NULL
, offsetof(CGroupContext
, tasks_max
), 0),
239 static int bus_cgroup_set_transient_property(
243 sd_bus_message
*message
,
244 UnitSetPropertiesMode mode
,
245 sd_bus_error
*error
) {
254 if (streq(name
, "Delegate")) {
257 r
= sd_bus_message_read(message
, "b", &b
);
261 if (mode
!= UNIT_CHECK
) {
263 unit_write_drop_in_private(u
, mode
, name
, b
? "Delegate=yes" : "Delegate=no");
272 int bus_cgroup_set_property(
276 sd_bus_message
*message
,
277 UnitSetPropertiesMode mode
,
278 sd_bus_error
*error
) {
280 CGroupIOLimitType iol_type
;
288 if (streq(name
, "CPUAccounting")) {
291 r
= sd_bus_message_read(message
, "b", &b
);
295 if (mode
!= UNIT_CHECK
) {
296 c
->cpu_accounting
= b
;
297 unit_invalidate_cgroup(u
, CGROUP_MASK_CPUACCT
|CGROUP_MASK_CPU
);
298 unit_write_drop_in_private(u
, mode
, name
, b
? "CPUAccounting=yes" : "CPUAccounting=no");
303 } else if (streq(name
, "CPUShares")) {
306 r
= sd_bus_message_read(message
, "t", &shares
);
310 if (!CGROUP_CPU_SHARES_IS_OK(shares
))
311 return sd_bus_error_set_errnof(error
, EINVAL
, "CPUShares value out of range");
313 if (mode
!= UNIT_CHECK
) {
314 c
->cpu_shares
= shares
;
315 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
317 if (shares
== CGROUP_CPU_SHARES_INVALID
)
318 unit_write_drop_in_private(u
, mode
, name
, "CPUShares=");
320 unit_write_drop_in_private_format(u
, mode
, name
, "CPUShares=%" PRIu64
, shares
);
325 } else if (streq(name
, "StartupCPUShares")) {
328 r
= sd_bus_message_read(message
, "t", &shares
);
332 if (!CGROUP_CPU_SHARES_IS_OK(shares
))
333 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupCPUShares value out of range");
335 if (mode
!= UNIT_CHECK
) {
336 c
->startup_cpu_shares
= shares
;
337 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
339 if (shares
== CGROUP_CPU_SHARES_INVALID
)
340 unit_write_drop_in_private(u
, mode
, name
, "StartupCPUShares=");
342 unit_write_drop_in_private_format(u
, mode
, name
, "StartupCPUShares=%" PRIu64
, shares
);
347 } else if (streq(name
, "CPUQuotaPerSecUSec")) {
350 r
= sd_bus_message_read(message
, "t", &u64
);
355 return sd_bus_error_set_errnof(error
, EINVAL
, "CPUQuotaPerSecUSec value out of range");
357 if (mode
!= UNIT_CHECK
) {
358 c
->cpu_quota_per_sec_usec
= u64
;
359 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
360 unit_write_drop_in_private_format(u
, mode
, "CPUQuota", "CPUQuota=%0.f%%", (double) (c
->cpu_quota_per_sec_usec
/ 10000));
365 } else if (streq(name
, "IOAccounting")) {
368 r
= sd_bus_message_read(message
, "b", &b
);
372 if (mode
!= UNIT_CHECK
) {
373 c
->io_accounting
= b
;
374 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
375 unit_write_drop_in_private(u
, mode
, name
, b
? "IOAccounting=yes" : "IOAccounting=no");
380 } else if (streq(name
, "IOWeight")) {
383 r
= sd_bus_message_read(message
, "t", &weight
);
387 if (!CGROUP_WEIGHT_IS_OK(weight
))
388 return sd_bus_error_set_errnof(error
, EINVAL
, "IOWeight value out of range");
390 if (mode
!= UNIT_CHECK
) {
391 c
->io_weight
= weight
;
392 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
394 if (weight
== CGROUP_WEIGHT_INVALID
)
395 unit_write_drop_in_private(u
, mode
, name
, "IOWeight=");
397 unit_write_drop_in_private_format(u
, mode
, name
, "IOWeight=%" PRIu64
, weight
);
402 } else if (streq(name
, "StartupIOWeight")) {
405 r
= sd_bus_message_read(message
, "t", &weight
);
409 if (CGROUP_WEIGHT_IS_OK(weight
))
410 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupIOWeight value out of range");
412 if (mode
!= UNIT_CHECK
) {
413 c
->startup_io_weight
= weight
;
414 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
416 if (weight
== CGROUP_WEIGHT_INVALID
)
417 unit_write_drop_in_private(u
, mode
, name
, "StartupIOWeight=");
419 unit_write_drop_in_private_format(u
, mode
, name
, "StartupIOWeight=%" PRIu64
, weight
);
424 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
429 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
433 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
435 if (mode
!= UNIT_CHECK
) {
436 CGroupIODeviceLimit
*a
= NULL
, *b
;
438 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
) {
439 if (path_equal(path
, b
->path
)) {
446 CGroupIOLimitType type
;
448 a
= new0(CGroupIODeviceLimit
, 1);
452 a
->path
= strdup(path
);
458 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
459 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
461 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
464 a
->limits
[iol_type
] = u64
;
472 r
= sd_bus_message_exit_container(message
);
476 if (mode
!= UNIT_CHECK
) {
477 CGroupIODeviceLimit
*a
;
478 _cleanup_free_
char *buf
= NULL
;
479 _cleanup_fclose_
FILE *f
= NULL
;
483 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
484 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
487 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
489 f
= open_memstream(&buf
, &size
);
493 fprintf(f
, "%s=\n", name
);
494 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
495 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
496 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
498 r
= fflush_and_check(f
);
501 unit_write_drop_in_private(u
, mode
, name
, buf
);
506 } else if (streq(name
, "IODeviceWeight")) {
511 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
515 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
517 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
518 return sd_bus_error_set_errnof(error
, EINVAL
, "IODeviceWeight out of range");
520 if (mode
!= UNIT_CHECK
) {
521 CGroupIODeviceWeight
*a
= NULL
, *b
;
523 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
) {
524 if (path_equal(b
->path
, path
)) {
531 a
= new0(CGroupIODeviceWeight
, 1);
535 a
->path
= strdup(path
);
540 LIST_PREPEND(device_weights
,c
->io_device_weights
, a
);
549 r
= sd_bus_message_exit_container(message
);
553 if (mode
!= UNIT_CHECK
) {
554 _cleanup_free_
char *buf
= NULL
;
555 _cleanup_fclose_
FILE *f
= NULL
;
556 CGroupIODeviceWeight
*a
;
560 while (c
->io_device_weights
)
561 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
564 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
566 f
= open_memstream(&buf
, &size
);
570 fputs("IODeviceWeight=\n", f
);
571 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
572 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
574 r
= fflush_and_check(f
);
577 unit_write_drop_in_private(u
, mode
, name
, buf
);
582 } else if (streq(name
, "BlockIOAccounting")) {
585 r
= sd_bus_message_read(message
, "b", &b
);
589 if (mode
!= UNIT_CHECK
) {
590 c
->blockio_accounting
= b
;
591 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
592 unit_write_drop_in_private(u
, mode
, name
, b
? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
597 } else if (streq(name
, "BlockIOWeight")) {
600 r
= sd_bus_message_read(message
, "t", &weight
);
604 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
))
605 return sd_bus_error_set_errnof(error
, EINVAL
, "BlockIOWeight value out of range");
607 if (mode
!= UNIT_CHECK
) {
608 c
->blockio_weight
= weight
;
609 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
611 if (weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
612 unit_write_drop_in_private(u
, mode
, name
, "BlockIOWeight=");
614 unit_write_drop_in_private_format(u
, mode
, name
, "BlockIOWeight=%" PRIu64
, weight
);
619 } else if (streq(name
, "StartupBlockIOWeight")) {
622 r
= sd_bus_message_read(message
, "t", &weight
);
626 if (CGROUP_BLKIO_WEIGHT_IS_OK(weight
))
627 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupBlockIOWeight value out of range");
629 if (mode
!= UNIT_CHECK
) {
630 c
->startup_blockio_weight
= weight
;
631 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
633 if (weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
634 unit_write_drop_in_private(u
, mode
, name
, "StartupBlockIOWeight=");
636 unit_write_drop_in_private_format(u
, mode
, name
, "StartupBlockIOWeight=%" PRIu64
, weight
);
641 } else if (streq(name
, "BlockIOReadBandwidth") || streq(name
, "BlockIOWriteBandwidth")) {
647 if (streq(name
, "BlockIOWriteBandwidth"))
650 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
654 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
656 if (mode
!= UNIT_CHECK
) {
657 CGroupBlockIODeviceBandwidth
*a
= NULL
, *b
;
659 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
660 if (path_equal(path
, b
->path
)) {
667 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
671 a
->rbps
= CGROUP_LIMIT_MAX
;
672 a
->wbps
= CGROUP_LIMIT_MAX
;
673 a
->path
= strdup(path
);
679 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
693 r
= sd_bus_message_exit_container(message
);
697 if (mode
!= UNIT_CHECK
) {
698 CGroupBlockIODeviceBandwidth
*a
;
699 _cleanup_free_
char *buf
= NULL
;
700 _cleanup_fclose_
FILE *f
= NULL
;
704 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
706 a
->rbps
= CGROUP_LIMIT_MAX
;
708 a
->wbps
= CGROUP_LIMIT_MAX
;
712 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
714 f
= open_memstream(&buf
, &size
);
719 fputs("BlockIOReadBandwidth=\n", f
);
720 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
721 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
722 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
724 fputs("BlockIOWriteBandwidth=\n", f
);
725 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
726 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
727 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
730 r
= fflush_and_check(f
);
733 unit_write_drop_in_private(u
, mode
, name
, buf
);
738 } else if (streq(name
, "BlockIODeviceWeight")) {
743 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
747 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
749 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
750 return sd_bus_error_set_errnof(error
, EINVAL
, "BlockIODeviceWeight out of range");
752 if (mode
!= UNIT_CHECK
) {
753 CGroupBlockIODeviceWeight
*a
= NULL
, *b
;
755 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
) {
756 if (path_equal(b
->path
, path
)) {
763 a
= new0(CGroupBlockIODeviceWeight
, 1);
767 a
->path
= strdup(path
);
772 LIST_PREPEND(device_weights
,c
->blockio_device_weights
, a
);
781 r
= sd_bus_message_exit_container(message
);
785 if (mode
!= UNIT_CHECK
) {
786 _cleanup_free_
char *buf
= NULL
;
787 _cleanup_fclose_
FILE *f
= NULL
;
788 CGroupBlockIODeviceWeight
*a
;
792 while (c
->blockio_device_weights
)
793 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
796 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
798 f
= open_memstream(&buf
, &size
);
802 fputs("BlockIODeviceWeight=\n", f
);
803 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
804 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
806 r
= fflush_and_check(f
);
809 unit_write_drop_in_private(u
, mode
, name
, buf
);
814 } else if (streq(name
, "MemoryAccounting")) {
817 r
= sd_bus_message_read(message
, "b", &b
);
821 if (mode
!= UNIT_CHECK
) {
822 c
->memory_accounting
= b
;
823 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
824 unit_write_drop_in_private(u
, mode
, name
, b
? "MemoryAccounting=yes" : "MemoryAccounting=no");
829 } else if (streq(name
, "MemoryLimit")) {
832 r
= sd_bus_message_read(message
, "t", &limit
);
836 if (mode
!= UNIT_CHECK
) {
837 c
->memory_limit
= limit
;
838 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
840 if (limit
== (uint64_t) -1)
841 unit_write_drop_in_private(u
, mode
, name
, "MemoryLimit=infinity");
843 unit_write_drop_in_private_format(u
, mode
, name
, "MemoryLimit=%" PRIu64
, limit
);
848 } else if (streq(name
, "DevicePolicy")) {
850 CGroupDevicePolicy p
;
852 r
= sd_bus_message_read(message
, "s", &policy
);
856 p
= cgroup_device_policy_from_string(policy
);
860 if (mode
!= UNIT_CHECK
) {
863 c
->device_policy
= p
;
864 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
866 buf
= strjoina("DevicePolicy=", policy
);
867 unit_write_drop_in_private(u
, mode
, name
, buf
);
872 } else if (streq(name
, "DeviceAllow")) {
873 const char *path
, *rwm
;
876 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
880 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
882 if ((!startswith(path
, "/dev/") &&
883 !startswith(path
, "block-") &&
884 !startswith(path
, "char-")) ||
885 strpbrk(path
, WHITESPACE
))
886 return sd_bus_error_set_errnof(error
, EINVAL
, "DeviceAllow= requires device node");
891 if (!in_charset(rwm
, "rwm"))
892 return sd_bus_error_set_errnof(error
, EINVAL
, "DeviceAllow= requires combination of rwm flags");
894 if (mode
!= UNIT_CHECK
) {
895 CGroupDeviceAllow
*a
= NULL
, *b
;
897 LIST_FOREACH(device_allow
, b
, c
->device_allow
) {
898 if (path_equal(b
->path
, path
)) {
905 a
= new0(CGroupDeviceAllow
, 1);
909 a
->path
= strdup(path
);
915 LIST_PREPEND(device_allow
, c
->device_allow
, a
);
918 a
->r
= !!strchr(rwm
, 'r');
919 a
->w
= !!strchr(rwm
, 'w');
920 a
->m
= !!strchr(rwm
, 'm');
928 r
= sd_bus_message_exit_container(message
);
932 if (mode
!= UNIT_CHECK
) {
933 _cleanup_free_
char *buf
= NULL
;
934 _cleanup_fclose_
FILE *f
= NULL
;
935 CGroupDeviceAllow
*a
;
939 while (c
->device_allow
)
940 cgroup_context_free_device_allow(c
, c
->device_allow
);
943 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
945 f
= open_memstream(&buf
, &size
);
949 fputs("DeviceAllow=\n", f
);
950 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
951 fprintf(f
, "DeviceAllow=%s %s%s%s\n", a
->path
, a
->r
? "r" : "", a
->w
? "w" : "", a
->m
? "m" : "");
953 r
= fflush_and_check(f
);
956 unit_write_drop_in_private(u
, mode
, name
, buf
);
961 } else if (streq(name
, "TasksAccounting")) {
964 r
= sd_bus_message_read(message
, "b", &b
);
968 if (mode
!= UNIT_CHECK
) {
969 c
->tasks_accounting
= b
;
970 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
971 unit_write_drop_in_private(u
, mode
, name
, b
? "TasksAccounting=yes" : "TasksAccounting=no");
976 } else if (streq(name
, "TasksMax")) {
979 r
= sd_bus_message_read(message
, "t", &limit
);
983 if (mode
!= UNIT_CHECK
) {
984 c
->tasks_max
= limit
;
985 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
987 if (limit
== (uint64_t) -1)
988 unit_write_drop_in_private(u
, mode
, name
, "TasksMax=infinity");
990 unit_write_drop_in_private_format(u
, mode
, name
, "TasksMax=%" PRIu64
, limit
);
996 if (u
->transient
&& u
->load_state
== UNIT_STUB
) {
997 r
= bus_cgroup_set_transient_property(u
, c
, name
, message
, mode
, error
);