1
0
mirror of https://github.com/systemd/systemd.git synced 2024-11-01 09:21:26 +03:00

oom: Introduce process_managed_oom_message()

Gets rid of a few gotos, allows removing the extra ret variable and
will also be used in a future commit by the codepath that receives
cgroups from user instances of systemd.
This commit is contained in:
Daan De Meyer 2021-09-02 13:24:23 +02:00
parent ccf7cf2aa4
commit 71feeae4bf

View File

@ -12,17 +12,17 @@
#include "path-util.h"
#include "percent-util.h"
typedef struct ManagedOOMReply {
typedef struct ManagedOOMMessage {
ManagedOOMMode mode;
char *path;
char *property;
uint32_t limit;
} ManagedOOMReply;
} ManagedOOMMessage;
static void managed_oom_reply_destroy(ManagedOOMReply *reply) {
assert(reply);
free(reply->path);
free(reply->property);
static void managed_oom_message_destroy(ManagedOOMMessage *message) {
assert(message);
free(message->path);
free(message->property);
}
static int managed_oom_mode(const char *name, JsonVariant *v, JsonDispatchFlags flags, void *userdata) {
@ -40,92 +40,96 @@ static int managed_oom_mode(const char *name, JsonVariant *v, JsonDispatchFlags
return 0;
}
static int process_managed_oom_message(Manager *m, JsonVariant *parameters) {
JsonVariant *c, *cgroups;
int r;
static const JsonDispatch dispatch_table[] = {
{ "mode", JSON_VARIANT_STRING, managed_oom_mode, offsetof(ManagedOOMMessage, mode), JSON_MANDATORY },
{ "path", JSON_VARIANT_STRING, json_dispatch_string, offsetof(ManagedOOMMessage, path), JSON_MANDATORY },
{ "property", JSON_VARIANT_STRING, json_dispatch_string, offsetof(ManagedOOMMessage, property), JSON_MANDATORY },
{ "limit", JSON_VARIANT_UNSIGNED, json_dispatch_uint32, offsetof(ManagedOOMMessage, limit), 0 },
{},
};
assert(m);
assert(parameters);
cgroups = json_variant_by_key(parameters, "cgroups");
if (!cgroups)
return -EINVAL;
/* Skip malformed elements and keep processing in case the others are good */
JSON_VARIANT_ARRAY_FOREACH(c, cgroups) {
_cleanup_(managed_oom_message_destroy) ManagedOOMMessage message = {};
OomdCGroupContext *ctx;
Hashmap *monitor_hm;
loadavg_t limit;
if (!json_variant_is_object(c))
continue;
r = json_dispatch(c, dispatch_table, NULL, 0, &message);
if (r == -ENOMEM)
return r;
if (r < 0)
continue;
monitor_hm = streq(message.property, "ManagedOOMSwap") ?
m->monitored_swap_cgroup_contexts : m->monitored_mem_pressure_cgroup_contexts;
if (message.mode == MANAGED_OOM_AUTO) {
(void) oomd_cgroup_context_free(hashmap_remove(monitor_hm, empty_to_root(message.path)));
continue;
}
limit = m->default_mem_pressure_limit;
if (streq(message.property, "ManagedOOMMemoryPressure") && message.limit > 0) {
int permyriad = UINT32_SCALE_TO_PERMYRIAD(message.limit);
r = store_loadavg_fixed_point(
(unsigned long) permyriad / 100,
(unsigned long) permyriad % 100,
&limit);
if (r < 0)
continue;
}
r = oomd_insert_cgroup_context(NULL, monitor_hm, message.path);
if (r == -ENOMEM)
return r;
if (r < 0 && r != -EEXIST)
log_debug_errno(r, "Failed to insert message, ignoring: %m");
/* Always update the limit in case it was changed. For non-memory pressure detection the value is
* ignored so always updating it here is not a problem. */
ctx = hashmap_get(monitor_hm, empty_to_root(message.path));
if (ctx)
ctx->mem_pressure_limit = limit;
}
return 0;
}
static int process_managed_oom_reply(
Varlink *link,
JsonVariant *parameters,
const char *error_id,
VarlinkReplyFlags flags,
void *userdata) {
JsonVariant *c, *cgroups;
Manager *m = userdata;
int r = 0;
int r;
assert(m);
static const JsonDispatch dispatch_table[] = {
{ "mode", JSON_VARIANT_STRING, managed_oom_mode, offsetof(ManagedOOMReply, mode), JSON_MANDATORY },
{ "path", JSON_VARIANT_STRING, json_dispatch_string, offsetof(ManagedOOMReply, path), JSON_MANDATORY },
{ "property", JSON_VARIANT_STRING, json_dispatch_string, offsetof(ManagedOOMReply, property), JSON_MANDATORY },
{ "limit", JSON_VARIANT_UNSIGNED, json_dispatch_uint32, offsetof(ManagedOOMReply, limit), 0 },
{},
};
if (error_id) {
r = -EIO;
log_debug("Error getting ManagedOOM cgroups: %s", error_id);
goto finish;
}
cgroups = json_variant_by_key(parameters, "cgroups");
if (!cgroups) {
r = -EINVAL;
goto finish;
}
/* Skip malformed elements and keep processing in case the others are good */
JSON_VARIANT_ARRAY_FOREACH(c, cgroups) {
_cleanup_(managed_oom_reply_destroy) ManagedOOMReply reply = {};
OomdCGroupContext *ctx;
Hashmap *monitor_hm;
loadavg_t limit;
int ret;
if (!json_variant_is_object(c))
continue;
ret = json_dispatch(c, dispatch_table, NULL, 0, &reply);
if (ret == -ENOMEM) {
r = ret;
goto finish;
}
if (ret < 0)
continue;
monitor_hm = streq(reply.property, "ManagedOOMSwap") ?
m->monitored_swap_cgroup_contexts : m->monitored_mem_pressure_cgroup_contexts;
if (reply.mode == MANAGED_OOM_AUTO) {
(void) oomd_cgroup_context_free(hashmap_remove(monitor_hm, empty_to_root(reply.path)));
continue;
}
limit = m->default_mem_pressure_limit;
if (streq(reply.property, "ManagedOOMMemoryPressure") && reply.limit > 0) {
int permyriad = UINT32_SCALE_TO_PERMYRIAD(reply.limit);
ret = store_loadavg_fixed_point(
(unsigned long) permyriad / 100,
(unsigned long) permyriad % 100,
&limit);
if (ret < 0)
continue;
}
ret = oomd_insert_cgroup_context(NULL, monitor_hm, reply.path);
if (ret == -ENOMEM) {
r = ret;
goto finish;
}
if (ret < 0 && ret != -EEXIST)
log_debug_errno(ret, "Failed to insert reply, ignoring: %m");
/* Always update the limit in case it was changed. For non-memory pressure detection the value is
* ignored so always updating it here is not a problem. */
ctx = hashmap_get(monitor_hm, empty_to_root(reply.path));
if (ctx)
ctx->mem_pressure_limit = limit;
}
r = process_managed_oom_message(m, parameters);
finish:
if (!FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))