]>
Commit | Line | Data |
---|---|---|
13a0632a GKH |
1 | From 9ab3b598d2dfbdb0153ffa7e4b1456bbff59a25d Mon Sep 17 00:00:00 2001 |
2 | From: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> | |
3 | Date: Thu, 12 Feb 2015 15:00:25 -0800 | |
4 | Subject: mm: hwpoison: drop lru_add_drain_all() in __soft_offline_page() | |
5 | ||
6 | From: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> | |
7 | ||
8 | commit 9ab3b598d2dfbdb0153ffa7e4b1456bbff59a25d upstream. | |
9 | ||
10 | A race condition starts to be visible in recent mmotm, where a PG_hwpoison | |
11 | flag is set on a migration source page *before* it's back in buddy page | |
12 | poo= l. | |
13 | ||
14 | This is problematic because no page flag is supposed to be set when | |
15 | freeing (see __free_one_page().) So the user-visible effect of this race | |
16 | is that it could trigger the BUG_ON() when soft-offlining is called. | |
17 | ||
18 | The root cause is that we call lru_add_drain_all() to make sure that the | |
19 | page is in buddy, but that doesn't work because this function just | |
20 | schedule= s a work item and doesn't wait its completion. | |
21 | drain_all_pages() does drainin= g directly, so simply dropping | |
22 | lru_add_drain_all() solves this problem. | |
23 | ||
24 | Fixes: f15bdfa802bf ("mm/memory-failure.c: fix memory leak in successful soft offlining") | |
25 | Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> | |
26 | Cc: Andi Kleen <andi@firstfloor.org> | |
27 | Cc: Tony Luck <tony.luck@intel.com> | |
28 | Cc: Chen Gong <gong.chen@linux.intel.com> | |
29 | Signed-off-by: Andrew Morton <akpm@linux-foundation.org> | |
30 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
31 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
32 | ||
33 | --- | |
34 | mm/memory-failure.c | 2 -- | |
35 | 1 file changed, 2 deletions(-) | |
36 | ||
37 | --- a/mm/memory-failure.c | |
38 | +++ b/mm/memory-failure.c | |
39 | @@ -1654,8 +1654,6 @@ static int __soft_offline_page(struct pa | |
40 | * setting PG_hwpoison. | |
41 | */ | |
42 | if (!is_free_buddy_page(page)) | |
43 | - lru_add_drain_all(); | |
44 | - if (!is_free_buddy_page(page)) | |
45 | drain_all_pages(page_zone(page)); | |
46 | SetPageHWPoison(page); | |
47 | if (!is_free_buddy_page(page)) |