diff options
author | Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> | 2014-07-23 14:00:19 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-07-31 12:53:51 -0700 |
commit | 32226c206801036be8d17e183ee51391f601a6cc (patch) | |
tree | ecbecac027890c1935e99399362e99380358d922 /mm/hugetlb.c | |
parent | b0c6b604a01b85e4f0ce86272e8e49ae9e52a8d5 (diff) | |
download | linux-stable-32226c206801036be8d17e183ee51391f601a6cc.tar.gz linux-stable-32226c206801036be8d17e183ee51391f601a6cc.tar.bz2 linux-stable-32226c206801036be8d17e183ee51391f601a6cc.zip |
mm: hugetlb: fix copy_hugetlb_page_range()
commit 0253d634e0803a8376a0d88efee0bf523d8673f9 upstream.
Commit 4a705fef9862 ("hugetlb: fix copy_hugetlb_page_range() to handle
migration/hwpoisoned entry") changed the order of
huge_ptep_set_wrprotect() and huge_ptep_get(), which leads to breakage
in some workloads like hugepage-backed heap allocation via libhugetlbfs.
This patch fixes it.
The test program for the problem is shown below:
$ cat heap.c
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define HPS 0x200000
int main() {
int i;
char *p = malloc(HPS);
memset(p, '1', HPS);
for (i = 0; i < 5; i++) {
if (!fork()) {
memset(p, '2', HPS);
p = malloc(HPS);
memset(p, '3', HPS);
free(p);
return 0;
}
}
sleep(1);
free(p);
return 0;
}
$ export HUGETLB_MORECORE=yes ; export HUGETLB_NO_PREFAULT= ; hugectl --heap ./heap
Fixes 4a705fef9862 ("hugetlb: fix copy_hugetlb_page_range() to handle
migration/hwpoisoned entry"), so is applicable to -stable kernels which
include it.
Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Reported-by: Guillaume Morin <guillaume@morinfr.org>
Suggested-by: Guillaume Morin <guillaume@morinfr.org>
Acked-by: Hugh Dickins <hughd@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'mm/hugetlb.c')
-rw-r--r-- | mm/hugetlb.c | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index dbc949c409c7..7de4f67c81fe 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2400,6 +2400,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, } else { if (cow) huge_ptep_set_wrprotect(src, addr, src_pte); + entry = huge_ptep_get(src_pte); ptepage = pte_page(entry); get_page(ptepage); page_dup_rmap(ptepage); |