[Devel,RHEL7,COMMIT] mm/memcg: sleep if mem_cgroup_force_empty_list() stumped on busy page

Submitted by Konstantin Khorenko on Sept. 6, 2017, 4:41 p.m.


Message ID 201709061641.v86GfpE0027858@finist_ce7.work
State New
Series "mm/memcg: sleep if mem_cgroup_force_empty_list() stumped on busy page"
Headers show

Commit Message

Konstantin Khorenko Sept. 6, 2017, 4:41 p.m.
The commit is pushed to "branch-rh7-3.10.0-514.26.1.vz7.35.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-514.26.1.vz7.35.7
commit e05136b00c77d9391045d556c8884d9e985af708
Author: Andrey Ryabinin <aryabinin@virtuozzo.com>
Date:   Wed Sep 6 19:41:51 2017 +0300

    mm/memcg: sleep if mem_cgroup_force_empty_list() stumped on busy page
    mem_cgroup_force_empty_list() executed in workqueue context. If work doesn't
    go to sleep the workqueue engine thinks that this work is making progress,
    so there is no need to start more workers to execute other works.
    So, if we need other works to be executed to unlock those pages we might
    have a deadlock. I think this easy might happen with fuse, something
    like this:
    fuse:                              cgroup_destroy work:
                                              //busy wait for fuse to unlock pages.
     //this may have to wait
     //for mem_cgroup_force_empty_list
     //to finish
     read pages and unlock them.
    The solution to this problem is to put mem_cgroup_force_empty_list() in short
    sleep() instead of cond_resched(). This will allow other works to make progress
    if mem_cgroup_force_empty_list() is stuck.
    Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
 mm/memcontrol.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 5372151..0ddcfd5 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -4039,7 +4039,7 @@  static void mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
 		if (mem_cgroup_move_parent(page, pc, memcg)) {
 			/* found lock contention or "pc" is obsolete. */
 			busy = page;
-			cond_resched();
+			schedule_timeout_uninterruptible(1);
 		} else
 			busy = NULL;
 	} while (!list_empty(list));