2013-06-27 04:14:27 +02:00
|
|
|
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
|
|
|
|
|
|
|
/***
|
|
|
|
This file is part of systemd.
|
|
|
|
|
|
|
|
Copyright 2013 Lennart Poettering
|
|
|
|
|
|
|
|
systemd is free software; you can redistribute it and/or modify it
|
|
|
|
under the terms of the GNU Lesser General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2.1 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
systemd is distributed in the hope that it will be useful, but
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public License
|
|
|
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
***/
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
#include "bus-util.h"
|
2013-06-27 23:13:17 +02:00
|
|
|
#include "path-util.h"
|
2013-11-19 21:12:59 +01:00
|
|
|
#include "cgroup-util.h"
|
|
|
|
#include "cgroup.h"
|
2013-06-27 04:14:27 +02:00
|
|
|
#include "dbus-cgroup.h"
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
|
|
|
|
|
|
|
|
static int property_get_blockio_device_weight(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2013-06-27 04:14:27 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
CGroupContext *c = userdata;
|
2013-06-27 04:14:27 +02:00
|
|
|
CGroupBlockIODeviceWeight *w;
|
2013-11-19 21:12:59 +01:00
|
|
|
int r;
|
2013-06-27 04:14:27 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
2013-06-27 04:14:27 +02:00
|
|
|
assert(c);
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_open_container(reply, 'a', "(st)");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 04:14:27 +02:00
|
|
|
|
|
|
|
LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 04:14:27 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_close_container(reply);
|
2013-06-27 04:14:27 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_blockio_device_bandwidths(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2013-11-19 21:12:59 +01:00
|
|
|
|
|
|
|
CGroupContext *c = userdata;
|
2013-06-27 04:14:27 +02:00
|
|
|
CGroupBlockIODeviceBandwidth *b;
|
2013-11-19 21:12:59 +01:00
|
|
|
int r;
|
2013-06-27 04:14:27 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
2013-06-27 04:14:27 +02:00
|
|
|
assert(c);
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_open_container(reply, 'a', "(st)");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 04:14:27 +02:00
|
|
|
|
|
|
|
LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
|
|
|
|
|
|
|
|
if (streq(property, "BlockIOReadBandwidth") != b->read)
|
|
|
|
continue;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_append(reply, "(st)", b->path, b->bandwidth);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 04:14:27 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_close_container(reply);
|
2013-06-27 04:14:27 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
static int property_get_device_allow(
|
|
|
|
sd_bus *bus,
|
|
|
|
const char *path,
|
|
|
|
const char *interface,
|
|
|
|
const char *property,
|
|
|
|
sd_bus_message *reply,
|
2013-11-21 19:34:37 +01:00
|
|
|
void *userdata,
|
|
|
|
sd_bus_error *error) {
|
2013-11-19 21:12:59 +01:00
|
|
|
|
|
|
|
CGroupContext *c = userdata;
|
2013-06-27 04:14:27 +02:00
|
|
|
CGroupDeviceAllow *a;
|
2013-11-19 21:12:59 +01:00
|
|
|
int r;
|
2013-06-27 04:14:27 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(bus);
|
|
|
|
assert(reply);
|
2013-06-27 04:14:27 +02:00
|
|
|
assert(c);
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_open_container(reply, 'a', "(ss)");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 04:14:27 +02:00
|
|
|
|
|
|
|
LIST_FOREACH(device_allow, a, c->device_allow) {
|
|
|
|
unsigned k = 0;
|
2013-11-19 21:12:59 +01:00
|
|
|
char rwm[4];
|
2013-06-27 04:14:27 +02:00
|
|
|
|
|
|
|
if (a->r)
|
2013-11-19 21:12:59 +01:00
|
|
|
rwm[k++] = 'r';
|
2013-06-27 04:14:27 +02:00
|
|
|
if (a->w)
|
2013-11-19 21:12:59 +01:00
|
|
|
rwm[k++] = 'w';
|
2013-06-27 04:14:27 +02:00
|
|
|
if (a->m)
|
2013-11-19 21:12:59 +01:00
|
|
|
rwm[k++] = 'm';
|
2013-06-27 04:14:27 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
rwm[k] = 0;
|
2013-06-27 04:14:27 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 04:14:27 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_message_close_container(reply);
|
2013-06-27 04:14:27 +02:00
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
const sd_bus_vtable bus_cgroup_vtable[] = {
|
|
|
|
SD_BUS_VTABLE_START(0),
|
2014-11-05 17:57:23 +01:00
|
|
|
SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
|
2013-12-22 19:44:04 +01:00
|
|
|
SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
|
2015-09-11 16:48:24 +02:00
|
|
|
SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0),
|
|
|
|
SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0),
|
2014-09-29 05:42:33 +02:00
|
|
|
SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
|
2013-12-22 19:44:04 +01:00
|
|
|
SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
|
2015-09-11 16:48:24 +02:00
|
|
|
SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0),
|
|
|
|
SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0),
|
2013-12-22 19:44:04 +01:00
|
|
|
SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
|
|
|
|
SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
|
|
|
|
SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
|
|
|
|
SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
|
|
|
|
SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
|
|
|
|
SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
|
|
|
|
SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
|
2015-09-10 12:32:16 +02:00
|
|
|
SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0),
|
|
|
|
SD_BUS_PROPERTY("TasksMax", "t", NULL, offsetof(CGroupContext, tasks_max), 0),
|
2013-11-19 21:12:59 +01:00
|
|
|
SD_BUS_VTABLE_END
|
2013-06-27 04:14:27 +02:00
|
|
|
};
|
2013-06-27 21:14:56 +02:00
|
|
|
|
2014-11-05 17:57:23 +01:00
|
|
|
static int bus_cgroup_set_transient_property(
|
|
|
|
Unit *u,
|
|
|
|
CGroupContext *c,
|
|
|
|
const char *name,
|
|
|
|
sd_bus_message *message,
|
|
|
|
UnitSetPropertiesMode mode,
|
|
|
|
sd_bus_error *error) {
|
|
|
|
|
|
|
|
int r;
|
|
|
|
|
|
|
|
assert(u);
|
|
|
|
assert(c);
|
|
|
|
assert(name);
|
|
|
|
assert(message);
|
|
|
|
|
|
|
|
if (streq(name, "Delegate")) {
|
|
|
|
int b;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(message, "b", &b);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
c->delegate = b;
|
|
|
|
unit_write_drop_in_private(u, mode, name, b ? "Delegate=yes" : "Delegate=no");
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-06-27 21:14:56 +02:00
|
|
|
int bus_cgroup_set_property(
|
|
|
|
Unit *u,
|
|
|
|
CGroupContext *c,
|
|
|
|
const char *name,
|
2013-11-19 21:12:59 +01:00
|
|
|
sd_bus_message *message,
|
2013-06-27 21:14:56 +02:00
|
|
|
UnitSetPropertiesMode mode,
|
2013-11-19 21:12:59 +01:00
|
|
|
sd_bus_error *error) {
|
|
|
|
|
|
|
|
int r;
|
2013-06-27 21:14:56 +02:00
|
|
|
|
|
|
|
assert(u);
|
|
|
|
assert(c);
|
2013-11-19 21:12:59 +01:00
|
|
|
assert(name);
|
|
|
|
assert(message);
|
2013-06-27 21:14:56 +02:00
|
|
|
|
|
|
|
if (streq(name, "CPUAccounting")) {
|
2013-11-19 21:12:59 +01:00
|
|
|
int b;
|
2013-06-27 21:14:56 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "b", &b);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 21:14:56 +02:00
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
c->cpu_accounting = b;
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_CPUACCT;
|
2013-07-11 21:29:33 +02:00
|
|
|
unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no");
|
2013-06-27 21:50:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
} else if (streq(name, "CPUShares")) {
|
2015-09-11 16:48:24 +02:00
|
|
|
uint64_t shares;
|
2013-06-27 21:50:35 +02:00
|
|
|
|
2015-09-11 16:48:24 +02:00
|
|
|
r = sd_bus_message_read(message, "t", &shares);
|
2013-11-19 21:12:59 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 21:50:35 +02:00
|
|
|
|
2015-09-11 16:48:24 +02:00
|
|
|
if (!CGROUP_CPU_SHARES_IS_OK(shares))
|
|
|
|
return sd_bus_error_set_errnof(error, EINVAL, "CPUShares value out of range");
|
2013-06-27 21:50:35 +02:00
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
2015-09-11 16:48:24 +02:00
|
|
|
c->cpu_shares = shares;
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_CPU;
|
2015-09-11 16:48:24 +02:00
|
|
|
|
|
|
|
if (shares == CGROUP_CPU_SHARES_INVALID)
|
|
|
|
unit_write_drop_in_private(u, mode, name, "CPUShares=");
|
|
|
|
else
|
|
|
|
unit_write_drop_in_private_format(u, mode, name, "CPUShares=%" PRIu64, shares);
|
2013-06-27 21:14:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
2014-05-15 17:09:34 +02:00
|
|
|
} else if (streq(name, "StartupCPUShares")) {
|
2015-09-11 16:48:24 +02:00
|
|
|
uint64_t shares;
|
2014-05-15 17:09:34 +02:00
|
|
|
|
2015-09-11 16:48:24 +02:00
|
|
|
r = sd_bus_message_read(message, "t", &shares);
|
2014-05-15 17:09:34 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2015-09-11 16:48:24 +02:00
|
|
|
if (!CGROUP_CPU_SHARES_IS_OK(shares))
|
|
|
|
return sd_bus_error_set_errnof(error, EINVAL, "StartupCPUShares value out of range");
|
2014-05-15 17:09:34 +02:00
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
2015-09-11 16:48:24 +02:00
|
|
|
c->startup_cpu_shares = shares;
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_CPU;
|
2015-09-11 16:48:24 +02:00
|
|
|
|
|
|
|
if (shares == CGROUP_CPU_SHARES_INVALID)
|
|
|
|
unit_write_drop_in_private(u, mode, name, "StartupCPUShares=");
|
|
|
|
else
|
|
|
|
unit_write_drop_in_private_format(u, mode, name, "StartupCPUShares=%" PRIu64, shares);
|
2014-05-15 17:09:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
2014-04-25 13:27:25 +02:00
|
|
|
} else if (streq(name, "CPUQuotaPerSecUSec")) {
|
|
|
|
uint64_t u64;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(message, "t", &u64);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (u64 <= 0)
|
|
|
|
return sd_bus_error_set_errnof(error, EINVAL, "CPUQuotaPerSecUSec value out of range");
|
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
c->cpu_quota_per_sec_usec = u64;
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_CPU;
|
2014-04-25 13:27:25 +02:00
|
|
|
unit_write_drop_in_private_format(u, mode, "CPUQuota", "CPUQuota=%0.f%%", (double) (c->cpu_quota_per_sec_usec / 10000));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
2013-06-27 21:14:56 +02:00
|
|
|
} else if (streq(name, "BlockIOAccounting")) {
|
2013-11-19 21:12:59 +01:00
|
|
|
int b;
|
2013-06-27 21:14:56 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "b", &b);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 21:14:56 +02:00
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
c->blockio_accounting = b;
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO;
|
2013-07-11 21:29:33 +02:00
|
|
|
unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no");
|
2013-06-27 21:14:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
2013-06-27 21:50:35 +02:00
|
|
|
|
|
|
|
} else if (streq(name, "BlockIOWeight")) {
|
2015-09-11 16:48:24 +02:00
|
|
|
uint64_t weight;
|
2013-06-27 21:50:35 +02:00
|
|
|
|
2015-09-11 16:48:24 +02:00
|
|
|
r = sd_bus_message_read(message, "t", &weight);
|
2013-11-19 21:12:59 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 21:50:35 +02:00
|
|
|
|
2015-09-11 16:48:24 +02:00
|
|
|
if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
|
|
|
|
return sd_bus_error_set_errnof(error, EINVAL, "BlockIOWeight value out of range");
|
2013-06-27 21:50:35 +02:00
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
2015-09-11 16:48:24 +02:00
|
|
|
c->blockio_weight = weight;
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO;
|
2015-09-11 16:48:24 +02:00
|
|
|
|
|
|
|
if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
|
|
|
|
unit_write_drop_in_private(u, mode, name, "BlockIOWeight=");
|
|
|
|
else
|
|
|
|
unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%" PRIu64, weight);
|
2013-06-27 21:50:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
2014-05-15 17:09:34 +02:00
|
|
|
|
|
|
|
} else if (streq(name, "StartupBlockIOWeight")) {
|
2015-09-11 16:48:24 +02:00
|
|
|
uint64_t weight;
|
2014-05-15 17:09:34 +02:00
|
|
|
|
2015-09-11 16:48:24 +02:00
|
|
|
r = sd_bus_message_read(message, "t", &weight);
|
2014-05-15 17:09:34 +02:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2015-09-11 16:48:24 +02:00
|
|
|
if (CGROUP_BLKIO_WEIGHT_IS_OK(weight))
|
|
|
|
return sd_bus_error_set_errnof(error, EINVAL, "StartupBlockIOWeight value out of range");
|
2014-05-15 17:09:34 +02:00
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
2015-09-11 16:48:24 +02:00
|
|
|
c->startup_blockio_weight = weight;
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO;
|
2015-09-11 16:48:24 +02:00
|
|
|
|
|
|
|
if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
|
|
|
|
unit_write_drop_in_private(u, mode, name, "StartupBlockIOWeight=");
|
|
|
|
else
|
|
|
|
unit_write_drop_in_private_format(u, mode, name, "StartupBlockIOWeight=%" PRIu64, weight);
|
2014-05-15 17:09:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
2013-06-27 21:50:35 +02:00
|
|
|
|
2013-09-10 17:23:07 +02:00
|
|
|
} else if (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth")) {
|
2013-11-19 21:12:59 +01:00
|
|
|
const char *path;
|
2013-09-10 17:23:07 +02:00
|
|
|
bool read = true;
|
2013-11-19 21:12:59 +01:00
|
|
|
unsigned n = 0;
|
|
|
|
uint64_t u64;
|
2013-09-10 17:23:07 +02:00
|
|
|
|
|
|
|
if (streq(name, "BlockIOWriteBandwidth"))
|
|
|
|
read = false;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_enter_container(message, 'a', "(st)");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-09-10 17:23:07 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
|
2013-09-10 17:23:07 +02:00
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
2013-11-19 21:12:59 +01:00
|
|
|
CGroupBlockIODeviceBandwidth *a = NULL, *b;
|
2013-09-10 17:23:07 +02:00
|
|
|
|
|
|
|
LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
|
|
|
|
if (path_equal(path, b->path) && read == b->read) {
|
|
|
|
a = b;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
if (!a) {
|
2013-09-10 17:23:07 +02:00
|
|
|
a = new0(CGroupBlockIODeviceBandwidth, 1);
|
|
|
|
if (!a)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
a->read = read;
|
|
|
|
a->path = strdup(path);
|
|
|
|
if (!a->path) {
|
|
|
|
free(a);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2013-11-19 21:12:59 +01:00
|
|
|
|
|
|
|
LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
|
2013-09-10 17:23:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
a->bandwidth = u64;
|
|
|
|
}
|
|
|
|
|
|
|
|
n++;
|
|
|
|
}
|
2013-11-19 21:12:59 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-09-10 17:23:07 +02:00
|
|
|
|
2014-02-24 02:59:57 +01:00
|
|
|
r = sd_bus_message_exit_container(message);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2013-09-10 17:23:07 +02:00
|
|
|
if (mode != UNIT_CHECK) {
|
2013-11-19 21:12:59 +01:00
|
|
|
CGroupBlockIODeviceBandwidth *a, *next;
|
2013-09-10 17:23:07 +02:00
|
|
|
_cleanup_free_ char *buf = NULL;
|
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
|
|
|
size_t size = 0;
|
|
|
|
|
|
|
|
if (n == 0) {
|
|
|
|
LIST_FOREACH_SAFE(device_bandwidths, a, next, c->blockio_device_bandwidths)
|
|
|
|
if (a->read == read)
|
|
|
|
cgroup_context_free_blockio_device_bandwidth(c, a);
|
|
|
|
}
|
|
|
|
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO;
|
2014-04-25 13:26:37 +02:00
|
|
|
|
2013-09-10 17:23:07 +02:00
|
|
|
f = open_memstream(&buf, &size);
|
|
|
|
if (!f)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2015-08-06 00:31:09 +02:00
|
|
|
if (read) {
|
2013-09-10 17:23:07 +02:00
|
|
|
fputs("BlockIOReadBandwidth=\n", f);
|
2015-08-06 00:31:09 +02:00
|
|
|
LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
|
2013-09-10 17:23:07 +02:00
|
|
|
if (a->read)
|
|
|
|
fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth);
|
|
|
|
} else {
|
|
|
|
fputs("BlockIOWriteBandwidth=\n", f);
|
|
|
|
LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
|
|
|
|
if (!a->read)
|
|
|
|
fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->bandwidth);
|
|
|
|
}
|
|
|
|
|
2013-08-27 07:36:53 +02:00
|
|
|
fflush(f);
|
|
|
|
unit_write_drop_in_private(u, mode, name, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
} else if (streq(name, "BlockIODeviceWeight")) {
|
2013-11-19 21:12:59 +01:00
|
|
|
const char *path;
|
2015-09-11 16:48:24 +02:00
|
|
|
uint64_t weight;
|
2013-08-27 07:36:53 +02:00
|
|
|
unsigned n = 0;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_enter_container(message, 'a', "(st)");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-08-27 07:36:53 +02:00
|
|
|
|
2015-09-11 16:48:24 +02:00
|
|
|
while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
|
2013-08-27 07:36:53 +02:00
|
|
|
|
2015-09-11 16:48:24 +02:00
|
|
|
if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
|
2013-11-19 21:12:59 +01:00
|
|
|
return sd_bus_error_set_errnof(error, EINVAL, "BlockIODeviceWeight out of range");
|
2013-08-27 07:36:53 +02:00
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
2013-11-19 21:12:59 +01:00
|
|
|
CGroupBlockIODeviceWeight *a = NULL, *b;
|
2013-08-27 07:36:53 +02:00
|
|
|
|
|
|
|
LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
|
|
|
|
if (path_equal(b->path, path)) {
|
|
|
|
a = b;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
if (!a) {
|
2013-08-27 07:36:53 +02:00
|
|
|
a = new0(CGroupBlockIODeviceWeight, 1);
|
|
|
|
if (!a)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
a->path = strdup(path);
|
|
|
|
if (!a->path) {
|
|
|
|
free(a);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2013-11-19 21:12:59 +01:00
|
|
|
LIST_PREPEND(device_weights,c->blockio_device_weights, a);
|
2013-08-27 07:36:53 +02:00
|
|
|
}
|
|
|
|
|
2015-09-11 16:48:24 +02:00
|
|
|
a->weight = weight;
|
2013-08-27 07:36:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
|
2014-02-24 02:59:57 +01:00
|
|
|
r = sd_bus_message_exit_container(message);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2013-08-27 07:36:53 +02:00
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
_cleanup_free_ char *buf = NULL;
|
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
|
|
|
CGroupBlockIODeviceWeight *a;
|
|
|
|
size_t size = 0;
|
|
|
|
|
|
|
|
if (n == 0) {
|
|
|
|
while (c->blockio_device_weights)
|
|
|
|
cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
|
|
|
|
}
|
|
|
|
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_BLKIO;
|
2014-04-25 13:26:37 +02:00
|
|
|
|
2013-08-27 07:36:53 +02:00
|
|
|
f = open_memstream(&buf, &size);
|
|
|
|
if (!f)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
fputs("BlockIODeviceWeight=\n", f);
|
|
|
|
LIST_FOREACH(device_weights, a, c->blockio_device_weights)
|
2015-09-11 16:48:24 +02:00
|
|
|
fprintf(f, "BlockIODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
|
2013-08-27 07:36:53 +02:00
|
|
|
|
2013-09-10 17:23:07 +02:00
|
|
|
fflush(f);
|
|
|
|
unit_write_drop_in_private(u, mode, name, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
2013-06-27 21:14:56 +02:00
|
|
|
} else if (streq(name, "MemoryAccounting")) {
|
2013-11-19 21:12:59 +01:00
|
|
|
int b;
|
2013-06-27 21:14:56 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "b", &b);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 21:14:56 +02:00
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
2013-06-27 21:50:35 +02:00
|
|
|
c->memory_accounting = b;
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_MEMORY;
|
2013-07-11 21:29:33 +02:00
|
|
|
unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no");
|
2013-06-27 21:14:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
2013-09-17 21:58:00 +02:00
|
|
|
} else if (streq(name, "MemoryLimit")) {
|
2013-11-19 21:12:59 +01:00
|
|
|
uint64_t limit;
|
2013-06-27 21:50:35 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "t", &limit);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 21:50:35 +02:00
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
2013-09-17 21:58:00 +02:00
|
|
|
c->memory_limit = limit;
|
core: unified cgroup hierarchy support
This patch set adds full support the new unified cgroup hierarchy logic
of modern kernels.
A new kernel command line option "systemd.unified_cgroup_hierarchy=1" is
added. If specified the unified hierarchy is mounted to /sys/fs/cgroup
instead of a tmpfs. No further hierarchies are mounted. The kernel
command line option defaults to off. We can turn it on by default as
soon as the kernel's APIs regarding this are stabilized (but even then
downstream distros might want to turn this off, as this will break any
tools that access cgroupfs directly).
It is possibly to choose for each boot individually whether the unified
or the legacy hierarchy is used. nspawn will by default provide the
legacy hierarchy to containers if the host is using it, and the unified
otherwise. However it is possible to run containers with the unified
hierarchy on a legacy host and vice versa, by setting the
$UNIFIED_CGROUP_HIERARCHY environment variable for nspawn to 1 or 0,
respectively.
The unified hierarchy provides reliable cgroup empty notifications for
the first time, via inotify. To make use of this we maintain one
manager-wide inotify fd, and each cgroup to it.
This patch also removes cg_delete() which is unused now.
On kernel 4.2 only the "memory" controller is compatible with the
unified hierarchy, hence that's the only controller systemd exposes when
booted in unified heirarchy mode.
This introduces a new enum for enumerating supported controllers, plus a
related enum for the mask bits mapping to it. The core is changed to
make use of this everywhere.
This moves PID 1 into a new "init.scope" implicit scope unit in the root
slice. This is necessary since on the unified hierarchy cgroups may
either contain subgroups or processes but not both. PID 1 hence has to
move out of the root cgroup (strictly speaking the root cgroup is the
only one where processes and subgroups are still allowed, but in order
to support containers nicey, we move PID 1 into the new scope in all
cases.) This new unit is also used on legacy hierarchy setups. It's
actually pretty useful on all systems, as it can then be used to filter
journal messages coming from PID 1, and so on.
The root slice ("-.slice") is now implicitly created and started (and
does not require a unit file on disk anymore), since
that's where "init.scope" is located and the slice needs to be started
before the scope can.
To check whether we are in unified or legacy hierarchy mode we use
statfs() on /sys/fs/cgroup. If the .f_type field reports tmpfs we are in
legacy mode, if it reports cgroupfs we are in unified mode.
This patch set carefuly makes sure that cgls and cgtop continue to work
as desired.
When invoking nspawn as a service it will implicitly create two
subcgroups in the cgroup it is using, one to move the nspawn process
into, the other to move the actual container processes into. This is
done because of the requirement that cgroups may either contain
processes or other subgroups.
2015-09-01 19:22:36 +02:00
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_MEMORY;
|
2015-09-10 12:32:16 +02:00
|
|
|
|
|
|
|
if (limit == (uint64_t) -1)
|
|
|
|
unit_write_drop_in_private(u, mode, name, "MemoryLimit=infinity");
|
|
|
|
else
|
|
|
|
unit_write_drop_in_private_format(u, mode, name, "MemoryLimit=%" PRIu64, limit);
|
2013-06-27 21:50:35 +02:00
|
|
|
}
|
|
|
|
|
2013-06-27 23:13:17 +02:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
} else if (streq(name, "DevicePolicy")) {
|
|
|
|
const char *policy;
|
|
|
|
CGroupDevicePolicy p;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_read(message, "s", &policy);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 23:13:17 +02:00
|
|
|
|
|
|
|
p = cgroup_device_policy_from_string(policy);
|
|
|
|
if (p < 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
char *buf;
|
|
|
|
|
|
|
|
c->device_policy = p;
|
2015-09-08 18:15:50 +02:00
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_DEVICES;
|
2013-06-27 23:13:17 +02:00
|
|
|
|
2015-02-03 02:05:59 +01:00
|
|
|
buf = strjoina("DevicePolicy=", policy);
|
2013-07-11 21:29:33 +02:00
|
|
|
unit_write_drop_in_private(u, mode, name, buf);
|
2013-06-27 23:13:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
} else if (streq(name, "DeviceAllow")) {
|
2013-11-19 21:12:59 +01:00
|
|
|
const char *path, *rwm;
|
2013-06-27 23:13:17 +02:00
|
|
|
unsigned n = 0;
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
r = sd_bus_message_enter_container(message, 'a', "(ss)");
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 23:13:17 +02:00
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
|
2013-06-27 23:13:17 +02:00
|
|
|
|
2014-02-22 02:47:29 +01:00
|
|
|
if ((!startswith(path, "/dev/") &&
|
|
|
|
!startswith(path, "block-") &&
|
|
|
|
!startswith(path, "char-")) ||
|
|
|
|
strpbrk(path, WHITESPACE))
|
|
|
|
return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node");
|
2013-06-27 23:13:17 +02:00
|
|
|
|
|
|
|
if (isempty(rwm))
|
|
|
|
rwm = "rwm";
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
if (!in_charset(rwm, "rwm"))
|
|
|
|
return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires combination of rwm flags");
|
2013-06-27 23:13:17 +02:00
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
2013-11-19 21:12:59 +01:00
|
|
|
CGroupDeviceAllow *a = NULL, *b;
|
2013-08-28 03:49:11 +02:00
|
|
|
|
|
|
|
LIST_FOREACH(device_allow, b, c->device_allow) {
|
2013-09-10 18:21:10 +02:00
|
|
|
if (path_equal(b->path, path)) {
|
2013-08-28 03:49:11 +02:00
|
|
|
a = b;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-19 21:12:59 +01:00
|
|
|
if (!a) {
|
2013-08-28 03:49:11 +02:00
|
|
|
a = new0(CGroupDeviceAllow, 1);
|
|
|
|
if (!a)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
a->path = strdup(path);
|
|
|
|
if (!a->path) {
|
|
|
|
free(a);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
2013-11-19 21:12:59 +01:00
|
|
|
|
|
|
|
LIST_PREPEND(device_allow, c->device_allow, a);
|
2013-06-27 23:13:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
a->r = !!strchr(rwm, 'r');
|
|
|
|
a->w = !!strchr(rwm, 'w');
|
|
|
|
a->m = !!strchr(rwm, 'm');
|
|
|
|
}
|
|
|
|
|
2013-06-28 04:12:58 +02:00
|
|
|
n++;
|
2013-06-27 23:13:17 +02:00
|
|
|
}
|
2013-12-25 19:00:12 +01:00
|
|
|
if (r < 0)
|
|
|
|
return r;
|
2013-06-27 23:13:17 +02:00
|
|
|
|
2014-02-24 02:59:57 +01:00
|
|
|
r = sd_bus_message_exit_container(message);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
2013-06-27 23:13:17 +02:00
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
_cleanup_free_ char *buf = NULL;
|
|
|
|
_cleanup_fclose_ FILE *f = NULL;
|
|
|
|
CGroupDeviceAllow *a;
|
|
|
|
size_t size = 0;
|
|
|
|
|
|
|
|
if (n == 0) {
|
|
|
|
while (c->device_allow)
|
|
|
|
cgroup_context_free_device_allow(c, c->device_allow);
|
|
|
|
}
|
|
|
|
|
2015-09-08 18:15:50 +02:00
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_DEVICES;
|
2014-04-25 13:26:37 +02:00
|
|
|
|
2013-06-27 23:13:17 +02:00
|
|
|
f = open_memstream(&buf, &size);
|
|
|
|
if (!f)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
fputs("DeviceAllow=\n", f);
|
|
|
|
LIST_FOREACH(device_allow, a, c->device_allow)
|
|
|
|
fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
|
|
|
|
|
|
|
|
fflush(f);
|
2013-07-11 21:29:33 +02:00
|
|
|
unit_write_drop_in_private(u, mode, name, buf);
|
2013-06-27 23:13:17 +02:00
|
|
|
}
|
|
|
|
|
2013-06-27 21:50:35 +02:00
|
|
|
return 1;
|
2014-11-05 17:57:23 +01:00
|
|
|
|
2015-09-10 12:32:16 +02:00
|
|
|
} else if (streq(name, "TasksAccounting")) {
|
|
|
|
int b;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(message, "b", &b);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
c->tasks_accounting = b;
|
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_PIDS;
|
|
|
|
unit_write_drop_in_private(u, mode, name, b ? "TasksAccounting=yes" : "TasksAccounting=no");
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
} else if (streq(name, "TasksMax")) {
|
|
|
|
uint64_t limit;
|
|
|
|
|
|
|
|
r = sd_bus_message_read(message, "t", &limit);
|
|
|
|
if (r < 0)
|
|
|
|
return r;
|
|
|
|
|
|
|
|
if (mode != UNIT_CHECK) {
|
|
|
|
c->tasks_max = limit;
|
|
|
|
u->cgroup_realized_mask &= ~CGROUP_MASK_PIDS;
|
|
|
|
|
|
|
|
if (limit == (uint64_t) -1)
|
|
|
|
unit_write_drop_in_private(u, mode, name, "TasksMax=infinity");
|
|
|
|
else
|
|
|
|
unit_write_drop_in_private_format(u, mode, name, "TasksMax=%" PRIu64, limit);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
2014-11-05 17:57:23 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (u->transient && u->load_state == UNIT_STUB) {
|
|
|
|
r = bus_cgroup_set_transient_property(u, c, name, message, mode, error);
|
|
|
|
if (r != 0)
|
|
|
|
return r;
|
|
|
|
|
2013-06-27 21:50:35 +02:00
|
|
|
}
|
2013-06-27 21:14:56 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|