#include "strv.h"
#include "user-util.h"
#include "varlink.h"
+#include "varlink-io.systemd.UserDatabase.h"
+#include "varlink-io.systemd.ManagedOOM.h"
typedef struct LookupParameters {
const char *user_name;
if (!c)
return -EINVAL;
+ CGroupRuntime *crt = unit_get_cgroup_runtime(u);
+ if (!crt)
+ return -EINVAL;
+
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)))
/* systemd-oomd should always treat inactive units as though they didn't enable any action since they
* should not have a valid cgroup */
return json_build(ret_v, JSON_BUILD_OBJECT(
JSON_BUILD_PAIR("mode", JSON_BUILD_STRING(mode)),
- JSON_BUILD_PAIR("path", JSON_BUILD_STRING(u->cgroup_path)),
+ JSON_BUILD_PAIR("path", JSON_BUILD_STRING(crt->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))));
}
int manager_varlink_send_managed_oom_update(Unit *u) {
_cleanup_(json_variant_unrefp) JsonVariant *arr = NULL, *v = NULL;
+ CGroupRuntime *crt;
CGroupContext *c;
int r;
assert(u);
- if (!UNIT_VTABLE(u)->can_set_managed_oom || !u->manager || !u->cgroup_path)
+ if (!UNIT_VTABLE(u)->can_set_managed_oom || !u->manager)
+ return 0;
+
+ crt = unit_get_cgroup_runtime(u);
+ if (!crt || !crt->cgroup_path)
return 0;
if (MANAGER_IS_SYSTEM(u->manager)) {
}
static int build_managed_oom_cgroups_json(Manager *m, JsonVariant **ret) {
- static const UnitType supported_unit_types[] = { UNIT_SLICE, UNIT_SERVICE, UNIT_SCOPE };
_cleanup_(json_variant_unrefp) JsonVariant *v = NULL, *arr = NULL;
int r;
if (r < 0)
return r;
- for (size_t i = 0; i < ELEMENTSOF(supported_unit_types); i++)
- LIST_FOREACH(units_by_type, u, m->units_by_type[supported_unit_types[i]]) {
+ for (UnitType t = 0; t < _UNIT_TYPE_MAX; t++) {
+
+ if (!unit_vtable[t]->can_set_managed_oom)
+ continue;
+
+ LIST_FOREACH(units_by_type, u, m->units_by_type[t]) {
CGroupContext *c;
if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(u)))
return r;
}
}
+ }
r = json_build(&v, JSON_BUILD_OBJECT(JSON_BUILD_PAIR("cgroups", JSON_BUILD_VARIANT(arr))));
if (r < 0)
/* We only take one subscriber for this method so return an error if there's already an existing one.
* This shouldn't happen since systemd-oomd is the only client of this method. */
if (FLAGS_SET(flags, VARLINK_METHOD_MORE) && m->managed_oom_varlink)
- return varlink_error(link, VARLINK_ERROR_SUBSCRIPTION_TAKEN, NULL);
+ return varlink_error(link, "io.systemd.ManagedOOM.SubscriptionTaken", NULL);
r = build_managed_oom_cgroups_json(m, &v);
if (r < 0)
assert(parameters);
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
- if (r < 0)
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
+ if (r != 0)
return r;
if (!streq_ptr(p.service, "io.systemd.DynamicUser"))
assert(parameters);
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
- if (r < 0)
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
+ if (r != 0)
return r;
if (!streq_ptr(p.service, "io.systemd.DynamicUser"))
assert(parameters);
- r = json_dispatch(parameters, dispatch_table, NULL, 0, &p);
- if (r < 0)
+ r = varlink_dispatch(link, parameters, dispatch_table, &p);
+ if (r != 0)
return r;
if (!streq_ptr(p.service, "io.systemd.DynamicUser"))
if (!MANAGER_IS_TEST_RUN(m)) {
(void) mkdir_p_label("/run/systemd/userdb", 0755);
- r = varlink_server_listen_address(s, "/run/systemd/userdb/io.systemd.DynamicUser", 0666);
- if (r < 0)
- return log_error_errno(r, "Failed to bind to varlink socket: %m");
+ FOREACH_STRING(address, "/run/systemd/userdb/io.systemd.DynamicUser", VARLINK_ADDR_PATH_MANAGED_OOM_SYSTEM) {
+ if (MANAGER_IS_RELOADING(m)) {
+ /* If manager is reloading, we skip listening on existing addresses, since
+ * the fd should be acquired later through deserialization. */
+ if (access(address, F_OK) >= 0)
+ continue;
+ if (errno != ENOENT)
+ return log_error_errno(errno,
+ "Failed to check if varlink socket '%s' exists: %m", address);
+ }
- r = varlink_server_listen_address(s, VARLINK_ADDR_PATH_MANAGED_OOM_SYSTEM, 0666);
- if (r < 0)
- return log_error_errno(r, "Failed to bind to varlink socket: %m");
+ r = varlink_server_listen_address(s, address, 0666);
+ if (r < 0)
+ return log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address);
+ }
}
- r = varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL);
+ r = varlink_server_attach_event(s, m->event, EVENT_PRIORITY_IPC);
if (r < 0)
return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
return 0;
r = varlink_connect_address(&link, VARLINK_ADDR_PATH_MANAGED_OOM_USER);
- if (r == -ENOENT || ERRNO_IS_DISCONNECT(r)) {
- log_debug("systemd-oomd varlink unix socket not found, skipping user manager varlink setup");
- return 0;
- }
- if (r < 0)
+ if (r < 0) {
+ if (r == -ENOENT || ERRNO_IS_DISCONNECT(r)) {
+ log_debug("systemd-oomd varlink unix socket not found, skipping user manager varlink setup");
+ return 0;
+ }
return log_error_errno(r, "Failed to connect to %s: %m", VARLINK_ADDR_PATH_MANAGED_OOM_USER);
+ }
varlink_set_userdata(link, m);
if (r < 0)
return r;
- r = varlink_attach_event(link, m->event, SD_EVENT_PRIORITY_NORMAL);
+ r = varlink_attach_event(link, m->event, EVENT_PRIORITY_IPC);
if (r < 0)
return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
varlink_server_set_userdata(s, m);
+ r = varlink_server_add_interface_many(
+ s,
+ &vl_interface_io_systemd_UserDatabase,
+ &vl_interface_io_systemd_ManagedOOM);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add interfaces to varlink server: %m");
+
r = varlink_server_bind_method_many(
s,
"io.systemd.UserDatabase.GetUserRecord", vl_method_get_user_record,