2004-04-13 23:22:31

by Chen, Kenneth W

[permalink] [raw]
Subject: hugetlb demand paging patch part [1/3]

Part 1 of 3

1. hugetlb_fix_pte.patch - with demand paging, we can not unconditionally
assume valid pmd/pte. Fix it up in arch specific huge_pge_offset()
and have all caller check the return value.


i386/mm/hugetlbpage.c | 11 +++++++----
ia64/mm/hugetlbpage.c | 18 ++++++++++++------
sh/mm/hugetlbpage.c | 15 +++++++--------
sparc64/mm/hugetlbpage.c | 15 +++++++--------
4 files changed, 33 insertions(+), 26 deletions(-)

diff -Nurp linux-2.6.5/arch/i386/mm/hugetlbpage.c linux-2.6.5.htlb/arch/i386/mm/hugetlbpage.c
--- linux-2.6.5/arch/i386/mm/hugetlbpage.c 2004-04-10 17:05:34.000000000 -0700
+++ linux-2.6.5.htlb/arch/i386/mm/hugetlbpage.c 2004-04-10 17:10:39.000000000 -0700
@@ -36,7 +36,8 @@ static pte_t *huge_pte_offset(struct mm_
pmd_t *pmd = NULL;

pgd = pgd_offset(mm, addr);
- pmd = pmd_offset(pgd, addr);
+ if (pgd_present(*pgd))
+ pmd = pmd_offset(pgd, addr);
return (pte_t *) pmd;
}

