Commit f61c42a7 authored by Michal Hocko's avatar Michal Hocko Committed by Tejun Heo

memcg: remove tasks/children test from mem_cgroup_force_empty()

Tejun has correctly pointed out that tasks/children test in
mem_cgroup_force_empty is not correct because there is no other locking
which preserves this state throughout the rest of the function so both
new tasks can join the group or new children groups can be added while
somebody is writing to memory.force_empty. A new task would break
mem_cgroup_reparent_charges expectation that all failures as described
by mem_cgroup_force_empty_list are temporal and there is no way out.

The main use case for the knob as described by
Documentation/cgroups/memory.txt is to:
"
  The typical use case for this interface is before calling rmdir().
  Because rmdir() moves all pages to parent, some out-of-use page caches can be
  moved to the parent. If you want to avoid that, force_empty will be useful.
"

This means that reparenting is not really required as rmdir will
reparent pages implicitly from the safe context. If we remove it from
mem_cgroup_force_empty then we are safe even with existing tasks because
the number of reclaim attempts is bounded. Moreover the knob still does
what the documentation claims (modulo reparenting which doesn't make any
difference) and users might expect. Longterm we want to deprecate the
whole knob and put the reparented pages to the tail of parent LRU during
cgroup removal.

tj: Removed unused variable @cgrp from mem_cgroup_force_empty()
Signed-off-by: default avatarMichal Hocko <mhocko@suse.cz>
Acked-by: default avatarJohannes Weiner <hannes@cmpxchg.org>
Acked-by: default avatarLi Zefan <lizefan@huawei.com>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
parent 5c9d535b
...@@ -453,15 +453,11 @@ About use_hierarchy, see Section 6. ...@@ -453,15 +453,11 @@ About use_hierarchy, see Section 6.
5.1 force_empty 5.1 force_empty
memory.force_empty interface is provided to make cgroup's memory usage empty. memory.force_empty interface is provided to make cgroup's memory usage empty.
You can use this interface only when the cgroup has no tasks.
When writing anything to this When writing anything to this
# echo 0 > memory.force_empty # echo 0 > memory.force_empty
Almost all pages tracked by this memory cgroup will be unmapped and freed. the cgroup will be reclaimed and as many pages reclaimed as possible.
Some pages cannot be freed because they are locked or in-use. Such pages are
moved to parent (if use_hierarchy==1) or root (if use_hierarchy==0) and this
cgroup will be empty.
The typical use case for this interface is before calling rmdir(). The typical use case for this interface is before calling rmdir().
Because rmdir() moves all pages to parent, some out-of-use page caches can be Because rmdir() moves all pages to parent, some out-of-use page caches can be
......
...@@ -4857,11 +4857,6 @@ static inline bool memcg_has_children(struct mem_cgroup *memcg) ...@@ -4857,11 +4857,6 @@ static inline bool memcg_has_children(struct mem_cgroup *memcg)
static int mem_cgroup_force_empty(struct mem_cgroup *memcg) static int mem_cgroup_force_empty(struct mem_cgroup *memcg)
{ {
int nr_retries = MEM_CGROUP_RECLAIM_RETRIES; int nr_retries = MEM_CGROUP_RECLAIM_RETRIES;
struct cgroup *cgrp = memcg->css.cgroup;
/* returns EBUSY if there is a task or if we come here twice. */
if (cgroup_has_tasks(cgrp) || !list_empty(&cgrp->children))
return -EBUSY;
/* we call try-to-free pages for make this cgroup empty */ /* we call try-to-free pages for make this cgroup empty */
lru_add_drain_all(); lru_add_drain_all();
...@@ -4881,8 +4876,6 @@ static int mem_cgroup_force_empty(struct mem_cgroup *memcg) ...@@ -4881,8 +4876,6 @@ static int mem_cgroup_force_empty(struct mem_cgroup *memcg)
} }
} }
lru_add_drain();
mem_cgroup_reparent_charges(memcg);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment