]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.1.1/s390-gup_huge_pmd-support-thp-tail-recounting.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.1.1 / s390-gup_huge_pmd-support-thp-tail-recounting.patch
CommitLineData
b9e9b117
GKH
1From 220a2eb228d032acde60e9fd044ca802706ff583 Mon Sep 17 00:00:00 2001
2From: Andrea Arcangeli <aarcange@redhat.com>
3Date: Wed, 2 Nov 2011 13:37:25 -0700
4Subject: s390: gup_huge_pmd() support THP tail recounting
5
6From: Andrea Arcangeli <aarcange@redhat.com>
7
8commit 220a2eb228d032acde60e9fd044ca802706ff583 upstream.
9
10Up to this point the code assumed old refcounting for hugepages (pre-thp).
11This updates the code directly to the thp mapcount tail page refcounting.
12
13Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
14Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
15Cc: Hugh Dickins <hughd@google.com>
16Cc: Johannes Weiner <jweiner@redhat.com>
17Cc: Rik van Riel <riel@redhat.com>
18Cc: Mel Gorman <mgorman@suse.de>
19Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
20Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
21Cc: David Gibson <david@gibson.dropbear.id.au>
22Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
23Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
24Cc: David Miller <davem@davemloft.net>
25Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
26Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
27Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
28
29---
30 arch/s390/mm/gup.c | 24 +++++++++++++++++++++++-
31 1 file changed, 23 insertions(+), 1 deletion(-)
32
33--- a/arch/s390/mm/gup.c
34+++ b/arch/s390/mm/gup.c
35@@ -48,11 +48,22 @@ static inline int gup_pte_range(pmd_t *p
36 return 1;
37 }
38
39+static inline void get_huge_page_tail(struct page *page)
40+{
41+ /*
42+ * __split_huge_page_refcount() cannot run
43+ * from under us.
44+ */
45+ VM_BUG_ON(page_mapcount(page) < 0);
46+ VM_BUG_ON(atomic_read(&page->_count) != 0);
47+ atomic_inc(&page->_mapcount);
48+}
49+
50 static inline int gup_huge_pmd(pmd_t *pmdp, pmd_t pmd, unsigned long addr,
51 unsigned long end, int write, struct page **pages, int *nr)
52 {
53 unsigned long mask, result;
54- struct page *head, *page;
55+ struct page *head, *page, *tail;
56 int refs;
57
58 result = write ? 0 : _SEGMENT_ENTRY_RO;
59@@ -64,6 +75,7 @@ static inline int gup_huge_pmd(pmd_t *pm
60 refs = 0;
61 head = pmd_page(pmd);
62 page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT);
63+ tail = page;
64 do {
65 VM_BUG_ON(compound_head(page) != head);
66 pages[*nr] = page;
67@@ -81,6 +93,16 @@ static inline int gup_huge_pmd(pmd_t *pm
68 *nr -= refs;
69 while (refs--)
70 put_page(head);
71+ } else {
72+ /*
73+ * Any tail page need their mapcount reference taken
74+ * before we return.
75+ */
76+ while (refs--) {
77+ if (PageTail(tail))
78+ get_huge_page_tail(tail);
79+ tail++;
80+ }
81 }
82
83 return 1;