ryantimwilson / rpms / systemd

Forked from rpms/systemd a month ago
Clone
834f04
From 2ccd5198faa8ca65001f90c551924e86bf737a85 Mon Sep 17 00:00:00 2001
834f04
From: Anita Zhang <the.anitazha@gmail.com>
834f04
Date: Mon, 25 Jan 2021 23:56:23 -0800
834f04
Subject: [PATCH 1/7] oom: shorten xattr name
834f04
834f04
---
834f04
 src/core/cgroup.c        | 2 +-
834f04
 src/oom/oomd-util.c      | 4 ++--
834f04
 src/oom/test-oomd-util.c | 2 +-
834f04
 3 files changed, 4 insertions(+), 4 deletions(-)
834f04
834f04
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
834f04
index c9cf7fb16c6..70282a7abda 100644
834f04
--- a/src/core/cgroup.c
834f04
+++ b/src/core/cgroup.c
834f04
@@ -2746,7 +2746,7 @@ int unit_check_oomd_kill(Unit *u) {
834f04
         else if (r == 0)
834f04
                 return 0;
834f04
 
834f04
-        r = cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "user.systemd_oomd_kill", &value);
834f04
+        r = cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "user.oomd_kill", &value);
834f04
         if (r < 0 && r != -ENODATA)
834f04
                 return r;
834f04
 
834f04
diff --git a/src/oom/oomd-util.c b/src/oom/oomd-util.c
834f04
index fcccddb92ea..80b9583440c 100644
834f04
--- a/src/oom/oomd-util.c
834f04
+++ b/src/oom/oomd-util.c
834f04
@@ -201,9 +201,9 @@ int oomd_cgroup_kill(const char *path, bool recurse, bool dry_run) {
834f04
         if (r < 0)
834f04
                 return r;
834f04
 
834f04
-        r = increment_oomd_xattr(path, "user.systemd_oomd_kill", set_size(pids_killed));
834f04
+        r = increment_oomd_xattr(path, "user.oomd_kill", set_size(pids_killed));
834f04
         if (r < 0)
834f04
-                log_debug_errno(r, "Failed to set user.systemd_oomd_kill on kill: %m");
834f04
+                log_debug_errno(r, "Failed to set user.oomd_kill on kill: %m");
834f04
 
834f04
         return set_size(pids_killed) != 0;
834f04
 }
834f04
diff --git a/src/oom/test-oomd-util.c b/src/oom/test-oomd-util.c
834f04
index 54fe2a03d14..3dec4f0ff06 100644
834f04
--- a/src/oom/test-oomd-util.c
834f04
+++ b/src/oom/test-oomd-util.c
834f04
@@ -79,7 +79,7 @@ static void test_oomd_cgroup_kill(void) {
834f04
                 sleep(2);
834f04
                 assert_se(cg_is_empty(SYSTEMD_CGROUP_CONTROLLER, cgroup) == true);
834f04
 
834f04
-                assert_se(cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.systemd_oomd_kill", &v) >= 0);
834f04
+                assert_se(cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_kill", &v) >= 0);
834f04
                 assert_se(memcmp(v, i == 0 ? "2" : "4", 2) == 0);
834f04
         }
834f04
 }
834f04
834f04
From d38916b398127e005d0cf131092a99317661ec3c Mon Sep 17 00:00:00 2001
834f04
From: Anita Zhang <the.anitazha@gmail.com>
834f04
Date: Fri, 5 Feb 2021 03:00:11 -0800
834f04
Subject: [PATCH 2/7] oom: wrap reply.path with empty_to_root
834f04
834f04
---
834f04
 src/oom/oomd-manager.c | 6 +++---
834f04
 1 file changed, 3 insertions(+), 3 deletions(-)
834f04
834f04
diff --git a/src/oom/oomd-manager.c b/src/oom/oomd-manager.c
834f04
index 338935b3ec6..825fe38e189 100644
834f04
--- a/src/oom/oomd-manager.c
834f04
+++ b/src/oom/oomd-manager.c
834f04
@@ -93,7 +93,7 @@ static int process_managed_oom_reply(
834f04
                                 m->monitored_swap_cgroup_contexts : m->monitored_mem_pressure_cgroup_contexts;
834f04
 
834f04
                 if (reply.mode == MANAGED_OOM_AUTO) {
834f04
-                        (void) oomd_cgroup_context_free(hashmap_remove(monitor_hm, reply.path));
834f04
+                        (void) oomd_cgroup_context_free(hashmap_remove(monitor_hm, empty_to_root(reply.path)));
834f04
                         continue;
834f04
                 }
834f04
 
834f04
@@ -109,7 +109,7 @@ static int process_managed_oom_reply(
834f04
                         }
834f04
                 }
834f04
 
834f04
-                ret = oomd_insert_cgroup_context(NULL, monitor_hm, reply.path);
834f04
+                ret = oomd_insert_cgroup_context(NULL, monitor_hm, empty_to_root(reply.path));
834f04
                 if (ret == -ENOMEM) {
834f04
                         r = ret;
834f04
                         goto finish;
834f04
@@ -117,7 +117,7 @@ static int process_managed_oom_reply(
834f04
 
834f04
                 /* Always update the limit in case it was changed. For non-memory pressure detection the value is
834f04
                  * ignored so always updating it here is not a problem. */
834f04
-                ctx = hashmap_get(monitor_hm, reply.path);
834f04
+                ctx = hashmap_get(monitor_hm, empty_to_root(reply.path));
834f04
                 if (ctx)
834f04
                         ctx->mem_pressure_limit = limit;
834f04
         }
834f04
834f04
From a695da238e7a6bd6eb440facc784aa6fca6c3d90 Mon Sep 17 00:00:00 2001
834f04
From: Anita Zhang <the.anitazha@gmail.com>
834f04
Date: Wed, 27 Jan 2021 23:43:13 -0800
834f04
Subject: [PATCH 3/7] oom: sort by pgscan and memory usage
834f04
834f04
If 2 candidates have the same pgscan, prioritize the one with the larger
834f04
memory usage.
834f04
---
834f04
 src/oom/oomd-util.c      |  2 +-
834f04
 src/oom/oomd-util.h      |  5 ++++-
834f04
 src/oom/test-oomd-util.c | 24 ++++++++++++++----------
834f04
 3 files changed, 19 insertions(+), 12 deletions(-)
834f04
834f04
diff --git a/src/oom/oomd-util.c b/src/oom/oomd-util.c
834f04
index 80b9583440c..8f138d64c6c 100644
834f04
--- a/src/oom/oomd-util.c
834f04
+++ b/src/oom/oomd-util.c
834f04
@@ -214,7 +214,7 @@ int oomd_kill_by_pgscan(Hashmap *h, const char *prefix, bool dry_run) {
834f04
 
834f04
         assert(h);
834f04
 
834f04
-        r = oomd_sort_cgroup_contexts(h, compare_pgscan, prefix, &sorted);
834f04
+        r = oomd_sort_cgroup_contexts(h, compare_pgscan_and_memory_usage, prefix, &sorted);
834f04
         if (r < 0)
834f04
                 return r;
834f04
 
834f04
diff --git a/src/oom/oomd-util.h b/src/oom/oomd-util.h
834f04
index d7a9890e7a2..f0648c5dcdd 100644
834f04
--- a/src/oom/oomd-util.h
834f04
+++ b/src/oom/oomd-util.h
834f04
@@ -61,10 +61,13 @@ bool oomd_memory_reclaim(Hashmap *h);
834f04
 /* Returns true if the amount of swap free is below the percentage of swap specified by `threshold_percent`. */
834f04
 bool oomd_swap_free_below(const OomdSystemContext *ctx, uint64_t threshold_percent);
834f04
 
834f04
-static inline int compare_pgscan(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) {
834f04
+static inline int compare_pgscan_and_memory_usage(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) {
834f04
         assert(c1);
834f04
         assert(c2);
834f04
 
834f04
+        if ((*c2)->pgscan == (*c1)->pgscan)
834f04
+                return CMP((*c2)->current_memory_usage, (*c1)->current_memory_usage);
834f04
+
834f04
         return CMP((*c2)->pgscan, (*c1)->pgscan);
834f04
 }
834f04
 
834f04
diff --git a/src/oom/test-oomd-util.c b/src/oom/test-oomd-util.c
834f04
index 3dec4f0ff06..a1fe78806a1 100644
834f04
--- a/src/oom/test-oomd-util.c
834f04
+++ b/src/oom/test-oomd-util.c
834f04
@@ -292,16 +292,20 @@ static void test_oomd_sort_cgroups(void) {
834f04
         OomdCGroupContext ctx[4] = {
834f04
                 { .path = paths[0],
834f04
                   .swap_usage = 20,
834f04
-                  .pgscan = 60 },
834f04
+                  .pgscan = 60,
834f04
+                  .current_memory_usage = 10 },
834f04
                 { .path = paths[1],
834f04
                   .swap_usage = 60,
834f04
-                  .pgscan = 40 },
834f04
+                  .pgscan = 40,
834f04
+                  .current_memory_usage = 20 },
834f04
                 { .path = paths[2],
834f04
                   .swap_usage = 40,
834f04
-                  .pgscan = 20 },
834f04
+                  .pgscan = 40,
834f04
+                  .current_memory_usage = 40 },
834f04
                 { .path = paths[3],
834f04
                   .swap_usage = 10,
834f04
-                  .pgscan = 80 },
834f04
+                  .pgscan = 80,
834f04
+                  .current_memory_usage = 10 },
834f04
         };
834f04
 
834f04
         assert_se(h = hashmap_new(&string_hash_ops));
834f04
@@ -318,16 +322,16 @@ static void test_oomd_sort_cgroups(void) {
834f04
         assert_se(sorted_cgroups[3] == &ctx[3]);
834f04
         sorted_cgroups = mfree(sorted_cgroups);
834f04
 
834f04
-        assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan, NULL, &sorted_cgroups) == 4);
834f04
+        assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan_and_memory_usage, NULL, &sorted_cgroups) == 4);
834f04
         assert_se(sorted_cgroups[0] == &ctx[3]);
