[RHEL7,COMMIT] mm/memcg: Don't enable interrupts too soon.

Submitted by Konstantin Khorenko on Oct. 30, 2017, 2:44 p.m.

Details

Message ID 201710301444.v9UEioZT015875@finist_ce7.work
State New
Series "Series without cover letter"
Headers show

Commit Message

Konstantin Khorenko Oct. 30, 2017, 2:44 p.m.
The commit is pushed to "branch-rh7-3.10.0-693.1.1.vz7.37.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.1.1.vz7.37.20
------>
commit a6ad9f4175718070c19743d775062e5a9688463d
Author: Andrey Ryabinin <aryabinin@virtuozzo.com>
Date:   Mon Oct 30 17:44:50 2017 +0300

    mm/memcg: Don't enable interrupts too soon.
    
    When mem_cgroup_move_parent() moves huge page it disables interrupt:
    
    	if (nr_pages > 1) {
    		VM_BUG_ON_PAGE(!PageTransHuge(page), page);
    		flags = compound_lock_irqsave(page);
    	}
    
    and calls:
    	ret = mem_cgroup_move_account(page, nr_pages, ...
    
    which does the following:
    
    	local_irq_disable();
    	mem_cgroup_charge_statistics(to, page, nr_pages);
    	...
    	local_irq_enable();
    
    So the last local_irq_enable() enables irq too early, which may lead
    to the deadlock. mem_cgroup_move_account() should use local_irq_save()/
    local_irq_restore() primitives instead.
    
    Found while investigating https://jira.sw.ru/browse/PSBM-76011
    but unrelated.
    
    Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 mm/memcontrol.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 239fbca..efc455d 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3597,15 +3597,14 @@  static int mem_cgroup_move_account(struct page *page,
 
 	/* caller should have done css_get */
 	pc->mem_cgroup = to;
-	move_unlock_mem_cgroup(from, &flags);
+	spin_unlock(&from->move_lock);
 	ret = 0;
 
-	local_irq_disable();
 	mem_cgroup_charge_statistics(to, page, nr_pages);
 	memcg_check_events(to, page);
 	mem_cgroup_charge_statistics(from, page, -nr_pages);
 	memcg_check_events(from, page);
-	local_irq_enable();
+	local_irq_restore(flags);
 out_unlock:
 	unlock_page(page);
 out: