]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.19.51/hugetlbfs-on-restore-reserve-error-path-retain-subpo.patch
Linux 4.19.51
[thirdparty/kernel/stable-queue.git] / releases / 4.19.51 / hugetlbfs-on-restore-reserve-error-path-retain-subpo.patch
CommitLineData
37554d48
SL
1From 2106462cb2dc5f2d487cf46958fafed8f716388b Mon Sep 17 00:00:00 2001
2From: Mike Kravetz <mike.kravetz@oracle.com>
3Date: Mon, 13 May 2019 17:19:38 -0700
4Subject: hugetlbfs: on restore reserve error path retain subpool reservation
5
6[ Upstream commit 0919e1b69ab459e06df45d3ba6658d281962db80 ]
7
8When a huge page is allocated, PagePrivate() is set if the allocation
9consumed a reservation. When freeing a huge page, PagePrivate is checked.
10If set, it indicates the reservation should be restored. PagePrivate
11being set at free huge page time mostly happens on error paths.
12
13When huge page reservations are created, a check is made to determine if
14the mapping is associated with an explicitly mounted filesystem. If so,
15pages are also reserved within the filesystem. The default action when
16freeing a huge page is to decrement the usage count in any associated
17explicitly mounted filesystem. However, if the reservation is to be
18restored the reservation/use count within the filesystem should not be
19decrementd. Otherwise, a subsequent page allocation and free for the same
20mapping location will cause the file filesystem usage to go 'negative'.
21
22Filesystem Size Used Avail Use% Mounted on
23nodev 4.0G -4.0M 4.1G - /opt/hugepool
24
25To fix, when freeing a huge page do not adjust filesystem usage if
26PagePrivate() is set to indicate the reservation should be restored.
27
28I did not cc stable as the problem has been around since reserves were
29added to hugetlbfs and nobody has noticed.
30
31Link: http://lkml.kernel.org/r/20190328234704.27083-2-mike.kravetz@oracle.com
32Signed-off-by: Mike Kravetz <mike.kravetz@oracle.com>
33Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
34Cc: Davidlohr Bueso <dave@stgolabs.net>
35Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
36Cc: Michal Hocko <mhocko@kernel.org>
37Cc: "Kirill A . Shutemov" <kirill.shutemov@linux.intel.com>
38Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
39Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
40Signed-off-by: Sasha Levin <sashal@kernel.org>
41---
42 mm/hugetlb.c | 21 ++++++++++++++++-----
43 1 file changed, 16 insertions(+), 5 deletions(-)
44
45diff --git a/mm/hugetlb.c b/mm/hugetlb.c
46index 0bbb033d7d8c..65179513c2b2 100644
47--- a/mm/hugetlb.c
48+++ b/mm/hugetlb.c
49@@ -1256,12 +1256,23 @@ void free_huge_page(struct page *page)
50 ClearPagePrivate(page);
51
52 /*
53- * A return code of zero implies that the subpool will be under its
54- * minimum size if the reservation is not restored after page is free.
55- * Therefore, force restore_reserve operation.
56+ * If PagePrivate() was set on page, page allocation consumed a
57+ * reservation. If the page was associated with a subpool, there
58+ * would have been a page reserved in the subpool before allocation
59+ * via hugepage_subpool_get_pages(). Since we are 'restoring' the
60+ * reservtion, do not call hugepage_subpool_put_pages() as this will
61+ * remove the reserved page from the subpool.
62 */
63- if (hugepage_subpool_put_pages(spool, 1) == 0)
64- restore_reserve = true;
65+ if (!restore_reserve) {
66+ /*
67+ * A return code of zero implies that the subpool will be
68+ * under its minimum size if the reservation is not restored
69+ * after page is free. Therefore, force restore_reserve
70+ * operation.
71+ */
72+ if (hugepage_subpool_put_pages(spool, 1) == 0)
73+ restore_reserve = true;
74+ }
75
76 spin_lock(&hugetlb_lock);
77 clear_page_huge_active(page);
78--
792.20.1
80