chiark / gitweb /
f7d1dd12ad35dfb31a918381a732bf341566ab47
[elogind.git] / src / core / dbus-cgroup.c
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
26 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_cgroup_append_device_policy, cgroup_device_policy, CGroupDevicePolicy);
27
28 static 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
55 static 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
85 static 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
125 const 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 };
140
141 int 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")) {
155                 dbus_bool_t b;
156
157                 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
158                         return -EINVAL;
159
160                 if (mode != UNIT_CHECK) {
161                         dbus_message_iter_get_basic(i, &b);
162
163                         c->cpu_accounting = b;
164                         unit_write_drop_in(u, mode, "cpu-accounting", b ? "CPUAccounting=yes" : "CPUAccounting=no");
165                 }
166
167                 return 1;
168
169         } else if (streq(name, "BlockIOAccounting")) {
170                 dbus_bool_t b;
171
172                 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
173                         return -EINVAL;
174
175                 if (mode != UNIT_CHECK) {
176                         dbus_message_iter_get_basic(i, &b);
177
178                         c->blockio_accounting = b;
179                         unit_write_drop_in(u, mode, "block-io-accounting", b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
180                 }
181
182                 return 1;
183         } else if (streq(name, "MemoryAccounting")) {
184                 dbus_bool_t b;
185
186                 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN)
187                         return -EINVAL;
188
189                 if (mode != UNIT_CHECK) {
190                         dbus_message_iter_get_basic(i, &b);
191
192                         c->blockio_accounting = b;
193                         unit_write_drop_in(u, mode, "memory-accounting", b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
194                 }
195
196                 return 1;
197         }
198
199
200         return 0;
201 }