Index: linux-2.6/arch/parisc/kernel/cache.c =================================================================== --- linux-2.6.orig/arch/parisc/kernel/cache.c 2007-06-27 19:59:08.000000000 -0700 +++ linux-2.6/arch/parisc/kernel/cache.c 2007-06-27 19:59:31.000000000 -0700 @@ -339,7 +339,7 @@ void flush_dcache_page(struct page *page) { - struct address_space *mapping = page_mapping(page); + struct address_space *mapping = any_page_mapping(page); struct vm_area_struct *mpnt; struct prio_tree_iter iter; unsigned long offset; Index: linux-2.6/arch/sparc64/mm/init.c =================================================================== --- linux-2.6.orig/arch/sparc64/mm/init.c 2007-06-27 20:01:13.000000000 -0700 +++ linux-2.6/arch/sparc64/mm/init.c 2007-06-27 20:02:49.000000000 -0700 @@ -339,7 +339,7 @@ this_cpu = get_cpu(); - mapping = page_mapping(page); + mapping = any_page_mapping(page); if (mapping && !mapping_mapped(mapping)) { int dirty = test_bit(PG_dcache_dirty, &page->flags); if (dirty) { Index: linux-2.6/include/linux/mm.h =================================================================== --- linux-2.6.orig/include/linux/mm.h 2007-06-27 19:51:17.000000000 -0700 +++ linux-2.6/include/linux/mm.h 2007-06-27 20:22:54.000000000 -0700 @@ -590,6 +590,9 @@ * page->mapping points to its anon_vma, not to a struct address_space; * with the PAGE_MAPPING_ANON bit set to distinguish it. * + * Similarly on a slab page the mapping points to the kmem_cache structure. + * PageSlab is set in page flags to distinguish it. + * * Please note that, confusingly, "page_mapping" refers to the inode * address_space which maps the page from disk; whereas "page_mapped" * refers to user virtual address space into which the page is mapped. @@ -597,24 +600,40 @@ #define PAGE_MAPPING_ANON 1 extern struct address_space swapper_space; -static inline struct address_space *page_mapping(struct page *page) + +static inline int PageAnon(struct page *page) { - struct address_space *mapping = page->mapping; + return ((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0; +} +/* + * Determine the mapping of a regular page. + */ +static inline struct address_space *page_mapping(struct page *page) +{ if (unlikely(PageSwapCache(page))) - mapping = &swapper_space; -#ifdef CONFIG_SLUB - else if (unlikely(PageSlab(page))) - mapping = NULL; -#endif - else if (unlikely((unsigned long)mapping & PAGE_MAPPING_ANON)) - mapping = NULL; - return mapping; + return &swapper_space; + else if (unlikely(PageAnon(page))) + return NULL; + return page->mapping; } -static inline int PageAnon(struct page *page) +/* + * Determine the mapping of an arbitrary page including slab pages. + * + * There are cases in the kernel where we need to determine the mapping + * of a page regardless of what type of page it is. For example + * flush_dcache_page may be passed a page struct that was determined + * from a slab object sinc the scatter gather lists may occasionally + * be filled with objects allocated via the slab allocator (yuck). + */ +static inline struct address_space *any_page_mapping(struct page *page) { - return ((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0; +#ifdef CONFIG_SLUB + if (unlikely(PageSlab(page))) + return NULL; +#endif + return page_mapping(page); } /* Index: linux-2.6/arch/xtensa/mm/init.c =================================================================== --- linux-2.6.orig/arch/xtensa/mm/init.c 2007-06-27 20:03:39.000000000 -0700 +++ linux-2.6/arch/xtensa/mm/init.c 2007-06-27 20:03:52.000000000 -0700 @@ -433,7 +433,7 @@ void flush_dcache_page(struct page *page) { unsigned long addr = __pa(page_address(page)); - struct address_space *mapping = page_mapping(page); + struct address_space *mapping = any_page_mapping(page); __flush_invalidate_dcache_page_phys(addr); Index: linux-2.6/arch/arm/mm/flush.c =================================================================== --- linux-2.6.orig/arch/arm/mm/flush.c 2007-06-27 20:11:55.000000000 -0700 +++ linux-2.6/arch/arm/mm/flush.c 2007-06-27 20:12:00.000000000 -0700 @@ -188,7 +188,7 @@ */ void flush_dcache_page(struct page *page) { - struct address_space *mapping = page_mapping(page); + struct address_space *mapping = any_page_mapping(page); #ifndef CONFIG_SMP if (mapping && !mapping_mapped(mapping))