]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-cgroup.c
dbus: make more cgroup attributes runtime settable
[thirdparty/systemd.git] / src / core / dbus-cgroup.c
CommitLineData
4ad49000
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <dbus/dbus.h>
23
24#include "dbus-cgroup.h"
25
26static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_cgroup_append_device_policy, cgroup_device_policy, CGroupDevicePolicy);
27
28static int bus_cgroup_append_device_weights(DBusMessageIter *i, const char *property, void *data) {
29 DBusMessageIter sub, sub2;
30 CGroupContext *c = data;
31 CGroupBlockIODeviceWeight *w;
32
33 assert(i);
34 assert(property);
35 assert(c);
36
37 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(st)", &sub))
38 return -ENOMEM;
39
40 LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
41
42 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
43 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &w->path) ||
44 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &w->weight) ||
45 !dbus_message_iter_close_container(&sub, &sub2))
46 return -ENOMEM;
47 }
48
49 if (!dbus_message_iter_close_container(i, &sub))
50 return -ENOMEM;
51
52 return 0;
53}
54
55static int bus_cgroup_append_device_bandwidths(DBusMessageIter *i, const char *property, void *data) {
56 DBusMessageIter sub, sub2;
57 CGroupContext *c = data;
58 CGroupBlockIODeviceBandwidth *b;
59
60 assert(i);
61 assert(property);
62 assert(c);
63
64 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(st)", &sub))
65 return -ENOMEM;
66
67 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
68
69 if (streq(property, "BlockIOReadBandwidth") != b->read)
70 continue;
71
72 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
73 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &b->path) ||
74 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &b->bandwidth) ||
75 !dbus_message_iter_close_container(&sub, &sub2))
76 return -ENOMEM;
77 }
78
79 if (!dbus_message_iter_close_container(i, &sub))
80 return -ENOMEM;
81
82 return 0;
83}
84
85static int bus_cgroup_append_device_allow(DBusMessageIter *i, const char *property, void *data) {
86 DBusMessageIter sub, sub2;
87 CGroupContext *c = data;
88 CGroupDeviceAllow *a;
89
90 assert(i);
91 assert(property);
92 assert(c);
93
94 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(ss)", &sub))
95 return -ENOMEM;
96
97 LIST_FOREACH(device_allow, a, c->device_allow) {
98 const char *rwm;
99 char buf[4];
100 unsigned k = 0;
101
102 if (a->r)
103 buf[k++] = 'r';
104 if (a->w)
105 buf[k++] = 'w';
106 if (a->m)
107 buf[k++] = 'm';
108
109 buf[k] = 0;
110 rwm = buf;
111
112 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
113 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &a->path) ||
114 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &rwm) ||
115 !dbus_message_iter_close_container(&sub, &sub2))
116 return -ENOMEM;
117 }
118
119 if (!dbus_message_iter_close_container(i, &sub))
120 return -ENOMEM;
121
122 return 0;
123}
124
125const BusProperty bus_cgroup_context_properties[] = {
126 { "CPUAccounting", bus_property_append_bool, "b", offsetof(CGroupContext, cpu_accounting) },
127 { "CPUShares", bus_property_append_ul, "t", offsetof(CGroupContext, cpu_shares) },
128 { "BlockIOAccounting", bus_property_append_bool, "b", offsetof(CGroupContext, blockio_accounting) },
129 { "BlockIOWeight", bus_property_append_ul, "t", offsetof(CGroupContext, blockio_weight) },
130 { "BlockIODeviceWeight", bus_cgroup_append_device_weights, "a(st)", 0 },
131 { "BlockIOReadBandwidth", bus_cgroup_append_device_bandwidths, "a(st)", 0 },
132 { "BlockIOWriteBandwidth", bus_cgroup_append_device_bandwidths, "a(st)", 0 },
133 { "MemoryAccounting", bus_property_append_bool, "b", offsetof(CGroupContext, memory_accounting) },
134 { "MemoryLimit", bus_property_append_uint64, "t", offsetof(CGroupContext, memory_limit) },
135 { "MemorySoftLimit", bus_property_append_uint64, "t", offsetof(CGroupContext, memory_soft_limit) },
136 { "DevicePolicy", bus_cgroup_append_device_policy, "s", offsetof(CGroupContext, device_policy) },
137 { "DeviceAllow", bus_cgroup_append_device_allow, "a(ss)", 0 },
138 {}
139};
8e2af478
LP
140
141int bus_cgroup_set_property(
142 Unit *u,
143 CGroupContext *c,
144 const char *name,
145 DBusMessageIter *i,
146 UnitSetPropertiesMode mode,
147 DBusError *error) {
148
149 assert(name);
150 assert(u);
151 assert(c);
152 assert(i);
153
154 if (streq(name, "CPUAccounting")) {
8e2af478
LP
155
156 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
157 return -EINVAL;
158
159 if (mode != UNIT_CHECK) {
b42defe3 160 dbus_bool_t b;
8e2af478
LP
161 dbus_message_iter_get_basic(i, &b);
162
163 c->cpu_accounting = b;
b42defe3
LP
164 unit_write_drop_in_private_section(u, mode, "cpu-accounting", b ? "CPUAccounting=yes" : "CPUAccounting=no");
165 }
166
167 return 1;
168
169 } else if (streq(name, "CPUShares")) {
170 uint64_t u64;
171 unsigned long ul;
172
173 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
174 return -EINVAL;
175
176 dbus_message_iter_get_basic(i, &u64);
177 ul = (unsigned long) u64;
178
179 if (u64 <= 0 || u64 != (uint64_t) ul)
180 return -EINVAL;
181
182 if (mode != UNIT_CHECK) {
183 char buf[sizeof("CPUShares=") + DECIMAL_STR_MAX(ul)];
184 c->cpu_shares = ul;
185
186 sprintf(buf, "CPUShares=%lu", ul);
187 unit_write_drop_in_private_section(u, mode, "cpu-shares", buf);
8e2af478
LP
188 }
189
190 return 1;
191
192 } else if (streq(name, "BlockIOAccounting")) {
8e2af478
LP
193
194 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
195 return -EINVAL;
196
197 if (mode != UNIT_CHECK) {
b42defe3 198 dbus_bool_t b;
8e2af478
LP
199 dbus_message_iter_get_basic(i, &b);
200
201 c->blockio_accounting = b;
b42defe3 202 unit_write_drop_in_private_section(u, mode, "block-io-accounting", b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
8e2af478
LP
203 }
204
205 return 1;
b42defe3
LP
206
207 } else if (streq(name, "BlockIOWeight")) {
208 uint64_t u64;
209 unsigned long ul;
210
211 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
212 return -EINVAL;
213
214 dbus_message_iter_get_basic(i, &u64);
215 ul = (unsigned long) u64;
216
217 if (u64 < 10 || u64 > 1000)
218 return -EINVAL;
219
220 if (mode != UNIT_CHECK) {
221 char buf[sizeof("BlockIOWeight=") + DECIMAL_STR_MAX(ul)];
222 c->cpu_shares = ul;
223
224 sprintf(buf, "BlockIOWeight=%lu", ul);
225 unit_write_drop_in_private_section(u, mode, "blockio-weight", buf);
226 }
227
228 return 1;
229
8e2af478 230 } else if (streq(name, "MemoryAccounting")) {
8e2af478
LP
231
232 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
233 return -EINVAL;
234
235 if (mode != UNIT_CHECK) {
b42defe3 236 dbus_bool_t b;
8e2af478
LP
237 dbus_message_iter_get_basic(i, &b);
238
b42defe3
LP
239 c->memory_accounting = b;
240 unit_write_drop_in_private_section(u, mode, "memory-accounting", b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
8e2af478
LP
241 }
242
243 return 1;
8e2af478 244
b42defe3
LP
245 } else if (streq(name, "MemoryLimit") || streq(name, "MemorySoftLimit")) {
246
247 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_UINT64)
248 return -EINVAL;
249
250 if (mode != UNIT_CHECK) {
251 uint64_t limit;
252 char buf[sizeof("MemorySoftLimit=") + DECIMAL_STR_MAX(limit)];
253
254 dbus_message_iter_get_basic(i, &limit);
255
256 if (streq(name, "MemoryLimit")) {
257 c->memory_limit = limit;
258 sprintf(buf, "MemoryLimit=%" PRIu64, limit);
259 unit_write_drop_in_private_section(u, mode, "memory-limit", buf);
260 } else {
261 c->memory_soft_limit = limit;
262 sprintf(buf, "MemorySoftLimit=%" PRIu64, limit);
263 unit_write_drop_in_private_section(u, mode, "memory-soft-limit", buf);
264 }
265 }
266
267 return 1;
268 }
8e2af478
LP
269
270 return 0;
271}