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("MemoryLow", "t", NULL
, offsetof(CGroupContext
, memory_low
), 0),
232 SD_BUS_PROPERTY("MemoryHigh", "t", NULL
, offsetof(CGroupContext
, memory_high
), 0),
233 SD_BUS_PROPERTY("MemoryMax", "t", NULL
, offsetof(CGroupContext
, memory_max
), 0),
234 SD_BUS_PROPERTY("MemoryLimit", "t", NULL
, offsetof(CGroupContext
, memory_limit
), 0),
235 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy
, offsetof(CGroupContext
, device_policy
), 0),
236 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow
, 0, 0),
237 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool
, offsetof(CGroupContext
, tasks_accounting
), 0),
238 SD_BUS_PROPERTY("TasksMax", "t", NULL
, offsetof(CGroupContext
, tasks_max
), 0),
242 static int bus_cgroup_set_transient_property(
246 sd_bus_message
*message
,
247 UnitSetPropertiesMode mode
,
248 sd_bus_error
*error
) {
257 if (streq(name
, "Delegate")) {
260 r
= sd_bus_message_read(message
, "b", &b
);
264 if (mode
!= UNIT_CHECK
) {
266 unit_write_drop_in_private(u
, mode
, name
, b
? "Delegate=yes" : "Delegate=no");
275 int bus_cgroup_set_property(
279 sd_bus_message
*message
,
280 UnitSetPropertiesMode mode
,
281 sd_bus_error
*error
) {
283 CGroupIOLimitType iol_type
;
291 if (streq(name
, "CPUAccounting")) {
294 r
= sd_bus_message_read(message
, "b", &b
);
298 if (mode
!= UNIT_CHECK
) {
299 c
->cpu_accounting
= b
;
300 unit_invalidate_cgroup(u
, CGROUP_MASK_CPUACCT
|CGROUP_MASK_CPU
);
301 unit_write_drop_in_private(u
, mode
, name
, b
? "CPUAccounting=yes" : "CPUAccounting=no");
306 } else if (streq(name
, "CPUShares")) {
309 r
= sd_bus_message_read(message
, "t", &shares
);
313 if (!CGROUP_CPU_SHARES_IS_OK(shares
))
314 return sd_bus_error_set_errnof(error
, EINVAL
, "CPUShares value out of range");
316 if (mode
!= UNIT_CHECK
) {
317 c
->cpu_shares
= shares
;
318 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
320 if (shares
== CGROUP_CPU_SHARES_INVALID
)
321 unit_write_drop_in_private(u
, mode
, name
, "CPUShares=");
323 unit_write_drop_in_private_format(u
, mode
, name
, "CPUShares=%" PRIu64
, shares
);
328 } else if (streq(name
, "StartupCPUShares")) {
331 r
= sd_bus_message_read(message
, "t", &shares
);
335 if (!CGROUP_CPU_SHARES_IS_OK(shares
))
336 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupCPUShares value out of range");
338 if (mode
!= UNIT_CHECK
) {
339 c
->startup_cpu_shares
= shares
;
340 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
342 if (shares
== CGROUP_CPU_SHARES_INVALID
)
343 unit_write_drop_in_private(u
, mode
, name
, "StartupCPUShares=");
345 unit_write_drop_in_private_format(u
, mode
, name
, "StartupCPUShares=%" PRIu64
, shares
);
350 } else if (streq(name
, "CPUQuotaPerSecUSec")) {
353 r
= sd_bus_message_read(message
, "t", &u64
);
358 return sd_bus_error_set_errnof(error
, EINVAL
, "CPUQuotaPerSecUSec value out of range");
360 if (mode
!= UNIT_CHECK
) {
361 c
->cpu_quota_per_sec_usec
= u64
;
362 unit_invalidate_cgroup(u
, CGROUP_MASK_CPU
);
363 unit_write_drop_in_private_format(u
, mode
, "CPUQuota", "CPUQuota=%0.f%%", (double) (c
->cpu_quota_per_sec_usec
/ 10000));
368 } else if (streq(name
, "IOAccounting")) {
371 r
= sd_bus_message_read(message
, "b", &b
);
375 if (mode
!= UNIT_CHECK
) {
376 c
->io_accounting
= b
;
377 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
378 unit_write_drop_in_private(u
, mode
, name
, b
? "IOAccounting=yes" : "IOAccounting=no");
383 } else if (streq(name
, "IOWeight")) {
386 r
= sd_bus_message_read(message
, "t", &weight
);
390 if (!CGROUP_WEIGHT_IS_OK(weight
))
391 return sd_bus_error_set_errnof(error
, EINVAL
, "IOWeight value out of range");
393 if (mode
!= UNIT_CHECK
) {
394 c
->io_weight
= weight
;
395 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
397 if (weight
== CGROUP_WEIGHT_INVALID
)
398 unit_write_drop_in_private(u
, mode
, name
, "IOWeight=");
400 unit_write_drop_in_private_format(u
, mode
, name
, "IOWeight=%" PRIu64
, weight
);
405 } else if (streq(name
, "StartupIOWeight")) {
408 r
= sd_bus_message_read(message
, "t", &weight
);
412 if (CGROUP_WEIGHT_IS_OK(weight
))
413 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupIOWeight value out of range");
415 if (mode
!= UNIT_CHECK
) {
416 c
->startup_io_weight
= weight
;
417 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
419 if (weight
== CGROUP_WEIGHT_INVALID
)
420 unit_write_drop_in_private(u
, mode
, name
, "StartupIOWeight=");
422 unit_write_drop_in_private_format(u
, mode
, name
, "StartupIOWeight=%" PRIu64
, weight
);
427 } else if ((iol_type
= cgroup_io_limit_type_from_string(name
)) >= 0) {
432 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
436 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
438 if (mode
!= UNIT_CHECK
) {
439 CGroupIODeviceLimit
*a
= NULL
, *b
;
441 LIST_FOREACH(device_limits
, b
, c
->io_device_limits
) {
442 if (path_equal(path
, b
->path
)) {
449 CGroupIOLimitType type
;
451 a
= new0(CGroupIODeviceLimit
, 1);
455 a
->path
= strdup(path
);
461 for (type
= 0; type
< _CGROUP_IO_LIMIT_TYPE_MAX
; type
++)
462 a
->limits
[type
] = cgroup_io_limit_defaults
[type
];
464 LIST_PREPEND(device_limits
, c
->io_device_limits
, a
);
467 a
->limits
[iol_type
] = u64
;
475 r
= sd_bus_message_exit_container(message
);
479 if (mode
!= UNIT_CHECK
) {
480 CGroupIODeviceLimit
*a
;
481 _cleanup_free_
char *buf
= NULL
;
482 _cleanup_fclose_
FILE *f
= NULL
;
486 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
487 a
->limits
[iol_type
] = cgroup_io_limit_defaults
[iol_type
];
490 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
492 f
= open_memstream(&buf
, &size
);
496 fprintf(f
, "%s=\n", name
);
497 LIST_FOREACH(device_limits
, a
, c
->io_device_limits
)
498 if (a
->limits
[iol_type
] != cgroup_io_limit_defaults
[iol_type
])
499 fprintf(f
, "%s=%s %" PRIu64
"\n", name
, a
->path
, a
->limits
[iol_type
]);
501 r
= fflush_and_check(f
);
504 unit_write_drop_in_private(u
, mode
, name
, buf
);
509 } else if (streq(name
, "IODeviceWeight")) {
514 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
518 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
520 if (!CGROUP_WEIGHT_IS_OK(weight
) || weight
== CGROUP_WEIGHT_INVALID
)
521 return sd_bus_error_set_errnof(error
, EINVAL
, "IODeviceWeight out of range");
523 if (mode
!= UNIT_CHECK
) {
524 CGroupIODeviceWeight
*a
= NULL
, *b
;
526 LIST_FOREACH(device_weights
, b
, c
->io_device_weights
) {
527 if (path_equal(b
->path
, path
)) {
534 a
= new0(CGroupIODeviceWeight
, 1);
538 a
->path
= strdup(path
);
543 LIST_PREPEND(device_weights
,c
->io_device_weights
, a
);
552 r
= sd_bus_message_exit_container(message
);
556 if (mode
!= UNIT_CHECK
) {
557 _cleanup_free_
char *buf
= NULL
;
558 _cleanup_fclose_
FILE *f
= NULL
;
559 CGroupIODeviceWeight
*a
;
563 while (c
->io_device_weights
)
564 cgroup_context_free_io_device_weight(c
, c
->io_device_weights
);
567 unit_invalidate_cgroup(u
, CGROUP_MASK_IO
);
569 f
= open_memstream(&buf
, &size
);
573 fputs("IODeviceWeight=\n", f
);
574 LIST_FOREACH(device_weights
, a
, c
->io_device_weights
)
575 fprintf(f
, "IODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
577 r
= fflush_and_check(f
);
580 unit_write_drop_in_private(u
, mode
, name
, buf
);
585 } else if (streq(name
, "BlockIOAccounting")) {
588 r
= sd_bus_message_read(message
, "b", &b
);
592 if (mode
!= UNIT_CHECK
) {
593 c
->blockio_accounting
= b
;
594 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
595 unit_write_drop_in_private(u
, mode
, name
, b
? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
600 } else if (streq(name
, "BlockIOWeight")) {
603 r
= sd_bus_message_read(message
, "t", &weight
);
607 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
))
608 return sd_bus_error_set_errnof(error
, EINVAL
, "BlockIOWeight value out of range");
610 if (mode
!= UNIT_CHECK
) {
611 c
->blockio_weight
= weight
;
612 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
614 if (weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
615 unit_write_drop_in_private(u
, mode
, name
, "BlockIOWeight=");
617 unit_write_drop_in_private_format(u
, mode
, name
, "BlockIOWeight=%" PRIu64
, weight
);
622 } else if (streq(name
, "StartupBlockIOWeight")) {
625 r
= sd_bus_message_read(message
, "t", &weight
);
629 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
))
630 return sd_bus_error_set_errnof(error
, EINVAL
, "StartupBlockIOWeight value out of range");
632 if (mode
!= UNIT_CHECK
) {
633 c
->startup_blockio_weight
= weight
;
634 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
636 if (weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
637 unit_write_drop_in_private(u
, mode
, name
, "StartupBlockIOWeight=");
639 unit_write_drop_in_private_format(u
, mode
, name
, "StartupBlockIOWeight=%" PRIu64
, weight
);
644 } else if (STR_IN_SET(name
, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
650 if (streq(name
, "BlockIOWriteBandwidth"))
653 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
657 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &u64
)) > 0) {
659 if (mode
!= UNIT_CHECK
) {
660 CGroupBlockIODeviceBandwidth
*a
= NULL
, *b
;
662 LIST_FOREACH(device_bandwidths
, b
, c
->blockio_device_bandwidths
) {
663 if (path_equal(path
, b
->path
)) {
670 a
= new0(CGroupBlockIODeviceBandwidth
, 1);
674 a
->rbps
= CGROUP_LIMIT_MAX
;
675 a
->wbps
= CGROUP_LIMIT_MAX
;
676 a
->path
= strdup(path
);
682 LIST_PREPEND(device_bandwidths
, c
->blockio_device_bandwidths
, a
);
696 r
= sd_bus_message_exit_container(message
);
700 if (mode
!= UNIT_CHECK
) {
701 CGroupBlockIODeviceBandwidth
*a
;
702 _cleanup_free_
char *buf
= NULL
;
703 _cleanup_fclose_
FILE *f
= NULL
;
707 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
) {
709 a
->rbps
= CGROUP_LIMIT_MAX
;
711 a
->wbps
= CGROUP_LIMIT_MAX
;
715 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
717 f
= open_memstream(&buf
, &size
);
722 fputs("BlockIOReadBandwidth=\n", f
);
723 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
724 if (a
->rbps
!= CGROUP_LIMIT_MAX
)
725 fprintf(f
, "BlockIOReadBandwidth=%s %" PRIu64
"\n", a
->path
, a
->rbps
);
727 fputs("BlockIOWriteBandwidth=\n", f
);
728 LIST_FOREACH(device_bandwidths
, a
, c
->blockio_device_bandwidths
)
729 if (a
->wbps
!= CGROUP_LIMIT_MAX
)
730 fprintf(f
, "BlockIOWriteBandwidth=%s %" PRIu64
"\n", a
->path
, a
->wbps
);
733 r
= fflush_and_check(f
);
736 unit_write_drop_in_private(u
, mode
, name
, buf
);
741 } else if (streq(name
, "BlockIODeviceWeight")) {
746 r
= sd_bus_message_enter_container(message
, 'a', "(st)");
750 while ((r
= sd_bus_message_read(message
, "(st)", &path
, &weight
)) > 0) {
752 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight
) || weight
== CGROUP_BLKIO_WEIGHT_INVALID
)
753 return sd_bus_error_set_errnof(error
, EINVAL
, "BlockIODeviceWeight out of range");
755 if (mode
!= UNIT_CHECK
) {
756 CGroupBlockIODeviceWeight
*a
= NULL
, *b
;
758 LIST_FOREACH(device_weights
, b
, c
->blockio_device_weights
) {
759 if (path_equal(b
->path
, path
)) {
766 a
= new0(CGroupBlockIODeviceWeight
, 1);
770 a
->path
= strdup(path
);
775 LIST_PREPEND(device_weights
,c
->blockio_device_weights
, a
);
784 r
= sd_bus_message_exit_container(message
);
788 if (mode
!= UNIT_CHECK
) {
789 _cleanup_free_
char *buf
= NULL
;
790 _cleanup_fclose_
FILE *f
= NULL
;
791 CGroupBlockIODeviceWeight
*a
;
795 while (c
->blockio_device_weights
)
796 cgroup_context_free_blockio_device_weight(c
, c
->blockio_device_weights
);
799 unit_invalidate_cgroup(u
, CGROUP_MASK_BLKIO
);
801 f
= open_memstream(&buf
, &size
);
805 fputs("BlockIODeviceWeight=\n", f
);
806 LIST_FOREACH(device_weights
, a
, c
->blockio_device_weights
)
807 fprintf(f
, "BlockIODeviceWeight=%s %" PRIu64
"\n", a
->path
, a
->weight
);
809 r
= fflush_and_check(f
);
812 unit_write_drop_in_private(u
, mode
, name
, buf
);
817 } else if (streq(name
, "MemoryAccounting")) {
820 r
= sd_bus_message_read(message
, "b", &b
);
824 if (mode
!= UNIT_CHECK
) {
825 c
->memory_accounting
= b
;
826 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
827 unit_write_drop_in_private(u
, mode
, name
, b
? "MemoryAccounting=yes" : "MemoryAccounting=no");
832 } else if (STR_IN_SET(name
, "MemoryLow", "MemoryHigh", "MemoryMax")) {
835 r
= sd_bus_message_read(message
, "t", &v
);
839 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is too small", name
);
841 if (mode
!= UNIT_CHECK
) {
842 if (streq(name
, "MemoryLow"))
844 else if (streq(name
, "MemoryHigh"))
849 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
851 if (v
== CGROUP_LIMIT_MAX
)
852 unit_write_drop_in_private_format(u
, mode
, name
, "%s=infinity", name
);
854 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%" PRIu64
, name
, v
);
859 } else if (STR_IN_SET(name
, "MemoryLowByPhysicalMemory", "MemoryHighByPhysicalMemory", "MemoryMaxByPhysicalMemory")) {
863 r
= sd_bus_message_read(message
, "u", &raw
);
867 v
= physical_memory_scale(raw
, UINT32_MAX
);
868 if (v
<= 0 || v
== UINT64_MAX
)
869 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is out of range", name
);
871 if (mode
!= UNIT_CHECK
) {
874 /* Chop off suffix */
875 assert_se(e
= endswith(name
, "ByPhysicalMemory"));
876 name
= strndupa(name
, e
- name
);
878 if (streq(name
, "MemoryLow"))
880 else if (streq(name
, "MemoryHigh"))
885 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
886 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%" PRIu32
"%%", name
, (uint32_t) (DIV_ROUND_UP((uint64_t) raw
* 100, (uint64_t) UINT32_MAX
)));
891 } else if (streq(name
, "MemoryLimit")) {
894 r
= sd_bus_message_read(message
, "t", &limit
);
898 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is too small", name
);
900 if (mode
!= UNIT_CHECK
) {
901 c
->memory_limit
= limit
;
902 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
904 if (limit
== (uint64_t) -1)
905 unit_write_drop_in_private(u
, mode
, name
, "MemoryLimit=infinity");
907 unit_write_drop_in_private_format(u
, mode
, name
, "MemoryLimit=%" PRIu64
, limit
);
912 } else if (streq(name
, "MemoryLimitByPhysicalMemory")) {
916 r
= sd_bus_message_read(message
, "u", &raw
);
920 limit
= physical_memory_scale(raw
, UINT32_MAX
);
921 if (limit
<= 0 || limit
== UINT64_MAX
)
922 return sd_bus_error_set_errnof(error
, EINVAL
, "%s= is out of range", name
);
924 if (mode
!= UNIT_CHECK
) {
925 c
->memory_limit
= limit
;
926 unit_invalidate_cgroup(u
, CGROUP_MASK_MEMORY
);
927 unit_write_drop_in_private_format(u
, mode
, "MemoryLimit", "MemoryLimit=%" PRIu32
"%%", (uint32_t) (DIV_ROUND_UP((uint64_t) raw
* 100, (uint64_t) UINT32_MAX
)));
932 } else if (streq(name
, "DevicePolicy")) {
934 CGroupDevicePolicy p
;
936 r
= sd_bus_message_read(message
, "s", &policy
);
940 p
= cgroup_device_policy_from_string(policy
);
944 if (mode
!= UNIT_CHECK
) {
945 c
->device_policy
= p
;
946 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
947 unit_write_drop_in_private_format(u
, mode
, name
, "DevicePolicy=%s", policy
);
952 } else if (streq(name
, "DeviceAllow")) {
953 const char *path
, *rwm
;
956 r
= sd_bus_message_enter_container(message
, 'a', "(ss)");
960 while ((r
= sd_bus_message_read(message
, "(ss)", &path
, &rwm
)) > 0) {
962 if ((!startswith(path
, "/dev/") &&
963 !startswith(path
, "block-") &&
964 !startswith(path
, "char-")) ||
965 strpbrk(path
, WHITESPACE
))
966 return sd_bus_error_set_errnof(error
, EINVAL
, "DeviceAllow= requires device node");
971 if (!in_charset(rwm
, "rwm"))
972 return sd_bus_error_set_errnof(error
, EINVAL
, "DeviceAllow= requires combination of rwm flags");
974 if (mode
!= UNIT_CHECK
) {
975 CGroupDeviceAllow
*a
= NULL
, *b
;
977 LIST_FOREACH(device_allow
, b
, c
->device_allow
) {
978 if (path_equal(b
->path
, path
)) {
985 a
= new0(CGroupDeviceAllow
, 1);
989 a
->path
= strdup(path
);
995 LIST_PREPEND(device_allow
, c
->device_allow
, a
);
998 a
->r
= !!strchr(rwm
, 'r');
999 a
->w
= !!strchr(rwm
, 'w');
1000 a
->m
= !!strchr(rwm
, 'm');
1008 r
= sd_bus_message_exit_container(message
);
1012 if (mode
!= UNIT_CHECK
) {
1013 _cleanup_free_
char *buf
= NULL
;
1014 _cleanup_fclose_
FILE *f
= NULL
;
1015 CGroupDeviceAllow
*a
;
1019 while (c
->device_allow
)
1020 cgroup_context_free_device_allow(c
, c
->device_allow
);
1023 unit_invalidate_cgroup(u
, CGROUP_MASK_DEVICES
);
1025 f
= open_memstream(&buf
, &size
);
1029 fputs("DeviceAllow=\n", f
);
1030 LIST_FOREACH(device_allow
, a
, c
->device_allow
)
1031 fprintf(f
, "DeviceAllow=%s %s%s%s\n", a
->path
, a
->r
? "r" : "", a
->w
? "w" : "", a
->m
? "m" : "");
1033 r
= fflush_and_check(f
);
1036 unit_write_drop_in_private(u
, mode
, name
, buf
);
1041 } else if (streq(name
, "TasksAccounting")) {
1044 r
= sd_bus_message_read(message
, "b", &b
);
1048 if (mode
!= UNIT_CHECK
) {
1049 c
->tasks_accounting
= b
;
1050 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1051 unit_write_drop_in_private(u
, mode
, name
, b
? "TasksAccounting=yes" : "TasksAccounting=no");
1056 } else if (streq(name
, "TasksMax")) {
1059 r
= sd_bus_message_read(message
, "t", &limit
);
1063 if (mode
!= UNIT_CHECK
) {
1064 c
->tasks_max
= limit
;
1065 unit_invalidate_cgroup(u
, CGROUP_MASK_PIDS
);
1067 if (limit
== (uint64_t) -1)
1068 unit_write_drop_in_private(u
, mode
, name
, "TasksMax=infinity");
1070 unit_write_drop_in_private_format(u
, mode
, name
, "TasksMax=%" PRIu64
, limit
);
1076 if (u
->transient
&& u
->load_state
== UNIT_STUB
) {
1077 r
= bus_cgroup_set_transient_property(u
, c
, name
, message
, mode
, error
);