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("CPUWeight", "t", NULL
, offsetof(CGroupContext
, cpu_weight
), 0),
214 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL
, offsetof(CGroupContext
, startup_cpu_weight
), 0),
215 SD_BUS_PROPERTY("CPUShares", "t", NULL
, offsetof(CGroupContext
, cpu_shares
), 0),
216 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL
, offsetof(CGroupContext
, startup_cpu_shares
), 0),
217 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_per_sec_usec
), 0),
218 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, io_accounting
), 0),
219 SD_BUS_PROPERTY("IOWeight", "t", NULL
, offsetof(CGroupContext
, io_weight
), 0),
220 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_io_weight
), 0),
221 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight
, 0, 0),
222 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
223 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
224 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
225 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
226 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, blockio_accounting
), 0),
227 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL
, offsetof(CGroupContext
, blockio_weight
), 0),
228 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_blockio_weight
), 0),
229 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight
, 0, 0),
230 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
231 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
232 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_accounting
), 0),
233 SD_BUS_PROPERTY("MemoryLow", "t", NULL
, offsetof(CGroupContext
, memory_low
), 0),
234 SD_BUS_PROPERTY("MemoryHigh", "t", NULL
, offsetof(CGroupContext
, memory_high
), 0),
235 SD_BUS_PROPERTY("MemoryMax", "t", NULL
, offsetof(CGroupContext
, memory_max
), 0),
236 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL
, offsetof(CGroupContext
, memory_swap_max
), 0),
237 SD_BUS_PROPERTY("MemoryLimit", "t", NULL
, offsetof(CGroupContext
, memory_limit
), 0),
238 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
239 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
240 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
241 SD_BUS_PROPERTY("TasksMax", "t", NULL
, offsetof(CGroupContext
, tasks_max
), 0),
245 static int bus_cgroup_set_transient_property(
249 sd_bus_message
*message
,
250 UnitSetPropertiesMode mode
,
251 sd_bus_error
*error
) {
260 if (streq(name
, "Delegate")) {
263 r
= sd_bus_message_read(message
, "b", &b
);
267 if (mode
!= UNIT_CHECK
) {
269 unit_write_drop_in_private(u
, mode
, name
, b
? "Delegate=yes" : "Delegate=no");
278 int bus_cgroup_set_property(
282 sd_bus_message
*message
,
283 UnitSetPropertiesMode mode
,
284 sd_bus_error
*error
) {
286 CGroupIOLimitType iol_type
;
294 if (streq(name
, "CPUAccounting")) {
297 r
= sd_bus_message_read(message
, "b", &b
);
301 if (mode
!= UNIT_CHECK
) {
302 c
->cpu_accounting
= b
;
303 unit_invalidate_cgroup(u
, CGROUP_MASK_CPUACCT
|CGROUP_MASK_CPU
);
304 unit_write_drop_in_private(u
, mode
, name
, b
? "CPUAccounting=yes" : "CPUAccounting=no");
309 } else if (streq(name
, "CPUWeight")) {
312 r
= sd_bus_message_read(message
, "t", &weight
);
316 if (!CGROUP_WEIGHT_IS_OK(weight
))
317 return sd_bus_error_set_errnof(error
, EINVAL
, "CPUWeight value out of range");
319 if (mode
!= UNIT_CHECK
) {
320 c
->cpu_weight
= weight
;
321 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
323 if (weight
== CGROUP_WEIGHT_INVALID
)
324 unit_write_drop_in_private(u
, mode
, name
, "CPUWeight=");
326 unit_write_drop_in_private_format(u
, mode
, name
, "CPUWeight=%" PRIu64
, weight
);
331 } else if (streq(name
, "StartupCPUWeight")) {
334 r
= sd_bus_message_read(message
, "t", &weight
);
338 if (!CGROUP_WEIGHT_IS_OK(weight
))
339 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupCPUWeight value out of range");
341 if (mode
!= UNIT_CHECK
) {
342 c
->startup_cpu_weight
= weight
;
343 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
345 if (weight
== CGROUP_CPU_SHARES_INVALID
)
346 unit_write_drop_in_private(u
, mode
, name
, "StartupCPUWeight=");
348 unit_write_drop_in_private_format(u
, mode
, name
, "StartupCPUWeight=%" PRIu64
, weight
);
353 } else if (streq(name
, "CPUShares")) {
356 r
= sd_bus_message_read(message
, "t", &shares
);
360 if (!CGROUP_CPU_SHARES_IS_OK(shares
))
361 return sd_bus_error_set_errnof(error
, EINVAL
, "CPUShares value out of range");
363 if (mode
!= UNIT_CHECK
) {
364 c
->cpu_shares
= shares
;
365 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
367 if (shares
== CGROUP_CPU_SHARES_INVALID
)
368 unit_write_drop_in_private(u
, mode
, name
, "CPUShares=");
370 unit_write_drop_in_private_format(u
, mode
, name
, "CPUShares=%" PRIu64
, shares
);
375 } else if (streq(name
, "StartupCPUShares")) {
378 r
= sd_bus_message_read(message
, "t", &shares
);
382 if (!CGROUP_CPU_SHARES_IS_OK(shares
))
383 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupCPUShares value out of range");
385 if (mode
!= UNIT_CHECK
) {
386 c
->startup_cpu_shares
= shares
;
387 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
389 if (shares
== CGROUP_CPU_SHARES_INVALID
)
390 unit_write_drop_in_private(u
, mode
, name
, "StartupCPUShares=");
392 unit_write_drop_in_private_format(u
, mode
, name
, "StartupCPUShares=%" PRIu64
, shares
);
397 } else if (streq(name
, "CPUQuotaPerSecUSec")) {
400 r
= sd_bus_message_read(message
, "t", &u64
);
405 return sd_bus_error_set_errnof(error
, EINVAL
, "CPUQuotaPerSecUSec value out of range");
407 if (mode
!= UNIT_CHECK
) {
408 c
->cpu_quota_per_sec_usec
= u64
;
409 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
410 if (c
->cpu_quota_per_sec_usec
== USEC_INFINITY
)
411 unit_write_drop_in_private_format(u
, mode
, "CPUQuota",
414 /* config_parse_cpu_quota() requires an integer, so
415 * truncating division is used on purpose here. */
416 unit_write_drop_in_private_format(u
, mode
, "CPUQuota",
418 (double) (c
->cpu_quota_per_sec_usec
/ 10000));
423 } else if (streq(name
, "IOAccounting")) {
426 r
= sd_bus_message_read(message
, "b", &b
);
430 if (mode
!= UNIT_CHECK
) {
431 c
->io_accounting
= b
;
432 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
433 unit_write_drop_in_private(u
, mode
, name
, b
? "IOAccounting=yes" : "IOAccounting=no");
438 } else if (streq(name
, "IOWeight")) {
441 r
= sd_bus_message_read(message
, "t", &weight
);
445 if (!CGROUP_WEIGHT_IS_OK(weight
))
446 return sd_bus_error_set_errnof(error
, EINVAL
, "IOWeight value out of range");
448 if (mode
!= UNIT_CHECK
) {
449 c
->io_weight
= weight
;
450 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
452 if (weight
== CGROUP_WEIGHT_INVALID
)
453 unit_write_drop_in_private(u
, mode
, name
, "IOWeight=");
455 unit_write_drop_in_private_format(u
, mode
, name
, "IOWeight=%" PRIu64
, weight
);
460 } else if (streq(name
, "StartupIOWeight")) {
463 r
= sd_bus_message_read(message
, "t", &weight
);
467 if (CGROUP_WEIGHT_IS_OK(weight
))
468 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupIOWeight value out of range");
470 if (mode
!= UNIT_CHECK
) {
471 c
->startup_io_weight
= weight
;
472 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
474 if (weight
== CGROUP_WEIGHT_INVALID
)
475 unit_write_drop_in_private(u
, mode
, name
, "StartupIOWeight=");
477 unit_write_drop_in_private_format(u
, mode
, name
, "StartupIOWeight=%" PRIu64
, weight
);
482 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
487 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
491 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
493 if (mode
!= UNIT_CHECK
) {
494 CGroupIODeviceLimit
*a
= NULL
, *b
;
496 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
) {
497 if (path_equal(path
, b
->path
)) {
504 CGroupIOLimitType type
;
506 a
= new0(CGroupIODeviceLimit
, 1);
510 a
->path
= strdup(path
);
516 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
517 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
519 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
522 a
->limits
[iol_type
] = u64
;
530 r
= sd_bus_message_exit_container(message
);
534 if (mode
!= UNIT_CHECK
) {
535 CGroupIODeviceLimit
*a
;
536 _cleanup_free_
char *buf
= NULL
;
537 _cleanup_fclose_
FILE *f
= NULL
;
541 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
542 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
545 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
547 f
= open_memstream(&buf
, &size
);
551 fprintf(f
, "%s=\n", name
);
552 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
553 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
554 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
556 r
= fflush_and_check(f
);
559 unit_write_drop_in_private(u
, mode
, name
, buf
);
564 } else if (streq(name
, "IODeviceWeight")) {
569 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
573 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
575 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
576 return sd_bus_error_set_errnof(error
, EINVAL
, "IODeviceWeight out of range");
578 if (mode
!= UNIT_CHECK
) {
579 CGroupIODeviceWeight
*a
= NULL
, *b
;
581 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
) {
582 if (path_equal(b
->path
, path
)) {
589 a
= new0(CGroupIODeviceWeight
, 1);
593 a
->path
= strdup(path
);
598 LIST_PREPEND(device_weights
,c
->io_device_weights
, a
);
607 r
= sd_bus_message_exit_container(message
);
611 if (mode
!= UNIT_CHECK
) {
612 _cleanup_free_
char *buf
= NULL
;
613 _cleanup_fclose_
FILE *f
= NULL
;
614 CGroupIODeviceWeight
*a
;
618 while (c
->io_device_weights
)
619 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
622 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
624 f
= open_memstream(&buf
, &size
);
628 fputs("IODeviceWeight=\n", f
);
629 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
630 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
632 r
= fflush_and_check(f
);
635 unit_write_drop_in_private(u
, mode
, name
, buf
);
640 } else if (streq(name
, "BlockIOAccounting")) {
643 r
= sd_bus_message_read(message
, "b", &b
);
647 if (mode
!= UNIT_CHECK
) {
648 c
->blockio_accounting
= b
;
649 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
650 unit_write_drop_in_private(u
, mode
, name
, b
? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
655 } else if (streq(name
, "BlockIOWeight")) {
658 r
= sd_bus_message_read(message
, "t", &weight
);
662 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
))
663 return sd_bus_error_set_errnof(error
, EINVAL
, "BlockIOWeight value out of range");
665 if (mode
!= UNIT_CHECK
) {
666 c
->blockio_weight
= weight
;
667 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
669 if (weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
670 unit_write_drop_in_private(u
, mode
, name
, "BlockIOWeight=");
672 unit_write_drop_in_private_format(u
, mode
, name
, "BlockIOWeight=%" PRIu64
, weight
);
677 } else if (streq(name
, "StartupBlockIOWeight")) {
680 r
= sd_bus_message_read(message
, "t", &weight
);
684 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
))
685 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupBlockIOWeight value out of range");
687 if (mode
!= UNIT_CHECK
) {
688 c
->startup_blockio_weight
= weight
;
689 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
691 if (weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
692 unit_write_drop_in_private(u
, mode
, name
, "StartupBlockIOWeight=");
694 unit_write_drop_in_private_format(u
, mode
, name
, "StartupBlockIOWeight=%" PRIu64
, weight
);
699 } else if (STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
705 if (streq(name
, "BlockIOWriteBandwidth"))
708 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
712 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
714 if (mode
!= UNIT_CHECK
) {
715 CGroupBlockIODeviceBandwidth
*a
= NULL
, *b
;
717 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
718 if (path_equal(path
, b
->path
)) {
725 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
729 a
->rbps
= CGROUP_LIMIT_MAX
;
730 a
->wbps
= CGROUP_LIMIT_MAX
;
731 a
->path
= strdup(path
);
737 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
751 r
= sd_bus_message_exit_container(message
);
755 if (mode
!= UNIT_CHECK
) {
756 CGroupBlockIODeviceBandwidth
*a
;
757 _cleanup_free_
char *buf
= NULL
;
758 _cleanup_fclose_
FILE *f
= NULL
;
762 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
764 a
->rbps
= CGROUP_LIMIT_MAX
;
766 a
->wbps
= CGROUP_LIMIT_MAX
;
770 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
772 f
= open_memstream(&buf
, &size
);
777 fputs("BlockIOReadBandwidth=\n", f
);
778 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
779 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
780 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
782 fputs("BlockIOWriteBandwidth=\n", f
);
783 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
784 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
785 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
788 r
= fflush_and_check(f
);
791 unit_write_drop_in_private(u
, mode
, name
, buf
);
796 } else if (streq(name
, "BlockIODeviceWeight")) {
801 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
805 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
807 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
808 return sd_bus_error_set_errnof(error
, EINVAL
, "BlockIODeviceWeight out of range");
810 if (mode
!= UNIT_CHECK
) {
811 CGroupBlockIODeviceWeight
*a
= NULL
, *b
;
813 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
) {
814 if (path_equal(b
->path
, path
)) {
821 a
= new0(CGroupBlockIODeviceWeight
, 1);
825 a
->path
= strdup(path
);
830 LIST_PREPEND(device_weights
,c
->blockio_device_weights
, a
);
839 r
= sd_bus_message_exit_container(message
);
843 if (mode
!= UNIT_CHECK
) {
844 _cleanup_free_
char *buf
= NULL
;
845 _cleanup_fclose_
FILE *f
= NULL
;
846 CGroupBlockIODeviceWeight
*a
;
850 while (c
->blockio_device_weights
)
851 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
854 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
856 f
= open_memstream(&buf
, &size
);
860 fputs("BlockIODeviceWeight=\n", f
);
861 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
862 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
864 r
= fflush_and_check(f
);
867 unit_write_drop_in_private(u
, mode
, name
, buf
);
872 } else if (streq(name
, "MemoryAccounting")) {
875 r
= sd_bus_message_read(message
, "b", &b
);
879 if (mode
!= UNIT_CHECK
) {
880 c
->memory_accounting
= b
;
881 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
882 unit_write_drop_in_private(u
, mode
, name
, b
? "MemoryAccounting=yes" : "MemoryAccounting=no");
887 } else if (STR_IN_SET(name
, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax")) {
890 r
= sd_bus_message_read(message
, "t", &v
);
894 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is too small", name
);
896 if (mode
!= UNIT_CHECK
) {
897 if (streq(name
, "MemoryLow"))
899 else if (streq(name
, "MemoryHigh"))
901 else if (streq(name
, "MemorySwapMax"))
902 c
->memory_swap_max
= v
;
906 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
908 if (v
== CGROUP_LIMIT_MAX
)
909 unit_write_drop_in_private_format(u
, mode
, name
, "%s=infinity", name
);
911 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%" PRIu64
, name
, v
);
916 } else if (STR_IN_SET(name
, "MemoryLowScale", "MemoryHighScale", "MemoryMaxScale")) {
920 r
= sd_bus_message_read(message
, "u", &raw
);
924 v
= physical_memory_scale(raw
, UINT32_MAX
);
925 if (v
<= 0 || v
== UINT64_MAX
)
926 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is out of range", name
);
928 if (mode
!= UNIT_CHECK
) {
931 /* Chop off suffix */
932 assert_se(e
= endswith(name
, "Scale"));
933 name
= strndupa(name
, e
- name
);
935 if (streq(name
, "MemoryLow"))
937 else if (streq(name
, "MemoryHigh"))
942 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
943 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%" PRIu32
"%%", name
,
944 (uint32_t) (DIV_ROUND_UP((uint64_t) raw
* 100U, (uint64_t) UINT32_MAX
)));
949 } else if (streq(name
, "MemoryLimit")) {
952 r
= sd_bus_message_read(message
, "t", &limit
);
956 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is too small", name
);
958 if (mode
!= UNIT_CHECK
) {
959 c
->memory_limit
= limit
;
960 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
962 if (limit
== (uint64_t) -1)
963 unit_write_drop_in_private(u
, mode
, name
, "MemoryLimit=infinity");
965 unit_write_drop_in_private_format(u
, mode
, name
, "MemoryLimit=%" PRIu64
, limit
);
970 } else if (streq(name
, "MemoryLimitScale")) {
974 r
= sd_bus_message_read(message
, "u", &raw
);
978 limit
= physical_memory_scale(raw
, UINT32_MAX
);
979 if (limit
<= 0 || limit
== UINT64_MAX
)
980 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is out of range", name
);
982 if (mode
!= UNIT_CHECK
) {
983 c
->memory_limit
= limit
;
984 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
985 unit_write_drop_in_private_format(u
, mode
, "MemoryLimit", "MemoryLimit=%" PRIu32
"%%",
986 (uint32_t) (DIV_ROUND_UP((uint64_t) raw
* 100U, (uint64_t) UINT32_MAX
)));
991 } else if (streq(name
, "DevicePolicy")) {
993 CGroupDevicePolicy p
;
995 r
= sd_bus_message_read(message
, "s", &policy
);
999 p
= cgroup_device_policy_from_string(policy
);
1003 if (mode
!= UNIT_CHECK
) {
1004 c
->device_policy
= p
;
1005 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1006 unit_write_drop_in_private_format(u
, mode
, name
, "DevicePolicy=%s", policy
);
1011 } else if (streq(name
, "DeviceAllow")) {
1012 const char *path
, *rwm
;
1015 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
1019 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
1021 if ((!startswith(path
, "/dev/") &&
1022 !startswith(path
, "/run/systemd/inaccessible/") &&
1023 !startswith(path
, "block-") &&
1024 !startswith(path
, "char-")) ||
1025 strpbrk(path
, WHITESPACE
))
1026 return sd_bus_error_set_errnof(error
, EINVAL
, "DeviceAllow= requires device node");
1031 if (!in_charset(rwm
, "rwm"))
1032 return sd_bus_error_set_errnof(error
, EINVAL
, "DeviceAllow= requires combination of rwm flags");
1034 if (mode
!= UNIT_CHECK
) {
1035 CGroupDeviceAllow
*a
= NULL
, *b
;
1037 LIST_FOREACH(device_allow
, b
, c
->device_allow
) {
1038 if (path_equal(b
->path
, path
)) {
1045 a
= new0(CGroupDeviceAllow
, 1);
1049 a
->path
= strdup(path
);
1055 LIST_PREPEND(device_allow
, c
->device_allow
, a
);
1058 a
->r
= !!strchr(rwm
, 'r');
1059 a
->w
= !!strchr(rwm
, 'w');
1060 a
->m
= !!strchr(rwm
, 'm');
1068 r
= sd_bus_message_exit_container(message
);
1072 if (mode
!= UNIT_CHECK
) {
1073 _cleanup_free_
char *buf
= NULL
;
1074 _cleanup_fclose_
FILE *f
= NULL
;
1075 CGroupDeviceAllow
*a
;
1079 while (c
->device_allow
)
1080 cgroup_context_free_device_allow(c
, c
->device_allow
);
1083 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1085 f
= open_memstream(&buf
, &size
);
1089 fputs("DeviceAllow=\n", f
);
1090 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
1091 fprintf(f
, "DeviceAllow=%s %s%s%s\n", a
->path
, a
->r
? "r" : "", a
->w
? "w" : "", a
->m
? "m" : "");
1093 r
= fflush_and_check(f
);
1096 unit_write_drop_in_private(u
, mode
, name
, buf
);
1101 } else if (streq(name
, "TasksAccounting")) {
1104 r
= sd_bus_message_read(message
, "b", &b
);
1108 if (mode
!= UNIT_CHECK
) {
1109 c
->tasks_accounting
= b
;
1110 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1111 unit_write_drop_in_private(u
, mode
, name
, b
? "TasksAccounting=yes" : "TasksAccounting=no");
1116 } else if (streq(name
, "TasksMax")) {
1119 r
= sd_bus_message_read(message
, "t", &limit
);
1123 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is too small", name
);
1125 if (mode
!= UNIT_CHECK
) {
1126 c
->tasks_max
= limit
;
1127 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1129 if (limit
== (uint64_t) -1)
1130 unit_write_drop_in_private(u
, mode
, name
, "TasksMax=infinity");
1132 unit_write_drop_in_private_format(u
, mode
, name
, "TasksMax=%" PRIu64
, limit
);
1136 } else if (streq(name
, "TasksMaxScale")) {
1140 r
= sd_bus_message_read(message
, "u", &raw
);
1144 limit
= system_tasks_max_scale(raw
, UINT32_MAX
);
1145 if (limit
<= 0 || limit
>= UINT64_MAX
)
1146 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is out of range", name
);
1148 if (mode
!= UNIT_CHECK
) {
1149 c
->tasks_max
= limit
;
1150 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1151 unit_write_drop_in_private_format(u
, mode
, name
, "TasksMax=%" PRIu32
"%%",
1152 (uint32_t) (DIV_ROUND_UP((uint64_t) raw
* 100U, (uint64_t) UINT32_MAX
)));
1158 if (u
->transient
&& u
->load_state
== UNIT_STUB
) {
1159 r
= bus_cgroup_set_transient_property(u
, c
, name
, message
, mode
, error
);