834f04
         assert_se(sorted_cgroups[1] == &ctx[0]);
834f04
-        assert_se(sorted_cgroups[2] == &ctx[1]);
834f04
-        assert_se(sorted_cgroups[3] == &ctx[2]);
834f04
+        assert_se(sorted_cgroups[2] == &ctx[2]);
834f04
+        assert_se(sorted_cgroups[3] == &ctx[1]);
834f04
         sorted_cgroups = mfree(sorted_cgroups);
834f04
 
834f04
-        assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan, "/herp.slice/derp.scope", &sorted_cgroups) == 2);
834f04
-        assert_se(sorted_cgroups[0] == &ctx[1]);
834f04
-        assert_se(sorted_cgroups[1] == &ctx[2]);
834f04
+        assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan_and_memory_usage, "/herp.slice/derp.scope", &sorted_cgroups) == 2);
834f04
+        assert_se(sorted_cgroups[0] == &ctx[2]);
834f04
+        assert_se(sorted_cgroups[1] == &ctx[1]);
834f04
         assert_se(sorted_cgroups[2] == 0);
834f04
         assert_se(sorted_cgroups[3] == 0);
834f04
         sorted_cgroups = mfree(sorted_cgroups);
834f04
834f04
From c73a2c3a6788a2a28899f29579fdd68816f60d59 Mon Sep 17 00:00:00 2001
834f04
From: Anita Zhang <the.anitazha@gmail.com>
834f04
Date: Thu, 28 Jan 2021 15:47:26 -0800
834f04
Subject: [PATCH 4/7] oom: skip over cgroups with no memory usage
834f04
834f04
---
834f04
 src/oom/oomd-util.c | 3 ++-
834f04
 1 file changed, 2 insertions(+), 1 deletion(-)
