mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-26 09:57:26 +03:00
Merge pull request #3193 from htejun/cgroup-io-controller
core: add io controller support on the unified hierarchy
This commit is contained in:
commit
3103459e90
@ -248,10 +248,104 @@
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>IOAccounting=</varname></term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Turn on Block I/O accounting for this unit on unified
|
||||||
|
hierarchy. Takes a boolean argument. Note that turning on
|
||||||
|
block I/O accounting for one unit will also implicitly turn
|
||||||
|
it on for all units contained in the same slice and all for
|
||||||
|
its parent slices and the units contained therein. The
|
||||||
|
system default for this setting may be controlled with
|
||||||
|
<varname>DefaultIOAccounting=</varname> in
|
||||||
|
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>IOWeight=<replaceable>weight</replaceable></varname></term>
|
||||||
|
<term><varname>StartupIOWeight=<replaceable>weight</replaceable></varname></term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Set the default overall block I/O weight for the
|
||||||
|
executed processes on unified hierarchy. Takes a single
|
||||||
|
weight value (between 1 and 10000) to set the default block
|
||||||
|
I/O weight. This controls the <literal>io.weight</literal>
|
||||||
|
control group attribute, which defaults to 100. For details
|
||||||
|
about this control group attribute, see <ulink
|
||||||
|
url="https://www.kernel.org/doc/Documentation/cgroup-v2.txt">cgroup-v2.txt</ulink>.
|
||||||
|
The available I/O bandwidth is split up among all units
|
||||||
|
within one slice relative to their block I/O weight.</para>
|
||||||
|
|
||||||
|
<para>While <varname>StartupIOWeight=</varname> only applies
|
||||||
|
to the startup phase of the system,
|
||||||
|
<varname>IOWeight=</varname> applies to the later runtime of
|
||||||
|
the system, and if the former is not set also to the startup
|
||||||
|
phase. This allows prioritizing specific services at boot-up
|
||||||
|
differently than during runtime.</para>
|
||||||
|
|
||||||
|
<para>Implies <literal>IOAccounting=true</literal>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>IODeviceWeight=<replaceable>device</replaceable> <replaceable>weight</replaceable></varname></term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Set the per-device overall block I/O weight for the
|
||||||
|
executed processes on unified hierarchy. Takes a
|
||||||
|
space-separated pair of a file path and a weight value to
|
||||||
|
specify the device specific weight value, between 1 and
|
||||||
|
10000. (Example: "/dev/sda 1000"). The file path may be
|
||||||
|
specified as path to a block device node or as any other
|
||||||
|
file, in which case the backing block device of the file
|
||||||
|
system of the file is determined. This controls the
|
||||||
|
<literal>io.weight</literal> control group attribute, which
|
||||||
|
defaults to 100. Use this option multiple times to set
|
||||||
|
weights for multiple devices. For details about this control
|
||||||
|
group attribute, see <ulink
|
||||||
|
url="https://www.kernel.org/doc/Documentation/cgroup-v2.txt">cgroup-v2.txt</ulink>.</para>
|
||||||
|
|
||||||
|
<para>Implies <literal>IOAccounting=true</literal>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>IOReadBandwidthMax=<replaceable>device</replaceable> <replaceable>bytes</replaceable></varname></term>
|
||||||
|
<term><varname>IOWriteBandwidthMax=<replaceable>device</replaceable> <replaceable>bytes</replaceable></varname></term>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>Set the per-device overall block I/O bandwidth maximum
|
||||||
|
limit for the executed processes on unified hierarchy. This
|
||||||
|
limit is not work-conserving and the executed processes are
|
||||||
|
not allowed to use more even if the device has idle
|
||||||
|
capacity. Takes a space-separated pair of a file path and a
|
||||||
|
bandwidth value (in bytes per second) to specify the device
|
||||||
|
specific bandwidth. The file path may be a path to a block
|
||||||
|
device node, or as any other file in which case the backing
|
||||||
|
block device of the file system of the file is used. If the
|
||||||
|
bandwidth is suffixed with K, M, G, or T, the specified
|
||||||
|
bandwidth is parsed as Kilobytes, Megabytes, Gigabytes, or
|
||||||
|
Terabytes, respectively, to the base of 1000. (Example:
|
||||||
|
"/dev/disk/by-path/pci-0000:00:1f.2-scsi-0:0:0:0 5M"). This
|
||||||
|
controls the <literal>io.max</literal> control group
|
||||||
|
attributes. Use this option multiple times to set bandwidth
|
||||||
|
limits for multiple devices. For details about this control
|
||||||
|
group attribute, see <ulink
|
||||||
|
url="https://www.kernel.org/doc/Documentation/cgroup-v2.txt">cgroup-v2.txt</ulink>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>Implies <literal>IOAccounting=true</literal>.</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>BlockIOAccounting=</varname></term>
|
<term><varname>BlockIOAccounting=</varname></term>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
|
<para>Use IOAccounting on unified hierarchy.</para>
|
||||||
|
|
||||||
<para>Turn on Block I/O accounting for this unit. Takes a
|
<para>Turn on Block I/O accounting for this unit. Takes a
|
||||||
boolean argument. Note that turning on block I/O accounting
|
boolean argument. Note that turning on block I/O accounting
|
||||||
for one unit will also implicitly turn it on for all units
|
for one unit will also implicitly turn it on for all units
|
||||||
@ -267,9 +361,12 @@
|
|||||||
<term><varname>BlockIOWeight=<replaceable>weight</replaceable></varname></term>
|
<term><varname>BlockIOWeight=<replaceable>weight</replaceable></varname></term>
|
||||||
<term><varname>StartupBlockIOWeight=<replaceable>weight</replaceable></varname></term>
|
<term><varname>StartupBlockIOWeight=<replaceable>weight</replaceable></varname></term>
|
||||||
|
|
||||||
<listitem><para>Set the default overall block I/O weight for
|
<listitem><para>Use IOWeight and StartupIOWeight on unified
|
||||||
the executed processes. Takes a single weight value (between
|
hierarchy.</para>
|
||||||
10 and 1000) to set the default block I/O weight. This controls
|
|
||||||
|
<para>Set the default overall block I/O weight for the
|
||||||
|
executed processes. Takes a single weight value (between 10
|
||||||
|
and 1000) to set the default block I/O weight. This controls
|
||||||
the <literal>blkio.weight</literal> control group attribute,
|
the <literal>blkio.weight</literal> control group attribute,
|
||||||
which defaults to 500. For details about this control group
|
which defaults to 500. For details about this control group
|
||||||
attribute, see <ulink
|
attribute, see <ulink
|
||||||
@ -293,6 +390,8 @@
|
|||||||
<term><varname>BlockIODeviceWeight=<replaceable>device</replaceable> <replaceable>weight</replaceable></varname></term>
|
<term><varname>BlockIODeviceWeight=<replaceable>device</replaceable> <replaceable>weight</replaceable></varname></term>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
|
<para>Use IODeviceWeight on unified hierarchy.</para>
|
||||||
|
|
||||||
<para>Set the per-device overall block I/O weight for the
|
<para>Set the per-device overall block I/O weight for the
|
||||||
executed processes. Takes a space-separated pair of a file
|
executed processes. Takes a space-separated pair of a file
|
||||||
path and a weight value to specify the device specific
|
path and a weight value to specify the device specific
|
||||||
@ -317,6 +416,9 @@
|
|||||||
<term><varname>BlockIOWriteBandwidth=<replaceable>device</replaceable> <replaceable>bytes</replaceable></varname></term>
|
<term><varname>BlockIOWriteBandwidth=<replaceable>device</replaceable> <replaceable>bytes</replaceable></varname></term>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
|
<para>Use IOReadBandwidthMax and IOWriteBandwidthMax on
|
||||||
|
unified hierarchy.</para>
|
||||||
|
|
||||||
<para>Set the per-device overall block I/O bandwidth limit
|
<para>Set the per-device overall block I/O bandwidth limit
|
||||||
for the executed processes. Takes a space-separated pair of
|
for the executed processes. Takes a space-separated pair of
|
||||||
a file path and a bandwidth value (in bytes per second) to
|
a file path and a bandwidth value (in bytes per second) to
|
||||||
|
@ -2060,10 +2060,10 @@ int cg_mask_supported(CGroupMask *ret) {
|
|||||||
mask |= CGROUP_CONTROLLER_TO_MASK(v);
|
mask |= CGROUP_CONTROLLER_TO_MASK(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Currently, we only support the memory and pids
|
/* Currently, we only support the memory, io and pids
|
||||||
* controller in the unified hierarchy, mask
|
* controller in the unified hierarchy, mask
|
||||||
* everything else off. */
|
* everything else off. */
|
||||||
mask &= CGROUP_MASK_MEMORY | CGROUP_MASK_PIDS;
|
mask &= CGROUP_MASK_MEMORY | CGROUP_MASK_IO | CGROUP_MASK_PIDS;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
CGroupController c;
|
CGroupController c;
|
||||||
@ -2249,6 +2249,26 @@ bool cg_is_legacy_wanted(void) {
|
|||||||
return !cg_is_unified_wanted();
|
return !cg_is_unified_wanted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cg_weight_parse(const char *s, uint64_t *ret) {
|
||||||
|
uint64_t u;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if (isempty(s)) {
|
||||||
|
*ret = CGROUP_WEIGHT_INVALID;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = safe_atou64(s, &u);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (u < CGROUP_WEIGHT_MIN || u > CGROUP_WEIGHT_MAX)
|
||||||
|
return -ERANGE;
|
||||||
|
|
||||||
|
*ret = u;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int cg_cpu_shares_parse(const char *s, uint64_t *ret) {
|
int cg_cpu_shares_parse(const char *s, uint64_t *ret) {
|
||||||
uint64_t u;
|
uint64_t u;
|
||||||
int r;
|
int r;
|
||||||
@ -2292,6 +2312,7 @@ int cg_blkio_weight_parse(const char *s, uint64_t *ret) {
|
|||||||
static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = {
|
static const char *cgroup_controller_table[_CGROUP_CONTROLLER_MAX] = {
|
||||||
[CGROUP_CONTROLLER_CPU] = "cpu",
|
[CGROUP_CONTROLLER_CPU] = "cpu",
|
||||||
[CGROUP_CONTROLLER_CPUACCT] = "cpuacct",
|
[CGROUP_CONTROLLER_CPUACCT] = "cpuacct",
|
||||||
|
[CGROUP_CONTROLLER_IO] = "io",
|
||||||
[CGROUP_CONTROLLER_BLKIO] = "blkio",
|
[CGROUP_CONTROLLER_BLKIO] = "blkio",
|
||||||
[CGROUP_CONTROLLER_MEMORY] = "memory",
|
[CGROUP_CONTROLLER_MEMORY] = "memory",
|
||||||
[CGROUP_CONTROLLER_DEVICES] = "devices",
|
[CGROUP_CONTROLLER_DEVICES] = "devices",
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
typedef enum CGroupController {
|
typedef enum CGroupController {
|
||||||
CGROUP_CONTROLLER_CPU,
|
CGROUP_CONTROLLER_CPU,
|
||||||
CGROUP_CONTROLLER_CPUACCT,
|
CGROUP_CONTROLLER_CPUACCT,
|
||||||
|
CGROUP_CONTROLLER_IO,
|
||||||
CGROUP_CONTROLLER_BLKIO,
|
CGROUP_CONTROLLER_BLKIO,
|
||||||
CGROUP_CONTROLLER_MEMORY,
|
CGROUP_CONTROLLER_MEMORY,
|
||||||
CGROUP_CONTROLLER_DEVICES,
|
CGROUP_CONTROLLER_DEVICES,
|
||||||
@ -48,6 +49,7 @@ typedef enum CGroupController {
|
|||||||
typedef enum CGroupMask {
|
typedef enum CGroupMask {
|
||||||
CGROUP_MASK_CPU = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPU),
|
CGROUP_MASK_CPU = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPU),
|
||||||
CGROUP_MASK_CPUACCT = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUACCT),
|
CGROUP_MASK_CPUACCT = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_CPUACCT),
|
||||||
|
CGROUP_MASK_IO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_IO),
|
||||||
CGROUP_MASK_BLKIO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BLKIO),
|
CGROUP_MASK_BLKIO = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_BLKIO),
|
||||||
CGROUP_MASK_MEMORY = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_MEMORY),
|
CGROUP_MASK_MEMORY = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_MEMORY),
|
||||||
CGROUP_MASK_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_DEVICES),
|
CGROUP_MASK_DEVICES = CGROUP_CONTROLLER_TO_MASK(CGROUP_CONTROLLER_DEVICES),
|
||||||
@ -55,6 +57,21 @@ typedef enum CGroupMask {
|
|||||||
_CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1
|
_CGROUP_MASK_ALL = CGROUP_CONTROLLER_TO_MASK(_CGROUP_CONTROLLER_MAX) - 1
|
||||||
} CGroupMask;
|
} CGroupMask;
|
||||||
|
|
||||||
|
/* Special values for all weight knobs on unified hierarchy */
|
||||||
|
#define CGROUP_WEIGHT_INVALID ((uint64_t) -1)
|
||||||
|
#define CGROUP_WEIGHT_MIN UINT64_C(1)
|
||||||
|
#define CGROUP_WEIGHT_MAX UINT64_C(10000)
|
||||||
|
#define CGROUP_WEIGHT_DEFAULT UINT64_C(100)
|
||||||
|
|
||||||
|
#define CGROUP_LIMIT_MIN UINT64_C(0)
|
||||||
|
#define CGROUP_LIMIT_MAX ((uint64_t) -1)
|
||||||
|
|
||||||
|
static inline bool CGROUP_WEIGHT_IS_OK(uint64_t x) {
|
||||||
|
return
|
||||||
|
x == CGROUP_WEIGHT_INVALID ||
|
||||||
|
(x >= CGROUP_WEIGHT_MIN && x <= CGROUP_WEIGHT_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
/* Special values for the cpu.shares attribute */
|
/* Special values for the cpu.shares attribute */
|
||||||
#define CGROUP_CPU_SHARES_INVALID ((uint64_t) -1)
|
#define CGROUP_CPU_SHARES_INVALID ((uint64_t) -1)
|
||||||
#define CGROUP_CPU_SHARES_MIN UINT64_C(2)
|
#define CGROUP_CPU_SHARES_MIN UINT64_C(2)
|
||||||
@ -190,5 +207,6 @@ bool cg_is_legacy_wanted(void);
|
|||||||
const char* cgroup_controller_to_string(CGroupController c) _const_;
|
const char* cgroup_controller_to_string(CGroupController c) _const_;
|
||||||
CGroupController cgroup_controller_from_string(const char *s) _pure_;
|
CGroupController cgroup_controller_from_string(const char *s) _pure_;
|
||||||
|
|
||||||
|
int cg_weight_parse(const char *s, uint64_t *ret);
|
||||||
int cg_cpu_shares_parse(const char *s, uint64_t *ret);
|
int cg_cpu_shares_parse(const char *s, uint64_t *ret);
|
||||||
int cg_blkio_weight_parse(const char *s, uint64_t *ret);
|
int cg_blkio_weight_parse(const char *s, uint64_t *ret);
|
||||||
|
@ -269,13 +269,15 @@ static int process(
|
|||||||
if (g->memory > 0)
|
if (g->memory > 0)
|
||||||
g->memory_valid = true;
|
g->memory_valid = true;
|
||||||
|
|
||||||
} else if (streq(controller, "blkio") && cg_unified() <= 0) {
|
} else if ((streq(controller, "io") && cg_unified() > 0) ||
|
||||||
|
(streq(controller, "blkio") && cg_unified() <= 0)) {
|
||||||
_cleanup_fclose_ FILE *f = NULL;
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
_cleanup_free_ char *p = NULL;
|
_cleanup_free_ char *p = NULL;
|
||||||
|
bool unified = cg_unified() > 0;
|
||||||
uint64_t wr = 0, rd = 0;
|
uint64_t wr = 0, rd = 0;
|
||||||
nsec_t timestamp;
|
nsec_t timestamp;
|
||||||
|
|
||||||
r = cg_get_path(controller, path, "blkio.io_service_bytes", &p);
|
r = cg_get_path(controller, path, unified ? "io.stat" : "blkio.io_service_bytes", &p);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
@ -293,25 +295,38 @@ static int process(
|
|||||||
if (!fgets(line, sizeof(line), f))
|
if (!fgets(line, sizeof(line), f))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Trim and skip the device */
|
||||||
l = strstrip(line);
|
l = strstrip(line);
|
||||||
l += strcspn(l, WHITESPACE);
|
l += strcspn(l, WHITESPACE);
|
||||||
l += strspn(l, WHITESPACE);
|
l += strspn(l, WHITESPACE);
|
||||||
|
|
||||||
if (first_word(l, "Read")) {
|
if (unified) {
|
||||||
l += 4;
|
while (!isempty(l)) {
|
||||||
q = &rd;
|
if (sscanf(l, "rbytes=%" SCNu64, &k))
|
||||||
} else if (first_word(l, "Write")) {
|
rd += k;
|
||||||
l += 5;
|
else if (sscanf(l, "wbytes=%" SCNu64, &k))
|
||||||
q = ≀
|
wr += k;
|
||||||
} else
|
|
||||||
continue;
|
|
||||||
|
|
||||||
l += strspn(l, WHITESPACE);
|
l += strcspn(l, WHITESPACE);
|
||||||
r = safe_atou64(l, &k);
|
l += strspn(l, WHITESPACE);
|
||||||
if (r < 0)
|
}
|
||||||
continue;
|
} else {
|
||||||
|
if (first_word(l, "Read")) {
|
||||||
|
l += 4;
|
||||||
|
q = &rd;
|
||||||
|
} else if (first_word(l, "Write")) {
|
||||||
|
l += 5;
|
||||||
|
q = ≀
|
||||||
|
} else
|
||||||
|
continue;
|
||||||
|
|
||||||
*q += k;
|
l += strspn(l, WHITESPACE);
|
||||||
|
r = safe_atou64(l, &k);
|
||||||
|
if (r < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*q += k;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
timestamp = now_nsec(CLOCK_MONOTONIC);
|
timestamp = now_nsec(CLOCK_MONOTONIC);
|
||||||
@ -437,6 +452,9 @@ static int refresh(const char *root, Hashmap *a, Hashmap *b, unsigned iteration)
|
|||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
r = refresh_one("memory", root, a, b, iteration, 0, NULL);
|
r = refresh_one("memory", root, a, b, iteration, 0, NULL);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
r = refresh_one("io", root, a, b, iteration, 0, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
r = refresh_one("blkio", root, a, b, iteration, 0, NULL);
|
r = refresh_one("blkio", root, a, b, iteration, 0, NULL);
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include "special.h"
|
#include "special.h"
|
||||||
#include "string-table.h"
|
#include "string-table.h"
|
||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
|
#include "stdio-util.h"
|
||||||
|
|
||||||
#define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
|
#define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
|
||||||
|
|
||||||
@ -47,6 +48,9 @@ void cgroup_context_init(CGroupContext *c) {
|
|||||||
|
|
||||||
c->memory_limit = (uint64_t) -1;
|
c->memory_limit = (uint64_t) -1;
|
||||||
|
|
||||||
|
c->io_weight = CGROUP_WEIGHT_INVALID;
|
||||||
|
c->startup_io_weight = CGROUP_WEIGHT_INVALID;
|
||||||
|
|
||||||
c->blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
|
c->blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
|
||||||
c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
|
c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
|
||||||
|
|
||||||
@ -62,6 +66,24 @@ void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
|
|||||||
free(a);
|
free(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight *w) {
|
||||||
|
assert(c);
|
||||||
|
assert(w);
|
||||||
|
|
||||||
|
LIST_REMOVE(device_weights, c->io_device_weights, w);
|
||||||
|
free(w->path);
|
||||||
|
free(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cgroup_context_free_io_device_limit(CGroupContext *c, CGroupIODeviceLimit *l) {
|
||||||
|
assert(c);
|
||||||
|
assert(l);
|
||||||
|
|
||||||
|
LIST_REMOVE(device_limits, c->io_device_limits, l);
|
||||||
|
free(l->path);
|
||||||
|
free(l);
|
||||||
|
}
|
||||||
|
|
||||||
void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) {
|
void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) {
|
||||||
assert(c);
|
assert(c);
|
||||||
assert(w);
|
assert(w);
|
||||||
@ -83,6 +105,12 @@ void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockI
|
|||||||
void cgroup_context_done(CGroupContext *c) {
|
void cgroup_context_done(CGroupContext *c) {
|
||||||
assert(c);
|
assert(c);
|
||||||
|
|
||||||
|
while (c->io_device_weights)
|
||||||
|
cgroup_context_free_io_device_weight(c, c->io_device_weights);
|
||||||
|
|
||||||
|
while (c->io_device_limits)
|
||||||
|
cgroup_context_free_io_device_limit(c, c->io_device_limits);
|
||||||
|
|
||||||
while (c->blockio_device_weights)
|
while (c->blockio_device_weights)
|
||||||
cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
|
cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
|
||||||
|
|
||||||
@ -94,6 +122,8 @@ void cgroup_context_done(CGroupContext *c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
|
void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
|
||||||
|
CGroupIODeviceLimit *il;
|
||||||
|
CGroupIODeviceWeight *iw;
|
||||||
CGroupBlockIODeviceBandwidth *b;
|
CGroupBlockIODeviceBandwidth *b;
|
||||||
CGroupBlockIODeviceWeight *w;
|
CGroupBlockIODeviceWeight *w;
|
||||||
CGroupDeviceAllow *a;
|
CGroupDeviceAllow *a;
|
||||||
@ -106,12 +136,15 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
|
|||||||
|
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"%sCPUAccounting=%s\n"
|
"%sCPUAccounting=%s\n"
|
||||||
|
"%sIOAccounting=%s\n"
|
||||||
"%sBlockIOAccounting=%s\n"
|
"%sBlockIOAccounting=%s\n"
|
||||||
"%sMemoryAccounting=%s\n"
|
"%sMemoryAccounting=%s\n"
|
||||||
"%sTasksAccounting=%s\n"
|
"%sTasksAccounting=%s\n"
|
||||||
"%sCPUShares=%" PRIu64 "\n"
|
"%sCPUShares=%" PRIu64 "\n"
|
||||||
"%sStartupCPUShares=%" PRIu64 "\n"
|
"%sStartupCPUShares=%" PRIu64 "\n"
|
||||||
"%sCPUQuotaPerSecSec=%s\n"
|
"%sCPUQuotaPerSecSec=%s\n"
|
||||||
|
"%sIOWeight=%" PRIu64 "\n"
|
||||||
|
"%sStartupIOWeight=%" PRIu64 "\n"
|
||||||
"%sBlockIOWeight=%" PRIu64 "\n"
|
"%sBlockIOWeight=%" PRIu64 "\n"
|
||||||
"%sStartupBlockIOWeight=%" PRIu64 "\n"
|
"%sStartupBlockIOWeight=%" PRIu64 "\n"
|
||||||
"%sMemoryLimit=%" PRIu64 "\n"
|
"%sMemoryLimit=%" PRIu64 "\n"
|
||||||
@ -119,12 +152,15 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
|
|||||||
"%sDevicePolicy=%s\n"
|
"%sDevicePolicy=%s\n"
|
||||||
"%sDelegate=%s\n",
|
"%sDelegate=%s\n",
|
||||||
prefix, yes_no(c->cpu_accounting),
|
prefix, yes_no(c->cpu_accounting),
|
||||||
|
prefix, yes_no(c->io_accounting),
|
||||||
prefix, yes_no(c->blockio_accounting),
|
prefix, yes_no(c->blockio_accounting),
|
||||||
prefix, yes_no(c->memory_accounting),
|
prefix, yes_no(c->memory_accounting),
|
||||||
prefix, yes_no(c->tasks_accounting),
|
prefix, yes_no(c->tasks_accounting),
|
||||||
prefix, c->cpu_shares,
|
prefix, c->cpu_shares,
|
||||||
prefix, c->startup_cpu_shares,
|
prefix, c->startup_cpu_shares,
|
||||||
prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
|
prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
|
||||||
|
prefix, c->io_weight,
|
||||||
|
prefix, c->startup_io_weight,
|
||||||
prefix, c->blockio_weight,
|
prefix, c->blockio_weight,
|
||||||
prefix, c->startup_blockio_weight,
|
prefix, c->startup_blockio_weight,
|
||||||
prefix, c->memory_limit,
|
prefix, c->memory_limit,
|
||||||
@ -139,6 +175,31 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
|
|||||||
a->path,
|
a->path,
|
||||||
a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
|
a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
|
||||||
|
|
||||||
|
LIST_FOREACH(device_weights, iw, c->io_device_weights)
|
||||||
|
fprintf(f,
|
||||||
|
"%sIODeviceWeight=%s %" PRIu64,
|
||||||
|
prefix,
|
||||||
|
iw->path,
|
||||||
|
iw->weight);
|
||||||
|
|
||||||
|
LIST_FOREACH(device_limits, il, c->io_device_limits) {
|
||||||
|
char buf[FORMAT_BYTES_MAX];
|
||||||
|
|
||||||
|
if (il->rbps_max != CGROUP_LIMIT_MAX)
|
||||||
|
fprintf(f,
|
||||||
|
"%sIOReadBandwidthMax=%s %s\n",
|
||||||
|
prefix,
|
||||||
|
il->path,
|
||||||
|
format_bytes(buf, sizeof(buf), il->rbps_max));
|
||||||
|
|
||||||
|
if (il->wbps_max != CGROUP_LIMIT_MAX)
|
||||||
|
fprintf(f,
|
||||||
|
"%sIOWriteBandwidthMax=%s %s\n",
|
||||||
|
prefix,
|
||||||
|
il->path,
|
||||||
|
format_bytes(buf, sizeof(buf), il->wbps_max));
|
||||||
|
}
|
||||||
|
|
||||||
LIST_FOREACH(device_weights, w, c->blockio_device_weights)
|
LIST_FOREACH(device_weights, w, c->blockio_device_weights)
|
||||||
fprintf(f,
|
fprintf(f,
|
||||||
"%sBlockIODeviceWeight=%s %" PRIu64,
|
"%sBlockIODeviceWeight=%s %" PRIu64,
|
||||||
@ -158,7 +219,7 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lookup_blkio_device(const char *p, dev_t *dev) {
|
static int lookup_block_device(const char *p, dev_t *dev) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
@ -343,6 +404,77 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
|
|||||||
"Failed to set cpu.cfs_quota_us on %s: %m", path);
|
"Failed to set cpu.cfs_quota_us on %s: %m", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mask & CGROUP_MASK_IO) {
|
||||||
|
CGroupIODeviceWeight *w;
|
||||||
|
CGroupIODeviceLimit *l, *next;
|
||||||
|
|
||||||
|
if (!is_root) {
|
||||||
|
char buf[MAX(8+DECIMAL_STR_MAX(uint64_t)+1,
|
||||||
|
DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)];
|
||||||
|
uint64_t weight = CGROUP_WEIGHT_DEFAULT;
|
||||||
|
|
||||||
|
if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
|
||||||
|
c->startup_io_weight != CGROUP_WEIGHT_INVALID)
|
||||||
|
weight = c->startup_io_weight;
|
||||||
|
else if (c->io_weight != CGROUP_WEIGHT_INVALID)
|
||||||
|
weight = c->io_weight;
|
||||||
|
|
||||||
|
xsprintf(buf, "default %" PRIu64 "\n", weight);
|
||||||
|
r = cg_set_attribute("io", path, "io.weight", buf);
|
||||||
|
if (r < 0)
|
||||||
|
log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
|
||||||
|
"Failed to set io.weight on %s: %m", path);
|
||||||
|
|
||||||
|
/* FIXME: no way to reset this list */
|
||||||
|
LIST_FOREACH(device_weights, w, c->io_device_weights) {
|
||||||
|
dev_t dev;
|
||||||
|
|
||||||
|
r = lookup_block_device(w->path, &dev);
|
||||||
|
if (r < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), w->weight);
|
||||||
|
r = cg_set_attribute("io", path, "io.weight", buf);
|
||||||
|
if (r < 0)
|
||||||
|
log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
|
||||||
|
"Failed to set io.weight on %s: %m", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LIST_FOREACH_SAFE(device_limits, l, next, c->io_device_limits) {
|
||||||
|
char rbps_buf[DECIMAL_STR_MAX(uint64_t)] = "max";
|
||||||
|
char wbps_buf[DECIMAL_STR_MAX(uint64_t)] = "max";
|
||||||
|
char buf[DECIMAL_STR_MAX(dev_t)*2+2+(5+DECIMAL_STR_MAX(uint64_t)+1)*2];
|
||||||
|
dev_t dev;
|
||||||
|
unsigned n = 0;
|
||||||
|
|
||||||
|
r = lookup_block_device(l->path, &dev);
|
||||||
|
if (r < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (l->rbps_max != CGROUP_LIMIT_MAX) {
|
||||||
|
xsprintf(rbps_buf, "%" PRIu64, l->rbps_max);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l->wbps_max != CGROUP_LIMIT_MAX) {
|
||||||
|
xsprintf(wbps_buf, "%" PRIu64, l->wbps_max);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
xsprintf(buf, "%u:%u rbps=%s wbps=%s\n", major(dev), minor(dev), rbps_buf, wbps_buf);
|
||||||
|
r = cg_set_attribute("io", path, "io.max", buf);
|
||||||
|
if (r < 0)
|
||||||
|
log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
|
||||||
|
"Failed to set io.max on %s: %m", path);
|
||||||
|
|
||||||
|
/* If @l contained no config, we just cleared the kernel
|
||||||
|
counterpart too. No reason to keep @l around. */
|
||||||
|
if (!n)
|
||||||
|
cgroup_context_free_io_device_limit(c, l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (mask & CGROUP_MASK_BLKIO) {
|
if (mask & CGROUP_MASK_BLKIO) {
|
||||||
char buf[MAX(DECIMAL_STR_MAX(uint64_t)+1,
|
char buf[MAX(DECIMAL_STR_MAX(uint64_t)+1,
|
||||||
DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)];
|
DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1)];
|
||||||
@ -362,7 +494,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
|
|||||||
LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
|
LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
|
|
||||||
r = lookup_blkio_device(w->path, &dev);
|
r = lookup_block_device(w->path, &dev);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -379,7 +511,7 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
|
|||||||
const char *a;
|
const char *a;
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
|
|
||||||
r = lookup_blkio_device(b->path, &dev);
|
r = lookup_block_device(b->path, &dev);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -506,6 +638,13 @@ CGroupMask cgroup_context_get_mask(CGroupContext *c) {
|
|||||||
c->cpu_quota_per_sec_usec != USEC_INFINITY)
|
c->cpu_quota_per_sec_usec != USEC_INFINITY)
|
||||||
mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU;
|
mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU;
|
||||||
|
|
||||||
|
if (c->io_accounting ||
|
||||||
|
c->io_weight != CGROUP_WEIGHT_INVALID ||
|
||||||
|
c->startup_io_weight != CGROUP_WEIGHT_INVALID ||
|
||||||
|
c->io_device_weights ||
|
||||||
|
c->io_device_limits)
|
||||||
|
mask |= CGROUP_MASK_IO;
|
||||||
|
|
||||||
if (c->blockio_accounting ||
|
if (c->blockio_accounting ||
|
||||||
c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
|
c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
|
||||||
c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
|
c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
|
||||||
@ -1615,7 +1754,7 @@ void manager_invalidate_startup_units(Manager *m) {
|
|||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
SET_FOREACH(u, m->startup_units, i)
|
SET_FOREACH(u, m->startup_units, i)
|
||||||
unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_BLKIO);
|
unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_IO|CGROUP_MASK_BLKIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
|
static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
|
||||||
|
@ -26,6 +26,8 @@
|
|||||||
|
|
||||||
typedef struct CGroupContext CGroupContext;
|
typedef struct CGroupContext CGroupContext;
|
||||||
typedef struct CGroupDeviceAllow CGroupDeviceAllow;
|
typedef struct CGroupDeviceAllow CGroupDeviceAllow;
|
||||||
|
typedef struct CGroupIODeviceWeight CGroupIODeviceWeight;
|
||||||
|
typedef struct CGroupIODeviceLimit CGroupIODeviceLimit;
|
||||||
typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight;
|
typedef struct CGroupBlockIODeviceWeight CGroupBlockIODeviceWeight;
|
||||||
typedef struct CGroupBlockIODeviceBandwidth CGroupBlockIODeviceBandwidth;
|
typedef struct CGroupBlockIODeviceBandwidth CGroupBlockIODeviceBandwidth;
|
||||||
|
|
||||||
@ -53,6 +55,19 @@ struct CGroupDeviceAllow {
|
|||||||
bool m:1;
|
bool m:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CGroupIODeviceWeight {
|
||||||
|
LIST_FIELDS(CGroupIODeviceWeight, device_weights);
|
||||||
|
char *path;
|
||||||
|
uint64_t weight;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CGroupIODeviceLimit {
|
||||||
|
LIST_FIELDS(CGroupIODeviceLimit, device_limits);
|
||||||
|
char *path;
|
||||||
|
uint64_t rbps_max;
|
||||||
|
uint64_t wbps_max;
|
||||||
|
};
|
||||||
|
|
||||||
struct CGroupBlockIODeviceWeight {
|
struct CGroupBlockIODeviceWeight {
|
||||||
LIST_FIELDS(CGroupBlockIODeviceWeight, device_weights);
|
LIST_FIELDS(CGroupBlockIODeviceWeight, device_weights);
|
||||||
char *path;
|
char *path;
|
||||||
@ -68,10 +83,18 @@ struct CGroupBlockIODeviceBandwidth {
|
|||||||
|
|
||||||
struct CGroupContext {
|
struct CGroupContext {
|
||||||
bool cpu_accounting;
|
bool cpu_accounting;
|
||||||
|
bool io_accounting;
|
||||||
bool blockio_accounting;
|
bool blockio_accounting;
|
||||||
bool memory_accounting;
|
bool memory_accounting;
|
||||||
bool tasks_accounting;
|
bool tasks_accounting;
|
||||||
|
|
||||||
|
/* For unified hierarchy */
|
||||||
|
uint64_t io_weight;
|
||||||
|
uint64_t startup_io_weight;
|
||||||
|
LIST_HEAD(CGroupIODeviceWeight, io_device_weights);
|
||||||
|
LIST_HEAD(CGroupIODeviceLimit, io_device_limits);
|
||||||
|
|
||||||
|
/* For legacy hierarchies */
|
||||||
uint64_t cpu_shares;
|
uint64_t cpu_shares;
|
||||||
uint64_t startup_cpu_shares;
|
uint64_t startup_cpu_shares;
|
||||||
usec_t cpu_quota_per_sec_usec;
|
usec_t cpu_quota_per_sec_usec;
|
||||||
@ -86,6 +109,7 @@ struct CGroupContext {
|
|||||||
CGroupDevicePolicy device_policy;
|
CGroupDevicePolicy device_policy;
|
||||||
LIST_HEAD(CGroupDeviceAllow, device_allow);
|
LIST_HEAD(CGroupDeviceAllow, device_allow);
|
||||||
|
|
||||||
|
/* Common */
|
||||||
uint64_t tasks_max;
|
uint64_t tasks_max;
|
||||||
|
|
||||||
bool delegate;
|
bool delegate;
|
||||||
@ -102,6 +126,8 @@ void cgroup_context_apply(CGroupContext *c, CGroupMask mask, const char *path, M
|
|||||||
CGroupMask cgroup_context_get_mask(CGroupContext *c);
|
CGroupMask cgroup_context_get_mask(CGroupContext *c);
|
||||||
|
|
||||||
void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a);
|
void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a);
|
||||||
|
void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight *w);
|
||||||
|
void cgroup_context_free_io_device_limit(CGroupContext *c, CGroupIODeviceLimit *l);
|
||||||
void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w);
|
void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w);
|
||||||
void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b);
|
void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b);
|
||||||
|
|
||||||
|
@ -28,6 +28,76 @@
|
|||||||
|
|
||||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
|
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
|
||||||
|
|
||||||
|
static int property_get_io_device_weight(
|
||||||
|
sd_bus *bus,
|
||||||
|
const char *path,
|
||||||
|
const char *interface,
|
||||||
|
const char *property,
|
||||||
|
sd_bus_message *reply,
|
||||||
|
void *userdata,
|
||||||
|
sd_bus_error *error) {
|
||||||
|
|
||||||
|
CGroupContext *c = userdata;
|
||||||
|
CGroupIODeviceWeight *w;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(bus);
|
||||||
|
assert(reply);
|
||||||
|
assert(c);
|
||||||
|
|
||||||
|
r = sd_bus_message_open_container(reply, 'a', "(st)");
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
LIST_FOREACH(device_weights, w, c->io_device_weights) {
|
||||||
|
r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sd_bus_message_close_container(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int property_get_io_device_limits(
|
||||||
|
sd_bus *bus,
|
||||||
|
const char *path,
|
||||||
|
const char *interface,
|
||||||
|
const char *property,
|
||||||
|
sd_bus_message *reply,
|
||||||
|
void *userdata,
|
||||||
|
sd_bus_error *error) {
|
||||||
|
|
||||||
|
CGroupContext *c = userdata;
|
||||||
|
CGroupIODeviceLimit *l;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(bus);
|
||||||
|
assert(reply);
|
||||||
|
assert(c);
|
||||||
|
|
||||||
|
r = sd_bus_message_open_container(reply, 'a', "(st)");
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
LIST_FOREACH(device_limits, l, c->io_device_limits) {
|
||||||
|
uint64_t v;
|
||||||
|
|
||||||
|
if (streq(property, "IOReadBandwidthMax"))
|
||||||
|
v = l->rbps_max;
|
||||||
|
else
|
||||||
|
v = l->wbps_max;
|
||||||
|
|
||||||
|
if (v == CGROUP_LIMIT_MAX)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
r = sd_bus_message_append(reply, "(st)", l->path, v);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sd_bus_message_close_container(reply);
|
||||||
|
}
|
||||||
|
|
||||||
static int property_get_blockio_device_weight(
|
static int property_get_blockio_device_weight(
|
||||||
sd_bus *bus,
|
sd_bus *bus,
|
||||||
const char *path,
|
const char *path,
|
||||||
@ -141,6 +211,12 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
|
|||||||
SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0),
|
SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0),
|
||||||
SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0),
|
SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0),
|
||||||
SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
|
SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
|
||||||
|
SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, io_accounting), 0),
|
||||||
|
SD_BUS_PROPERTY("IOWeight", "t", NULL, offsetof(CGroupContext, io_weight), 0),
|
||||||
|
SD_BUS_PROPERTY("StartupIOWeight", "t", NULL, offsetof(CGroupContext, startup_io_weight), 0),
|
||||||
|
SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight, 0, 0),
|
||||||
|
SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
|
||||||
|
SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
|
||||||
SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
|
SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
|
||||||
SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0),
|
SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0),
|
||||||
SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0),
|
SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0),
|
||||||
@ -281,6 +357,238 @@ int bus_cgroup_set_property(
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
} else if (streq(name, "IOAccounting")) {
|
||||||
|
int b;
|
||||||
|
|
||||||
|
r = sd_bus_message_read(message, "b", &b);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (mode != UNIT_CHECK) {
|
||||||
|
c->io_accounting = b;
|
||||||
|
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
|
||||||
|
unit_write_drop_in_private(u, mode, name, b ? "IOAccounting=yes" : "IOAccounting=no");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
} else if (streq(name, "IOWeight")) {
|
||||||
|
uint64_t weight;
|
||||||
|
|
||||||
|
r = sd_bus_message_read(message, "t", &weight);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (!CGROUP_WEIGHT_IS_OK(weight))
|
||||||
|
return sd_bus_error_set_errnof(error, EINVAL, "IOWeight value out of range");
|
||||||
|
|
||||||
|
if (mode != UNIT_CHECK) {
|
||||||
|
c->io_weight = weight;
|
||||||
|
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
|
||||||
|
|
||||||
|
if (weight == CGROUP_WEIGHT_INVALID)
|
||||||
|
unit_write_drop_in_private(u, mode, name, "IOWeight=");
|
||||||
|
else
|
||||||
|
unit_write_drop_in_private_format(u, mode, name, "IOWeight=%" PRIu64, weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
} else if (streq(name, "StartupIOWeight")) {
|
||||||
|
uint64_t weight;
|
||||||
|
|
||||||
|
r = sd_bus_message_read(message, "t", &weight);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (CGROUP_WEIGHT_IS_OK(weight))
|
||||||
|
return sd_bus_error_set_errnof(error, EINVAL, "StartupIOWeight value out of range");
|
||||||
|
|
||||||
|
if (mode != UNIT_CHECK) {
|
||||||
|
c->startup_io_weight = weight;
|
||||||
|
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
|
||||||
|
|
||||||
|
if (weight == CGROUP_WEIGHT_INVALID)
|
||||||
|
unit_write_drop_in_private(u, mode, name, "StartupIOWeight=");
|
||||||
|
else
|
||||||
|
unit_write_drop_in_private_format(u, mode, name, "StartupIOWeight=%" PRIu64, weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
} else if (streq(name, "IOReadBandwidthMax") || streq(name, "IOWriteBandwidthMax")) {
|
||||||
|
const char *path;
|
||||||
|
bool read = true;
|
||||||
|
unsigned n = 0;
|
||||||
|
uint64_t u64;
|
||||||
|
|
||||||
|
if (streq(name, "IOWriteBandwidthMax"))
|
||||||
|
read = false;
|
||||||
|
|
||||||
|
r = sd_bus_message_enter_container(message, 'a', "(st)");
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
|
||||||
|
|
||||||
|
if (mode != UNIT_CHECK) {
|
||||||
|
CGroupIODeviceLimit *a = NULL, *b;
|
||||||
|
|
||||||
|
LIST_FOREACH(device_limits, b, c->io_device_limits) {
|
||||||
|
if (path_equal(path, b->path)) {
|
||||||
|
a = b;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!a) {
|
||||||
|
a = new0(CGroupIODeviceLimit, 1);
|
||||||
|
if (!a)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
a->path = strdup(path);
|
||||||
|
if (!a->path) {
|
||||||
|
free(a);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
a->rbps_max = CGROUP_LIMIT_MAX;
|
||||||
|
a->wbps_max = CGROUP_LIMIT_MAX;
|
||||||
|
|
||||||
|
LIST_PREPEND(device_limits, c->io_device_limits, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read)
|
||||||
|
a->rbps_max = u64;
|
||||||
|
else
|
||||||
|
a->wbps_max = u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = sd_bus_message_exit_container(message);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (mode != UNIT_CHECK) {
|
||||||
|
CGroupIODeviceLimit *a;
|
||||||
|
_cleanup_free_ char *buf = NULL;
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
LIST_FOREACH(device_limits, a, c->io_device_limits)
|
||||||
|
if (read)
|
||||||
|
a->rbps_max = CGROUP_LIMIT_MAX;
|
||||||
|
else
|
||||||
|
a->wbps_max = CGROUP_LIMIT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
|
||||||
|
|
||||||
|
f = open_memstream(&buf, &size);
|
||||||
|
if (!f)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if (read) {
|
||||||
|
fputs("IOReadBandwidthMax=\n", f);
|
||||||
|
LIST_FOREACH(device_limits, a, c->io_device_limits)
|
||||||
|
if (a->rbps_max != CGROUP_LIMIT_MAX)
|
||||||
|
fprintf(f, "IOReadBandwidthMax=%s %" PRIu64 "\n", a->path, a->rbps_max);
|
||||||
|
} else {
|
||||||
|
fputs("IOWriteBandwidthMax=\n", f);
|
||||||
|
LIST_FOREACH(device_limits, a, c->io_device_limits)
|
||||||
|
if (a->wbps_max != CGROUP_LIMIT_MAX)
|
||||||
|
fprintf(f, "IOWriteBandwidthMax=%s %" PRIu64 "\n", a->path, a->wbps_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = fflush_and_check(f);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
unit_write_drop_in_private(u, mode, name, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
} else if (streq(name, "IODeviceWeight")) {
|
||||||
|
const char *path;
|
||||||
|
uint64_t weight;
|
||||||
|
unsigned n = 0;
|
||||||
|
|
||||||
|
r = sd_bus_message_enter_container(message, 'a', "(st)");
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
|
||||||
|
|
||||||
|
if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID)
|
||||||
|
return sd_bus_error_set_errnof(error, EINVAL, "IODeviceWeight out of range");
|
||||||
|
|
||||||
|
if (mode != UNIT_CHECK) {
|
||||||
|
CGroupIODeviceWeight *a = NULL, *b;
|
||||||
|
|
||||||
|
LIST_FOREACH(device_weights, b, c->io_device_weights) {
|
||||||
|
if (path_equal(b->path, path)) {
|
||||||
|
a = b;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!a) {
|
||||||
|
a = new0(CGroupIODeviceWeight, 1);
|
||||||
|
if (!a)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
a->path = strdup(path);
|
||||||
|
if (!a->path) {
|
||||||
|
free(a);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
LIST_PREPEND(device_weights,c->io_device_weights, a);
|
||||||
|
}
|
||||||
|
|
||||||
|
a->weight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_bus_message_exit_container(message);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (mode != UNIT_CHECK) {
|
||||||
|
_cleanup_free_ char *buf = NULL;
|
||||||
|
_cleanup_fclose_ FILE *f = NULL;
|
||||||
|
CGroupIODeviceWeight *a;
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
if (n == 0) {
|
||||||
|
while (c->io_device_weights)
|
||||||
|
cgroup_context_free_io_device_weight(c, c->io_device_weights);
|
||||||
|
}
|
||||||
|
|
||||||
|
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
|
||||||
|
|
||||||
|
f = open_memstream(&buf, &size);
|
||||||
|
if (!f)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
fputs("IODeviceWeight=\n", f);
|
||||||
|
LIST_FOREACH(device_weights, a, c->io_device_weights)
|
||||||
|
fprintf(f, "IODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
|
||||||
|
|
||||||
|
r = fflush_and_check(f);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
unit_write_drop_in_private(u, mode, name, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
} else if (streq(name, "BlockIOAccounting")) {
|
} else if (streq(name, "BlockIOAccounting")) {
|
||||||
int b;
|
int b;
|
||||||
|
|
||||||
|
@ -120,6 +120,12 @@ $1.MemoryAccounting, config_parse_bool, 0,
|
|||||||
$1.MemoryLimit, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
|
$1.MemoryLimit, config_parse_memory_limit, 0, offsetof($1, cgroup_context)
|
||||||
$1.DeviceAllow, config_parse_device_allow, 0, offsetof($1, cgroup_context)
|
$1.DeviceAllow, config_parse_device_allow, 0, offsetof($1, cgroup_context)
|
||||||
$1.DevicePolicy, config_parse_device_policy, 0, offsetof($1, cgroup_context.device_policy)
|
$1.DevicePolicy, config_parse_device_policy, 0, offsetof($1, cgroup_context.device_policy)
|
||||||
|
$1.IOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.io_accounting)
|
||||||
|
$1.IOWeight, config_parse_io_weight, 0, offsetof($1, cgroup_context.io_weight)
|
||||||
|
$1.StartupIOWeight, config_parse_io_weight, 0, offsetof($1, cgroup_context.startup_io_weight)
|
||||||
|
$1.IODeviceWeight, config_parse_io_device_weight, 0, offsetof($1, cgroup_context)
|
||||||
|
$1.IOReadBandwidthMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
|
||||||
|
$1.IOWriteBandwidthMax, config_parse_io_limit, 0, offsetof($1, cgroup_context)
|
||||||
$1.BlockIOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.blockio_accounting)
|
$1.BlockIOAccounting, config_parse_bool, 0, offsetof($1, cgroup_context.blockio_accounting)
|
||||||
$1.BlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.blockio_weight)
|
$1.BlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.blockio_weight)
|
||||||
$1.StartupBlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.startup_blockio_weight)
|
$1.StartupBlockIOWeight, config_parse_blockio_weight, 0, offsetof($1, cgroup_context.startup_blockio_weight)
|
||||||
|
@ -2910,6 +2910,196 @@ int config_parse_device_allow(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int config_parse_io_weight(
|
||||||
|
const char *unit,
|
||||||
|
const char *filename,
|
||||||
|
unsigned line,
|
||||||
|
const char *section,
|
||||||
|
unsigned section_line,
|
||||||
|
const char *lvalue,
|
||||||
|
int ltype,
|
||||||
|
const char *rvalue,
|
||||||
|
void *data,
|
||||||
|
void *userdata) {
|
||||||
|
|
||||||
|
uint64_t *weight = data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
|
||||||
|
r = cg_weight_parse(rvalue, weight);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, r, "IO weight '%s' invalid. Ignoring.", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_parse_io_device_weight(
|
||||||
|
const char *unit,
|
||||||
|
const char *filename,
|
||||||
|
unsigned line,
|
||||||
|
const char *section,
|
||||||
|
unsigned section_line,
|
||||||
|
const char *lvalue,
|
||||||
|
int ltype,
|
||||||
|
const char *rvalue,
|
||||||
|
void *data,
|
||||||
|
void *userdata) {
|
||||||
|
|
||||||
|
_cleanup_free_ char *path = NULL;
|
||||||
|
CGroupIODeviceWeight *w;
|
||||||
|
CGroupContext *c = data;
|
||||||
|
const char *weight;
|
||||||
|
uint64_t u;
|
||||||
|
size_t n;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
|
||||||
|
if (isempty(rvalue)) {
|
||||||
|
while (c->io_device_weights)
|
||||||
|
cgroup_context_free_io_device_weight(c, c->io_device_weights);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = strcspn(rvalue, WHITESPACE);
|
||||||
|
weight = rvalue + n;
|
||||||
|
weight += strspn(weight, WHITESPACE);
|
||||||
|
|
||||||
|
if (isempty(weight)) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, 0, "Expected block device and device weight. Ignoring.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = strndup(rvalue, n);
|
||||||
|
if (!path)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
if (!path_startswith(path, "/dev")) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = cg_weight_parse(weight, &u);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, r, "IO weight '%s' invalid. Ignoring.", weight);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(u != CGROUP_WEIGHT_INVALID);
|
||||||
|
|
||||||
|
w = new0(CGroupIODeviceWeight, 1);
|
||||||
|
if (!w)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
w->path = path;
|
||||||
|
path = NULL;
|
||||||
|
|
||||||
|
w->weight = u;
|
||||||
|
|
||||||
|
LIST_PREPEND(device_weights, c->io_device_weights, w);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int config_parse_io_limit(
|
||||||
|
const char *unit,
|
||||||
|
const char *filename,
|
||||||
|
unsigned line,
|
||||||
|
const char *section,
|
||||||
|
unsigned section_line,
|
||||||
|
const char *lvalue,
|
||||||
|
int ltype,
|
||||||
|
const char *rvalue,
|
||||||
|
void *data,
|
||||||
|
void *userdata) {
|
||||||
|
|
||||||
|
_cleanup_free_ char *path = NULL;
|
||||||
|
CGroupIODeviceLimit *l = NULL, *t;
|
||||||
|
CGroupContext *c = data;
|
||||||
|
const char *limit;
|
||||||
|
uint64_t num;
|
||||||
|
bool read;
|
||||||
|
size_t n;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
|
||||||
|
read = streq("IOReadBandwidthMax", lvalue);
|
||||||
|
|
||||||
|
if (isempty(rvalue)) {
|
||||||
|
LIST_FOREACH(device_limits, l, c->io_device_limits)
|
||||||
|
if (read)
|
||||||
|
l->rbps_max = CGROUP_LIMIT_MAX;
|
||||||
|
else
|
||||||
|
l->wbps_max = CGROUP_LIMIT_MAX;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = strcspn(rvalue, WHITESPACE);
|
||||||
|
limit = rvalue + n;
|
||||||
|
limit += strspn(limit, WHITESPACE);
|
||||||
|
|
||||||
|
if (!*limit) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, 0, "Expected space separated pair of device node and bandwidth. Ignoring.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = strndup(rvalue, n);
|
||||||
|
if (!path)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
if (!path_startswith(path, "/dev")) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (streq("max", limit)) {
|
||||||
|
num = CGROUP_LIMIT_MAX;
|
||||||
|
} else {
|
||||||
|
r = parse_size(limit, 1000, &num);
|
||||||
|
if (r < 0 || num <= 0) {
|
||||||
|
log_syntax(unit, LOG_ERR, filename, line, r, "IO Limit '%s' invalid. Ignoring.", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LIST_FOREACH(device_limits, t, c->io_device_limits) {
|
||||||
|
if (path_equal(path, t->path)) {
|
||||||
|
l = t;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!l) {
|
||||||
|
l = new0(CGroupIODeviceLimit, 1);
|
||||||
|
if (!l)
|
||||||
|
return log_oom();
|
||||||
|
|
||||||
|
l->path = path;
|
||||||
|
path = NULL;
|
||||||
|
l->rbps_max = CGROUP_LIMIT_MAX;
|
||||||
|
l->wbps_max = CGROUP_LIMIT_MAX;
|
||||||
|
|
||||||
|
LIST_PREPEND(device_limits, c->io_device_limits, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read)
|
||||||
|
l->rbps_max = num;
|
||||||
|
else
|
||||||
|
l->wbps_max = num;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int config_parse_blockio_weight(
|
int config_parse_blockio_weight(
|
||||||
const char *unit,
|
const char *unit,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
@ -3830,6 +4020,9 @@ void unit_dump_config_items(FILE *f) {
|
|||||||
{ config_parse_memory_limit, "LIMIT" },
|
{ config_parse_memory_limit, "LIMIT" },
|
||||||
{ config_parse_device_allow, "DEVICE" },
|
{ config_parse_device_allow, "DEVICE" },
|
||||||
{ config_parse_device_policy, "POLICY" },
|
{ config_parse_device_policy, "POLICY" },
|
||||||
|
{ config_parse_io_limit, "LIMIT" },
|
||||||
|
{ config_parse_io_weight, "WEIGHT" },
|
||||||
|
{ config_parse_io_device_weight, "DEVICEWEIGHT" },
|
||||||
{ config_parse_blockio_bandwidth, "BANDWIDTH" },
|
{ config_parse_blockio_bandwidth, "BANDWIDTH" },
|
||||||
{ config_parse_blockio_weight, "WEIGHT" },
|
{ config_parse_blockio_weight, "WEIGHT" },
|
||||||
{ config_parse_blockio_device_weight, "DEVICEWEIGHT" },
|
{ config_parse_blockio_device_weight, "DEVICEWEIGHT" },
|
||||||
|
@ -86,6 +86,9 @@ int config_parse_memory_limit(const char *unit, const char *filename, unsigned l
|
|||||||
int config_parse_tasks_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
int config_parse_tasks_max(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||||
int config_parse_device_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
int config_parse_device_policy(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||||
int config_parse_device_allow(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
int config_parse_device_allow(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||||
|
int config_parse_io_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||||
|
int config_parse_io_device_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||||
|
int config_parse_io_limit(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||||
int config_parse_blockio_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
int config_parse_blockio_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||||
int config_parse_blockio_device_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
int config_parse_blockio_device_weight(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||||
int config_parse_blockio_bandwidth(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
int config_parse_blockio_bandwidth(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
|
||||||
|
@ -122,6 +122,7 @@ static usec_t arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE;
|
|||||||
static Set* arg_syscall_archs = NULL;
|
static Set* arg_syscall_archs = NULL;
|
||||||
static FILE* arg_serialization = NULL;
|
static FILE* arg_serialization = NULL;
|
||||||
static bool arg_default_cpu_accounting = false;
|
static bool arg_default_cpu_accounting = false;
|
||||||
|
static bool arg_default_io_accounting = false;
|
||||||
static bool arg_default_blockio_accounting = false;
|
static bool arg_default_blockio_accounting = false;
|
||||||
static bool arg_default_memory_accounting = false;
|
static bool arg_default_memory_accounting = false;
|
||||||
static bool arg_default_tasks_accounting = true;
|
static bool arg_default_tasks_accounting = true;
|
||||||
@ -691,6 +692,7 @@ static int parse_config_file(void) {
|
|||||||
{ "Manager", "DefaultLimitRTPRIO", config_parse_limit, RLIMIT_RTPRIO, arg_default_rlimit },
|
{ "Manager", "DefaultLimitRTPRIO", config_parse_limit, RLIMIT_RTPRIO, arg_default_rlimit },
|
||||||
{ "Manager", "DefaultLimitRTTIME", config_parse_limit, RLIMIT_RTTIME, arg_default_rlimit },
|
{ "Manager", "DefaultLimitRTTIME", config_parse_limit, RLIMIT_RTTIME, arg_default_rlimit },
|
||||||
{ "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting },
|
{ "Manager", "DefaultCPUAccounting", config_parse_bool, 0, &arg_default_cpu_accounting },
|
||||||
|
{ "Manager", "DefaultIOAccounting", config_parse_bool, 0, &arg_default_io_accounting },
|
||||||
{ "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting },
|
{ "Manager", "DefaultBlockIOAccounting", config_parse_bool, 0, &arg_default_blockio_accounting },
|
||||||
{ "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting },
|
{ "Manager", "DefaultMemoryAccounting", config_parse_bool, 0, &arg_default_memory_accounting },
|
||||||
{ "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting },
|
{ "Manager", "DefaultTasksAccounting", config_parse_bool, 0, &arg_default_tasks_accounting },
|
||||||
@ -733,6 +735,7 @@ static void manager_set_defaults(Manager *m) {
|
|||||||
m->default_start_limit_interval = arg_default_start_limit_interval;
|
m->default_start_limit_interval = arg_default_start_limit_interval;
|
||||||
m->default_start_limit_burst = arg_default_start_limit_burst;
|
m->default_start_limit_burst = arg_default_start_limit_burst;
|
||||||
m->default_cpu_accounting = arg_default_cpu_accounting;
|
m->default_cpu_accounting = arg_default_cpu_accounting;
|
||||||
|
m->default_io_accounting = arg_default_io_accounting;
|
||||||
m->default_blockio_accounting = arg_default_blockio_accounting;
|
m->default_blockio_accounting = arg_default_blockio_accounting;
|
||||||
m->default_memory_accounting = arg_default_memory_accounting;
|
m->default_memory_accounting = arg_default_memory_accounting;
|
||||||
m->default_tasks_accounting = arg_default_tasks_accounting;
|
m->default_tasks_accounting = arg_default_tasks_accounting;
|
||||||
|
@ -255,6 +255,7 @@ struct Manager {
|
|||||||
|
|
||||||
bool default_cpu_accounting;
|
bool default_cpu_accounting;
|
||||||
bool default_memory_accounting;
|
bool default_memory_accounting;
|
||||||
|
bool default_io_accounting;
|
||||||
bool default_blockio_accounting;
|
bool default_blockio_accounting;
|
||||||
bool default_tasks_accounting;
|
bool default_tasks_accounting;
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#DefaultStartLimitBurst=5
|
#DefaultStartLimitBurst=5
|
||||||
#DefaultEnvironment=
|
#DefaultEnvironment=
|
||||||
#DefaultCPUAccounting=no
|
#DefaultCPUAccounting=no
|
||||||
|
#DefaultIOAccounting=no
|
||||||
#DefaultBlockIOAccounting=no
|
#DefaultBlockIOAccounting=no
|
||||||
#DefaultMemoryAccounting=no
|
#DefaultMemoryAccounting=no
|
||||||
#DefaultTasksAccounting=yes
|
#DefaultTasksAccounting=yes
|
||||||
|
@ -132,6 +132,7 @@ static void unit_init(Unit *u) {
|
|||||||
* been initialized */
|
* been initialized */
|
||||||
|
|
||||||
cc->cpu_accounting = u->manager->default_cpu_accounting;
|
cc->cpu_accounting = u->manager->default_cpu_accounting;
|
||||||
|
cc->io_accounting = u->manager->default_io_accounting;
|
||||||
cc->blockio_accounting = u->manager->default_blockio_accounting;
|
cc->blockio_accounting = u->manager->default_blockio_accounting;
|
||||||
cc->memory_accounting = u->manager->default_memory_accounting;
|
cc->memory_accounting = u->manager->default_memory_accounting;
|
||||||
cc->tasks_accounting = u->manager->default_tasks_accounting;
|
cc->tasks_accounting = u->manager->default_tasks_accounting;
|
||||||
@ -1213,6 +1214,7 @@ static int unit_add_startup_units(Unit *u) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (c->startup_cpu_shares == CGROUP_CPU_SHARES_INVALID &&
|
if (c->startup_cpu_shares == CGROUP_CPU_SHARES_INVALID &&
|
||||||
|
c->startup_io_weight == CGROUP_WEIGHT_INVALID &&
|
||||||
c->startup_blockio_weight == CGROUP_BLKIO_WEIGHT_INVALID)
|
c->startup_blockio_weight == CGROUP_BLKIO_WEIGHT_INVALID)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
|
|||||||
r = sd_bus_message_append(m, "sv", sn, "t", l.rlim_cur);
|
r = sd_bus_message_append(m, "sv", sn, "t", l.rlim_cur);
|
||||||
|
|
||||||
} else if (STR_IN_SET(field,
|
} else if (STR_IN_SET(field,
|
||||||
"CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
|
"CPUAccounting", "MemoryAccounting", "IOAccounting", "BlockIOAccounting", "TasksAccounting",
|
||||||
"SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
|
"SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
|
||||||
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
|
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
|
||||||
"PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
|
"PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
|
||||||
@ -207,6 +207,17 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
|
|||||||
|
|
||||||
r = sd_bus_message_append(m, "v", "t", u);
|
r = sd_bus_message_append(m, "v", "t", u);
|
||||||
|
|
||||||
|
} else if (STR_IN_SET(field, "IOWeight", "StartupIOWeight")) {
|
||||||
|
uint64_t u;
|
||||||
|
|
||||||
|
r = cg_weight_parse(eq, &u);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error("Failed to parse %s value %s.", field, eq);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = sd_bus_message_append(m, "v", "t", u);
|
||||||
|
|
||||||
} else if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight")) {
|
} else if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight")) {
|
||||||
uint64_t u;
|
uint64_t u;
|
||||||
|
|
||||||
@ -273,7 +284,8 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
|
|||||||
r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
|
r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
|
} else if (STR_IN_SET(field, "IOReadBandwidthMax", "IOWriteBandwidthMax",
|
||||||
|
"BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
|
||||||
|
|
||||||
if (isempty(eq))
|
if (isempty(eq))
|
||||||
r = sd_bus_message_append(m, "v", "a(st)", 0);
|
r = sd_bus_message_append(m, "v", "a(st)", 0);
|
||||||
@ -295,16 +307,20 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = parse_size(bandwidth, 1000, &bytes);
|
if (streq(bandwidth, "max")) {
|
||||||
if (r < 0) {
|
bytes = CGROUP_LIMIT_MAX;
|
||||||
log_error("Failed to parse byte value %s.", bandwidth);
|
} else {
|
||||||
return -EINVAL;
|
r = parse_size(bandwidth, 1000, &bytes);
|
||||||
|
if (r < 0) {
|
||||||
|
log_error("Failed to parse byte value %s.", bandwidth);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_bus_message_append(m, "v", "a(st)", 1, path, bytes);
|
r = sd_bus_message_append(m, "v", "a(st)", 1, path, bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (streq(field, "BlockIODeviceWeight")) {
|
} else if (STR_IN_SET(field, "IODeviceWeight", "BlockIODeviceWeight")) {
|
||||||
|
|
||||||
if (isempty(eq))
|
if (isempty(eq))
|
||||||
r = sd_bus_message_append(m, "v", "a(st)", 0);
|
r = sd_bus_message_append(m, "v", "a(st)", 0);
|
||||||
|
@ -4428,7 +4428,7 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
} else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && streq(name, "BlockIODeviceWeight")) {
|
} else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "IODeviceWeight") || streq(name, "BlockIODeviceWeight"))) {
|
||||||
const char *path;
|
const char *path;
|
||||||
uint64_t weight;
|
uint64_t weight;
|
||||||
|
|
||||||
@ -4447,7 +4447,8 @@ static int print_property(const char *name, sd_bus_message *m, const char *conte
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
} else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
|
} else if (contents[1] == SD_BUS_TYPE_STRUCT_BEGIN && (streq(name, "IOReadBandwidthMax") || streq(name, "IOWriteBandwidthMax") ||
|
||||||
|
streq(name, "BlockIOReadBandwidth") || streq(name, "BlockIOWriteBandwidth"))) {
|
||||||
const char *path;
|
const char *path;
|
||||||
uint64_t bandwidth;
|
uint64_t bandwidth;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user