✓ IPAddressDeny=
✓ ManagedOOMSwap=
✓ ManagedOOMMemoryPressure=
-✓ ManagedOOMMemoryPressureLimitPercent=
+✓ ManagedOOMMemoryPressureLimit=
```
## Process Killing Settings
</varlistentry>
<varlistentry>
- <term><varname>DefaultMemoryPressureLimitPercent=</varname></term>
+ <term><varname>DefaultMemoryPressureLimit=</varname></term>
<listitem><para>Sets the limit for memory pressure on the unit's cgroup before <command>systemd-oomd</command>
- will take action. A unit can override this value with <varname>ManagedOOMMemoryPressureLimitPercent=</varname>.
+ will take action. A unit can override this value with <varname>ManagedOOMMemoryPressureLimit=</varname>.
The memory pressure for this property represents the fraction of time in a 10 second window in which all tasks
in the cgroup were delayed. For each monitored cgroup, if the memory pressure on that cgroup exceeds the
limit set for longer than the duration set by <varname>DefaultMemoryPressureDurationSec=</varname>,
<listitem><para>Sets the amount of time a unit's cgroup needs to have exceeded memory pressure limits before
<command>systemd-oomd</command> will take action. Memory pressure limits are defined by
- <varname>DefaultMemoryPressureLimitPercent=</varname> and <varname>ManagedOOMMemoryPressureLimitPercent=</varname>.
+ <varname>DefaultMemoryPressureLimit=</varname> and <varname>ManagedOOMMemoryPressureLimit=</varname>.
Defaults to 30 seconds when this property is unset or set to 0.</para></listitem>
</varlistentry>
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
- readonly s ManagedOOMMemoryPressureLimitPercent = '...';
+ readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
<!--property ManagedOOMMemoryPressure is not documented!-->
- <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+ <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
- readonly s ManagedOOMMemoryPressureLimitPercent = '...';
+ readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
<!--property ManagedOOMMemoryPressure is not documented!-->
- <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+ <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
- readonly s ManagedOOMMemoryPressureLimitPercent = '...';
+ readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
<!--property ManagedOOMMemoryPressure is not documented!-->
- <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+ <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
- readonly s ManagedOOMMemoryPressureLimitPercent = '...';
+ readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
<!--property ManagedOOMMemoryPressure is not documented!-->
- <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+ <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property EnvironmentFiles is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
- readonly s ManagedOOMMemoryPressureLimitPercent = '...';
+ readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
<!--property ManagedOOMMemoryPressure is not documented!-->
- <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+ <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--Autogenerated cross-references for systemd.directives, do not edit-->
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
<!--End of Autogenerated section-->
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
- readonly s ManagedOOMMemoryPressureLimitPercent = '...';
+ readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
<!--property ManagedOOMMemoryPressure is not documented!-->
- <!--property ManagedOOMMemoryPressureLimitPercent is not documented!-->
+ <!--property ManagedOOMMemoryPressureLimitPermyriad is not documented!-->
<!--property KillMode is not documented!-->
<variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressure"/>
- <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPercent"/>
+ <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
</varlistentry>
<varlistentry>
- <term><varname>ManagedOOMMemoryPressureLimitPercent=</varname></term>
+ <term><varname>ManagedOOMMemoryPressureLimit=</varname></term>
<listitem>
<para>Overrides the default memory pressure limit set by
return 0;
}
-int parse_percent_unbounded(const char *p) {
+static int parse_parts_value_whole(const char *p, const char *symbol) {
const char *pc, *n;
int r, v;
- pc = endswith(p, "%");
+ pc = endswith(p, symbol);
if (!pc)
return -EINVAL;
return v;
}
+static int parse_parts_value_with_tenths_place(const char *p, const char *symbol) {
+ const char *pc, *dot, *n;
+ int r, q, v;
+
+ pc = endswith(p, symbol);
+ if (!pc)
+ return -EINVAL;
+
+ dot = memchr(p, '.', pc - p);
+ if (dot) {
+ if (dot + 2 != pc)
+ return -EINVAL;
+ if (dot[1] < '0' || dot[1] > '9')
+ return -EINVAL;
+ q = dot[1] - '0';
+ n = strndupa(p, dot - p);
+ } else {
+ q = 0;
+ n = strndupa(p, pc - p);
+ }
+ r = safe_atoi(n, &v);
+ if (r < 0)
+ return r;
+ if (v < 0)
+ return -ERANGE;
+ if (v > (INT_MAX - q) / 10)
+ return -ERANGE;
+
+ v = v * 10 + q;
+ return v;
+}
+
+static int parse_parts_value_with_hundredths_place(const char *p, const char *symbol) {
+ const char *pc, *dot, *n;
+ int r, q, v;
+
+ pc = endswith(p, symbol);
+ if (!pc)
+ return -EINVAL;
+
+ dot = memchr(p, '.', pc - p);
+ if (dot) {
+ if (dot + 3 != pc)
+ return -EINVAL;
+ if (dot[1] < '0' || dot[1] > '9' || dot[2] < '0' || dot[2] > '9')
+ return -EINVAL;
+ q = (dot[1] - '0') * 10 + (dot[2] - '0');
+ n = strndupa(p, dot - p);
+ } else {
+ q = 0;
+ n = strndupa(p, pc - p);
+ }
+ r = safe_atoi(n, &v);
+ if (r < 0)
+ return r;
+ if (v < 0)
+ return -ERANGE;
+ if (v > (INT_MAX - q) / 100)
+ return -ERANGE;
+
+ v = v * 100 + q;
+ return v;
+}
+
+int parse_percent_unbounded(const char *p) {
+ return parse_parts_value_whole(p, "%");
+}
+
int parse_percent(const char *p) {
int v;
}
int parse_permille_unbounded(const char *p) {
- const char *pc, *pm, *dot, *n;
- int r, q, v;
+ const char *pm;
pm = endswith(p, "‰");
- if (pm) {
- n = strndupa(p, pm - p);
- r = safe_atoi(n, &v);
- if (r < 0)
- return r;
- if (v < 0)
- return -ERANGE;
- } else {
- pc = endswith(p, "%");
- if (!pc)
- return -EINVAL;
-
- dot = memchr(p, '.', pc - p);
- if (dot) {
- if (dot + 2 != pc)
- return -EINVAL;
- if (dot[1] < '0' || dot[1] > '9')
- return -EINVAL;
- q = dot[1] - '0';
- n = strndupa(p, dot - p);
- } else {
- q = 0;
- n = strndupa(p, pc - p);
- }
- r = safe_atoi(n, &v);
- if (r < 0)
- return r;
- if (v < 0)
- return -ERANGE;
- if (v > (INT_MAX - q) / 10)
- return -ERANGE;
+ if (pm)
+ return parse_parts_value_whole(p, "‰");
- v = v * 10 + q;
- }
-
- return v;
+ return parse_parts_value_with_tenths_place(p, "%");
}
int parse_permille(const char *p) {
return v;
}
+int parse_permyriad_unbounded(const char *p) {
+ const char *pm;
+
+ pm = endswith(p, "‱");
+ if (pm)
+ return parse_parts_value_whole(p, "‱");
+
+ pm = endswith(p, "‰");
+ if (pm)
+ return parse_parts_value_with_tenths_place(p, "‰");
+
+ return parse_parts_value_with_hundredths_place(p, "%");
+}
+
+int parse_permyriad(const char *p) {
+ int v;
+
+ v = parse_permyriad_unbounded(p);
+ if (v > 10000)
+ return -ERANGE;
+
+ return v;
+}
+
int parse_nice(const char *p, int *ret) {
int n, r;
int parse_permille_unbounded(const char *p);
int parse_permille(const char *p);
+int parse_permyriad_unbounded(const char *p);
+int parse_permyriad(const char *p);
+
int parse_nice(const char *p, int *ret);
int parse_ip_port(const char *s, uint16_t *ret);
"%sDelegate: %s\n"
"%sManagedOOMSwap: %s\n"
"%sManagedOOMMemoryPressure: %s\n"
- "%sManagedOOMMemoryPressureLimitPercent: %d%%\n",
+ "%sManagedOOMMemoryPressureLimit: %" PRIu32 ".%02" PRIu32 "%%\n",
prefix, yes_no(c->cpu_accounting),
prefix, yes_no(c->io_accounting),
prefix, yes_no(c->blockio_accounting),
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);
+ prefix, c->moom_mem_pressure_limit_permyriad / 100, c->moom_mem_pressure_limit_permyriad % 100);
if (c->delegate) {
_cleanup_free_ char *t = NULL;
/* Settings for systemd-oomd */
ManagedOOMMode moom_swap;
ManagedOOMMode moom_mem_pressure;
- int moom_mem_pressure_limit;
+ uint32_t moom_mem_pressure_limit_permyriad;
};
/* Used when querying IP accounting data */
JSON_BUILD_PAIR("mode", JSON_BUILD_STRING(mode)),
JSON_BUILD_PAIR("path", JSON_BUILD_STRING(u->cgroup_path)),
JSON_BUILD_PAIR("property", JSON_BUILD_STRING(property)),
- JSON_BUILD_PAIR_CONDITION(use_limit, "limit", JSON_BUILD_UNSIGNED(c->moom_mem_pressure_limit))));
+ JSON_BUILD_PAIR_CONDITION(use_limit, "limit", JSON_BUILD_UNSIGNED(c->moom_mem_pressure_limit_permyriad))));
}
int manager_varlink_send_managed_oom_update(Unit *u) {
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_PROPERTY("ManagedOOMMemoryPressureLimitPermyriad", "u", NULL, offsetof(CGroupContext, moom_mem_pressure_limit_permyriad), 0),
SD_BUS_VTABLE_END
};
return 1;
}
- if (streq(name, "ManagedOOMMemoryPressureLimitPercent")) {
+ if (streq(name, "ManagedOOMMemoryPressureLimitPermyriad")) {
+ uint32_t v;
+
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 = bus_set_transient_percent(u, name, &c->moom_mem_pressure_limit, message, flags, error);
+ r = sd_bus_message_read(message, "u", &v);
if (r < 0)
return r;
+ if (v > 10000)
+ return -ERANGE;
+
+ if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+ c->moom_mem_pressure_limit_permyriad = v;
+ unit_write_settingf(u, flags, name, "ManagedOOMMemoryPressureLimit=%" PRIu32 ".%02" PRIu32 "%%", v / 100, v % 100);
+ }
+
if (c->moom_mem_pressure == MANAGED_OOM_KILL)
(void) manager_varlink_send_managed_oom_update(u);
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,
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);
$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.ManagedOOMMemoryPressureLimit, config_parse_managed_oom_mem_pressure_limit, 0, offsetof($1, cgroup_context.moom_mem_pressure_limit_permyriad)
$1.NetClass, config_parse_warn_compat, DISABLED_LEGACY, 0'
)m4_dnl
Unit.Description, config_parse_unit_string_printf, 0, offsetof(Unit, description)
const char *rvalue,
void *data,
void *userdata) {
- int *limit = data;
+ uint32_t *limit = data;
UnitType t;
int r;
return 0;
}
- r = parse_percent(rvalue);
+ r = parse_permyriad(rvalue);
if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse limit percent value, ignoring: %s", rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse memory pressure limit value, ignoring: %s", rvalue);
return 0;
}
limit = m->default_mem_pressure_limit;
if (streq(reply.property, "ManagedOOMMemoryPressure")) {
- if (reply.limit > 100)
+ if (reply.limit > 10000)
continue;
else if (reply.limit != 0) {
- ret = store_loadavg_fixed_point((unsigned long) reply.limit, 0, &limit);
+ ret = store_loadavg_fixed_point((unsigned long) reply.limit / 100, (unsigned long) reply.limit % 100, &limit);
if (ret < 0)
continue;
}
return 0;
}
-int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit, usec_t mem_pressure_usec) {
- unsigned long l;
+int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit_permyriad, usec_t mem_pressure_usec) {
+ unsigned long l, f;
int r;
assert(m);
m->swap_used_limit = swap_used_limit != -1 ? swap_used_limit : DEFAULT_SWAP_USED_LIMIT;
assert(m->swap_used_limit <= 100);
- l = mem_pressure_limit != -1 ? mem_pressure_limit : DEFAULT_MEM_PRESSURE_LIMIT;
- r = store_loadavg_fixed_point(l, 0, &m->default_mem_pressure_limit);
+ if (mem_pressure_limit_permyriad != -1) {
+ assert(mem_pressure_limit_permyriad <= 10000);
+
+ l = mem_pressure_limit_permyriad / 100;
+ f = mem_pressure_limit_permyriad % 100;
+ } else {
+ l = DEFAULT_MEM_PRESSURE_LIMIT_PERCENT;
+ f = 0;
+ }
+ r = store_loadavg_fixed_point(l, f, &m->default_mem_pressure_limit);
if (r < 0)
return r;
fprintf(f,
"Dry Run: %s\n"
"Swap Used Limit: %u%%\n"
- "Default Memory Pressure Limit: %lu%%\n"
+ "Default Memory Pressure Limit: %lu.%02lu%%\n"
"Default Memory Pressure Duration: %s\n"
"System Context:\n",
yes_no(m->dry_run),
m->swap_used_limit,
- LOAD_INT(m->default_mem_pressure_limit),
+ LOAD_INT(m->default_mem_pressure_limit), LOAD_FRAC(m->default_mem_pressure_limit),
format_timespan(buf, sizeof(buf), m->default_mem_pressure_duration_usec, USEC_PER_SEC));
oomd_dump_system_context(&m->system_context, f, "\t");
* Generally 60 or higher might be acceptable for something like system.slice with no memory.high set; processes in
* system.slice are assumed to be less latency sensitive. */
#define DEFAULT_MEM_PRESSURE_DURATION_USEC (30 * USEC_PER_SEC)
-#define DEFAULT_MEM_PRESSURE_LIMIT 60
+#define DEFAULT_MEM_PRESSURE_LIMIT_PERCENT 60
#define DEFAULT_SWAP_USED_LIMIT 90
#define RECLAIM_DURATION_USEC (30 * USEC_PER_SEC)
int manager_new(Manager **ret);
-int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit, usec_t mem_pressure_usec);
+int manager_start(Manager *m, bool dry_run, int swap_used_limit, int mem_pressure_limit_permyriad, usec_t mem_pressure_usec);
int manager_get_dump_string(Manager *m, char **ret);
fprintf(f,
"%sPath: %s\n"
- "%s\tMemory Pressure Limit: %lu%%\n"
+ "%s\tMemory Pressure Limit: %lu.%02lu%%\n"
"%s\tPressure: Avg10: %lu.%02lu Avg60: %lu.%02lu Avg300: %lu.%02lu Total: %s\n"
"%s\tCurrent Memory Usage: %s\n",
strempty(prefix), ctx->path,
- strempty(prefix), LOAD_INT(ctx->mem_pressure_limit),
+ strempty(prefix), LOAD_INT(ctx->mem_pressure_limit), LOAD_FRAC(ctx->mem_pressure_limit),
strempty(prefix),
LOAD_INT(ctx->memory_pressure.avg10), LOAD_FRAC(ctx->memory_pressure.avg10),
LOAD_INT(ctx->memory_pressure.avg60), LOAD_FRAC(ctx->memory_pressure.avg60),
static bool arg_dry_run = false;
static int arg_swap_used_limit = -1;
-static int arg_mem_pressure_limit = -1;
+static int arg_mem_pressure_limit_permyriad = -1;
static usec_t arg_mem_pressure_usec = 0;
static int parse_config(void) {
static const ConfigTableItem items[] = {
- { "OOM", "SwapUsedLimitPercent", config_parse_percent, 0, &arg_swap_used_limit },
- { "OOM", "DefaultMemoryPressureLimitPercent", config_parse_percent, 0, &arg_mem_pressure_limit },
- { "OOM", "DefaultMemoryPressureDurationSec", config_parse_sec, 0, &arg_mem_pressure_usec },
+ { "OOM", "SwapUsedLimitPercent", config_parse_percent, 0, &arg_swap_used_limit },
+ { "OOM", "DefaultMemoryPressureLimit", config_parse_permyriad, 0, &arg_mem_pressure_limit_permyriad },
+ { "OOM", "DefaultMemoryPressureDurationSec", config_parse_sec, 0, &arg_mem_pressure_usec },
{}
};
if (r < 0)
return log_error_errno(r, "Failed to create manager: %m");
- r = manager_start(m, arg_dry_run, arg_swap_used_limit, arg_mem_pressure_limit, arg_mem_pressure_usec);
+ r = manager_start(m, arg_dry_run, arg_swap_used_limit, arg_mem_pressure_limit_permyriad, arg_mem_pressure_usec);
if (r < 0)
return log_error_errno(r, "Failed to start up daemon: %m");
[OOM]
#SwapUsedLimitPercent=90%
-#DefaultMemoryPressureLimitPercent=60%
+#DefaultMemoryPressureLimit=60%
#DefaultMemoryPressureDurationSec=30s
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,
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)
if (STR_IN_SET(field, "DevicePolicy",
"Slice",
"ManagedOOMSwap",
- "ManagedOOMMemoryPressure",
- "ManagedOOMMemoryPressureLimitPercent"))
+ "ManagedOOMMemoryPressure"))
return bus_append_string(m, field, eq);
+ if (STR_IN_SET(field, "ManagedOOMMemoryPressureLimit")) {
+ char *n;
+
+ r = parse_permyriad(eq);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
+
+ n = strjoina(field, "Permyriad");
+
+ r = sd_bus_message_append(m, "(sv)", n, "u", (uint32_t) r);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ return 1;
+ }
+
if (STR_IN_SET(field, "CPUAccounting",
"MemoryAccounting",
"IOAccounting",
}
DEFINE_CONFIG_PARSE(config_parse_percent, parse_percent, "Failed to parse percent value");
+DEFINE_CONFIG_PARSE(config_parse_permyriad, parse_permyriad, "Failed to parse permyriad value");
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddr);
CONFIG_PARSER_PROTOTYPE(config_parse_hwaddrs);
CONFIG_PARSER_PROTOTYPE(config_parse_percent);
+CONFIG_PARSER_PROTOTYPE(config_parse_permyriad);
typedef enum Disabled {
DISABLED_CONFIGURATION,
assert_se(parse_permille_unbounded("429496729.6%") == -ERANGE);
}
+static void test_parse_permyriad(void) {
+ assert_se(parse_permyriad("") == -EINVAL);
+ assert_se(parse_permyriad("foo") == -EINVAL);
+ assert_se(parse_permyriad("0") == -EINVAL);
+ assert_se(parse_permyriad("50") == -EINVAL);
+ assert_se(parse_permyriad("100") == -EINVAL);
+ assert_se(parse_permyriad("-1") == -EINVAL);
+
+ assert_se(parse_permyriad("0‱") == 0);
+ assert_se(parse_permyriad("555‱") == 555);
+ assert_se(parse_permyriad("1000‱") == 1000);
+ assert_se(parse_permyriad("-7‱") == -ERANGE);
+ assert_se(parse_permyriad("10007‱") == -ERANGE);
+ assert_se(parse_permyriad("‱") == -EINVAL);
+ assert_se(parse_permyriad("‱‱") == -EINVAL);
+ assert_se(parse_permyriad("‱1") == -EINVAL);
+ assert_se(parse_permyriad("1‱‱") == -EINVAL);
+ assert_se(parse_permyriad("3.2‱") == -EINVAL);
+
+ assert_se(parse_permyriad("0‰") == 0);
+ assert_se(parse_permyriad("555.5‰") == 5555);
+ assert_se(parse_permyriad("1000.0‰") == 10000);
+ assert_se(parse_permyriad("-7‰") == -ERANGE);
+ assert_se(parse_permyriad("1007‰") == -ERANGE);
+ assert_se(parse_permyriad("‰") == -EINVAL);
+ assert_se(parse_permyriad("‰‰") == -EINVAL);
+ assert_se(parse_permyriad("‰1") == -EINVAL);
+ assert_se(parse_permyriad("1‰‰") == -EINVAL);
+ assert_se(parse_permyriad("3.22‰") == -EINVAL);
+
+ assert_se(parse_permyriad("0%") == 0);
+ assert_se(parse_permyriad("55%") == 5500);
+ assert_se(parse_permyriad("55.53%") == 5553);
+ assert_se(parse_permyriad("100%") == 10000);
+ assert_se(parse_permyriad("-7%") == -ERANGE);
+ assert_se(parse_permyriad("107%") == -ERANGE);
+ assert_se(parse_permyriad("%") == -EINVAL);
+ assert_se(parse_permyriad("%%") == -EINVAL);
+ assert_se(parse_permyriad("%1") == -EINVAL);
+ assert_se(parse_permyriad("1%%") == -EINVAL);
+ assert_se(parse_permyriad("3.212%") == -EINVAL);
+}
+
+static void test_parse_permyriad_unbounded(void) {
+ assert_se(parse_permyriad_unbounded("1001‱") == 1001);
+ assert_se(parse_permyriad_unbounded("4000‱") == 4000);
+ assert_se(parse_permyriad_unbounded("2147483647‱") == 2147483647);
+ assert_se(parse_permyriad_unbounded("2147483648‱") == -ERANGE);
+ assert_se(parse_permyriad_unbounded("4294967295‱") == -ERANGE);
+ assert_se(parse_permyriad_unbounded("4294967296‱") == -ERANGE);
+
+ assert_se(parse_permyriad_unbounded("101‰") == 1010);
+ assert_se(parse_permyriad_unbounded("400‰") == 4000);
+ assert_se(parse_permyriad_unbounded("214748364.7‰") == 2147483647);
+ assert_se(parse_permyriad_unbounded("214748364.8‰") == -ERANGE);
+ assert_se(parse_permyriad_unbounded("429496729.5‰") == -ERANGE);
+ assert_se(parse_permyriad_unbounded("429496729.6‰") == -ERANGE);
+
+ assert_se(parse_permyriad_unbounded("99%") == 9900);
+ assert_se(parse_permyriad_unbounded("40%") == 4000);
+ assert_se(parse_permyriad_unbounded("21474836.47%") == 2147483647);
+ assert_se(parse_permyriad_unbounded("21474836.48%") == -ERANGE);
+ assert_se(parse_permyriad_unbounded("42949672.95%") == -ERANGE);
+ assert_se(parse_permyriad_unbounded("42949672.96%") == -ERANGE);
+}
+
static void test_parse_nice(void) {
int n;
test_parse_percent_unbounded();
test_parse_permille();
test_parse_permille_unbounded();
+ test_parse_permyriad();
+ test_parse_permyriad_unbounded();
test_parse_nice();
test_parse_dev();
test_parse_errno();
IOAccounting=true
TasksAccounting=true
ManagedOOMMemoryPressure=kill
-ManagedOOMMemoryPressureLimitPercent=1%
+ManagedOOMMemoryPressureLimit=1%
# Verify systemd-oomd is monitoring the expected units
oomctl | grep "/testsuite-56-workload.slice"
-oomctl | grep "1%"
+oomctl | grep "1.00%"
oomctl | grep "Default Memory Pressure Duration: 5s"
# systemd-oomd watches for elevated pressure for 30 seconds before acting.