diff --git a/docs/TRANSIENT-SETTINGS.md b/docs/TRANSIENT-SETTINGS.md
index f8ff413d28..f0dc2ee20f 100644
--- a/docs/TRANSIENT-SETTINGS.md
+++ b/docs/TRANSIENT-SETTINGS.md
@@ -270,6 +270,9 @@ All cgroup/resource control settings are available for transient units
✓ IPAccounting=
✓ IPAddressAllow=
✓ IPAddressDeny=
+✓ ManagedOOMSwap=
+✓ ManagedOOMMemoryPressure=
+✓ ManagedOOMMemoryPressureLimitPercent=
```
## Process Killing Settings
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml
index 02f7293288..3c0e5b6eb1 100644
--- a/man/org.freedesktop.systemd1.xml
+++ b/man/org.freedesktop.systemd1.xml
@@ -2414,6 +2414,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMSwap = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressure = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -2928,6 +2934,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
+
+
+
+
+
+
@@ -3478,6 +3490,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
+
+
+
+
+
+
@@ -4121,6 +4139,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMSwap = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressure = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -4661,6 +4685,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
+
+
+
+
+
+
@@ -5211,6 +5241,12 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
+
+
+
+
+
+
@@ -5780,6 +5816,12 @@ node /org/freedesktop/systemd1/unit/home_2emount {
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMSwap = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressure = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -6250,6 +6292,12 @@ node /org/freedesktop/systemd1/unit/home_2emount {
+
+
+
+
+
+
@@ -6720,6 +6768,12 @@ node /org/freedesktop/systemd1/unit/home_2emount {
+
+
+
+
+
+
@@ -7404,6 +7458,12 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMSwap = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressure = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -7860,6 +7920,12 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
+
+
+
+
+
+
@@ -8316,6 +8382,12 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
+
+
+
+
+
+
@@ -8859,6 +8931,12 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMSwap = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressure = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressureLimitPercent = '...';
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
@@ -8989,6 +9067,12 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
+
+
+
+
+
+
@@ -9123,6 +9207,12 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
+
+
+
+
+
+
@@ -9276,6 +9366,12 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMSwap = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressure = '...';
+ @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
+ readonly s ManagedOOMMemoryPressureLimitPercent = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@@ -9422,6 +9518,12 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
+
+
+
+
+
+
@@ -9582,6 +9684,12 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
+
+
+
+
+
+
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
index 6210347553..8f32296333 100644
--- a/src/basic/cgroup-util.c
+++ b/src/basic/cgroup-util.c
@@ -2161,3 +2161,10 @@ CGroupMask get_cpu_accounting_mask(void) {
bool cpu_accounting_is_cheap(void) {
return get_cpu_accounting_mask() == 0;
}
+
+static const char* const managed_oom_mode_table[_MANAGED_OOM_MODE_MAX] = {
+ [MANAGED_OOM_AUTO] = "auto",
+ [MANAGED_OOM_KILL] = "kill",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(managed_oom_mode, ManagedOOMMode);
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
index 2b88571bc1..6f76417a04 100644
--- a/src/basic/cgroup-util.h
+++ b/src/basic/cgroup-util.h
@@ -275,3 +275,13 @@ CGroupController cgroup_controller_from_string(const char *s) _pure_;
bool is_cgroup_fs(const struct statfs *s);
bool fd_is_cgroup_fs(int fd);
+
+typedef enum ManagedOOMMode {
+ MANAGED_OOM_AUTO,
+ MANAGED_OOM_KILL,
+ _MANAGED_OOM_MODE_MAX,
+ _MANAGED_OOM_MODE_INVALID = -1,
+} ManagedOOMMode;
+
+const char* managed_oom_mode_to_string(ManagedOOMMode m) _const_;
+ManagedOOMMode managed_oom_mode_from_string(const char *s) _pure_;
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 211e4a5945..95b5f2de59 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -128,6 +128,9 @@ void cgroup_context_init(CGroupContext *c) {
.startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID,
.tasks_max = TASKS_MAX_UNSET,
+
+ .moom_swap = MANAGED_OOM_AUTO,
+ .moom_mem_pressure = MANAGED_OOM_AUTO,
};
}
@@ -411,7 +414,10 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
"%sTasksMax: %" PRIu64 "\n"
"%sDevicePolicy: %s\n"
"%sDisableControllers: %s\n"
- "%sDelegate: %s\n",
+ "%sDelegate: %s\n"
+ "%sManagedOOMSwap: %s\n"
+ "%sManagedOOMMemoryPressure: %s\n"
+ "%sManagedOOMMemoryPressureLimitPercent: %d%%\n",
prefix, yes_no(c->cpu_accounting),
prefix, yes_no(c->io_accounting),
prefix, yes_no(c->blockio_accounting),
@@ -441,7 +447,10 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
prefix, tasks_max_resolve(&c->tasks_max),
prefix, cgroup_device_policy_to_string(c->device_policy),
prefix, strempty(disable_controllers_str),
- prefix, yes_no(c->delegate));
+ prefix, yes_no(c->delegate),
+ prefix, managed_oom_mode_to_string(c->moom_swap),
+ prefix, managed_oom_mode_to_string(c->moom_mem_pressure),
+ prefix, c->moom_mem_pressure_limit);
if (c->delegate) {
_cleanup_free_ char *t = NULL;
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
index 9ac5c8bfc0..1f592ef559 100644
--- a/src/core/cgroup.h
+++ b/src/core/cgroup.h
@@ -159,6 +159,11 @@ struct CGroupContext {
/* Common */
TasksMax tasks_max;
+
+ /* Settings for systemd-oomd */
+ ManagedOOMMode moom_swap;
+ ManagedOOMMode moom_mem_pressure;
+ int moom_mem_pressure_limit;
};
/* Used when querying IP accounting data */
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
index b7d2e32639..78abcbdbc8 100644
--- a/src/core/dbus-cgroup.c
+++ b/src/core/dbus-cgroup.c
@@ -19,6 +19,7 @@
BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max, "t", TasksMax, tasks_max_resolve);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_mode, managed_oom_mode, ManagedOOMMode);
static int property_get_cgroup_mask(
sd_bus *bus,
@@ -391,6 +392,9 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
SD_BUS_PROPERTY("IPIngressFilterPath", "as", NULL, offsetof(CGroupContext, ip_filters_ingress), 0),
SD_BUS_PROPERTY("IPEgressFilterPath", "as", NULL, offsetof(CGroupContext, ip_filters_egress), 0),
SD_BUS_PROPERTY("DisableControllers", "as", property_get_cgroup_mask, offsetof(CGroupContext, disable_controllers), 0),
+ SD_BUS_PROPERTY("ManagedOOMSwap", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_swap), 0),
+ SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_mem_pressure), 0),
+ SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimitPercent", "s", bus_property_get_percent, offsetof(CGroupContext, moom_mem_pressure_limit), 0),
SD_BUS_VTABLE_END
};
@@ -1667,6 +1671,37 @@ int bus_cgroup_set_property(
return 1;
}
+ if (STR_IN_SET(name, "ManagedOOMSwap", "ManagedOOMMemoryPressure")) {
+ ManagedOOMMode *cgroup_mode = streq(name, "ManagedOOMSwap") ? &c->moom_swap : &c->moom_mem_pressure;
+ ManagedOOMMode m;
+ const char *mode;
+
+ if (!UNIT_VTABLE(u)->can_set_managed_oom)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set %s for this unit type", name);
+
+ r = sd_bus_message_read(message, "s", &mode);
+ if (r < 0)
+ return r;
+
+ m = managed_oom_mode_from_string(mode);
+ if (m < 0)
+ return -EINVAL;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ *cgroup_mode = m;
+ unit_write_settingf(u, flags, name, "%s=%s", name, mode);
+ }
+
+ return 1;
+ }
+
+ if (streq(name, "ManagedOOMMemoryPressureLimitPercent")) {
+ if (!UNIT_VTABLE(u)->can_set_managed_oom)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot set %s for this unit type", name);
+
+ return bus_set_transient_percent(u, name, &c->moom_mem_pressure_limit, message, flags, error);
+ }
+
if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB))
return bus_cgroup_set_transient_property(u, c, name, message, flags, error);
diff --git a/src/core/dbus-util.c b/src/core/dbus-util.c
index 951450e53d..f534001a9c 100644
--- a/src/core/dbus-util.c
+++ b/src/core/dbus-util.c
@@ -91,6 +91,35 @@ int bus_set_transient_bool(
return 1;
}
+int bus_set_transient_percent(
+ Unit *u,
+ const char *name,
+ int *p,
+ sd_bus_message *message,
+ UnitWriteFlags flags,
+ sd_bus_error *error) {
+
+ const char *v;
+ int r;
+
+ assert(p);
+
+ r = sd_bus_message_read(message, "s", &v);
+ if (r < 0)
+ return r;
+
+ r = parse_percent(v);
+ if (r < 0)
+ return r;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ *p = r;
+ unit_write_settingf(u, flags, name, "%s=%d%%", name, r);
+ }
+
+ return 1;
+}
+
int bus_set_transient_usec_internal(
Unit *u,
const char *name,
diff --git a/src/core/dbus-util.h b/src/core/dbus-util.h
index 654ceb5279..7781a425be 100644
--- a/src/core/dbus-util.h
+++ b/src/core/dbus-util.h
@@ -240,6 +240,7 @@ int bus_set_transient_user_relaxed(Unit *u, const char *name, char **p, sd_bus_m
int bus_set_transient_path(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_set_transient_string(Unit *u, const char *name, char **p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_set_transient_bool(Unit *u, const char *name, bool *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
+int bus_set_transient_percent(Unit *u, const char *name, int *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
int bus_set_transient_usec_internal(Unit *u, const char *name, usec_t *p, bool fix_0, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
static inline int bus_set_transient_usec(Unit *u, const char *name, usec_t *p, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error) {
return bus_set_transient_usec_internal(u, name, p, false, message, flags, error);
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
index c60d565eb4..f84febd953 100644
--- a/src/core/load-fragment-gperf.gperf.m4
+++ b/src/core/load-fragment-gperf.gperf.m4
@@ -224,6 +224,9 @@ $1.IPAddressAllow, config_parse_ip_address_access, 0,
$1.IPAddressDeny, config_parse_ip_address_access, 0, offsetof($1, cgroup_context.ip_address_deny)
$1.IPIngressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof($1, cgroup_context.ip_filters_ingress)
$1.IPEgressFilterPath, config_parse_ip_filter_bpf_progs, 0, offsetof($1, cgroup_context.ip_filters_egress)
+$1.ManagedOOMSwap, config_parse_managed_oom_mode, 0, offsetof($1, cgroup_context.moom_swap)
+$1.ManagedOOMMemoryPressure, config_parse_managed_oom_mode, 0, offsetof($1, cgroup_context.moom_mem_pressure)
+$1.ManagedOOMMemoryPressureLimitPercent,config_parse_managed_oom_mem_pressure_limit,0, offsetof($1, cgroup_context.moom_mem_pressure_limit)
$1.NetClass, config_parse_warn_compat, DISABLED_LEGACY, 0'
)m4_dnl
Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index df40119175..81253239aa 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -3812,6 +3812,79 @@ int config_parse_delegate(
return 0;
}
+int config_parse_managed_oom_mode(
+ 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) {
+
+ ManagedOOMMode *mode = data, m;
+ UnitType t;
+
+ t = unit_name_to_type(unit);
+ assert(t != _UNIT_TYPE_INVALID);
+
+ if (!unit_vtable[t]->can_set_managed_oom)
+ return log_syntax(unit, LOG_WARNING, filename, line, 0, "%s= is not supported for this unit type, ignoring.", lvalue);
+
+ if (isempty(rvalue)) {
+ *mode = MANAGED_OOM_AUTO;
+ return 0;
+ }
+
+ m = managed_oom_mode_from_string(rvalue);
+ if (m < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid syntax, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ *mode = m;
+ return 0;
+}
+
+int config_parse_managed_oom_mem_pressure_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) {
+
+ unsigned *limit = data;
+ UnitType t;
+ int r;
+
+ t = unit_name_to_type(unit);
+ assert(t != _UNIT_TYPE_INVALID);
+
+ if (!unit_vtable[t]->can_set_managed_oom)
+ return log_syntax(unit, LOG_WARNING, filename, line, 0, "%s= is not supported for this unit type, ignoring.", lvalue);
+
+ if (isempty(rvalue)) {
+ *limit = 0;
+ return 0;
+ }
+
+ r = parse_percent(rvalue);
+ if (r < 0) {
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse limit percent value, ignoring: %s", rvalue);
+ return 0;
+ }
+
+ *limit = r;
+ return 0;
+}
+
int config_parse_device_allow(
const char *unit,
const char *filename,
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
index d67852a74d..fa4c1fb1a0 100644
--- a/src/core/load-fragment.h
+++ b/src/core/load-fragment.h
@@ -76,6 +76,8 @@ CONFIG_PARSER_PROTOTYPE(config_parse_cpu_shares);
CONFIG_PARSER_PROTOTYPE(config_parse_memory_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_tasks_max);
CONFIG_PARSER_PROTOTYPE(config_parse_delegate);
+CONFIG_PARSER_PROTOTYPE(config_parse_managed_oom_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_managed_oom_mem_pressure_limit);
CONFIG_PARSER_PROTOTYPE(config_parse_device_policy);
CONFIG_PARSER_PROTOTYPE(config_parse_device_allow);
CONFIG_PARSER_PROTOTYPE(config_parse_io_device_latency);
diff --git a/src/core/scope.c b/src/core/scope.c
index 42c51b0865..540c83ba45 100644
--- a/src/core/scope.c
+++ b/src/core/scope.c
@@ -621,6 +621,7 @@ const UnitVTable scope_vtable = {
.can_delegate = true,
.can_fail = true,
.once_only = true,
+ .can_set_managed_oom = true,
.init = scope_init,
.load = scope_load,
diff --git a/src/core/service.c b/src/core/service.c
index 863b6755b1..131f462a9c 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -4533,6 +4533,7 @@ const UnitVTable service_vtable = {
.can_transient = true,
.can_delegate = true,
.can_fail = true,
+ .can_set_managed_oom = true,
.init = service_init,
.done = service_done,
diff --git a/src/core/slice.c b/src/core/slice.c
index 49541aacab..36e5d6a40f 100644
--- a/src/core/slice.c
+++ b/src/core/slice.c
@@ -435,6 +435,7 @@ const UnitVTable slice_vtable = {
.private_section = "Slice",
.can_transient = true,
+ .can_set_managed_oom = true,
.init = slice_init,
.load = slice_load,
diff --git a/src/core/unit.h b/src/core/unit.h
index 35873d57bc..9b2ea6c79f 100644
--- a/src/core/unit.h
+++ b/src/core/unit.h
@@ -625,6 +625,9 @@ typedef struct UnitVTable {
/* True if queued jobs of this type should be GC'ed if no other job needs them anymore */
bool gc_jobs:1;
+
+ /* True if systemd-oomd can monitor and act on this unit's recursive children's cgroup(s) */
+ bool can_set_managed_oom:1;
} UnitVTable;
extern const UnitVTable * const unit_vtable[_UNIT_TYPE_MAX];
diff --git a/src/shared/bus-get-properties.c b/src/shared/bus-get-properties.c
index 8ad4694046..5a123bb8f3 100644
--- a/src/shared/bus-get-properties.c
+++ b/src/shared/bus-get-properties.c
@@ -2,6 +2,7 @@
#include "bus-get-properties.h"
#include "rlimit-util.h"
+#include "stdio-util.h"
#include "string-util.h"
int bus_property_get_bool(
@@ -54,6 +55,23 @@ int bus_property_get_id128(
return sd_bus_message_append_array(reply, 'y', id->bytes, 16);
}
+int bus_property_get_percent(
+ sd_bus *bus,
+ const char *path,
+ const char *interface,
+ const char *property,
+ sd_bus_message *reply,
+ void *userdata,
+ sd_bus_error *error) {
+
+ char pstr[DECIMAL_STR_MAX(int) + 2];
+ int p = *(int*) userdata;
+
+ xsprintf(pstr, "%d%%", p);
+
+ return sd_bus_message_append_basic(reply, 's', pstr);
+}
+
#if __SIZEOF_SIZE_T__ != 8
int bus_property_get_size(
sd_bus *bus,
diff --git a/src/shared/bus-get-properties.h b/src/shared/bus-get-properties.h
index 81af74309d..f3934a86a2 100644
--- a/src/shared/bus-get-properties.h
+++ b/src/shared/bus-get-properties.h
@@ -8,6 +8,7 @@
int bus_property_get_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
int bus_property_set_bool(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error);
int bus_property_get_id128(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
+int bus_property_get_percent(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error);
#define bus_property_get_usec ((sd_bus_property_get_t) NULL)
#define bus_property_set_usec ((sd_bus_property_set_t) NULL)
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
index 3ae3c12f92..f51a99c8d7 100644
--- a/src/shared/bus-unit-util.c
+++ b/src/shared/bus-unit-util.c
@@ -432,7 +432,11 @@ static int bus_append_ip_address_access(sd_bus_message *m, int family, const uni
static int bus_append_cgroup_property(sd_bus_message *m, const char *field, const char *eq) {
int r;
- if (STR_IN_SET(field, "DevicePolicy", "Slice"))
+ if (STR_IN_SET(field, "DevicePolicy",
+ "Slice",
+ "ManagedOOMSwap",
+ "ManagedOOMMemoryPressure",
+ "ManagedOOMMemoryPressureLimitPercent"))
return bus_append_string(m, field, eq);
if (STR_IN_SET(field, "CPUAccounting",
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
index 59f90b76ec..7273611143 100644
--- a/src/test/test-tables.c
+++ b/src/test/test-tables.c
@@ -3,6 +3,7 @@
#include "architecture.h"
#include "automount.h"
#include "cgroup.h"
+#include "cgroup-util.h"
#include "compress.h"
#include "condition.h"
#include "device-private.h"
@@ -71,6 +72,7 @@ int main(int argc, char **argv) {
test_table(locale_variable, VARIABLE_LC);
test_table(log_target, LOG_TARGET);
test_table(mac_address_policy, MAC_ADDRESS_POLICY);
+ test_table(managed_oom_mode, MANAGED_OOM_MODE);
test_table(manager_state, MANAGER_STATE);
test_table(manager_timestamp, MANAGER_TIMESTAMP);
test_table(mount_exec_command, MOUNT_EXEC_COMMAND);