1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "alloc-util.h"
7 #include "bpf-firewall.h"
8 #include "bpf-foreign.h"
9 #include "bus-get-properties.h"
10 #include "cgroup-util.h"
12 #include "core-varlink.h"
13 #include "dbus-cgroup.h"
14 #include "dbus-util.h"
15 #include "errno-util.h"
18 #include "limits-util.h"
19 #include "path-util.h"
20 #include "percent-util.h"
22 BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max
, "t", TasksMax
, tasks_max_resolve
);
24 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy
, cgroup_device_policy
, CGroupDevicePolicy
);
25 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_mode
, managed_oom_mode
, ManagedOOMMode
);
26 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_preference
, managed_oom_preference
, ManagedOOMPreference
);
28 static int property_get_cgroup_mask(
31 const char *interface
,
33 sd_bus_message
*reply
,
35 sd_bus_error
*error
) {
37 CGroupMask
*mask
= userdata
;
43 r
= sd_bus_message_open_container(reply
, 'a', "s");
47 for (CGroupController ctrl
= 0; ctrl
< _CGROUP_CONTROLLER_MAX
; ctrl
++) {
48 if ((*mask
& CGROUP_CONTROLLER_TO_MASK(ctrl
)) == 0)
51 r
= sd_bus_message_append(reply
, "s", cgroup_controller_to_string(ctrl
));
56 return sd_bus_message_close_container(reply
);
59 static int property_get_delegate_controllers(
62 const char *interface
,
64 sd_bus_message
*reply
,
66 sd_bus_error
*error
) {
68 CGroupContext
*c
= userdata
;
75 return sd_bus_message_append(reply
, "as", 0);
77 return property_get_cgroup_mask(bus
, path
, interface
, property
, reply
, &c
->delegate_controllers
, error
);
80 static int property_get_cpuset(
83 const char *interface
,
85 sd_bus_message
*reply
,
87 sd_bus_error
*error
) {
89 CPUSet
*cpus
= userdata
;
90 _cleanup_free_
uint8_t *array
= NULL
;
97 (void) cpu_set_to_dbus(cpus
, &array
, &allocated
);
98 return sd_bus_message_append_array(reply
, 'y', array
, allocated
);
101 static int property_get_io_device_weight(
104 const char *interface
,
105 const char *property
,
106 sd_bus_message
*reply
,
108 sd_bus_error
*error
) {
110 CGroupContext
*c
= userdata
;
111 CGroupIODeviceWeight
*w
;
118 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
122 LIST_FOREACH(device_weights
, w
, c
->io_device_weights
) {
123 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
128 return sd_bus_message_close_container(reply
);
131 static int property_get_io_device_limits(
134 const char *interface
,
135 const char *property
,
136 sd_bus_message
*reply
,
138 sd_bus_error
*error
) {
140 CGroupContext
*c
= userdata
;
141 CGroupIODeviceLimit
*l
;
148 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
152 LIST_FOREACH(device_limits
, l
, c
->io_device_limits
) {
153 CGroupIOLimitType type
;
155 type
= cgroup_io_limit_type_from_string(property
);
156 if (type
< 0 || l
->limits
[type
] == cgroup_io_limit_defaults
[type
])
159 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->limits
[type
]);
164 return sd_bus_message_close_container(reply
);
167 static int property_get_io_device_latency(
170 const char *interface
,
171 const char *property
,
172 sd_bus_message
*reply
,
174 sd_bus_error
*error
) {
176 CGroupContext
*c
= userdata
;
177 CGroupIODeviceLatency
*l
;
184 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
188 LIST_FOREACH(device_latencies
, l
, c
->io_device_latencies
) {
189 r
= sd_bus_message_append(reply
, "(st)", l
->path
, l
->target_usec
);
194 return sd_bus_message_close_container(reply
);
197 static int property_get_blockio_device_weight(
200 const char *interface
,
201 const char *property
,
202 sd_bus_message
*reply
,
204 sd_bus_error
*error
) {
206 CGroupContext
*c
= userdata
;
207 CGroupBlockIODeviceWeight
*w
;
214 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
218 LIST_FOREACH(device_weights
, w
, c
->blockio_device_weights
) {
219 r
= sd_bus_message_append(reply
, "(st)", w
->path
, w
->weight
);
224 return sd_bus_message_close_container(reply
);
227 static int property_get_blockio_device_bandwidths(
230 const char *interface
,
231 const char *property
,
232 sd_bus_message
*reply
,
234 sd_bus_error
*error
) {
236 CGroupContext
*c
= userdata
;
237 CGroupBlockIODeviceBandwidth
*b
;
244 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
248 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
251 if (streq(property
, "BlockIOReadBandwidth"))
256 if (v
== CGROUP_LIMIT_MAX
)
259 r
= sd_bus_message_append(reply
, "(st)", b
->path
, v
);
264 return sd_bus_message_close_container(reply
);
267 static int property_get_device_allow(
270 const char *interface
,
271 const char *property
,
272 sd_bus_message
*reply
,
274 sd_bus_error
*error
) {
276 CGroupContext
*c
= userdata
;
277 CGroupDeviceAllow
*a
;
284 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
288 LIST_FOREACH(device_allow
, a
, c
->device_allow
) {
301 r
= sd_bus_message_append(reply
, "(ss)", a
->path
, rwm
);
306 return sd_bus_message_close_container(reply
);
309 static int property_get_ip_address_access(
312 const char *interface
,
313 const char *property
,
314 sd_bus_message
*reply
,
316 sd_bus_error
*error
) {
318 IPAddressAccessItem
** items
= userdata
, *i
;
321 r
= sd_bus_message_open_container(reply
, 'a', "(iayu)");
325 LIST_FOREACH(items
, i
, *items
) {
327 r
= sd_bus_message_open_container(reply
, 'r', "iayu");
331 r
= sd_bus_message_append(reply
, "i", i
->family
);
335 r
= sd_bus_message_append_array(reply
, 'y', &i
->address
, FAMILY_ADDRESS_SIZE(i
->family
));
339 r
= sd_bus_message_append(reply
, "u", (uint32_t) i
->prefixlen
);
343 r
= sd_bus_message_close_container(reply
);
348 return sd_bus_message_close_container(reply
);
351 static int property_get_bpf_foreign_program(
354 const char *interface
,
355 const char *property
,
356 sd_bus_message
*reply
,
358 sd_bus_error
*error
) {
359 CGroupContext
*c
= userdata
;
360 CGroupBPFForeignProgram
*p
;
363 r
= sd_bus_message_open_container(reply
, 'a', "(ss)");
367 LIST_FOREACH(programs
, p
, c
->bpf_foreign_programs
) {
368 const char *attach_type
= bpf_cgroup_attach_type_to_string(p
->attach_type
);
370 r
= sd_bus_message_append(reply
, "(ss)", attach_type
, p
->bpffs_path
);
375 return sd_bus_message_close_container(reply
);
378 const sd_bus_vtable bus_cgroup_vtable
[] = {
379 SD_BUS_VTABLE_START(0),
380 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool
, offsetof(CGroupContext
, delegate
), 0),
381 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers
, 0, 0),
382 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, cpu_accounting
), 0),
383 SD_BUS_PROPERTY("CPUWeight", "t", NULL
, offsetof(CGroupContext
, cpu_weight
), 0),
384 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL
, offsetof(CGroupContext
, startup_cpu_weight
), 0),
385 SD_BUS_PROPERTY("CPUShares", "t", NULL
, offsetof(CGroupContext
, cpu_shares
), 0),
386 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL
, offsetof(CGroupContext
, startup_cpu_shares
), 0),
387 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_per_sec_usec
), 0),
388 SD_BUS_PROPERTY("CPUQuotaPeriodUSec", "t", bus_property_get_usec
, offsetof(CGroupContext
, cpu_quota_period_usec
), 0),
389 SD_BUS_PROPERTY("AllowedCPUs", "ay", property_get_cpuset
, offsetof(CGroupContext
, cpuset_cpus
), 0),
390 SD_BUS_PROPERTY("AllowedMemoryNodes", "ay", property_get_cpuset
, offsetof(CGroupContext
, cpuset_mems
), 0),
391 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, io_accounting
), 0),
392 SD_BUS_PROPERTY("IOWeight", "t", NULL
, offsetof(CGroupContext
, io_weight
), 0),
393 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_io_weight
), 0),
394 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight
, 0, 0),
395 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
396 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits
, 0, 0),
397 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
398 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits
, 0, 0),
399 SD_BUS_PROPERTY("IODeviceLatencyTargetUSec", "a(st)", property_get_io_device_latency
, 0, 0),
400 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, blockio_accounting
), 0),
401 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL
, offsetof(CGroupContext
, blockio_weight
), 0),
402 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL
, offsetof(CGroupContext
, startup_blockio_weight
), 0),
403 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight
, 0, 0),
404 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
405 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths
, 0, 0),
406 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, memory_accounting
), 0),
407 SD_BUS_PROPERTY("DefaultMemoryLow", "t", NULL
, offsetof(CGroupContext
, default_memory_low
), 0),
408 SD_BUS_PROPERTY("DefaultMemoryMin", "t", NULL
, offsetof(CGroupContext
, default_memory_min
), 0),
409 SD_BUS_PROPERTY("MemoryMin", "t", NULL
, offsetof(CGroupContext
, memory_min
), 0),
410 SD_BUS_PROPERTY("MemoryLow", "t", NULL
, offsetof(CGroupContext
, memory_low
), 0),
411 SD_BUS_PROPERTY("MemoryHigh", "t", NULL
, offsetof(CGroupContext
, memory_high
), 0),
412 SD_BUS_PROPERTY("MemoryMax", "t", NULL
, offsetof(CGroupContext
, memory_max
), 0),
413 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL
, offsetof(CGroupContext
, memory_swap_max
), 0),
414 SD_BUS_PROPERTY("MemoryLimit", "t", NULL
, offsetof(CGroupContext
, memory_limit
), 0),
415 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
416 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
417 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
418 SD_BUS_PROPERTY("TasksMax", "t", bus_property_get_tasks_max
, offsetof(CGroupContext
, tasks_max
), 0),
419 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, ip_accounting
), 0),
420 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_allow
), 0),
421 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access
, offsetof(CGroupContext
, ip_address_deny
), 0),
422 SD_BUS_PROPERTY("IPIngressFilterPath", "as", NULL
, offsetof(CGroupContext
, ip_filters_ingress
), 0),
423 SD_BUS_PROPERTY("IPEgressFilterPath", "as", NULL
, offsetof(CGroupContext
, ip_filters_egress
), 0),
424 SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask
, offsetof(CGroupContext
, disable_controllers
), 0),
425 SD_BUS_PROPERTY("ManagedOOMSwap", "s", property_get_managed_oom_mode
, offsetof(CGroupContext
, moom_swap
), 0),
426 SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode
, offsetof(CGroupContext
, moom_mem_pressure
), 0),
427 SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimit", "u", NULL
, offsetof(CGroupContext
, moom_mem_pressure_limit
), 0),
428 SD_BUS_PROPERTY("ManagedOOMPreference", "s", property_get_managed_oom_preference
, offsetof(CGroupContext
, moom_preference
), 0),
429 SD_BUS_PROPERTY("BPFProgram", "a(ss)", property_get_bpf_foreign_program
, 0, 0),
433 static int bus_cgroup_set_transient_property(
437 sd_bus_message
*message
,
438 UnitWriteFlags flags
,
439 sd_bus_error
*error
) {
448 flags
|= UNIT_PRIVATE
;
450 if (streq(name
, "Delegate")) {
453 if (!UNIT_VTABLE(u
)->can_delegate
)
454 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
456 r
= sd_bus_message_read(message
, "b", &b
);
460 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
462 c
->delegate_controllers
= b
? _CGROUP_MASK_ALL
: 0;
464 unit_write_settingf(u
, flags
, name
, "Delegate=%s", yes_no(b
));
469 } else if (STR_IN_SET(name
, "DelegateControllers", "DisableControllers")) {
472 if (streq(name
, "DelegateControllers") && !UNIT_VTABLE(u
)->can_delegate
)
473 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "Delegation not available for unit type");
475 r
= sd_bus_message_enter_container(message
, 'a', "s");
483 r
= sd_bus_message_read(message
, "s", &t
);
489 cc
= cgroup_controller_from_string(t
);
491 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown cgroup controller '%s'", t
);
493 mask
|= CGROUP_CONTROLLER_TO_MASK(cc
);
496 r
= sd_bus_message_exit_container(message
);
500 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
501 _cleanup_free_
char *t
= NULL
;
503 r
= cg_mask_to_string(mask
, &t
);
507 if (streq(name
, "DelegateControllers")) {
511 c
->delegate_controllers
= 0;
513 c
->delegate_controllers
|= mask
;
515 unit_write_settingf(u
, flags
, name
, "Delegate=%s", strempty(t
));
517 } else if (streq(name
, "DisableControllers")) {
520 c
->disable_controllers
= 0;
522 c
->disable_controllers
|= mask
;
524 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, strempty(t
));
529 } else if (STR_IN_SET(name
, "IPIngressFilterPath", "IPEgressFilterPath")) {
533 filters
= streq(name
, "IPIngressFilterPath") ? &c
->ip_filters_ingress
: &c
->ip_filters_egress
;
534 r
= sd_bus_message_enter_container(message
, 'a', "s");
541 r
= sd_bus_message_read(message
, "s", &path
);
547 if (!path_is_normalized(path
) || !path_is_absolute(path
))
548 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects a normalized absolute path.", name
);
550 if (!UNIT_WRITE_FLAGS_NOOP(flags
) && !strv_contains(*filters
, path
)) {
551 r
= strv_extend(filters
, path
);
557 r
= sd_bus_message_exit_container(message
);
561 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
562 _cleanup_free_
char *buf
= NULL
;
563 _cleanup_fclose_
FILE *f
= NULL
;
568 *filters
= strv_free(*filters
);
570 unit_invalidate_cgroup_bpf(u
);
571 f
= open_memstream_unlocked(&buf
, &size
);
578 STRV_FOREACH(entry
, *filters
)
579 fprintf(f
, "%s=%s\n", name
, *entry
);
581 r
= fflush_and_check(f
);
585 unit_write_setting(u
, flags
, name
, buf
);
588 r
= bpf_firewall_supported();
591 if (r
!= BPF_FIREWALL_SUPPORTED_WITH_MULTI
) {
592 static bool warned
= false;
594 log_full(warned
? LOG_DEBUG
: LOG_WARNING
,
595 "Transient unit %s configures an IP firewall with BPF, but the local system does not support BPF/cgroup firewalling with multiple filters.\n"
596 "Starting this unit will fail! (This warning is only shown for the first started transient unit using IP firewalling.)", u
->id
);
603 } else if (streq(name
, "BPFProgram")) {
607 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
611 while ((r
= sd_bus_message_read(message
, "(ss)", &a
, &p
)) > 0) {
612 int attach_type
= bpf_cgroup_attach_type_from_string(a
);
614 return sd_bus_error_setf(
616 SD_BUS_ERROR_INVALID_ARGS
,
617 "%s expects a valid BPF attach type, got '%s'.",
620 if (!path_is_normalized(p
) || !path_is_absolute(p
))
621 return sd_bus_error_setf(
623 SD_BUS_ERROR_INVALID_ARGS
,
624 "%s= expects a normalized absolute path.",
627 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
628 r
= cgroup_add_bpf_foreign_program(c
, attach_type
, p
);
637 r
= sd_bus_message_exit_container(message
);
641 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
642 _cleanup_free_
char *buf
= NULL
;
643 _cleanup_fclose_
FILE *f
= NULL
;
644 CGroupBPFForeignProgram
*fp
;
648 while (c
->bpf_foreign_programs
)
649 cgroup_context_remove_bpf_foreign_program(c
, c
->bpf_foreign_programs
);
651 f
= open_memstream_unlocked(&buf
, &size
);
658 LIST_FOREACH(programs
, fp
, c
->bpf_foreign_programs
)
659 fprintf(f
, "%s=%s:%s\n", name
,
660 bpf_cgroup_attach_type_to_string(fp
->attach_type
),
663 r
= fflush_and_check(f
);
667 unit_write_setting(u
, flags
, name
, buf
);
669 if (!LIST_IS_EMPTY(c
->bpf_foreign_programs
)) {
670 r
= bpf_foreign_supported();
675 "Transient unit %s configures a BPF program pinned to BPF "
676 "filesystem, but the local system does not support that.\n"
677 "Starting this unit will fail!", u
->id
);
687 static int bus_cgroup_set_boolean(
692 sd_bus_message
*message
,
693 UnitWriteFlags flags
,
694 sd_bus_error
*error
) {
700 r
= sd_bus_message_read(message
, "b", &b
);
704 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
706 unit_invalidate_cgroup(u
, mask
);
707 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, yes_no(b
));
713 #define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \
714 static int bus_cgroup_set_##function( \
718 sd_bus_message *message, \
719 UnitWriteFlags flags, \
720 sd_bus_error *error) { \
727 r = sd_bus_message_read(message, "t", &v); \
732 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
733 "Value specified in %s is out of range", name); \
735 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
737 unit_invalidate_cgroup(u, mask); \
740 unit_write_settingf(u, flags, name, \
743 unit_write_settingf(u, flags, name, \
744 "%s=%" PRIu64, name, v); \
750 #define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \
751 static int bus_cgroup_set_##function( \
755 sd_bus_message *message, \
756 UnitWriteFlags flags, \
757 sd_bus_error *error) { \
764 r = sd_bus_message_read(message, "t", &v); \
769 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
770 "Value specified in %s is out of range", name); \
772 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
774 unit_invalidate_cgroup(u, mask); \
776 if (v == CGROUP_LIMIT_MAX) \
777 unit_write_settingf(u, flags, name, \
778 "%s=infinity", name); \
780 unit_write_settingf(u, flags, name, \
781 "%s=%" PRIu64, name, v); \
786 static int bus_cgroup_set_##function##_scale( \
790 sd_bus_message *message, \
791 UnitWriteFlags flags, \
792 sd_bus_error *error) { \
800 r = sd_bus_message_read(message, "u", &raw); \
804 v = scale(raw, UINT32_MAX); \
805 if (v < minimum || v >= UINT64_MAX) \
806 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
807 "Value specified in %s is out of range", name); \
809 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
811 unit_invalidate_cgroup(u, mask); \
813 /* Prepare to chop off suffix */ \
814 assert_se(endswith(name, "Scale")); \
816 int scaled = UINT32_SCALE_TO_PERMYRIAD(raw); \
817 unit_write_settingf(u, flags, name, "%.*s=" PERMYRIAD_AS_PERCENT_FORMAT_STR, \
818 (int)(strlen(name) - strlen("Scale")), name, \
819 PERMYRIAD_AS_PERCENT_FORMAT_VAL(scaled)); \
825 DISABLE_WARNING_TYPE_LIMITS
;
826 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight
, CGROUP_MASK_CPU
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
827 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares
, CGROUP_MASK_CPU
, CGROUP_CPU_SHARES_IS_OK
, CGROUP_CPU_SHARES_INVALID
);
828 BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight
, CGROUP_MASK_IO
, CGROUP_WEIGHT_IS_OK
, CGROUP_WEIGHT_INVALID
);
829 BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight
, CGROUP_MASK_BLKIO
, CGROUP_BLKIO_WEIGHT_IS_OK
, CGROUP_BLKIO_WEIGHT_INVALID
);
830 BUS_DEFINE_SET_CGROUP_LIMIT(memory
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 1);
831 BUS_DEFINE_SET_CGROUP_LIMIT(memory_protection
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
832 BUS_DEFINE_SET_CGROUP_LIMIT(swap
, CGROUP_MASK_MEMORY
, physical_memory_scale
, 0);
835 static int bus_cgroup_set_tasks_max(
839 sd_bus_message
*message
,
840 UnitWriteFlags flags
,
841 sd_bus_error
*error
) {
848 r
= sd_bus_message_read(message
, "t", &v
);
853 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
854 "Value specified in %s is out of range", name
);
856 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
857 *p
= (TasksMax
) { .value
= v
, .scale
= 0 }; /* When .scale==0, .value is the absolute value */
858 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
860 if (v
== CGROUP_LIMIT_MAX
)
861 unit_write_settingf(u
, flags
, name
,
862 "%s=infinity", name
);
864 unit_write_settingf(u
, flags
, name
,
865 "%s=%" PRIu64
, name
, v
);
871 static int bus_cgroup_set_tasks_max_scale(
875 sd_bus_message
*message
,
876 UnitWriteFlags flags
,
877 sd_bus_error
*error
) {
884 r
= sd_bus_message_read(message
, "u", &v
);
888 if (v
< 1 || v
>= UINT32_MAX
)
889 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
,
890 "Value specified in %s is out of range", name
);
892 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
893 *p
= (TasksMax
) { v
, UINT32_MAX
}; /* .scale is not 0, so this is interpreted as v/UINT32_MAX. */
894 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
896 uint32_t scaled
= DIV_ROUND_UP((uint64_t) v
* 100U, (uint64_t) UINT32_MAX
);
897 unit_write_settingf(u
, flags
, name
, "%s=%" PRIu32
".%" PRIu32
"%%", "TasksMax",
898 scaled
/ 10, scaled
% 10);
904 int bus_cgroup_set_property(
908 sd_bus_message
*message
,
909 UnitWriteFlags flags
,
910 sd_bus_error
*error
) {
912 CGroupIOLimitType iol_type
;
920 flags
|= UNIT_PRIVATE
;
922 if (streq(name
, "CPUAccounting"))
923 return bus_cgroup_set_boolean(u
, name
, &c
->cpu_accounting
, get_cpu_accounting_mask(), message
, flags
, error
);
925 if (streq(name
, "CPUWeight"))
926 return bus_cgroup_set_cpu_weight(u
, name
, &c
->cpu_weight
, message
, flags
, error
);
928 if (streq(name
, "StartupCPUWeight"))
929 return bus_cgroup_set_cpu_weight(u
, name
, &c
->startup_cpu_weight
, message
, flags
, error
);
931 if (streq(name
, "CPUShares"))
932 return bus_cgroup_set_cpu_shares(u
, name
, &c
->cpu_shares
, message
, flags
, error
);
934 if (streq(name
, "StartupCPUShares"))
935 return bus_cgroup_set_cpu_shares(u
, name
, &c
->startup_cpu_shares
, message
, flags
, error
);
937 if (streq(name
, "IOAccounting"))
938 return bus_cgroup_set_boolean(u
, name
, &c
->io_accounting
, CGROUP_MASK_IO
, message
, flags
, error
);
940 if (streq(name
, "IOWeight"))
941 return bus_cgroup_set_io_weight(u
, name
, &c
->io_weight
, message
, flags
, error
);
943 if (streq(name
, "StartupIOWeight"))
944 return bus_cgroup_set_io_weight(u
, name
, &c
->startup_io_weight
, message
, flags
, error
);
946 if (streq(name
, "BlockIOAccounting"))
947 return bus_cgroup_set_boolean(u
, name
, &c
->blockio_accounting
, CGROUP_MASK_BLKIO
, message
, flags
, error
);
949 if (streq(name
, "BlockIOWeight"))
950 return bus_cgroup_set_blockio_weight(u
, name
, &c
->blockio_weight
, message
, flags
, error
);
952 if (streq(name
, "StartupBlockIOWeight"))
953 return bus_cgroup_set_blockio_weight(u
, name
, &c
->startup_blockio_weight
, message
, flags
, error
);
955 if (streq(name
, "MemoryAccounting"))
956 return bus_cgroup_set_boolean(u
, name
, &c
->memory_accounting
, CGROUP_MASK_MEMORY
, message
, flags
, error
);
958 if (streq(name
, "MemoryMin")) {
959 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->memory_min
, message
, flags
, error
);
961 c
->memory_min_set
= true;
965 if (streq(name
, "MemoryLow")) {
966 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->memory_low
, message
, flags
, error
);
968 c
->memory_low_set
= true;
972 if (streq(name
, "DefaultMemoryMin")) {
973 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->default_memory_min
, message
, flags
, error
);
975 c
->default_memory_min_set
= true;
979 if (streq(name
, "DefaultMemoryLow")) {
980 r
= bus_cgroup_set_memory_protection(u
, name
, &c
->default_memory_low
, message
, flags
, error
);
982 c
->default_memory_low_set
= true;
986 if (streq(name
, "MemoryHigh"))
987 return bus_cgroup_set_memory(u
, name
, &c
->memory_high
, message
, flags
, error
);
989 if (streq(name
, "MemorySwapMax"))
990 return bus_cgroup_set_swap(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
992 if (streq(name
, "MemoryMax"))
993 return bus_cgroup_set_memory(u
, name
, &c
->memory_max
, message
, flags
, error
);
995 if (streq(name
, "MemoryLimit"))
996 return bus_cgroup_set_memory(u
, name
, &c
->memory_limit
, message
, flags
, error
);
998 if (streq(name
, "MemoryMinScale")) {
999 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->memory_min
, message
, flags
, error
);
1001 c
->memory_min_set
= true;
1005 if (streq(name
, "MemoryLowScale")) {
1006 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->memory_low
, message
, flags
, error
);
1008 c
->memory_low_set
= true;
1012 if (streq(name
, "DefaultMemoryMinScale")) {
1013 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->default_memory_min
, message
, flags
, error
);
1015 c
->default_memory_min_set
= true;
1019 if (streq(name
, "DefaultMemoryLowScale")) {
1020 r
= bus_cgroup_set_memory_protection_scale(u
, name
, &c
->default_memory_low
, message
, flags
, error
);
1022 c
->default_memory_low_set
= true;
1026 if (streq(name
, "MemoryHighScale"))
1027 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_high
, message
, flags
, error
);
1029 if (streq(name
, "MemorySwapMaxScale"))
1030 return bus_cgroup_set_swap_scale(u
, name
, &c
->memory_swap_max
, message
, flags
, error
);
1032 if (streq(name
, "MemoryMaxScale"))
1033 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_max
, message
, flags
, error
);
1035 if (streq(name
, "MemoryLimitScale"))
1036 return bus_cgroup_set_memory_scale(u
, name
, &c
->memory_limit
, message
, flags
, error
);
1038 if (streq(name
, "TasksAccounting"))
1039 return bus_cgroup_set_boolean(u
, name
, &c
->tasks_accounting
, CGROUP_MASK_PIDS
, message
, flags
, error
);
1041 if (streq(name
, "TasksMax"))
1042 return bus_cgroup_set_tasks_max(u
, name
, &c
->tasks_max
, message
, flags
, error
);
1044 if (streq(name
, "TasksMaxScale"))
1045 return bus_cgroup_set_tasks_max_scale(u
, name
, &c
->tasks_max
, message
, flags
, error
);
1047 if (streq(name
, "CPUQuotaPerSecUSec")) {
1050 r
= sd_bus_message_read(message
, "t", &u64
);
1055 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "CPUQuotaPerSecUSec= value out of range");
1057 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1058 c
->cpu_quota_per_sec_usec
= u64
;
1059 u
->warned_clamping_cpu_quota_period
= false;
1060 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
1062 if (c
->cpu_quota_per_sec_usec
== USEC_INFINITY
)
1063 unit_write_setting(u
, flags
, "CPUQuota", "CPUQuota=");
1065 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
1067 unit_write_settingf(u
, flags
, "CPUQuota",
1069 (double) (c
->cpu_quota_per_sec_usec
/ 10000));
1074 } else if (streq(name
, "CPUQuotaPeriodUSec")) {
1077 r
= sd_bus_message_read(message
, "t", &u64
);
1081 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1082 c
->cpu_quota_period_usec
= u64
;
1083 u
->warned_clamping_cpu_quota_period
= false;
1084 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
1085 if (c
->cpu_quota_period_usec
== USEC_INFINITY
)
1086 unit_write_setting(u
, flags
, "CPUQuotaPeriodSec", "CPUQuotaPeriodSec=");
1088 char v
[FORMAT_TIMESPAN_MAX
];
1089 unit_write_settingf(u
, flags
, "CPUQuotaPeriodSec",
1090 "CPUQuotaPeriodSec=%s",
1091 format_timespan(v
, sizeof(v
), c
->cpu_quota_period_usec
, 1));
1097 } else if (STR_IN_SET(name
, "AllowedCPUs", "AllowedMemoryNodes")) {
1100 _cleanup_(cpu_set_reset
) CPUSet new_set
= {};
1102 r
= sd_bus_message_read_array(message
, 'y', &a
, &n
);
1106 r
= cpu_set_from_dbus(a
, n
, &new_set
);
1110 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1111 _cleanup_free_
char *setstr
= NULL
;
1114 setstr
= cpu_set_to_range_string(&new_set
);
1118 if (streq(name
, "AllowedCPUs"))
1119 set
= &c
->cpuset_cpus
;
1121 set
= &c
->cpuset_mems
;
1125 new_set
= (CPUSet
) {};
1127 unit_invalidate_cgroup(u
, CGROUP_MASK_CPUSET
);
1128 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, setstr
);
1133 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
1138 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1142 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
1144 if (!path_is_normalized(path
))
1145 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1147 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1148 CGroupIODeviceLimit
*a
= NULL
, *b
;
1150 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
) {
1151 if (path_equal(path
, b
->path
)) {
1158 CGroupIOLimitType type
;
1160 a
= new0(CGroupIODeviceLimit
, 1);
1164 a
->path
= strdup(path
);
1170 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
1171 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
1173 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
1176 a
->limits
[iol_type
] = u64
;
1184 r
= sd_bus_message_exit_container(message
);
1188 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1189 CGroupIODeviceLimit
*a
;
1190 _cleanup_free_
char *buf
= NULL
;
1191 _cleanup_fclose_
FILE *f
= NULL
;
1195 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
1196 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
1199 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1201 f
= open_memstream_unlocked(&buf
, &size
);
1205 fprintf(f
, "%s=\n", name
);
1206 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
1207 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
1208 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
1210 r
= fflush_and_check(f
);
1213 unit_write_setting(u
, flags
, name
, buf
);
1218 } else if (streq(name
, "IODeviceWeight")) {
1223 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1227 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
1229 if (!path_is_normalized(path
))
1230 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1232 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
1233 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "IODeviceWeight= value out of range");
1235 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1236 CGroupIODeviceWeight
*a
= NULL
, *b
;
1238 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
) {
1239 if (path_equal(b
->path
, path
)) {
1246 a
= new0(CGroupIODeviceWeight
, 1);
1250 a
->path
= strdup(path
);
1255 LIST_PREPEND(device_weights
, c
->io_device_weights
, a
);
1264 r
= sd_bus_message_exit_container(message
);
1268 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1269 _cleanup_free_
char *buf
= NULL
;
1270 _cleanup_fclose_
FILE *f
= NULL
;
1271 CGroupIODeviceWeight
*a
;
1275 while (c
->io_device_weights
)
1276 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
1279 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1281 f
= open_memstream_unlocked(&buf
, &size
);
1285 fputs("IODeviceWeight=\n", f
);
1286 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
1287 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1289 r
= fflush_and_check(f
);
1292 unit_write_setting(u
, flags
, name
, buf
);
1297 } else if (streq(name
, "IODeviceLatencyTargetUSec")) {
1302 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1306 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &target
)) > 0) {
1308 if (!path_is_normalized(path
))
1309 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1311 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1312 CGroupIODeviceLatency
*a
= NULL
, *b
;
1314 LIST_FOREACH(device_latencies
, b
, c
->io_device_latencies
) {
1315 if (path_equal(b
->path
, path
)) {
1322 a
= new0(CGroupIODeviceLatency
, 1);
1326 a
->path
= strdup(path
);
1331 LIST_PREPEND(device_latencies
, c
->io_device_latencies
, a
);
1334 a
->target_usec
= target
;
1340 r
= sd_bus_message_exit_container(message
);
1344 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1345 _cleanup_free_
char *buf
= NULL
;
1346 _cleanup_fclose_
FILE *f
= NULL
;
1347 char ts
[FORMAT_TIMESPAN_MAX
];
1348 CGroupIODeviceLatency
*a
;
1352 while (c
->io_device_latencies
)
1353 cgroup_context_free_io_device_latency(c
, c
->io_device_latencies
);
1356 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
1358 f
= open_memstream_unlocked(&buf
, &size
);
1362 fputs("IODeviceLatencyTargetSec=\n", f
);
1363 LIST_FOREACH(device_latencies
, a
, c
->io_device_latencies
)
1364 fprintf(f
, "IODeviceLatencyTargetSec=%s %s\n",
1365 a
->path
, format_timespan(ts
, sizeof(ts
), a
->target_usec
, 1));
1367 r
= fflush_and_check(f
);
1370 unit_write_setting(u
, flags
, name
, buf
);
1375 } else if (STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1381 if (streq(name
, "BlockIOWriteBandwidth"))
1384 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1388 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
1390 if (!path_is_normalized(path
))
1391 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1393 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1394 CGroupBlockIODeviceBandwidth
*a
= NULL
, *b
;
1396 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
1397 if (path_equal(path
, b
->path
)) {
1404 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
1408 a
->rbps
= CGROUP_LIMIT_MAX
;
1409 a
->wbps
= CGROUP_LIMIT_MAX
;
1410 a
->path
= strdup(path
);
1416 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
1430 r
= sd_bus_message_exit_container(message
);
1434 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1435 CGroupBlockIODeviceBandwidth
*a
;
1436 _cleanup_free_
char *buf
= NULL
;
1437 _cleanup_fclose_
FILE *f
= NULL
;
1441 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
1443 a
->rbps
= CGROUP_LIMIT_MAX
;
1445 a
->wbps
= CGROUP_LIMIT_MAX
;
1449 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1451 f
= open_memstream_unlocked(&buf
, &size
);
1456 fputs("BlockIOReadBandwidth=\n", f
);
1457 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
1458 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
1459 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
1461 fputs("BlockIOWriteBandwidth=\n", f
);
1462 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
1463 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
1464 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
1467 r
= fflush_and_check(f
);
1471 unit_write_setting(u
, flags
, name
, buf
);
1476 } else if (streq(name
, "BlockIODeviceWeight")) {
1481 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
1485 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
1487 if (!path_is_normalized(path
))
1488 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path '%s' specified in %s= is not normalized.", name
, path
);
1490 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
1491 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "BlockIODeviceWeight= out of range");
1493 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1494 CGroupBlockIODeviceWeight
*a
= NULL
, *b
;
1496 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
) {
1497 if (path_equal(b
->path
, path
)) {
1504 a
= new0(CGroupBlockIODeviceWeight
, 1);
1508 a
->path
= strdup(path
);
1513 LIST_PREPEND(device_weights
, c
->blockio_device_weights
, a
);
1522 r
= sd_bus_message_exit_container(message
);
1526 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1527 _cleanup_free_
char *buf
= NULL
;
1528 _cleanup_fclose_
FILE *f
= NULL
;
1529 CGroupBlockIODeviceWeight
*a
;
1533 while (c
->blockio_device_weights
)
1534 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
1537 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
1539 f
= open_memstream_unlocked(&buf
, &size
);
1543 fputs("BlockIODeviceWeight=\n", f
);
1544 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
1545 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
1547 r
= fflush_and_check(f
);
1551 unit_write_setting(u
, flags
, name
, buf
);
1556 } else if (streq(name
, "DevicePolicy")) {
1558 CGroupDevicePolicy p
;
1560 r
= sd_bus_message_read(message
, "s", &policy
);
1564 p
= cgroup_device_policy_from_string(policy
);
1568 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1569 c
->device_policy
= p
;
1570 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1571 unit_write_settingf(u
, flags
, name
, "DevicePolicy=%s", policy
);
1576 } else if (streq(name
, "DeviceAllow")) {
1577 const char *path
, *rwm
;
1580 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
1584 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
1586 if (!valid_device_allow_pattern(path
) || strpbrk(path
, WHITESPACE
))
1587 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires device node or pattern");
1591 else if (!in_charset(rwm
, "rwm"))
1592 return sd_bus_error_set(error
, SD_BUS_ERROR_INVALID_ARGS
, "DeviceAllow= requires combination of rwm flags");
1594 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1595 CGroupDeviceAllow
*a
= NULL
, *b
;
1597 LIST_FOREACH(device_allow
, b
, c
->device_allow
) {
1598 if (path_equal(b
->path
, path
)) {
1605 a
= new0(CGroupDeviceAllow
, 1);
1609 a
->path
= strdup(path
);
1615 LIST_PREPEND(device_allow
, c
->device_allow
, a
);
1618 a
->r
= strchr(rwm
, 'r');
1619 a
->w
= strchr(rwm
, 'w');
1620 a
->m
= strchr(rwm
, 'm');
1628 r
= sd_bus_message_exit_container(message
);
1632 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1633 _cleanup_free_
char *buf
= NULL
;
1634 _cleanup_fclose_
FILE *f
= NULL
;
1635 CGroupDeviceAllow
*a
;
1639 while (c
->device_allow
)
1640 cgroup_context_free_device_allow(c
, c
->device_allow
);
1643 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1645 f
= open_memstream_unlocked(&buf
, &size
);
1649 fputs("DeviceAllow=\n", f
);
1650 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
1651 fprintf(f
, "DeviceAllow=%s %s%s%s\n", a
->path
, a
->r
? "r" : "", a
->w
? "w" : "", a
->m
? "m" : "");
1653 r
= fflush_and_check(f
);
1656 unit_write_setting(u
, flags
, name
, buf
);
1661 } else if (streq(name
, "IPAccounting")) {
1664 r
= sd_bus_message_read(message
, "b", &b
);
1668 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1669 c
->ip_accounting
= b
;
1671 unit_invalidate_cgroup_bpf(u
);
1672 unit_write_settingf(u
, flags
, name
, "IPAccounting=%s", yes_no(b
));
1677 } else if (STR_IN_SET(name
, "IPAddressAllow", "IPAddressDeny")) {
1678 IPAddressAccessItem
**list
;
1681 list
= streq(name
, "IPAddressAllow") ? &c
->ip_address_allow
: &c
->ip_address_deny
;
1683 r
= sd_bus_message_enter_container(message
, 'a', "(iayu)");
1693 r
= sd_bus_message_enter_container(message
, 'r', "iayu");
1699 r
= sd_bus_message_read(message
, "i", &family
);
1703 if (!IN_SET(family
, AF_INET
, AF_INET6
))
1704 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s= expects IPv4 or IPv6 addresses only.", name
);
1706 r
= sd_bus_message_read_array(message
, 'y', &ap
, &an
);
1710 if (an
!= FAMILY_ADDRESS_SIZE(family
))
1711 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1712 af_to_name(family
), FAMILY_ADDRESS_SIZE(family
), an
);
1714 r
= sd_bus_message_read(message
, "u", &prefixlen
);
1718 if (prefixlen
> FAMILY_ADDRESS_SIZE(family
)*8)
1719 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Prefix length %" PRIu32
" too large for address family %s.", prefixlen
, af_to_name(family
));
1721 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1722 IPAddressAccessItem
*item
;
1724 item
= new0(IPAddressAccessItem
, 1);
1728 item
->family
= family
;
1729 item
->prefixlen
= prefixlen
;
1730 memcpy(&item
->address
, ap
, an
);
1732 LIST_PREPEND(items
, *list
, item
);
1735 r
= sd_bus_message_exit_container(message
);
1742 r
= sd_bus_message_exit_container(message
);
1746 *list
= ip_address_access_reduce(*list
);
1748 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1749 _cleanup_free_
char *buf
= NULL
;
1750 _cleanup_fclose_
FILE *f
= NULL
;
1751 IPAddressAccessItem
*item
;
1755 *list
= ip_address_access_free_all(*list
);
1757 unit_invalidate_cgroup_bpf(u
);
1758 f
= open_memstream_unlocked(&buf
, &size
);
1765 LIST_FOREACH(items
, item
, *list
) {
1766 char buffer
[CONST_MAX(INET_ADDRSTRLEN
, INET6_ADDRSTRLEN
)];
1769 if (!inet_ntop(item
->family
, &item
->address
, buffer
, sizeof(buffer
)))
1770 return errno_or_else(EINVAL
);
1772 fprintf(f
, "%s=%s/%u\n", name
, buffer
, item
->prefixlen
);
1775 r
= fflush_and_check(f
);
1779 unit_write_setting(u
, flags
, name
, buf
);
1785 if (STR_IN_SET(name
, "ManagedOOMSwap", "ManagedOOMMemoryPressure")) {
1786 ManagedOOMMode
*cgroup_mode
= streq(name
, "ManagedOOMSwap") ? &c
->moom_swap
: &c
->moom_mem_pressure
;
1790 if (!UNIT_VTABLE(u
)->can_set_managed_oom
)
1791 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot set %s for this unit type", name
);
1793 r
= sd_bus_message_read(message
, "s", &mode
);
1797 m
= managed_oom_mode_from_string(mode
);
1801 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1803 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, mode
);
1806 (void) manager_varlink_send_managed_oom_update(u
);
1810 if (streq(name
, "ManagedOOMMemoryPressureLimit")) {
1813 if (!UNIT_VTABLE(u
)->can_set_managed_oom
)
1814 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Cannot set %s for this unit type", name
);
1816 r
= sd_bus_message_read(message
, "u", &v
);
1820 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1821 c
->moom_mem_pressure_limit
= v
;
1822 unit_write_settingf(u
, flags
, name
,
1823 "ManagedOOMMemoryPressureLimit=" PERMYRIAD_AS_PERCENT_FORMAT_STR
,
1824 PERMYRIAD_AS_PERCENT_FORMAT_VAL(UINT32_SCALE_TO_PERMYRIAD(v
)));
1827 if (c
->moom_mem_pressure
== MANAGED_OOM_KILL
)
1828 (void) manager_varlink_send_managed_oom_update(u
);
1833 if (streq(name
, "ManagedOOMPreference")) {
1834 ManagedOOMPreference p
;
1837 r
= sd_bus_message_read(message
, "s", &pref
);
1841 p
= managed_oom_preference_from_string(pref
);
1845 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
1846 c
->moom_preference
= p
;
1847 unit_write_settingf(u
, flags
, name
, "ManagedOOMPreference=%s", pref
);
1853 if (streq(name
, "DisableControllers") || (u
->transient
&& u
->load_state
== UNIT_STUB
))
1854 return bus_cgroup_set_transient_property(u
, c
, name
, message
, flags
, error
);