From: William Lee Irwin III mm/hugetlb.c is putting the destructor in head->lru.prev not head[1].mapping; fix below along with nuking huge_page_release(), which simply duplicates put_page(). --- 25-akpm/arch/i386/mm/hugetlbpage.c | 2 +- 25-akpm/arch/ia64/mm/hugetlbpage.c | 2 +- 25-akpm/arch/ppc64/mm/hugetlbpage.c | 2 +- 25-akpm/arch/sh/mm/hugetlbpage.c | 2 +- 25-akpm/arch/sparc64/mm/hugetlbpage.c | 2 +- 25-akpm/include/linux/hugetlb.h | 2 -- 25-akpm/mm/hugetlb.c | 10 +--------- 7 files changed, 6 insertions(+), 16 deletions(-) diff -puN arch/i386/mm/hugetlbpage.c~hugepage-fixes arch/i386/mm/hugetlbpage.c --- 25/arch/i386/mm/hugetlbpage.c~hugepage-fixes 2004-04-23 03:57:28.963860480 -0700 +++ 25-akpm/arch/i386/mm/hugetlbpage.c 2004-04-23 03:57:28.992856072 -0700 @@ -220,7 +220,7 @@ void unmap_hugepage_range(struct vm_area if (pte_none(pte)) continue; page = pte_page(pte); - huge_page_release(page); + put_page(page); } mm->rss -= (end - start) >> PAGE_SHIFT; flush_tlb_range(vma, start, end); diff -puN arch/ia64/mm/hugetlbpage.c~hugepage-fixes arch/ia64/mm/hugetlbpage.c --- 25/arch/ia64/mm/hugetlbpage.c~hugepage-fixes 2004-04-23 03:57:28.965860176 -0700 +++ 25-akpm/arch/ia64/mm/hugetlbpage.c 2004-04-23 03:57:28.993855920 -0700 @@ -249,7 +249,7 @@ void unmap_hugepage_range(struct vm_area if (pte_none(*pte)) continue; page = pte_page(*pte); - huge_page_release(page); + put_page(page); pte_clear(pte); } mm->rss -= (end - start) >> PAGE_SHIFT; diff -puN arch/ppc64/mm/hugetlbpage.c~hugepage-fixes arch/ppc64/mm/hugetlbpage.c --- 25/arch/ppc64/mm/hugetlbpage.c~hugepage-fixes 2004-04-23 03:57:28.980857896 -0700 +++ 25-akpm/arch/ppc64/mm/hugetlbpage.c 2004-04-23 03:57:28.994855768 -0700 @@ -394,7 +394,7 @@ void unmap_hugepage_range(struct vm_area flush_hash_hugepage(mm->context, addr, pte, local); - huge_page_release(page); + put_page(page); } mm->rss -= (end - start) >> PAGE_SHIFT; diff -puN arch/sh/mm/hugetlbpage.c~hugepage-fixes arch/sh/mm/hugetlbpage.c --- 25/arch/sh/mm/hugetlbpage.c~hugepage-fixes 2004-04-23 03:57:28.985857136 -0700 +++ 25-akpm/arch/sh/mm/hugetlbpage.c 2004-04-23 03:57:28.994855768 -0700 @@ -200,7 +200,7 @@ void unmap_hugepage_range(struct vm_area if (pte_none(*pte)) continue; page = pte_page(*pte); - huge_page_release(page); + put_page(page); for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { pte_clear(pte); pte++; diff -puN arch/sparc64/mm/hugetlbpage.c~hugepage-fixes arch/sparc64/mm/hugetlbpage.c --- 25/arch/sparc64/mm/hugetlbpage.c~hugepage-fixes 2004-04-23 03:57:28.986856984 -0700 +++ 25-akpm/arch/sparc64/mm/hugetlbpage.c 2004-04-23 03:57:28.994855768 -0700 @@ -198,7 +198,7 @@ void unmap_hugepage_range(struct vm_area if (pte_none(*pte)) continue; page = pte_page(*pte); - huge_page_release(page); + put_page(page); for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { pte_clear(pte); pte++; diff -puN include/linux/hugetlb.h~hugepage-fixes include/linux/hugetlb.h --- 25/include/linux/hugetlb.h~hugepage-fixes 2004-04-23 03:57:28.987856832 -0700 +++ 25-akpm/include/linux/hugetlb.h 2004-04-23 03:57:28.992856072 -0700 @@ -18,7 +18,6 @@ int follow_hugetlb_page(struct mm_struct 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 *); -void huge_page_release(struct page *); int hugetlb_report_meminfo(char *); int is_hugepage_mem_enough(size_t); unsigned long hugetlb_total_pages(void); @@ -70,7 +69,6 @@ static inline unsigned long hugetlb_tota #define hugetlb_prefault(mapping, vma) ({ BUG(); 0; }) #define zap_hugepage_range(vma, start, len) BUG() #define unmap_hugepage_range(vma, start, end) BUG() -#define huge_page_release(page) BUG() #define is_hugepage_mem_enough(size) 0 #define hugetlb_report_meminfo(buf) 0 #define mark_mm_hugetlb(mm, vma) do { } while (0) diff -puN mm/hugetlb.c~hugepage-fixes mm/hugetlb.c --- 25/mm/hugetlb.c~hugepage-fixes 2004-04-23 03:57:28.989856528 -0700 +++ 25-akpm/mm/hugetlb.c 2004-04-23 03:57:28.992856072 -0700 @@ -78,20 +78,12 @@ struct page *alloc_huge_page(void) free_huge_pages--; spin_unlock(&hugetlb_lock); set_page_count(page, 1); - page->lru.prev = (void *)free_huge_page; + page[1].mapping = (void *)free_huge_page; for (i = 0; i < (HPAGE_SIZE/PAGE_SIZE); ++i) clear_highpage(&page[i]); return page; } -void huge_page_release(struct page *page) -{ - if (!put_page_testzero(page)) - return; - - free_huge_page(page); -} - static int __init hugetlb_init(void) { unsigned long i; _