[RHEL7,COMMIT] ms/vmpressure: make sure there are no events queued after memcg is offlined

Submitted by Konstantin Khorenko on April 17, 2019, 10:13 a.m.

Details

Message ID 201904171013.x3HADL06015158@finist-ce7.sw.ru
State New
Series "ms/vmpressure: make sure there are no events queued after memcg is offlined"
Headers show

Commit Message

Konstantin Khorenko April 17, 2019, 10:13 a.m.
The commit is pushed to "branch-rh7-3.10.0-957.10.1.vz7.94.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-957.10.1.vz7.94.15
------>
commit f61e04383f7772f73fdad39581d61432e10096e4
Author: Michal Hocko <mhocko@suse.cz>
Date:   Wed Jul 31 13:53:51 2013 -0700

    ms/vmpressure: make sure there are no events queued after memcg is offlined
    
    vmpressure is called synchronously from reclaim where the target_memcg
    is guaranteed to be alive but the eventfd is signaled from the work
    queue context.  This means that memcg (along with vmpressure structure
    which is embedded into it) might go away while the work item is pending
    which would result in use-after-release bug.
    
    We have two possible ways how to fix this.  Either vmpressure pins memcg
    before it schedules vmpr->work and unpin it in vmpressure_work_fn or
    explicitely flush the work item from the css_offline context (as
    suggested by Tejun).
    
    This patch implements the later one and it introduces vmpressure_cleanup
    which flushes the vmpressure work queue item item.  It hooks into
    mem_cgroup_css_offline after the memcg itself is cleaned up.
    
    [akpm@linux-foundation.org: coding-style fixes]
    Signed-off-by: Michal Hocko <mhocko@suse.cz>
    Reported-by: Tejun Heo <tj@kernel.org>
    Cc: Anton Vorontsov <anton.vorontsov@linaro.org>
    Cc: Johannes Weiner <hannes@cmpxchg.org>
    Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
    Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
    Cc: Li Zefan <lizefan@huawei.com>
    Acked-by: Tejun Heo <tj@kernel.org>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    
    (cherry picked from commit 33cb876e947b9ddda8dca3fb99234b743a597ef9)
    https://jira.sw.ru/browse/PSBM-93884
    
    Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
---
 include/linux/vmpressure.h |  1 +
 mm/memcontrol.c            |  1 +
 mm/vmpressure.c            | 16 ++++++++++++++++
 3 files changed, 18 insertions(+)

Patch hide | download patch | download mbox

diff --git a/include/linux/vmpressure.h b/include/linux/vmpressure.h
index 76be077340ea..a9021c358a9c 100644
--- a/include/linux/vmpressure.h
+++ b/include/linux/vmpressure.h
@@ -30,6 +30,7 @@  extern void vmpressure(gfp_t gfp, struct mem_cgroup *memcg,
 extern void vmpressure_prio(gfp_t gfp, struct mem_cgroup *memcg, int prio);
 
 extern void vmpressure_init(struct vmpressure *vmpr);
+extern void vmpressure_cleanup(struct vmpressure *vmpr);
 extern struct vmpressure *memcg_to_vmpressure(struct mem_cgroup *memcg);
 extern struct cgroup_subsys_state *vmpressure_to_css(struct vmpressure *vmpr);
 extern struct vmpressure *css_to_vmpressure(struct cgroup_subsys_state *css);
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index f2a81d72d3bf..a7121534a1eb 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -6564,6 +6564,7 @@  static void mem_cgroup_css_offline(struct cgroup *cont)
 	rcu_read_unlock();
 	mem_cgroup_free_all(memcg);
 	mem_cgroup_reparent_charges(memcg);
+	vmpressure_cleanup(&memcg->vmpressure);
 
 	/*
 	 * A cgroup can be destroyed while somebody is waiting for its
diff --git a/mm/vmpressure.c b/mm/vmpressure.c
index 736a6011c2c8..7a3da89f790a 100644
--- a/mm/vmpressure.c
+++ b/mm/vmpressure.c
@@ -372,3 +372,19 @@  void vmpressure_init(struct vmpressure *vmpr)
 	INIT_LIST_HEAD(&vmpr->events);
 	INIT_WORK(&vmpr->work, vmpressure_work_fn);
 }
+
+/**
+ * vmpressure_cleanup() - shuts down vmpressure control structure
+ * @vmpr:	Structure to be cleaned up
+ *
+ * This function should be called before the structure in which it is
+ * embedded is cleaned up.
+ */
+void vmpressure_cleanup(struct vmpressure *vmpr)
+{
+	/*
+	 * Make sure there is no pending work before eventfd infrastructure
+	 * goes away.
+	 */
+	flush_work(&vmpr->work);
+}