diff -Naur linux-2.5.46/arch/i386/mm/hugetlbpage.c linux-2.5.46-ioe/arch/i386/mm/hugetlbpage.c --- linux-2.5.46/arch/i386/mm/hugetlbpage.c Tue Nov 5 21:32:52 2002 +++ linux-2.5.46-ioe/arch/i386/mm/hugetlbpage.c Tue Nov 5 23:54:29 2002 @@ -180,15 +180,16 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, - struct page **pages, struct vm_area_struct **vmas, - unsigned long *st, int *length, int i) + unsigned long *st, + custom_page_walker_t walker, void *customdata) { pte_t *ptep, pte; unsigned long start = *st; unsigned long pstart; - int len = *length; + int ret = 0; struct page *page; + spin_lock(&mm->page_table_lock); do { pstart = start; ptep = huge_pte_offset(mm, start); @@ -196,22 +197,31 @@ back1: page = pte_page(pte); - if (pages) { - page += ((start & ~HPAGE_MASK) >> PAGE_SHIFT); - pages[i] = page; + page += ((start & ~HPAGE_MASK) >> PAGE_SHIFT); + ret = walker(vma, page, start, customdata); + switch (ret) { + /* Common case -> continue walking. */ + case 0: + break; + /* We are satisfied with our walking. */ + case 1: + ret = 0; + goto out_unlock; + default: + /* Error cases do unlock, + * if necessary. -ioe */ + goto out; } - if (vmas) - vmas[i] = vma; - i++; - len--; start += PAGE_SIZE; - if (((start & HPAGE_MASK) == pstart) && len && + if (((start & HPAGE_MASK) == pstart) && (start < vma->vm_end)) goto back1; - } while (len && start < vma->vm_end); - *length = len; + } while (start < vma->vm_end); +out_unlock: + spin_unlock(&mm->page_table_lock); +out: *st = start; - return i; + return ret; } void free_huge_page(struct page *page) diff -Naur linux-2.5.46/arch/ia64/mm/hugetlbpage.c linux-2.5.46-ioe/arch/ia64/mm/hugetlbpage.c --- linux-2.5.46/arch/ia64/mm/hugetlbpage.c Tue Nov 5 21:32:52 2002 +++ linux-2.5.46-ioe/arch/ia64/mm/hugetlbpage.c Tue Nov 5 23:54:29 2002 @@ -226,16 +226,17 @@ } int -follow_hugetlb_page (struct mm_struct *mm, struct vm_area_struct *vma, - struct page **pages, struct vm_area_struct **vmas, - unsigned long *st, int *length, int i) +follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, + unsigned long *st, + custom_page_walker_t walker, void *customdata) { pte_t *ptep, pte; unsigned long start = *st; unsigned long pstart; - int len = *length; + int ret = 0; struct page *page; + spin_lock(&mm->page_table_lock); do { pstart = start & HPAGE_MASK; ptep = huge_pte_offset(mm, start); @@ -243,22 +244,30 @@ back1: page = pte_page(pte); - if (pages) { - page += ((start & ~HPAGE_MASK) >> PAGE_SHIFT); - pages[i] = page; + page += ((start & ~HPAGE_MASK) >> PAGE_SHIFT); + ret = walker(vma, page, start, customdata); + switch (ret) { + /* Common case -> continue walking. */ + case 0: + break; + /* We are satisfied with our walking. */ + case 1: + ret = 0; + goto out_unlock; + default: + /* Error cases do unlock, + * if necessary. -ioe */ + goto out; } - if (vmas) - vmas[i] = vma; - i++; - len--; start += PAGE_SIZE; - if (((start & HPAGE_MASK) == pstart) && len - && (start < vma->vm_end)) + if (((start & HPAGE_MASK) == pstart) && (start < vma->vm_end)) goto back1; - } while (len && start < vma->vm_end); - *length = len; + } while (start < vma->vm_end); +out_unlock: + spin_unlock(&mm->page_table_lock); +out: *st = start; - return i; + return ret; } static void diff -Naur linux-2.5.46/arch/sparc64/mm/hugetlbpage.c linux-2.5.46-ioe/arch/sparc64/mm/hugetlbpage.c --- linux-2.5.46/arch/sparc64/mm/hugetlbpage.c Tue Nov 5 21:32:53 2002 +++ linux-2.5.46-ioe/arch/sparc64/mm/hugetlbpage.c Tue Nov 5 23:59:12 2002 @@ -269,16 +269,18 @@ return -ENOMEM; } + int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, - struct page **pages, struct vm_area_struct **vmas, - unsigned long *st, int *length, int i) + unsigned long *st, + custom_page_walker_t walker, void *customdata) { pte_t *ptep, pte; unsigned long start = *st; unsigned long pstart; - int len = *length; + int ret = 0; struct page *page; + spin_lock(&mm->page_table_lock); do { pstart = start; ptep = huge_pte_offset_map(mm, start); @@ -286,14 +288,22 @@ back1: page = pte_page(pte); - if (pages) { - page += ((start & ~HPAGE_MASK) >> PAGE_SHIFT); - pages[i] = page; + page += ((start & ~HPAGE_MASK) >> PAGE_SHIFT); + ret = walker(vma, page, start, customdata); + switch (ret) { + /* Common case -> continue walking. */ + case 0: + break; + /* We are satisfied with our walking. */ + case 1: + ret = 0; + spin_unlock(&mm->page_table_lock); + default: + /* Error cases do unlock, + * if necessary. -ioe */ + pte_unmap(ptep); + goto out; } - if (vmas) - vmas[i] = vma; - i++; - len--; start += PAGE_SIZE; if (((start & HPAGE_MASK) == pstart) && len && (start < vma->vm_end)) @@ -301,10 +311,10 @@ pte_unmap(ptep); } while (len && start < vma->vm_end); - - *length = len; + spin_unlock(&mm->page_table_lock); +out: *st = start; - return i; + return ret; } static void zap_hugetlb_resources(struct vm_area_struct *mpnt) diff -Naur linux-2.5.46/include/linux/hugetlb.h linux-2.5.46-ioe/include/linux/hugetlb.h --- linux-2.5.46/include/linux/hugetlb.h Tue Nov 5 21:32:53 2002 +++ linux-2.5.46-ioe/include/linux/hugetlb.h Tue Nov 5 23:44:46 2002 @@ -8,7 +8,16 @@ } int copy_hugetlb_page_range(struct mm_struct *, struct mm_struct *, struct vm_area_struct *); -int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int); +//int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, struct page **, struct vm_area_struct **, unsigned long *, int *, int); +/* Sorry for the ugliness, but the other option was to always + * include linux/mm.h -ioe + */ +int follow_hugetlb_page(struct mm_struct *, struct vm_area_struct *, + unsigned long *, + int (*)(struct vm_area_struct *, + struct page *, unsigned long, void *), + void *); + void zap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long); void unmap_hugepage_range(struct vm_area_struct *, unsigned long, unsigned long); int hugetlb_prefault(struct address_space *, struct vm_area_struct *); @@ -19,7 +28,7 @@ return 0; } -#define follow_hugetlb_page(m,v,p,vs,a,b,i) ({ BUG(); 0; }) +#define follow_hugetlb_page(m,v,a,w,c) ({ BUG(); 0; }) #define copy_hugetlb_page_range(src, dst, vma) ({ BUG(); 0; }) #define hugetlb_prefault(mapping, vma) ({ BUG(); 0; }) #define zap_hugepage_range(vma, start, len) BUG()