Index: linux-2.6/include/linux/mm.h =================================================================== --- linux-2.6.orig/include/linux/mm.h 2007-03-26 13:56:22.000000000 -0700 +++ linux-2.6/include/linux/mm.h 2007-03-26 13:56:48.000000000 -0700 @@ -269,14 +269,14 @@ static inline int get_page_unless_zero(s static inline int page_count(struct page *page) { - if (unlikely(PageCompound(page))) + if (unlikely(PageTail(page))) page = (struct page *)page_private(page); return atomic_read(&page->_count); } static inline void get_page(struct page *page) { - if (unlikely(PageCompound(page))) + if (unlikely(PageTail(page))) page = (struct page *)page_private(page); VM_BUG_ON(atomic_read(&page->_count) == 0); atomic_inc(&page->_count); Index: linux-2.6/include/linux/page-flags.h =================================================================== --- linux-2.6.orig/include/linux/page-flags.h 2007-03-26 13:49:50.000000000 -0700 +++ linux-2.6/include/linux/page-flags.h 2007-03-26 13:51:06.000000000 -0700 @@ -91,6 +91,8 @@ #define PG_nosave_free 18 /* Used for system suspend/resume */ #define PG_buddy 19 /* Page is free, on buddy lists */ +#define PG_tail 20 /* Tail portion of a compound page */ + /* PG_owner_priv_1 users should have descriptive aliases */ #define PG_checked PG_owner_priv_1 /* Used by some filesystems */ @@ -241,6 +243,10 @@ static inline void SetPageUptodate(struc #define __SetPageCompound(page) __set_bit(PG_compound, &(page)->flags) #define __ClearPageCompound(page) __clear_bit(PG_compound, &(page)->flags) +#define PageTail(page) test_bit(PG_tail, &(page)->flags) +#define __SetPageTail(page) __set_bit(PG_tail, &(page)->flags) +#define __ClearPageTail(page) __clear_bit(PG_tail, &(page)->flags) + #ifdef CONFIG_SWAP #define PageSwapCache(page) test_bit(PG_swapcache, &(page)->flags) #define SetPageSwapCache(page) set_bit(PG_swapcache, &(page)->flags) Index: linux-2.6/mm/internal.h =================================================================== --- linux-2.6.orig/mm/internal.h 2007-03-26 13:57:15.000000000 -0700 +++ linux-2.6/mm/internal.h 2007-03-26 13:57:51.000000000 -0700 @@ -24,7 +24,7 @@ static inline void set_page_count(struct */ static inline void set_page_refcounted(struct page *page) { - VM_BUG_ON(PageCompound(page) && page_private(page) != (unsigned long)page); + VM_BUG_ON(PageTail(page)); VM_BUG_ON(atomic_read(&page->_count)); set_page_count(page, 1); } Index: linux-2.6/mm/page_alloc.c =================================================================== --- linux-2.6.orig/mm/page_alloc.c 2007-03-26 13:51:11.000000000 -0700 +++ linux-2.6/mm/page_alloc.c 2007-03-26 13:54:54.000000000 -0700 @@ -236,10 +236,12 @@ static void prep_compound_page(struct pa int nr_pages = 1 << order; set_compound_page_dtor(page, free_compound_page); + __SetPageCompound(page); page[1].lru.prev = (void *)order; - for (i = 0; i < nr_pages; i++) { + for (i = 1; i < nr_pages; i++) { struct page *p = page + i; + __SetPageTail(p); __SetPageCompound(p); set_page_private(p, (unsigned long)page); } @@ -253,12 +255,16 @@ static void destroy_compound_page(struct if (unlikely((unsigned long)page[1].lru.prev != order)) bad_page(page); - for (i = 0; i < nr_pages; i++) { + if (unlikely(!PageCompound(page))) + bad_page(page); + __ClearPageCompound(p); + for (i = 1; i < nr_pages; i++) { struct page *p = page + i; - if (unlikely(!PageCompound(p) | + if (unlikely(!PageTail(p) | !PageCompound(p) | (page_private(p) != (unsigned long)page))) bad_page(page); + __ClearPageTail(p); __ClearPageCompound(p); } } @@ -854,6 +860,7 @@ void split_page(struct page *page, unsig int i; VM_BUG_ON(PageCompound(page)); + VM_BUG_ON(PageTail(page)); VM_BUG_ON(!page_count(page)); for (i = 1; i < (1 << order); i++) set_page_refcounted(page + i); Index: linux-2.6/mm/slab.c =================================================================== --- linux-2.6.orig/mm/slab.c 2007-03-26 13:58:27.000000000 -0700 +++ linux-2.6/mm/slab.c 2007-03-26 13:58:32.000000000 -0700 @@ -605,7 +605,7 @@ static inline void page_set_slab(struct static inline struct slab *page_get_slab(struct page *page) { - if (unlikely(PageCompound(page))) + if (unlikely(PageTail(page))) page = (struct page *)page_private(page); BUG_ON(!PageSlab(page)); return (struct slab *)page->lru.prev;