]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.1.1/powerpc-get_hugepte-don-t-put_page-the-wrong-page.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.1.1 / powerpc-get_hugepte-don-t-put_page-the-wrong-page.patch
1 From 405e44f2e312dd5dd63e5a9f459bffcbcd4368ef Mon Sep 17 00:00:00 2001
2 From: Andrea Arcangeli <aarcange@redhat.com>
3 Date: Wed, 2 Nov 2011 13:37:08 -0700
4 Subject: powerpc: get_hugepte() don't put_page() the wrong page
5
6 From: Andrea Arcangeli <aarcange@redhat.com>
7
8 commit 405e44f2e312dd5dd63e5a9f459bffcbcd4368ef upstream.
9
10 "page" may have changed to point to the next hugepage after the loop
11 completed, The references have been taken on the head page, so the
12 put_page must happen there too.
13
14 This is a longstanding issue pre-thp inclusion.
15
16 It's totally unclear how these page_cache_add_speculative and
17 pte_val(pte) != pte_val(*ptep) checks are necessary across all the
18 powerpc gup_fast code, when x86 doesn't need any of that: there's no way
19 the page can be freed with irq disabled so we're guaranteed the
20 atomic_inc will happen on a page with page_count > 0 (so not needing the
21 speculative check).
22
23 The pte check is also meaningless on x86: no need to rollback on x86 if
24 the pte changed, because the pte can still change a CPU tick after the
25 check succeeded and it won't be rolled back in that case. The important
26 thing is we got a reference on a valid page that was mapped there a CPU
27 tick ago. So not knowing the soft tlb refill code of ppc64 in great
28 detail I'm not removing the "speculative" page_count increase and the
29 pte checks across all the code, but unless there's a strong reason for
30 it they should be later cleaned up too.
31
32 If a pte can change from huge to non-huge (like it could happen with
33 THP) passing a pte_t *ptep to gup_hugepte() would also require to repeat
34 the is_hugepd in gup_hugepte(), but that shouldn't happen with hugetlbfs
35 only so I'm not altering that.
36
37 Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
38 Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
39 Cc: Hugh Dickins <hughd@google.com>
40 Cc: Johannes Weiner <jweiner@redhat.com>
41 Cc: Rik van Riel <riel@redhat.com>
42 Cc: Mel Gorman <mgorman@suse.de>
43 Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
44 Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
45 Acked-by: David Gibson <david@gibson.dropbear.id.au>
46 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
47 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
48 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
49
50 ---
51 arch/powerpc/mm/hugetlbpage.c | 2 +-
52 1 file changed, 1 insertion(+), 1 deletion(-)
53
54 --- a/arch/powerpc/mm/hugetlbpage.c
55 +++ b/arch/powerpc/mm/hugetlbpage.c
56 @@ -429,7 +429,7 @@ static noinline int gup_hugepte(pte_t *p
57 if (unlikely(pte_val(pte) != pte_val(*ptep))) {
58 /* Could be optimized better */
59 while (*nr) {
60 - put_page(page);
61 + put_page(head);
62 (*nr)--;
63 }
64 }