Index: linux-2.6.21-rc1/include/linux/mm.h =================================================================== --- linux-2.6.21-rc1.orig/include/linux/mm.h 2007-02-21 04:55:27.000000000 -0800 +++ linux-2.6.21-rc1/include/linux/mm.h 2007-02-21 05:13:22.000000000 -0800 @@ -263,20 +263,20 @@ static inline int put_page_testzero(stru */ static inline int get_page_unless_zero(struct page *page) { - VM_BUG_ON(PageCompound(page)); + VM_BUG_ON(PageCompound(page) || PageTail(page)); return atomic_inc_not_zero(&page->_count); } 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.21-rc1/include/linux/page-flags.h =================================================================== --- linux-2.6.21-rc1.orig/include/linux/page-flags.h 2007-02-21 04:48:04.000000000 -0800 +++ linux-2.6.21-rc1/include/linux/page-flags.h 2007-02-21 05:02:02.000000000 -0800 @@ -91,6 +91,7 @@ #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 of a compound page */ #if (BITS_PER_LONG > 32) /* @@ -239,6 +240,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.21-rc1/mm/internal.h =================================================================== --- linux-2.6.21-rc1.orig/mm/internal.h 2007-02-21 04:56:10.000000000 -0800 +++ linux-2.6.21-rc1/mm/internal.h 2007-02-21 05:13:41.000000000 -0800 @@ -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(PageCompound(page) || PageTail(page)); VM_BUG_ON(atomic_read(&page->_count)); set_page_count(page, 1); } Index: linux-2.6.21-rc1/mm/page_alloc.c =================================================================== --- linux-2.6.21-rc1.orig/mm/page_alloc.c 2007-02-21 04:49:26.000000000 -0800 +++ linux-2.6.21-rc1/mm/page_alloc.c 2007-02-21 05:14:41.000000000 -0800 @@ -237,10 +237,11 @@ static void prep_compound_page(struct pa set_compound_page_dtor(page, free_compound_page); page[1].lru.prev = (void *)order; - for (i = 0; i < nr_pages; i++) { + __SetPageCompound(page); + for (i = 1; i < nr_pages; i++) { struct page *p = page + i; - __SetPageCompound(p); + __SetPageTail(p); set_page_private(p, (unsigned long)page); } } @@ -253,13 +254,14 @@ 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++) { + __ClearPageCompound(page); + for (i = 1; i < nr_pages; i++) { struct page *p = page + i; - if (unlikely(!PageCompound(p) | + if (unlikely(!PageTail(p) | (page_private(p) != (unsigned long)page))) bad_page(page); - __ClearPageCompound(p); + __ClearPageTail(p); } } @@ -397,6 +399,7 @@ static inline void __free_one_page(struc page_idx = page_to_pfn(page) & ((1 << MAX_ORDER) - 1); VM_BUG_ON(page_idx & (order_size - 1)); + VM_BUG_ON(PageTail(page)); VM_BUG_ON(bad_range(zone, page)); __mod_zone_page_state(zone, NR_FREE_PAGES, order_size); @@ -853,7 +856,7 @@ void split_page(struct page *page, unsig { int i; - VM_BUG_ON(PageCompound(page)); + VM_BUG_ON(PageCompound(page) || PageTail(page)); VM_BUG_ON(!page_count(page)); for (i = 1; i < (1 << order); i++) set_page_refcounted(page + i); Index: linux-2.6.21-rc1/mm/slab.c =================================================================== --- linux-2.6.21-rc1.orig/mm/slab.c 2007-02-21 04:51:56.000000000 -0800 +++ linux-2.6.21-rc1/mm/slab.c 2007-02-21 04:52:47.000000000 -0800 @@ -592,7 +592,7 @@ static inline void page_set_cache(struct static inline struct kmem_cache *page_get_cache(struct page *page) { - if (unlikely(PageCompound(page))) + if (unlikely(PageTail(page))) page = (struct page *)page_private(page); BUG_ON(!PageSlab(page)); return (struct kmem_cache *)page->lru.next; @@ -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;