Skip to contentSkip to conversation

OOM notification for cgroupsv1 broken in 4.19

PATCH Applied Burt Holzman 3 participants 5 messages Dec 21, 2018 – Dec 24, 2018

Subsystems (4)
lore
Share & tools
lore
#0 lore raw

Hi,

This patch: 29ef680ae7c21110af8e6416d84d8a72fc147b14 [PATCH] memcg, oom: move out_of_memory back to the charge path

has broken the eventfd notification for cgroups-v1. This is because mem_cgroup_oom_notify() is called only in mem_cgroup_oom_synchronize and not with the new, additional call to mem_cgroup_out_of_memory in the charge path.

- B

maintainer
#1 lore raw
Quoted 9 lines · Burt Holzman

Hi,

This patch: 29ef680ae7c21110af8e6416d84d8a72fc147b14 [PATCH] memcg, oom: move out_of_memory back to the charge path

has broken the eventfd notification for cgroups-v1. This is because mem_cgroup_oom_notify() is called only in mem_cgroup_oom_synchronize and not with the new, additional call to mem_cgroup_out_of_memory in the charge path.

Yes, you are right and this is a clear regression. Does the following patch fixes the issue for you? I am not super happy about the code duplication but I wasn't able to separate this out from mem_cgroup_oom_synchronize because that one has to handle the oom_killer disabled case which is not the case in the charge path because we simply back off and hand over to mem_cgroup_oom_synchronize in that case.
---

Quoted 1 line

From 51633f683173013741f4d0ab3e31bae575341c55 Mon Sep 17 00:00:00 2001

From: Michal Hocko <[email protected]>
Date: Fri, 21 Dec 2018 16:28:29 +0100
Subject: [PATCH] memcg, oom: notify on oom killer invocation from the charge
path

Burt Holzman has noticed that memcg v1 doesn't notify about OOM events via eventfd anymore. The reason is that 29ef680ae7c2 ("memcg, oom: move out_of_memory back to the charge path") has moved the oom handling back to the charge path. While doing so the notification was left behind in mem_cgroup_oom_synchronize.

Fix the issue by replicating the oom hierarchy locking and the notification.

Fixes 29ef680ae7c2 ("memcg, oom: move out_of_memory back to the charge path")
Cc stable # 4.19+
---
 mm/memcontrol.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)
mm/memcontrol.c +18 -2
index 6e1469b80cb7..7e6bf74ddb1e 100644
@@ -1666,6 +1666,9 @@ enum oom_status {
 
 static enum oom_status mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int order)
 {
+	enum oom_status ret;
+	bool locked;
+
 	if (order > PAGE_ALLOC_COSTLY_ORDER)
 		return OOM_SKIPPED;
 
@@ -1700,10 +1703,23 @@ static enum oom_status mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int
 		return OOM_ASYNC;
 	}
 
+	mem_cgroup_mark_under_oom(memcg);
+
+	locked = mem_cgroup_oom_trylock(memcg);
+
+	if (locked)
+		mem_cgroup_oom_notify(memcg);
+
+	mem_cgroup_unmark_under_oom(memcg);
 	if (mem_cgroup_out_of_memory(memcg, mask, order))
-		return OOM_SUCCESS;
+		ret = OOM_SUCCESS;
+	else
+		ret = OOM_FAILED;
 