@@ -75,11 +76,13 @@ int copy_hugetlb_page_range(struct mm_st
unsigned long addr = vma->vm_start;
unsigned long end = vma->vm_end;

- while (addr < end) {
+ for (; addr < end; addr+= HPAGE_SIZE) {
+ src_pte = huge_pte_offset(src, addr);
+ if (!src_pte || pte_none(*src_pte))
+ continue;
dst_pte = huge_pte_alloc(dst, addr);
if (!dst_pte)
goto nomem;
- src_pte = huge_pte_offset(src, addr);
entry = *src_pte;
ptepage = pte_page(entry);
get_page(ptepage);
@@ -227,7 +230,7 @@ void unmap_hugepage_range(struct vm_area

for (address = start; address < end; address += HPAGE_SIZE) {
pte = huge_pte_offset(mm, address);
- if (pte_none(*pte))
+ if (!pte || pte_none(*pte))
continue;
page = pte_page(*pte);
huge_page_release(page);
diff -Nurp linux-2.6.5/arch/ia64/mm/hugetlbpage.c linux-2.6.5.htlb/arch/ia64/mm/hugetlbpage.c
--- linux-2.6.5/arch/ia64/mm/hugetlbpage.c 2004-04-10 17:05:34.000000000 -0700
+++ linux-2.6.5.htlb/arch/ia64/mm/hugetlbpage.c 2004-04-10 17:10:29.000000000 -0700
@@ -48,8 +48,11 @@ huge_pte_offset (struct mm_struct *mm, u
pte_t *pte = NULL;

pgd = pgd_offset(mm, taddr);
- pmd = pmd_offset(pgd, taddr);
- pte = pte_offset_map(pmd, taddr);
+ if (pgd_present(*pgd)) {
+ pmd = pmd_offset(pgd, taddr);
+ if (pmd_present(*pmd))
+ pte = pte_offset_map(pmd, taddr);
+ }
return pte;
}

@@ -95,17 +98,18 @@ int copy_hugetlb_page_range(struct mm_st
unsigned long addr = vma->vm_start;
unsigned long end = vma->vm_end;

- while (addr < end) {
+ for (; addr < end; addr += HPAGE_SIZE) {
+ src_pte = huge_pte_offset(src, addr);
+ if (!src_pte || pte_none(*src_pte))
+ continue;
dst_pte = huge_pte_alloc(dst, addr);
if (!dst_pte)
goto nomem;
- src_pte = huge_pte_offset(src, addr);
entry = *src_pte;
ptepage = pte_page(entry);
get_page(ptepage);
set_pte(dst_pte, entry);
dst->rss += (HPAGE_SIZE / PAGE_SIZE);
- addr += HPAGE_SIZE;
}
return 0;
nomem:
@@ -167,6 +171,8 @@ struct page *follow_huge_addr(struct mm_
pte_t *ptep;

ptep = huge_pte_offset(mm, addr);
+ if (!ptep || pte_none(*ptep))
+ return NULL;
page = pte_page(*ptep);
page += ((addr & ~HPAGE_MASK) >> PAGE_SHIFT);
get_page(page);
@@ -247,7 +253,7 @@ void unmap_hugepage_range(struct vm_area

for (address = start; address < end; address += HPAGE_SIZE) {
pte = huge_pte_offset(mm, address);
- if (pte_none(*pte))
+ if (!pte || pte_none(*pte))
continue;
page = pte_page(*pte);
huge_page_release(page);
diff -Nurp linux-2.6.5/arch/sh/mm/hugetlbpage.c linux-2.6.5.htlb/arch/sh/mm/hugetlbpage.c
--- linux-2.6.5/arch/sh/mm/hugetlbpage.c 2004-04-10 17:05:34.000000000 -0700
+++ linux-2.6.5.htlb/arch/sh/mm/hugetlbpage.c 2004-04-10 17:45:40.000000000 -0700
@@ -46,9 +46,9 @@ static pte_t *huge_pte_offset(struct mm_
pte_t *pte = NULL;

pgd = pgd_offset(mm, addr);
- if (pgd) {
+ if (pgd_present(*pgd)) {
pmd = pmd_offset(pgd, addr);
- if (pmd)
+ if (pmd_present(*pmd))
pte = pte_offset_map(pmd, addr);
}
return pte;
@@ -101,12 +101,13 @@ int copy_hugetlb_page_range(struct mm_st
unsigned long end = vma->vm_end;
int i;

- while (addr < end) {
+ for (; addr < end; addr += HPAGE_SIZE) {
+ src_pte = huge_pte_offset(src, addr);
+ if (!src_pte || pte_none(*src_pte))
+ continue;
dst_pte = huge_pte_alloc(dst, addr);
if (!dst_pte)
goto nomem;
- src_pte = huge_pte_offset(src, addr);
- BUG_ON(!src_pte || pte_none(*src_pte));
entry = *src_pte;
ptepage = pte_page(entry);
get_page(ptepage);
@@ -116,7 +117,6 @@ int copy_hugetlb_page_range(struct mm_st
dst_pte++;
}
dst->rss += (HPAGE_SIZE / PAGE_SIZE);
- addr += HPAGE_SIZE;
}
return 0;

@@ -202,8 +202,7 @@ void unmap_hugepage_range(struct vm_area

for (address = start; address < end; address += HPAGE_SIZE) {
pte = huge_pte_offset(mm, address);
- BUG_ON(!pte);
- if (pte_none(*pte))
+ if (!pte || pte_none(*pte))
continue;
page = pte_page(*pte);
huge_page_release(page);
diff -Nurp linux-2.6.5/arch/sparc64/mm/hugetlbpage.c linux-2.6.5.htlb/arch/sparc64/mm/hugetlbpage.c
--- linux-2.6.5/arch/sparc64/mm/hugetlbpage.c 2004-04-10 17:05:34.000000000 -0700
+++ linux-2.6.5.htlb/arch/sparc64/mm/hugetlbpage.c 2004-04-10 17:44:04.000000000 -0700
@@ -43,9 +43,9 @@ static pte_t *huge_pte_offset(struct mm_
pte_t *pte = NULL;

pgd = pgd_offset(mm, addr);
- if (pgd) {
+ if (pgd_present(*pgd)) {
pmd = pmd_offset(pgd, addr);
- if (pmd)
+ if (pmd_present(*pmd))
pte = pte_offset_map(pmd, addr);
}
return pte;
@@ -98,12 +98,13 @@ int copy_hugetlb_page_range(struct mm_st
unsigned long end = vma->vm_end;
int i;

- while (addr < end) {
+ for (; addr < end; addr += HPAGE_SIZE) {
+ src_pte = huge_pte_offset(src, addr);
+ if (!src_pte || pte_none(*src_pte))
+ continue;
dst_pte = huge_pte_alloc(dst, addr);
if (!dst_pte)
goto nomem;
- src_pte = huge_pte_offset(src, addr);
- BUG_ON(!src_pte || pte_none(*src_pte));
entry = *src_pte;
ptepage = pte_page(entry);
get_page(ptepage);
@@ -113,7 +114,6 @@ int copy_hugetlb_page_range(struct mm_st
dst_pte++;
}
dst->rss += (HPAGE_SIZE / PAGE_SIZE);
- addr += HPAGE_SIZE;
}
return 0;

@@ -199,8 +199,7 @@ void unmap_hugepage_range(struct vm_area

for (address = start; address < end; address += HPAGE_SIZE) {
pte = huge_pte_offset(mm, address);
- BUG_ON(!pte);
- if (pte_none(*pte))
+ if (!pte || pte_none(*pte))
continue;
page = pte_page(*pte);
huge_page_release(page);