834f04
834f04
diff --git a/src/oom/oomd-util.c b/src/oom/oomd-util.c
834f04
index 8f138d64c6c..fa8b8b70b19 100644
834f04
--- a/src/oom/oomd-util.c
834f04
+++ b/src/oom/oomd-util.c
834f04
@@ -219,7 +219,8 @@ int oomd_kill_by_pgscan(Hashmap *h, const char *prefix, bool dry_run) {
834f04
                 return r;
834f04
 
834f04
         for (int i = 0; i < r; i++) {
834f04
-                if (sorted[i]->pgscan == 0)
834f04
+                /* Skip cgroups with no reclaim and memory usage; it won't alleviate pressure */
834f04
+                if (sorted[i]->pgscan == 0 && sorted[i]->current_memory_usage == 0)
834f04
                         break;
834f04
 
834f04
                 r = oomd_cgroup_kill(sorted[i]->path, true, dry_run);
834f04
834f04
From 63d6d9160523a2c1a71e96ff4125a1440d827b32 Mon Sep 17 00:00:00 2001
834f04
From: Anita Zhang <the.anitazha@gmail.com>
834f04
Date: Tue, 26 Jan 2021 00:57:36 -0800
834f04
Subject: [PATCH 5/7] oom: implement avoid/omit xattr support
834f04
834f04
There may be situations where a cgroup should be protected from killing
834f04
or deprioritized as a candidate. In FB oomd xattrs are used to bias oomd
834f04
away from supervisor cgroups and towards worker cgroups in container
834f04
tasks. On desktops this can be used to protect important units with
834f04
unpredictable resource consumption.
834f04
834f04
The patch allows systemd-oomd to understand 2 xattrs:
834f04
"user.oomd_avoid" and "user.oomd_omit". If systemd-oomd sees these
834f04
xattrs set to 1 on a candidate cgroup (i.e. while attempting to kill something)
834f04
AND the cgroup is owned by root:root, it will either deprioritize the cgroup as
834f04
a candidate (avoid) or remove it completely as a candidate (omit).
834f04
834f04
Usage is restricted to root:root cgroups to prevent situations where an
834f04
unprivileged user can set their own cgroups lower in the kill priority than
834f04
another user's (and prevent them from omitting their units from
834f04
systemd-oomd killing).
834f04
---
834f04
 src/basic/cgroup-util.c                   | 22 +++++++++
834f04
 src/basic/cgroup-util.h                   |  1 +
834f04
 src/oom/oomd-util.c                       | 35 ++++++++++++---
834f04
 src/oom/oomd-util.h                       | 11 +++++
834f04
 src/oom/test-oomd-util.c                  | 54 +++++++++++++++++++++--
834f04
 test/test-functions                       |  1 +
834f04
 test/units/testsuite-56-testmunch.service |  7 +++
834f04
 test/units/testsuite-56.sh                | 31 +++++++++++--
834f04
 8 files changed, 149 insertions(+), 13 deletions(-)
834f04
 create mode 100644 test/units/testsuite-56-testmunch.service
834f04
834f04
diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c
834f04
index b567822b7ef..45dc1142048 100644
834f04
--- a/src/basic/cgroup-util.c
834f04
+++ b/src/basic/cgroup-util.c
834f04
@@ -1703,6 +1703,28 @@ int cg_get_attribute_as_bool(const char *controller, const char *path, const cha
834f04
         return 0;
834f04
 }
834f04
 
834f04
+
834f04
+int cg_get_owner(const char *controller, const char *path, uid_t *ret_uid, gid_t *ret_gid) {
834f04
+        _cleanup_free_ char *f = NULL;
834f04
+        struct stat stats;
834f04
+        int r;
834f04
+
834f04
+        assert(ret_uid);
834f04
+        assert(ret_gid);
834f04
+
834f04
+        r = cg_get_path(controller, path, NULL, &f);
834f04
+        if (r < 0)
834f04
+                return r;
834f04
+
834f04
+        r = stat(f, &stats);
834f04
+        if (r < 0)
834f04
+                return -errno;
834f04
+
834f04
+        *ret_uid = stats.st_uid;
834f04
+        *ret_gid = stats.st_gid;
834f04
+        return 0;
834f04
+}
834f04
+
834f04
 int cg_get_keyed_attribute_full(
834f04
                 const char *controller,
834f04
                 const char *path,
834f04
diff --git a/src/basic/cgroup-util.h b/src/basic/cgroup-util.h
834f04
index bdc0d0d086c..63bd25f703e 100644
834f04
--- a/src/basic/cgroup-util.h
834f04
+++ b/src/basic/cgroup-util.h
834f04
@@ -212,6 +212,7 @@ int cg_get_attribute_as_uint64(const char *controller, const char *path, const c
834f04
 int cg_get_attribute_as_bool(const char *controller, const char *path, const char *attribute, bool *ret);
834f04
 
834f04
 int cg_set_access(const char *controller, const char *path, uid_t uid, gid_t gid);
834f04
+int cg_get_owner(const char *controller, const char *path, uid_t *ret_uid, gid_t *ret_gid);
834f04
 
834f04
 int cg_set_xattr(const char *controller, const char *path, const char *name, const void *value, size_t size, int flags);
834f04
 int cg_get_xattr(const char *controller, const char *path, const char *name, void *value, size_t size);
834f04
diff --git a/src/oom/oomd-util.c b/src/oom/oomd-util.c
834f04
index fa8b8b70b19..db6383bf436 100644
834f04
--- a/src/oom/oomd-util.c
834f04
+++ b/src/oom/oomd-util.c
834f04
@@ -159,7 +159,8 @@ int oomd_sort_cgroup_contexts(Hashmap *h, oomd_compare_t compare_func, const cha
834f04
                 return -ENOMEM;
834f04
 
834f04
         HASHMAP_FOREACH(item, h) {
834f04
-                if (item->path && prefix && !path_startswith(item->path, prefix))
834f04
+                /* Skip over cgroups that are not valid candidates or are explicitly marked for omission */
834f04
+                if ((item->path && prefix && !path_startswith(item->path, prefix)) || item->omit)
834f04
                         continue;
834f04
 
834f04
                 sorted[k++] = item;
834f04
@@ -219,9 +220,10 @@ int oomd_kill_by_pgscan(Hashmap *h, const char *prefix, bool dry_run) {
834f04
                 return r;
834f04
 
834f04
         for (int i = 0; i < r; i++) {
834f04
-                /* Skip cgroups with no reclaim and memory usage; it won't alleviate pressure */
834f04
+                /* Skip cgroups with no reclaim and memory usage; it won't alleviate pressure. */
834f04
+                /* Don't break since there might be "avoid" cgroups at the end. */
834f04
                 if (sorted[i]->pgscan == 0 && sorted[i]->current_memory_usage == 0)
834f04
-                        break;
834f04
+                        continue;
834f04
 
834f04
                 r = oomd_cgroup_kill(sorted[i]->path, true, dry_run);
834f04
                 if (r > 0 || r == -ENOMEM)
834f04
@@ -244,8 +246,10 @@ int oomd_kill_by_swap_usage(Hashmap *h, bool dry_run) {
834f04
         /* Try to kill cgroups with non-zero swap usage until we either succeed in
834f04
          * killing or we get to a cgroup with no swap usage. */
834f04
         for (int i = 0; i < r; i++) {
834f04
+                /* Skip over cgroups with no resource usage. Don't break since there might be "avoid"
834f04
+                 * cgroups at the end. */
834f04
                 if (sorted[i]->swap_usage == 0)
834f04
-                        break;
834f04
+                        continue;
834f04
 
834f04
                 r = oomd_cgroup_kill(sorted[i]->path, true, dry_run);
834f04
                 if (r > 0 || r == -ENOMEM)
834f04
@@ -257,8 +261,10 @@ int oomd_kill_by_swap_usage(Hashmap *h, bool dry_run) {
834f04
 
834f04
 int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret) {
834f04
         _cleanup_(oomd_cgroup_context_freep) OomdCGroupContext *ctx = NULL;
834f04
-        _cleanup_free_ char *p = NULL, *val = NULL;
834f04
+        _cleanup_free_ char *p = NULL, *val = NULL, *avoid_val = NULL, *omit_val = NULL;
834f04
         bool is_root;
834f04
+        uid_t uid;
834f04
+        gid_t gid;
834f04
         int r;
834f04
 
834f04
         assert(path);
834f04
@@ -278,6 +284,25 @@ int oomd_cgroup_context_acquire(const char *path, OomdCGroupContext **ret) {
834f04
         if (r < 0)
834f04
                 return log_debug_errno(r, "Error parsing memory pressure from %s: %m", p);
834f04
 
834f04
+        r = cg_get_owner(SYSTEMD_CGROUP_CONTROLLER, path, &uid, &gid;;
834f04
+        if (r < 0)
834f04
+                log_debug_errno(r, "Failed to get owner/group from %s: %m", path);
834f04
+        else if (uid == 0 && gid == 0) {
834f04
+                /* Ignore most errors when reading the xattr since it is usually unset and cgroup xattrs are only used
834f04
+                 * as an optional feature of systemd-oomd (and the system might not even support them). */
834f04
+                r = cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, path, "user.oomd_avoid", &avoid_val);
834f04
+                if (r >= 0 && streq(avoid_val, "1"))
834f04
+                        ctx->avoid = true;
834f04
+                else if (r == -ENOMEM)
834f04
+                        return r;
834f04
+
834f04
+                r = cg_get_xattr_malloc(SYSTEMD_CGROUP_CONTROLLER, path, "user.oomd_omit", &omit_val);
834f04
+                if (r >= 0 && streq(omit_val, "1"))
834f04
+                        ctx->omit = true;
834f04
+                else if (r == -ENOMEM)
834f04
+                        return r;
834f04
+        }
834f04
+
834f04
         if (is_root) {
834f04
                 r = procfs_memory_get_used(&ctx->current_memory_usage);
834f04
                 if (r < 0)
834f04
diff --git a/src/oom/oomd-util.h b/src/oom/oomd-util.h
834f04
index f0648c5dcdd..ab6a8da1ef6 100644
834f04
--- a/src/oom/oomd-util.h
834f04
+++ b/src/oom/oomd-util.h
834f04
@@ -29,6 +29,9 @@ struct OomdCGroupContext {
834f04
         uint64_t last_pgscan;
834f04
         uint64_t pgscan;
834f04
 
834f04
+        bool avoid;
834f04
+        bool omit;
834f04
+
834f04
         /* These are only used by oomd_pressure_above for acting on high memory pressure. */
834f04
         loadavg_t mem_pressure_limit;
834f04
         usec_t mem_pressure_duration_usec;
834f04
@@ -61,10 +64,15 @@ bool oomd_memory_reclaim(Hashmap *h);
834f04
 /* Returns true if the amount of swap free is below the percentage of swap specified by `threshold_percent`. */
834f04
 bool oomd_swap_free_below(const OomdSystemContext *ctx, uint64_t threshold_percent);
834f04
 
834f04
+/* The compare functions will sort from largest to smallest, putting all the contexts with "avoid" at the end
834f04
+ * (after the smallest values). */
834f04
 static inline int compare_pgscan_and_memory_usage(OomdCGroupContext * const *c1, OomdCGroupContext * const *c2) {
834f04
         assert(c1);
834f04
         assert(c2);
834f04
 
834f04
+        if ((*c1)->avoid != (*c2)->avoid)
834f04
+                return CMP((*c1)->avoid, (*c2)->avoid);
834f04
+
834f04
         if ((*c2)->pgscan == (*c1)->pgscan)
834f04
                 return CMP((*c2)->current_memory_usage, (*c1)->current_memory_usage);
834f04
 
834f04
@@ -75,6 +83,9 @@ static inline int compare_swap_usage(OomdCGroupContext * const *c1, OomdCGroupCo
834f04
         assert(c1);
834f04
         assert(c2);
834f04
 
834f04
+        if ((*c1)->avoid != (*c2)->avoid)
834f04
+                return CMP((*c1)->avoid, (*c2)->avoid);
834f04
+
834f04
         return CMP((*c2)->swap_usage, (*c1)->swap_usage);
834f04
 }
834f04
 
834f04
diff --git a/src/oom/test-oomd-util.c b/src/oom/test-oomd-util.c
834f04
index a1fe78806a1..193edee0eba 100644
834f04
--- a/src/oom/test-oomd-util.c
834f04
+++ b/src/oom/test-oomd-util.c
834f04
@@ -89,6 +89,8 @@ static void test_oomd_cgroup_context_acquire_and_insert(void) {
834f04
         _cleanup_(oomd_cgroup_context_freep) OomdCGroupContext *ctx = NULL;
834f04
         _cleanup_free_ char *cgroup = NULL;
834f04
         OomdCGroupContext *c1, *c2;
834f04
+        bool test_xattrs;
834f04
+        int r;
834f04
 
834f04
         if (geteuid() != 0)
834f04
                 return (void) log_tests_skipped("not root");
834f04
@@ -101,6 +103,16 @@ static void test_oomd_cgroup_context_acquire_and_insert(void) {
834f04
 
834f04
         assert_se(cg_pid_get_path(NULL, 0, &cgroup) >= 0);
834f04
 
834f04
+        /* If we don't have permissions to set xattrs we're likely in a userns or missing capabilities
834f04
+         * so skip the xattr portions of the test. */
834f04
+        r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_test", "1", 1, 0);
834f04
+        test_xattrs = !ERRNO_IS_PRIVILEGE(r) && !ERRNO_IS_NOT_SUPPORTED(r);
834f04
+
834f04
+        if (test_xattrs) {
834f04
+                assert_se(cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_omit", "1", 1, 0) >= 0);
834f04
+                assert_se(cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup, "user.oomd_avoid", "1", 1, 0) >= 0);
834f04
+        }
834f04
+
834f04
         assert_se(oomd_cgroup_context_acquire(cgroup, &ctx) == 0);
834f04
 
834f04
         assert_se(streq(ctx->path, cgroup));
834f04
@@ -110,12 +122,21 @@ static void test_oomd_cgroup_context_acquire_and_insert(void) {
834f04
         assert_se(ctx->swap_usage == 0);
834f04
         assert_se(ctx->last_pgscan == 0);
834f04
         assert_se(ctx->pgscan == 0);
834f04
+        if (test_xattrs) {
834f04
+                assert_se(ctx->omit == true);
834f04
+                assert_se(ctx->avoid == true);
834f04
+        } else {
834f04
+                assert_se(ctx->omit == false);
834f04
+                assert_se(ctx->avoid == false);
834f04
+        }
834f04
         ctx = oomd_cgroup_context_free(ctx);
834f04
 
834f04
         /* Test the root cgroup */
834f04
         assert_se(oomd_cgroup_context_acquire("", &ctx) == 0);
834f04
         assert_se(streq(ctx->path, "/"));
834f04
         assert_se(ctx->current_memory_usage > 0);
834f04
+        assert_se(ctx->omit == false);
834f04
+        assert_se(ctx->avoid == false);
834f04
 
834f04
         /* Test hashmap inserts */
834f04
         assert_se(h1 = hashmap_new(&oomd_cgroup_ctx_hash_ops));
834f04
@@ -137,6 +158,15 @@ static void test_oomd_cgroup_context_acquire_and_insert(void) {
834f04
         assert_se(c2->last_pgscan == 5555);
834f04
         assert_se(c2->mem_pressure_limit == 6789);
834f04
         assert_se(c2->last_hit_mem_pressure_limit == 42);
834f04
+
834f04
+        /* Assert that avoid/omit are not set if the cgroup is not owned by root */
834f04
+        if (test_xattrs) {
834f04
+                ctx = oomd_cgroup_context_free(ctx);
834f04
+                assert_se(cg_set_access(SYSTEMD_CGROUP_CONTROLLER, cgroup, 65534, 65534) >= 0);
834f04
+                assert_se(oomd_cgroup_context_acquire(cgroup, &ctx) == 0);
834f04
+                assert_se(ctx->omit == false);
834f04
+                assert_se(ctx->avoid == false);
834f04
+        }
834f04
 }
834f04
 
834f04
 static void test_oomd_system_context_acquire(void) {
834f04
@@ -287,9 +317,11 @@ static void test_oomd_sort_cgroups(void) {
834f04
         char **paths = STRV_MAKE("/herp.slice",
834f04
                                  "/herp.slice/derp.scope",
834f04
                                  "/herp.slice/derp.scope/sheep.service",
834f04
-                                 "/zupa.slice");
834f04
+                                 "/zupa.slice",
834f04
+                                 "/omitted.slice",
834f04
+                                 "/avoid.slice");
834f04
 
834f04
-        OomdCGroupContext ctx[4] = {
834f04
+        OomdCGroupContext ctx[6] = {
834f04
                 { .path = paths[0],
834f04
                   .swap_usage = 20,
834f04
                   .pgscan = 60,
834f04
@@ -306,6 +338,14 @@ static void test_oomd_sort_cgroups(void) {
834f04
                   .swap_usage = 10,
834f04
                   .pgscan = 80,
834f04
                   .current_memory_usage = 10 },
834f04
+                { .path = paths[4],
834f04
+                  .swap_usage = 90,
834f04
+                  .pgscan = 100,
834f04
+                  .omit = true },
834f04
+                { .path = paths[5],
834f04
+                  .swap_usage = 99,
834f04
+                  .pgscan = 200,
834f04
+                  .avoid = true },
834f04
         };
834f04
 
834f04
         assert_se(h = hashmap_new(&string_hash_ops));
834f04
@@ -314,19 +354,23 @@ static void test_oomd_sort_cgroups(void) {
834f04
         assert_se(hashmap_put(h, "/herp.slice/derp.scope", &ctx[1]) >= 0);
834f04
         assert_se(hashmap_put(h, "/herp.slice/derp.scope/sheep.service", &ctx[2]) >= 0);
834f04
         assert_se(hashmap_put(h, "/zupa.slice", &ctx[3]) >= 0);
834f04
+        assert_se(hashmap_put(h, "/omitted.slice", &ctx[4]) >= 0);
834f04
+        assert_se(hashmap_put(h, "/avoid.slice", &ctx[5]) >= 0);
834f04
 
834f04
-        assert_se(oomd_sort_cgroup_contexts(h, compare_swap_usage, NULL, &sorted_cgroups) == 4);
834f04
+        assert_se(oomd_sort_cgroup_contexts(h, compare_swap_usage, NULL, &sorted_cgroups) == 5);
834f04
         assert_se(sorted_cgroups[0] == &ctx[1]);
834f04
         assert_se(sorted_cgroups[1] == &ctx[2]);
834f04
         assert_se(sorted_cgroups[2] == &ctx[0]);
834f04
         assert_se(sorted_cgroups[3] == &ctx[3]);
834f04
+        assert_se(sorted_cgroups[4] == &ctx[5]);
834f04
         sorted_cgroups = mfree(sorted_cgroups);
834f04
 
834f04
-        assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan_and_memory_usage, NULL, &sorted_cgroups) == 4);
834f04
+        assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan_and_memory_usage, NULL, &sorted_cgroups) == 5);
834f04
         assert_se(sorted_cgroups[0] == &ctx[3]);
834f04
         assert_se(sorted_cgroups[1] == &ctx[0]);
834f04
         assert_se(sorted_cgroups[2] == &ctx[2]);
834f04
         assert_se(sorted_cgroups[3] == &ctx[1]);
834f04
+        assert_se(sorted_cgroups[4] == &ctx[5]);
834f04
         sorted_cgroups = mfree(sorted_cgroups);
834f04
 
834f04
         assert_se(oomd_sort_cgroup_contexts(h, compare_pgscan_and_memory_usage, "/herp.slice/derp.scope", &sorted_cgroups) == 2);
834f04
@@ -334,6 +378,8 @@ static void test_oomd_sort_cgroups(void) {
834f04
         assert_se(sorted_cgroups[1] == &ctx[1]);
834f04
         assert_se(sorted_cgroups[2] == 0);
834f04
         assert_se(sorted_cgroups[3] == 0);
834f04
+        assert_se(sorted_cgroups[4] == 0);
834f04
+        assert_se(sorted_cgroups[5] == 0);
834f04
         sorted_cgroups = mfree(sorted_cgroups);
834f04
 }
834f04
 
834f04
diff --git a/test/test-functions b/test/test-functions
834f04
index df6022982c2..6996cd74752 100644
834f04
--- a/test/test-functions
834f04
+++ b/test/test-functions
834f04
@@ -124,6 +124,7 @@ BASICTOOLS=(
834f04
     rmdir
834f04
     sed
834f04
     seq
834f04
+    setfattr
834f04
     setfont
834f04
     setsid
834f04
     sfdisk
834f04
diff --git a/test/units/testsuite-56-testmunch.service b/test/units/testsuite-56-testmunch.service
834f04
new file mode 100644
834f04
index 00000000000..b4b925a7af0
834f04
--- /dev/null
834f04
+++ b/test/units/testsuite-56-testmunch.service
834f04
@@ -0,0 +1,7 @@
834f04
+[Unit]
834f04
+Description=Create some memory pressure
834f04
+
834f04
+[Service]
834f04
+MemoryHigh=2M
834f04
+Slice=testsuite-56-workload.slice
834f04
+ExecStart=/usr/lib/systemd/tests/testdata/units/testsuite-56-slowgrowth.sh
834f04
diff --git a/test/units/testsuite-56.sh b/test/units/testsuite-56.sh
834f04
index 8b01fe37ed4..88c185b8869 100755
834f04
--- a/test/units/testsuite-56.sh
834f04
+++ b/test/units/testsuite-56.sh
834f04
@@ -23,20 +23,43 @@ oomctl | grep "/testsuite-56-workload.slice"
834f04
 oomctl | grep "1.00%"
834f04
 oomctl | grep "Default Memory Pressure Duration: 5s"
834f04
 
834f04
-# systemd-oomd watches for elevated pressure for 30 seconds before acting.
834f04
-# It can take time to build up pressure so either wait 5 minutes or for the service to fail.
834f04
-timeout=$(date -ud "5 minutes" +%s)
834f04
+# systemd-oomd watches for elevated pressure for 5 seconds before acting.
834f04
+# It can take time to build up pressure so either wait 2 minutes or for the service to fail.
834f04
+timeout=$(date -ud "2 minutes" +%s)
834f04
 while [[ $(date -u +%s) -le $timeout ]]; do
834f04
     if ! systemctl status testsuite-56-testbloat.service; then
834f04
         break
834f04
     fi
834f04
-    sleep 15
834f04
+    sleep 5
834f04
 done
834f04
 
834f04
 # testbloat should be killed and testchill should be fine
834f04
 if systemctl status testsuite-56-testbloat.service; then exit 42; fi
834f04
 if ! systemctl status testsuite-56-testchill.service; then exit 24; fi
834f04
 
834f04
+# only run this portion of the test if we can set xattrs
834f04
+if setfattr -n user.xattr_test -v 1 /sys/fs/cgroup/; then
834f04
+    sleep 120 # wait for systemd-oomd kill cool down and elevated memory pressure to come down
834f04
+
834f04
+    systemctl start testsuite-56-testchill.service
834f04
+    systemctl start testsuite-56-testmunch.service
834f04
+    systemctl start testsuite-56-testbloat.service
834f04
+    setfattr -n user.oomd_avoid -v 1 /sys/fs/cgroup/testsuite.slice/testsuite-56.slice/testsuite-56-workload.slice/testsuite-56-testbloat.service
834f04
+
834f04
+    timeout=$(date -ud "2 minutes" +%s)
834f04
+    while [[ $(date -u +%s) -le $timeout ]]; do
834f04
+        if ! systemctl status testsuite-56-testmunch.service; then
834f04
+            break
834f04
+        fi
834f04
+        sleep 5
834f04
+    done
834f04
+
834f04
+    # testmunch should be killed since testbloat had the avoid xattr on it
834f04
+    if ! systemctl status testsuite-56-testbloat.service; then exit 25; fi
834f04
+    if systemctl status testsuite-56-testmunch.service; then exit 43; fi
834f04
+    if ! systemctl status testsuite-56-testchill.service; then exit 24; fi
834f04
+fi
834f04
+
834f04
 systemd-analyze log-level info
834f04
 
834f04
 echo OK > /testok
834f04
834f04
From d87ecfecdb6fb77097f843888e2a05945b6b396b Mon Sep 17 00:00:00 2001
834f04
From: Anita Zhang <the.anitazha@gmail.com>
834f04
Date: Thu, 28 Jan 2021 02:31:44 -0800
834f04
Subject: [PATCH 6/7] oom: add unit file settings for oomd avoid/omit xattrs
834f04
834f04
---
834f04
 docs/TRANSIENT-SETTINGS.md                  |  1 +
834f04
 src/core/cgroup.c                           | 58 ++++++++++++++++++---
834f04
 src/core/cgroup.h                           | 15 ++++++
834f04
 src/core/dbus-cgroup.c                      | 22 ++++++++
834f04
 src/core/execute.c                          |  4 ++
834f04
 src/core/load-fragment-gperf.gperf.m4       |  1 +
834f04
 src/core/load-fragment.c                    |  1 +
834f04
 src/core/load-fragment.h                    |  1 +
834f04
 src/shared/bus-unit-util.c                  |  3 +-
834f04
 src/test/test-tables.c                      |  1 +
834f04
 test/fuzz/fuzz-unit-file/directives.service |  4 ++
834f04
 test/units/testsuite-56.sh                  |  8 ++-
834f04
 12 files changed, 109 insertions(+), 10 deletions(-)
834f04
834f04
diff --git a/docs/TRANSIENT-SETTINGS.md b/docs/TRANSIENT-SETTINGS.md
834f04
index 50370602543..9f69a3162a0 100644
834f04
--- a/docs/TRANSIENT-SETTINGS.md
834f04
+++ b/docs/TRANSIENT-SETTINGS.md
834f04
@@ -273,6 +273,7 @@ All cgroup/resource control settings are available for transient units
834f04
 ✓ ManagedOOMSwap=
834f04
 ✓ ManagedOOMMemoryPressure=
834f04
 ✓ ManagedOOMMemoryPressureLimit=
834f04
+✓ ManagedOOMPreference=
834f04
 ```
834f04
 
834f04
 ## Process Killing Settings
834f04
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
834f04
index 70282a7abda..833b434b555 100644
834f04
--- a/src/core/cgroup.c
834f04
+++ b/src/core/cgroup.c
834f04
@@ -131,6 +131,7 @@ void cgroup_context_init(CGroupContext *c) {
834f04
 
834f04
                 .moom_swap = MANAGED_OOM_AUTO,
834f04
                 .moom_mem_pressure = MANAGED_OOM_AUTO,
834f04
+                .moom_preference = MANAGED_OOM_PREFERENCE_NONE,
834f04
         };
834f04
 }
834f04
 
834f04
@@ -417,7 +418,8 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
834f04
                 "%sDelegate: %s\n"
834f04
                 "%sManagedOOMSwap: %s\n"
834f04
                 "%sManagedOOMMemoryPressure: %s\n"
834f04
-                "%sManagedOOMMemoryPressureLimit: %" PRIu32 ".%02" PRIu32 "%%\n",
834f04
+                "%sManagedOOMMemoryPressureLimit: %" PRIu32 ".%02" PRIu32 "%%\n"
834f04
+                "%sManagedOOMPreference: %s%%\n",
834f04
                 prefix, yes_no(c->cpu_accounting),
834f04
                 prefix, yes_no(c->io_accounting),
834f04
                 prefix, yes_no(c->blockio_accounting),
834f04
@@ -450,7 +452,8 @@ void cgroup_context_dump(Unit *u, FILE* f, const char *prefix) {
834f04
                 prefix, yes_no(c->delegate),
834f04
                 prefix, managed_oom_mode_to_string(c->moom_swap),
834f04
                 prefix, managed_oom_mode_to_string(c->moom_mem_pressure),
834f04
-                prefix, c->moom_mem_pressure_limit_permyriad / 100, c->moom_mem_pressure_limit_permyriad % 100);
834f04
+                prefix, c->moom_mem_pressure_limit_permyriad / 100, c->moom_mem_pressure_limit_permyriad % 100,
834f04
+                prefix, managed_oom_preference_to_string(c->moom_preference));
834f04
 
834f04
         if (c->delegate) {
834f04
                 _cleanup_free_ char *t = NULL;
834f04
@@ -600,6 +603,35 @@ int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode)
834f04
 UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(memory_low);
834f04
 UNIT_DEFINE_ANCESTOR_MEMORY_LOOKUP(memory_min);
834f04
 
834f04
+void cgroup_oomd_xattr_apply(Unit *u, const char *cgroup_path) {
834f04
+        CGroupContext *c;
834f04
+        int r;
834f04
+
834f04
+        assert(u);
834f04
+
834f04
+        c = unit_get_cgroup_context(u);
834f04
+        if (!c)
834f04
+                return;
834f04
+
834f04
+        r = cg_remove_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_avoid");
834f04
+        if (r != -ENODATA)
834f04
+                log_unit_debug_errno(u, r, "Failed to remove oomd_avoid flag on control group %s, ignoring: %m", cgroup_path);
834f04
+
834f04
+        r = cg_remove_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_omit");
834f04
+        if (r != -ENODATA)
834f04
+                log_unit_debug_errno(u, r, "Failed to remove oomd_omit flag on control group %s, ignoring: %m", cgroup_path);
834f04
+
834f04
+        if (c->moom_preference == MANAGED_OOM_PREFERENCE_AVOID) {
834f04
+                r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_avoid", "1", 1, 0);
834f04
+                if (r < 0)
834f04
+                        log_unit_debug_errno(u, r, "Failed to set oomd_avoid flag on control group %s, ignoring: %m", cgroup_path);
834f04
+        } else if (c->moom_preference == MANAGED_OOM_PREFERENCE_OMIT) {
834f04
+                r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, "user.oomd_omit", "1", 1, 0);
834f04
+                if (r < 0)
834f04
+                        log_unit_debug_errno(u, r, "Failed to set oomd_omit flag on control group %s, ignoring: %m", cgroup_path);
834f04
+        }
834f04
+}
834f04
+
834f04
 static void cgroup_xattr_apply(Unit *u) {
834f04
         char ids[SD_ID128_STRING_MAX];
834f04
         int r;
834f04
@@ -630,6 +662,8 @@ static void cgroup_xattr_apply(Unit *u) {
834f04
                 if (r != -ENODATA)
834f04
                         log_unit_debug_errno(u, r, "Failed to remove delegate flag on control group %s, ignoring: %m", u->cgroup_path);
834f04
         }
834f04
+
834f04
+        cgroup_oomd_xattr_apply(u, u->cgroup_path);
834f04
 }
834f04
 
834f04
 static int lookup_block_device(const char *p, dev_t *ret) {
834f04
@@ -3737,12 +3771,6 @@ int unit_cgroup_freezer_action(Unit *u, FreezerAction action) {
834f04
         return 1;
834f04
 }
834f04
 
834f04
-static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
834f04
-        [CGROUP_DEVICE_POLICY_AUTO]   = "auto",
834f04
-        [CGROUP_DEVICE_POLICY_CLOSED] = "closed",
834f04
-        [CGROUP_DEVICE_POLICY_STRICT] = "strict",
834f04
-};
834f04
-
834f04
 int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name) {
834f04
         _cleanup_free_ char *v = NULL;
834f04
         int r;
834f04
@@ -3771,6 +3799,12 @@ int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name) {
834f04
         return parse_cpu_set_full(v, cpus, false, NULL, NULL, 0, NULL);
834f04
 }
834f04
 
834f04
+static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
834f04
+        [CGROUP_DEVICE_POLICY_AUTO]   = "auto",
834f04
+        [CGROUP_DEVICE_POLICY_CLOSED] = "closed",
834f04
+        [CGROUP_DEVICE_POLICY_STRICT] = "strict",
834f04
+};
834f04
+
834f04
 DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy);
834f04
 
834f04
 static const char* const freezer_action_table[_FREEZER_ACTION_MAX] = {
834f04
@@ -3779,3 +3813,11 @@ static const char* const freezer_action_table[_FREEZER_ACTION_MAX] = {
834f04
 };
834f04
 
834f04
 DEFINE_STRING_TABLE_LOOKUP(freezer_action, FreezerAction);
834f04
+
834f04
+static const char* const managed_oom_preference_table[_MANAGED_OOM_PREFERENCE_MAX] = {
834f04
+        [MANAGED_OOM_PREFERENCE_NONE] = "none",
834f04
+        [MANAGED_OOM_PREFERENCE_AVOID] = "avoid",
834f04
+        [MANAGED_OOM_PREFERENCE_OMIT] = "omit",
834f04
+};
834f04
+
834f04
+DEFINE_STRING_TABLE_LOOKUP(managed_oom_preference, ManagedOOMPreference);
834f04
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
834f04
index 9fbfabbb7e3..7d9ab4ae6b8 100644
834f04
--- a/src/core/cgroup.h
834f04
+++ b/src/core/cgroup.h
834f04
@@ -94,6 +94,15 @@ struct CGroupBlockIODeviceBandwidth {
834f04
         uint64_t wbps;
834f04
 };
834f04
 
834f04
+typedef enum ManagedOOMPreference {
834f04
+        MANAGED_OOM_PREFERENCE_NONE,
834f04
+        MANAGED_OOM_PREFERENCE_AVOID,
834f04
+        MANAGED_OOM_PREFERENCE_OMIT,
834f04
+
834f04
+        _MANAGED_OOM_PREFERENCE_MAX,
834f04
+        _MANAGED_OOM_PREFERENCE_INVALID = -1
834f04
+} ManagedOOMPreference;
834f04
+
834f04
 struct CGroupContext {
834f04
         bool cpu_accounting;
834f04
         bool io_accounting;
834f04
@@ -164,6 +173,7 @@ struct CGroupContext {
834f04
         ManagedOOMMode moom_swap;
834f04
         ManagedOOMMode moom_mem_pressure;
834f04
         uint32_t moom_mem_pressure_limit_permyriad;
834f04
+        ManagedOOMPreference moom_preference;
834f04
 };
834f04
 
834f04
 /* Used when querying IP accounting data */
834f04
@@ -204,6 +214,8 @@ void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockI
834f04
 
834f04
 int cgroup_add_device_allow(CGroupContext *c, const char *dev, const char *mode);
834f04
 
834f04
+void cgroup_oomd_xattr_apply(Unit *u, const char *cgroup_path);
834f04
+
834f04
 CGroupMask unit_get_own_mask(Unit *u);
834f04
 CGroupMask unit_get_delegate_mask(Unit *u);
834f04
 CGroupMask unit_get_members_mask(Unit *u);
834f04
@@ -294,3 +306,6 @@ int unit_cgroup_freezer_action(Unit *u, FreezerAction action);
834f04
 
834f04
 const char* freezer_action_to_string(FreezerAction a) _const_;
834f04
 FreezerAction freezer_action_from_string(const char *s) _pure_;
834f04
+
834f04
+const char* managed_oom_preference_to_string(ManagedOOMPreference a) _const_;
834f04
+ManagedOOMPreference managed_oom_preference_from_string(const char *s) _pure_;
834f04
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
834f04
index 6f309feb236..0b2d945283e 100644
834f04
--- a/src/core/dbus-cgroup.c
834f04
+++ b/src/core/dbus-cgroup.c
834f04
@@ -21,6 +21,7 @@ BUS_DEFINE_PROPERTY_GET(bus_property_get_tasks_max, "t", TasksMax, tasks_max_res
834f04
 
834f04
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
834f04
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_mode, managed_oom_mode, ManagedOOMMode);
834f04
+static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_managed_oom_preference, managed_oom_preference, ManagedOOMPreference);
834f04
 
834f04
 static int property_get_cgroup_mask(
834f04
                 sd_bus *bus,
834f04
@@ -395,6 +396,7 @@ const sd_bus_vtable bus_cgroup_vtable[] = {
834f04
         SD_BUS_PROPERTY("ManagedOOMSwap", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_swap), 0),
834f04
         SD_BUS_PROPERTY("ManagedOOMMemoryPressure", "s", property_get_managed_oom_mode, offsetof(CGroupContext, moom_mem_pressure), 0),
834f04
         SD_BUS_PROPERTY("ManagedOOMMemoryPressureLimitPermyriad", "u", NULL, offsetof(CGroupContext, moom_mem_pressure_limit_permyriad), 0),
834f04
+        SD_BUS_PROPERTY("ManagedOOMPreference", "s", property_get_managed_oom_preference, offsetof(CGroupContext, moom_preference), 0),
834f04
         SD_BUS_VTABLE_END
834f04
 };
834f04
 
834f04
@@ -1720,6 +1722,26 @@ int bus_cgroup_set_property(
834f04
                 return 1;
834f04
         }
834f04
 
834f04
+        if (streq(name, "ManagedOOMPreference")) {
834f04
+                ManagedOOMPreference p;
834f04
+                const char *pref;
834f04
+
834f04
+                r = sd_bus_message_read(message, "s", &pref;;
834f04
+                if (r < 0)
834f04
+                        return r;
834f04
+
834f04
+                p = managed_oom_preference_from_string(pref);
834f04
+                if (p < 0)
834f04
+                        return -EINVAL;
834f04
+
834f04
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
834f04
+                        c->moom_preference = p;
834f04
+                        unit_write_settingf(u, flags, name, "ManagedOOMPreference=%s", pref);
834f04
+                }
834f04
+
834f04
+                return 1;
834f04
+        }
834f04
+
834f04
         if (streq(name, "DisableControllers") || (u->transient && u->load_state == UNIT_STUB))
834f04
                 return bus_cgroup_set_transient_property(u, c, name, message, flags, error);
834f04
 
834f04
diff --git a/src/core/execute.c b/src/core/execute.c
834f04
index b7d78f2197e..0368582884c 100644
834f04
--- a/src/core/execute.c
834f04
+++ b/src/core/execute.c
834f04
@@ -4701,6 +4701,10 @@ int exec_spawn(Unit *unit,
834f04
                         r = cg_create(SYSTEMD_CGROUP_CONTROLLER, subcgroup_path);
834f04
                         if (r < 0)
834f04
                                 return log_unit_error_errno(unit, r, "Failed to create control group '%s': %m", subcgroup_path);
834f04
+
834f04
+                        /* Normally we would not propagate the oomd xattrs to children but since we created this
834f04
+                         * sub-cgroup interally we should do it. */
834f04
+                        cgroup_oomd_xattr_apply(unit, subcgroup_path);
834f04
                 }
834f04
         }
834f04
 
834f04
diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4
834f04
index 81f4561a572..dbcbe645934 100644
834f04
--- a/src/core/load-fragment-gperf.gperf.m4
834f04
+++ b/src/core/load-fragment-gperf.gperf.m4
834f04
@@ -230,6 +230,7 @@ $1.IPEgressFilterPath,                   config_parse_ip_filter_bpf_progs,
834f04
 $1.ManagedOOMSwap,                       config_parse_managed_oom_mode,               0,                                  offsetof($1, cgroup_context.moom_swap)
834f04
 $1.ManagedOOMMemoryPressure,             config_parse_managed_oom_mode,               0,                                  offsetof($1, cgroup_context.moom_mem_pressure)
834f04
 $1.ManagedOOMMemoryPressureLimit,        config_parse_managed_oom_mem_pressure_limit, 0,                                  offsetof($1, cgroup_context.moom_mem_pressure_limit_permyriad)
834f04
+$1.ManagedOOMPreference,                 config_parse_managed_oom_preference,         0,                                  offsetof($1, cgroup_context.moom_preference)
834f04
 $1.NetClass,                             config_parse_warn_compat,                    DISABLED_LEGACY,                    0'
834f04
 )m4_dnl
834f04
 Unit.Description,                        config_parse_unit_string_printf,             0,                                  offsetof(Unit, description)
834f04
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
834f04
index 06b71aaf157..c6b017556f9 100644
834f04
--- a/src/core/load-fragment.c
834f04
+++ b/src/core/load-fragment.c
834f04
@@ -133,6 +133,7 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceR
834f04
 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_timeout_failure_mode, service_timeout_failure_mode, ServiceTimeoutFailureMode, "Failed to parse timeout failure mode");
834f04
 DEFINE_CONFIG_PARSE_ENUM(config_parse_socket_bind, socket_address_bind_ipv6_only_or_bool, SocketAddressBindIPv6Only, "Failed to parse bind IPv6 only value");
834f04
 DEFINE_CONFIG_PARSE_ENUM(config_parse_oom_policy, oom_policy, OOMPolicy, "Failed to parse OOM policy");
834f04
+DEFINE_CONFIG_PARSE_ENUM(config_parse_managed_oom_preference, managed_oom_preference, ManagedOOMPreference, "Failed to parse ManagedOOMPreference=");
834f04
 DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_ip_tos, ip_tos, int, -1, "Failed to parse IP TOS value");
834f04
 DEFINE_CONFIG_PARSE_PTR(config_parse_blockio_weight, cg_blkio_weight_parse, uint64_t, "Invalid block IO weight");
834f04
 DEFINE_CONFIG_PARSE_PTR(config_parse_cg_weight, cg_weight_parse, uint64_t, "Invalid weight");
834f04
diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h
834f04
index 6b2175cd2af..e4a5cb79869 100644
834f04
--- a/src/core/load-fragment.h
834f04
+++ b/src/core/load-fragment.h
834f04
@@ -78,6 +78,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_tasks_max);
834f04
 CONFIG_PARSER_PROTOTYPE(config_parse_delegate);
834f04
 CONFIG_PARSER_PROTOTYPE(config_parse_managed_oom_mode);
834f04
 CONFIG_PARSER_PROTOTYPE(config_parse_managed_oom_mem_pressure_limit);
834f04
+CONFIG_PARSER_PROTOTYPE(config_parse_managed_oom_preference);
834f04
 CONFIG_PARSER_PROTOTYPE(config_parse_device_policy);
834f04
 CONFIG_PARSER_PROTOTYPE(config_parse_device_allow);
834f04
 CONFIG_PARSER_PROTOTYPE(config_parse_io_device_latency);
834f04
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c
834f04
index 84f57d94d23..5bbaa07dd1c 100644
834f04
--- a/src/shared/bus-unit-util.c
834f04
+++ b/src/shared/bus-unit-util.c
834f04
@@ -435,7 +435,8 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons
834f04
         if (STR_IN_SET(field, "DevicePolicy",
834f04
                               "Slice",
834f04
                               "ManagedOOMSwap",
834f04
-                              "ManagedOOMMemoryPressure"))
834f04
+                              "ManagedOOMMemoryPressure",
834f04
+                              "ManagedOOMPreference"))
834f04
                 return bus_append_string(m, field, eq);
834f04
 
834f04
         if (STR_IN_SET(field, "ManagedOOMMemoryPressureLimit")) {
834f04
diff --git a/src/test/test-tables.c b/src/test/test-tables.c
834f04
index 641cadec858..cc93bbbc749 100644
834f04
--- a/src/test/test-tables.c
834f04
+++ b/src/test/test-tables.c
834f04
@@ -73,6 +73,7 @@ int main(int argc, char **argv) {
834f04
         test_table(log_target, LOG_TARGET);
834f04
         test_table(mac_address_policy, MAC_ADDRESS_POLICY);
834f04
         test_table(managed_oom_mode, MANAGED_OOM_MODE);
834f04
+        test_table(managed_oom_preference, MANAGED_OOM_PREFERENCE);
834f04
         test_table(manager_state, MANAGER_STATE);
834f04
         test_table(manager_timestamp, MANAGER_TIMESTAMP);
834f04
         test_table(mount_exec_command, MOUNT_EXEC_COMMAND);
834f04
diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service
834f04
index 15fa556dd64..0c7ded6786a 100644
834f04
--- a/test/fuzz/fuzz-unit-file/directives.service
834f04
+++ b/test/fuzz/fuzz-unit-file/directives.service
834f04
@@ -138,6 +138,10 @@ MakeDirectory=
834f04
 Mark=
834f04
 MaxConnections=
834f04
 MaxConnectionsPerSource=
834f04
+ManagedOOMSwap=
834f04
+ManagedOOMMemoryPressure=
834f04
+ManagedOOMMemoryPressureLimitPercent=
834f04
+ManagedOOMPreference=
834f04
 MemoryAccounting=
834f04
 MemoryHigh=
834f04
 MemoryLimit=
834f04
diff --git a/test/units/testsuite-56.sh b/test/units/testsuite-56.sh
834f04
index 88c185b8869..1884f814689 100755
834f04
--- a/test/units/testsuite-56.sh
834f04
+++ b/test/units/testsuite-56.sh
834f04
@@ -13,6 +13,8 @@ if [[ "$cgroup_type" != *"cgroup2"* ]] && [[ "$cgroup_type" != *"0x63677270"* ]]
834f04
 fi
834f04
 [[ -e /skipped ]] && exit 0 || true
834f04
 
834f04
+rm -rf /etc/systemd/system/testsuite-56-testbloat.service.d
834f04
+
834f04
 echo "DefaultMemoryPressureDurationSec=5s" >> /etc/systemd/oomd.conf
834f04
 
834f04
 systemctl start testsuite-56-testchill.service
834f04
@@ -41,10 +43,14 @@ if ! systemctl status testsuite-56-testchill.service; then exit 24; fi
834f04
 if setfattr -n user.xattr_test -v 1 /sys/fs/cgroup/; then
834f04
     sleep 120 # wait for systemd-oomd kill cool down and elevated memory pressure to come down
834f04
 
834f04
+    mkdir -p /etc/systemd/system/testsuite-56-testbloat.service.d/
834f04
+    echo "[Service]" > /etc/systemd/system/testsuite-56-testbloat.service.d/override.conf
834f04
+    echo "ManagedOOMPreference=avoid" >> /etc/systemd/system/testsuite-56-testbloat.service.d/override.conf
834f04
+
834f04
+    systemctl daemon-reload
834f04
     systemctl start testsuite-56-testchill.service
834f04
     systemctl start testsuite-56-testmunch.service
834f04
     systemctl start testsuite-56-testbloat.service
834f04
-    setfattr -n user.oomd_avoid -v 1 /sys/fs/cgroup/testsuite.slice/testsuite-56.slice/testsuite-56-workload.slice/testsuite-56-testbloat.service
834f04
 
834f04
     timeout=$(date -ud "2 minutes" +%s)
834f04
     while [[ $(date -u +%s) -le $timeout ]]; do
834f04
834f04
From 32d695eccfeef00023992cdf20bf39f9d0288c67 Mon Sep 17 00:00:00 2001
834f04
From: Anita Zhang <the.anitazha@gmail.com>
834f04
Date: Thu, 28 Jan 2021 17:35:17 -0800
834f04
Subject: [PATCH 7/7] man: document ManagedOOMPreference=
834f04
834f04
---
834f04
 man/org.freedesktop.systemd1.xml | 36 ++++++++++++++++++++++++++++++++
834f04
 man/systemd.resource-control.xml | 32 ++++++++++++++++++++++++++++
834f04
 2 files changed, 68 insertions(+)
834f04
834f04
diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml
834f04
index 7543a617b78..1d419ac495e 100644
834f04
--- a/man/org.freedesktop.systemd1.xml
834f04
+++ b/man/org.freedesktop.systemd1.xml
834f04
@@ -2450,6 +2450,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
834f04
       readonly s ManagedOOMMemoryPressure = '...';
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
834f04
       readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
834f04
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
834f04
+      readonly s ManagedOOMPreference = '...';
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
834f04
       readonly as Environment = ['...', ...];
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
834f04
@@ -2974,6 +2976,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
834f04
 
834f04
     
834f04
 
834f04
+    
834f04
+
834f04
     
834f04
 
834f04
     
834f04
@@ -3538,6 +3542,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
834f04
 
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
834f04
 
834f04
+    <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
834f04
+
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
834f04
 
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
834f04
@@ -4204,6 +4210,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
834f04
       readonly s ManagedOOMMemoryPressure = '...';
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
834f04
       readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
834f04
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
834f04
+      readonly s ManagedOOMPreference = '...';
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
834f04
       readonly as Environment = ['...', ...];
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
834f04
@@ -4756,6 +4764,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
834f04
 
834f04
     
834f04
 
834f04
+    
834f04
+
834f04
     
834f04
 
834f04
     
834f04
@@ -5318,6 +5328,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
834f04
 
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
834f04
 
834f04
+    <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
834f04
+
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
834f04
 
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
834f04
@@ -5897,6 +5909,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
834f04
       readonly s ManagedOOMMemoryPressure = '...';
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
834f04
       readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
834f04
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
834f04
+      readonly s ManagedOOMPreference = '...';
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
834f04
       readonly as Environment = ['...', ...];
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
834f04
@@ -6377,6 +6391,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
834f04
 
834f04
     
834f04
 
834f04
+    
834f04
+
834f04
     
834f04
 
834f04
     
834f04
@@ -6857,6 +6873,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
834f04
 
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
834f04
 
834f04
+    <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
834f04
+
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
834f04
 
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
834f04
@@ -7557,6 +7575,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
834f04
       readonly s ManagedOOMMemoryPressure = '...';
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
834f04
       readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
834f04
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
834f04
+      readonly s ManagedOOMPreference = '...';
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
834f04
       readonly as Environment = ['...', ...];
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
834f04
@@ -8023,6 +8043,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
834f04
 
834f04
     
834f04
 
834f04
+    
834f04
+
834f04
     
834f04
 
834f04
     
834f04
@@ -8489,6 +8511,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
834f04
 
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
834f04
 
834f04
+    <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
834f04
+
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="Environment"/>
834f04
 
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="EnvironmentFiles"/>
834f04
@@ -9042,6 +9066,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
834f04
       readonly s ManagedOOMMemoryPressure = '...';
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
834f04
       readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
834f04
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
834f04
+      readonly s ManagedOOMPreference = '...';
834f04
   };
834f04
   interface org.freedesktop.DBus.Peer { ... };
834f04
   interface org.freedesktop.DBus.Introspectable { ... };
834f04
@@ -9178,6 +9204,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
834f04
 
834f04
     
834f04
 
834f04
+    
834f04
+
834f04
     
834f04
 
834f04
     <variablelist class="dbus-interface" generated="True" extra-ref="org.freedesktop.systemd1.Unit"/>
834f04
@@ -9318,6 +9346,8 @@ node /org/freedesktop/systemd1/unit/system_2eslice {
834f04
 
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
834f04
 
834f04
+    <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
834f04
+
834f04
     
834f04
 
834f04
     <refsect2>
834f04
@@ -9477,6 +9507,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
834f04
       readonly s ManagedOOMMemoryPressure = '...';
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
834f04
       readonly u ManagedOOMMemoryPressureLimitPermyriad = ...;
834f04
+      @org.freedesktop.DBus.Property.EmitsChangedSignal("false")
834f04
+      readonly s ManagedOOMPreference = '...';
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
834f04
       readonly s KillMode = '...';
834f04
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
834f04
@@ -9629,6 +9661,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
834f04
 
834f04
     
834f04
 
834f04
+    
834f04
+
834f04
     
834f04
 
834f04
     
834f04
@@ -9795,6 +9829,8 @@ node /org/freedesktop/systemd1/unit/session_2d1_2escope {
834f04
 
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMMemoryPressureLimitPermyriad"/>
834f04
 
834f04
+    <variablelist class="dbus-property" generated="True" extra-ref="ManagedOOMPreference"/>
834f04
+
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
834f04
 
834f04
     <variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
834f04
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
834f04
index be9c35057db..13ff7e9a740 100644
834f04
--- a/man/systemd.resource-control.xml
834f04
+++ b/man/systemd.resource-control.xml
834f04
@@ -913,6 +913,38 @@ DeviceAllow=/dev/loop-control
834f04
           </para>
834f04
         </listitem>
834f04
       </varlistentry>
834f04
+
834f04
+      <varlistentry>
834f04
+        <term><varname>ManagedOOMPreference=none|avoid|omit</varname></term>
834f04
+
834f04
+        <listitem>
834f04
+          <para>Allows deprioritizing or omitting this unit's cgroup as a candidate when <command>systemd-oomd</command>
834f04
+          needs to act. Requires support for extended attributes (see
834f04
+          <citerefentry project='man-pages'><refentrytitle>xattr</refentrytitle><manvolnum>7</manvolnum></citerefentry>)
834f04
+          in order to use <option>avoid</option> or <option>omit</option>. Additionally, <command>systemd-oomd</command>
834f04
+          will ignore these extended attributes if the unit's cgroup is not owned by the root user and group.</para>
834f04
+
834f04
+          <para>If this property is set to <option>avoid</option>, the service manager will set the
834f04
+          "user.oomd_avoid" extended attribute on the unit's cgroup to "1". If <command>systemd-oomd</command> sees
834f04
+          this extended attribute on a cgroup set to "1" when choosing between candidates, it will only select the
834f04
+          cgroup with "user.oomd_avoid" if there are no other viable candidates.</para>
834f04
+
834f04
+          <para>If this property is set to <option>omit</option>, the service manager will set the "user.oomd_omit"
834f04
+          extended attribute on the unit's cgroup to "1". If <command>systemd-oomd</command> sees the this extended
834f04
+          attribute on the cgroup set to "1", it will ignore the cgroup as a candidate and will not perform any actions
834f04
+          on the cgroup.</para>
834f04
+
834f04
+          <para>It is recommended to use <option>avoid</option> and <option>omit</option> sparingly as it can adversely
834f04
+          affect <command>systemd-oomd</command>'s kill behavior. Also note that these extended attributes are not
834f04
+          applied recursively to cgroups under this unit's cgroup.</para>
834f04
+
834f04
+          <para>Defaults to <option>none</option> which means no extended attributes will be set and systemd-oomd will
834f04
+          sort this unit's cgroup as defined in
834f04
+          <citerefentry><refentrytitle>systemd-oomd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
834f04
+          and <citerefentry><refentrytitle>oomd.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry> (if this
834f04
+          unit's cgroup becomes a candidate).</para>
834f04
+        </listitem>
834f04
+      </varlistentry>
834f04
     </variablelist>
834f04
   </refsect1>
834f04