-	return OOM_FAILED;
+	if (locked)
+		mem_cgroup_oom_unlock(memcg);
+
+	return ret;
 }
 
 /**
Signature · 5 lines
2.19.2

-- 
Michal Hocko
SUSE Labs
#2 lore raw
Quoted 14 lines · Michal Hocko
Quoted 9 lines · Burt Holzman

Hi,

This patch: 29ef680ae7c21110af8e6416d84d8a72fc147b14 [PATCH] memcg, oom: move out_of_memory back to the charge path

has broken the eventfd notification for cgroups-v1. This is because mem_cgroup_oom_notify() is called only in mem_cgroup_oom_synchronize and not with the new, additional call to mem_cgroup_out_of_memory in the charge path.

Quoted 6 lines

Yes, you are right and this is a clear regression. Does the following patch fixes the issue for you? I am not super happy about the code duplication but I wasn't able to separate this out from mem_cgroup_oom_synchronize because that one has to handle the oom_killer disabled case which is not the case in the charge path because we simply back off and hand over to mem_cgroup_oom_synchronize in that case.

Hi Michal,

Thanks for the quick response & patch. I can confirm that with this patch the notification is working for my sample test case.

- B

maintainer Acked-by
#3 lore raw
In reply to Michal Hocko
Quoted 12 lines · Michal Hocko

From 51633f683173013741f4d0ab3e31bae575341c55 Mon Sep 17 00:00:00 2001
From: Michal Hocko <[email protected]>
Date: Fri, 21 Dec 2018 16:28:29 +0100
Subject: [PATCH] memcg, oom: notify on oom killer invocation from the charge
path

Burt Holzman has noticed that memcg v1 doesn't notify about OOM events via eventfd anymore. The reason is that 29ef680ae7c2 ("memcg, oom: move out_of_memory back to the charge path") has moved the oom handling back to the charge path. While doing so the notification was left behind in mem_cgroup_oom_synchronize.

Quoted 7 lines

Fix the issue by replicating the oom hierarchy locking and the notification.

Fixes 29ef680ae7c2 ("memcg, oom: move out_of_memory back to the charge path")
Cc stable # 4.19+

Looks good to me. The async side really does too much other stuff to cleanly share code between them, so I don't mind separate code even if it means they both have to do the mark, lock, notify dance.

maintainer
#4 lore raw

PATCH 1/1 memcg, oom: notify on oom killer invocation from the charge path

In reply to Burt Holzman

From: Michal Hocko <[email protected]>

Burt Holzman has noticed that memcg v1 doesn't notify about OOM events via eventfd anymore. The reason is that 29ef680ae7c2 ("memcg, oom: move out_of_memory back to the charge path") has moved the oom handling back to the charge path. While doing so the notification was left behind in mem_cgroup_oom_synchronize.

Fix the issue by replicating the oom hierarchy locking and the notification.

Fixes 29ef680ae7c2 ("memcg, oom: move out_of_memory back to the charge path")
Cc stable # 4.19+

---
Hi Andrew,
I forgot to CC you on the patch sent as a reply to the original bug report [1] so I am reposting with Ack from Johannes. Burt has confirmed this is resolving the regression for him [2]. 4.20 is out but I have marked the patch for stable so it should hit both 4.19 and 4.20.

[1] http://lkml.kernel.org/r/[email protected]
[2] http://lkml.kernel.org/r/[email protected]

 mm/memcontrol.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)
mm/memcontrol.c +18 -2
index 6e1469b80cb7..7e6bf74ddb1e 100644
@@ -1666,6 +1666,9 @@ enum oom_status {
 
 static enum oom_status mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int order)
 {
+	enum oom_status ret;
+	bool locked;
+
 	if (order > PAGE_ALLOC_COSTLY_ORDER)
 		return OOM_SKIPPED;
 
@@ -1700,10 +1703,23 @@ static enum oom_status mem_cgroup_oom(struct mem_cgroup *memcg, gfp_t mask, int
 		return OOM_ASYNC;
 	}
 
+	mem_cgroup_mark_under_oom(memcg);
+
+	locked = mem_cgroup_oom_trylock(memcg);
+
+	if (locked)
+		mem_cgroup_oom_notify(memcg);
+
+	mem_cgroup_unmark_under_oom(memcg);
 	if (mem_cgroup_out_of_memory(memcg, mask, order))
-		return OOM_SUCCESS;
+		ret = OOM_SUCCESS;
+	else
+		ret = OOM_FAILED;
 
-	return OOM_FAILED;
+	if (locked)
+		mem_cgroup_oom_unlock(memcg);
+
+	return ret;
 }
 
 /**
Signature · 1 line
2.19.2