Index: linux-2.6/include/linux/mm_types.h =================================================================== --- linux-2.6.orig/include/linux/mm_types.h +++ linux-2.6/include/linux/mm_types.h @@ -23,27 +23,20 @@ struct page { * to show when page is mapped * & limit reverse map searches. */ - union { - struct { - unsigned long private; /* Mapping-private opaque data: - * usually used for buffer_heads - * if PagePrivate set; used for - * swp_entry_t if PageSwapCache; - * indicates order in the buddy - * system if PG_buddy is set. - */ - struct address_space *mapping; /* If low bit clear, points to - * inode address_space, or NULL. - * If page mapped as anonymous - * memory, low bit is set, and - * it points to anon_vma object: - * see PAGE_MAPPING_ANON below. - */ - }; -#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS - spinlock_t ptl; -#endif - }; + unsigned long private; /* Mapping-private opaque data: + * usually used for buffer_heads + * if PagePrivate set; used for + * swp_entry_t if PageSwapCache; + * indicates order in the buddy + * system if PG_buddy is set. + */ + struct address_space *mapping; /* If low bit clear, points to + * inode address_space, or NULL. + * If page mapped as anonymous + * memory, low bit is set, and + * it points to anon_vma object: + * see PAGE_MAPPING_ANON below. + */ pgoff_t index; /* Our offset within mapping. */ struct list_head lru; /* Pageout list, eg. active_list * protected by zone->lru_lock ! @@ -64,4 +57,45 @@ struct page { #endif /* WANT_PAGE_VIRTUAL */ }; +/* + * We can provide alternate delcarations for 'struct page', instead of + * overloading fields that we would like to use for non-pagecache (eg. + * page tables or slab pages). However flags and _count must always be + * in the correct position, and not overloaded, because they might be + * accessed by thing without a direct reference (eg. buddy allocator, + * swsusp). So flags and _count get defined for us, and our struct is + * automatically padded out to the size of struct page. A compile time + * check ensures that this size isn't exceeded. + */ +#define DEFINE_PAGE_STRUCT(name) \ +struct name { \ + union { \ + struct { \ + unsigned long flags; \ + atomic_t _count; \ + struct + +#define END_PAGE_STRUCT(name) \ + ; \ + }; \ + struct page ___page; \ + }; \ +}; \ + \ +static inline void struct_##name##_build_bug_on(void) \ +{ \ + BUILD_BUG_ON(sizeof(struct name) > sizeof(struct page)); \ +} + +DEFINE_PAGE_STRUCT(pt_page) { +#if NR_CPUS >= CONFIG_SPLIT_PTLOCK_CPUS + spinlock_t ptl; +#endif +} END_PAGE_STRUCT(pt_page) + +DEFINE_PAGE_STRUCT(buddy_page) { + unsigned int order; + struct list_head list; +} END_PAGE_STRUCT(buddy_page) + #endif /* _LINUX_MM_TYPES_H */ Index: linux-2.6/mm/slab.c =================================================================== --- linux-2.6.orig/mm/slab.c +++ linux-2.6/mm/slab.c @@ -446,6 +446,11 @@ struct kmem_cache { #endif }; +DEFINE_PAGE_STRUCT(slab_page) { + struct list_head *cache; + struct list_head *slab; +} END_PAGE_STRUCT(slab_page) + #define CFLGS_OFF_SLAB (0x80000000UL) #define OFF_SLAB(x) ((x)->flags & CFLGS_OFF_SLAB)