--- include/linux/page-flags.h | 283 +++++++++++++++++++-------------------------- mm/page_alloc.c | 2 2 files changed, 122 insertions(+), 163 deletions(-) Index: linux-2.6/include/linux/page-flags.h =================================================================== --- linux-2.6.orig/include/linux/page-flags.h 2008-02-17 21:29:17.000000000 -0800 +++ linux-2.6/include/linux/page-flags.h 2008-02-17 21:31:56.000000000 -0800 @@ -67,69 +67,119 @@ * FLAGS_RESERVED which defines the width of the fields section * (see linux/mmzone.h). New flags must _not_ overlap with this area. */ -#define PG_locked 0 /* Page is locked. Don't touch. */ -#define PG_error 1 -#define PG_referenced 2 -#define PG_uptodate 3 - -#define PG_dirty 4 -#define PG_lru 5 -#define PG_active 6 -#define PG_slab 7 /* slab debug (Suparna wants this) */ - -#define PG_owner_priv_1 8 /* Owner use. If pagecache, fs may use*/ -#define PG_arch_1 9 -#define PG_reserved 10 -#define PG_private 11 /* If pagecache, has fs-private data */ - -#define PG_writeback 12 /* Page is under writeback */ -#define PG_compound 14 /* Part of a compound page */ -#define PG_swapcache 15 /* Swap page: swp_entry_t in private */ - -#define PG_mappedtodisk 16 /* Has blocks allocated on-disk */ -#define PG_reclaim 17 /* To be reclaimed asap */ -#define PG_buddy 19 /* Page is free, on buddy lists */ +enum pageflags { + PG_locked, /* Page is locked. Don't touch. */ + PG_error, + PG_referenced, + PG_uptodate, + PG_dirty, + PG_lru, + PG_active, + PG_slab, + PG_owner_priv_1, /* Owner use. If pagecache, fs may use*/ + PG_arch_1, + PG_reserved, + PG_private, /* If pagecache, has fs-private data */ + PG_writeback, /* Page is under writeback */ + PG_compound, /* A compound page */ + PG_swapcache, /* Swap page: swp_entry_t in private */ + PG_mappedtodisk, /* Has blocks allocated on-disk */ + PG_reclaim, /* To be reclaimed asap */ + PG_buddy, /* Page is free, on buddy lists */ -/* PG_readahead is only used for file reads; PG_reclaim is only for writes */ -#define PG_readahead PG_reclaim /* Reminder to do async read-ahead */ +#ifdef CONFIG_IA64_UNCACHED_ALLOCATOR + PG_uncached, /* Page has been mapped as uncached */ +#endif + NR_PAGEFLAGS /* For verification purposes */ +}; -/* PG_owner_priv_1 users should have descriptive aliases */ -#define PG_checked PG_owner_priv_1 /* Used by some filesystems */ -#define PG_pinned PG_owner_priv_1 /* Xen pinned pagetable */ +struct page; /* forward declaration */ -#if (BITS_PER_LONG > 32) /* - * 64-bit-only flags build down from bit 31 - * - * 32 bit -------------------------------| FIELDS | FLAGS | - * 64 bit | FIELDS | ?????? FLAGS | - * 63 32 0 + * Manipulation of page state flags */ -#define PG_uncached 31 /* Page has been mapped as uncached */ -#endif + +#define TESTPAGEFLAG(uname, lname) \ +static inline int Page##uname(struct page *page) \ + { return test_bit(PG_##lname, page); } + +#define SETPAGEFLAG(uname, lname) \ +static inline void SetPage##uname(struct page *page) \ + { set_bit(PG_##lname, page); } + +#define CLEARPAGEFLAG(uname, lname) \ +static inline void ClearPage##uname(struct page *page) \ + { clear_bit(PG_##lname, page); } + +#define __SETPAGEFLAG(uname, lname) \ +static inline void __SetPage##uname(struct page *page) \ + { __set_bit(PG_##lname, page); } + +#define __CLEARPAGEFLAG(uname, lname) \ +static inline void __ClearPage##uname(struct page *page) \ + { __clear_bit(PG_##lname, page); } + +#define TESTSETFLAG(uname, lname) \ +static inline int TestSetPage##uname(struct page *page) \ + { return test_and_set_bit(PG_##lname, &page->flags); } + +#define TESTCLEARFLAG(uname, lname) \ +static inline int TestClearPage##uname(struct page *page) \ + { return test_and_clear_bit(PG_##lname, &page->flags); } + + +#define PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \ + SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname) + +#define __PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \ + __SETPAGEFLAG(uname, lname) __CLEARPAGEFLAG(uname, lname) + +#define TESTSCFLAG(uname, lname) \ + TESTSETFLAG(uname, lname) TESTCLEARFLAG(uname, lname) + +PAGEFLAG(Locked, locked) TESTSCFLAG(Locked, locked) +PAGEFLAG(Error, error) +PAGEFLAG(Referenced, referenced) TESTCLEARFLAG(Referenced, referenced) +PAGEFLAG(Dirty, dirty) TESTSCFLAG(Dirty, dirty) __CLEARPAGEFLAG(Dirty, dirty) +PAGEFLAG(LRU, lru) __CLEARPAGEFLAG(LRU, lru) +PAGEFLAG(Active, active) __CLEARPAGEFLAG(Active, active) +__PAGEFLAG(Slab, slab) +PAGEFLAG(Checked, owner_priv_1) /* Used by some filesystems */ +PAGEFLAG(Pinned, owner_priv_1) /* Xen pinned pagetable */ +PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved) +PAGEFLAG(Private, private) __CLEARPAGEFLAG(Private, private) + __SETPAGEFLAG(Private, private) /* - * Manipulation of page state flags + * Only test-and-set exist for PG_writeback. The unconditional operators are + * risky: they bypass page accounting. */ -#define PageLocked(page) \ - test_bit(PG_locked, &(page)->flags) -#define SetPageLocked(page) \ - set_bit(PG_locked, &(page)->flags) -#define TestSetPageLocked(page) \ - test_and_set_bit(PG_locked, &(page)->flags) -#define ClearPageLocked(page) \ - clear_bit(PG_locked, &(page)->flags) -#define TestClearPageLocked(page) \ - test_and_clear_bit(PG_locked, &(page)->flags) - -#define PageError(page) test_bit(PG_error, &(page)->flags) -#define SetPageError(page) set_bit(PG_error, &(page)->flags) -#define ClearPageError(page) clear_bit(PG_error, &(page)->flags) - -#define PageReferenced(page) test_bit(PG_referenced, &(page)->flags) -#define SetPageReferenced(page) set_bit(PG_referenced, &(page)->flags) -#define ClearPageReferenced(page) clear_bit(PG_referenced, &(page)->flags) -#define TestClearPageReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags) +TESTPAGEFLAG(Writeback, writeback) TESTSCFLAG(Writeback, writeback) +__PAGEFLAG(Buddy, buddy) +PAGEFLAG(MappedToDisk, mappedtodisk) + +/* PG_readahead is only used for file reads; PG_reclaim is only for writes */ +PAGEFLAG(Reclaim, reclaim) TESTCLEARFLAG(Reclaim, reclaim) +PAGEFLAG(Readahead, reclaim) /* Reminder to do async read-ahead */ + +#ifdef CONFIG_HIGHMEM +#define PageHighMem(page) is_highmem(page_zone(page)) +#else +#define PageHighMem(page) 0 /* needed to optimize away at compile time */ +#endif + +#ifdef CONFIG_SWAP +PAGEFLAG(SwapCache, swapcache) +#else +static inline int PageSwapCache(struct page *page) +{ + return 0; +} +#endif + +#ifdef CONFIG_IA64_UNCACHED_ALLOCATOR +PAGEFLAG(Uncached, uncached) +#endif static inline int PageUptodate(struct page *page) { @@ -177,97 +227,35 @@ static inline void SetPageUptodate(struc #endif } -#define ClearPageUptodate(page) clear_bit(PG_uptodate, &(page)->flags) +CLEARPAGEFLAG(Uptodate, uptodate) -#define PageDirty(page) test_bit(PG_dirty, &(page)->flags) -#define SetPageDirty(page) set_bit(PG_dirty, &(page)->flags) -#define TestSetPageDirty(page) test_and_set_bit(PG_dirty, &(page)->flags) -#define ClearPageDirty(page) clear_bit(PG_dirty, &(page)->flags) -#define __ClearPageDirty(page) __clear_bit(PG_dirty, &(page)->flags) -#define TestClearPageDirty(page) test_and_clear_bit(PG_dirty, &(page)->flags) - -#define PageLRU(page) test_bit(PG_lru, &(page)->flags) -#define SetPageLRU(page) set_bit(PG_lru, &(page)->flags) -#define ClearPageLRU(page) clear_bit(PG_lru, &(page)->flags) -#define __ClearPageLRU(page) __clear_bit(PG_lru, &(page)->flags) - -#define PageActive(page) test_bit(PG_active, &(page)->flags) -#define SetPageActive(page) set_bit(PG_active, &(page)->flags) -#define ClearPageActive(page) clear_bit(PG_active, &(page)->flags) -#define __ClearPageActive(page) __clear_bit(PG_active, &(page)->flags) - -#define PageSlab(page) test_bit(PG_slab, &(page)->flags) -#define __SetPageSlab(page) __set_bit(PG_slab, &(page)->flags) -#define __ClearPageSlab(page) __clear_bit(PG_slab, &(page)->flags) +extern void cancel_dirty_page(struct page *page, unsigned int account_size); -#ifdef CONFIG_HIGHMEM -#define PageHighMem(page) is_highmem(page_zone(page)) -#else -#define PageHighMem(page) 0 /* needed to optimize away at compile time */ -#endif +int test_clear_page_writeback(struct page *page); +int test_set_page_writeback(struct page *page); -#define PageChecked(page) test_bit(PG_checked, &(page)->flags) -#define SetPageChecked(page) set_bit(PG_checked, &(page)->flags) -#define ClearPageChecked(page) clear_bit(PG_checked, &(page)->flags) - -#define PagePinned(page) test_bit(PG_pinned, &(page)->flags) -#define SetPagePinned(page) set_bit(PG_pinned, &(page)->flags) -#define ClearPagePinned(page) clear_bit(PG_pinned, &(page)->flags) - -#define PageReserved(page) test_bit(PG_reserved, &(page)->flags) -#define SetPageReserved(page) set_bit(PG_reserved, &(page)->flags) -#define ClearPageReserved(page) clear_bit(PG_reserved, &(page)->flags) -#define __ClearPageReserved(page) __clear_bit(PG_reserved, &(page)->flags) - -#define SetPagePrivate(page) set_bit(PG_private, &(page)->flags) -#define ClearPagePrivate(page) clear_bit(PG_private, &(page)->flags) -#define PagePrivate(page) test_bit(PG_private, &(page)->flags) -#define __SetPagePrivate(page) __set_bit(PG_private, &(page)->flags) -#define __ClearPagePrivate(page) __clear_bit(PG_private, &(page)->flags) +static inline void set_page_writeback(struct page *page) +{ + test_set_page_writeback(page); +} -/* - * Only test-and-set exist for PG_writeback. The unconditional operators are - * risky: they bypass page accounting. - */ -#define PageWriteback(page) test_bit(PG_writeback, &(page)->flags) -#define TestSetPageWriteback(page) test_and_set_bit(PG_writeback, \ - &(page)->flags) -#define TestClearPageWriteback(page) test_and_clear_bit(PG_writeback, \ - &(page)->flags) - -#define PageBuddy(page) test_bit(PG_buddy, &(page)->flags) -#define __SetPageBuddy(page) __set_bit(PG_buddy, &(page)->flags) -#define __ClearPageBuddy(page) __clear_bit(PG_buddy, &(page)->flags) - -#define PageMappedToDisk(page) test_bit(PG_mappedtodisk, &(page)->flags) -#define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags) -#define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags) - -#define PageReadahead(page) test_bit(PG_readahead, &(page)->flags) -#define SetPageReadahead(page) set_bit(PG_readahead, &(page)->flags) -#define ClearPageReadahead(page) clear_bit(PG_readahead, &(page)->flags) - -#define PageReclaim(page) test_bit(PG_reclaim, &(page)->flags) -#define SetPageReclaim(page) set_bit(PG_reclaim, &(page)->flags) -#define ClearPageReclaim(page) clear_bit(PG_reclaim, &(page)->flags) -#define TestClearPageReclaim(page) test_and_clear_bit(PG_reclaim, &(page)->flags) - -#define PageCompound(page) test_bit(PG_compound, &(page)->flags) -#define __SetPageCompound(page) __set_bit(PG_compound, &(page)->flags) -#define __ClearPageCompound(page) __clear_bit(PG_compound, &(page)->flags) +TESTPAGEFLAG(Compound, compound) +__PAGEFLAG(Head, compound) /* * PG_reclaim is used in combination with PG_compound to mark the - * head and tail of a compound page + * head and tail of a compound page. This saved one page flag + * but makes it impossible to use compound pages for the page cache. * * PG_compound & PG_reclaim => Tail page * PG_compound & ~PG_reclaim => Head page */ - #define PG_head_tail_mask ((1L << PG_compound) | (1L << PG_reclaim)) -#define PageTail(page) ((page->flags & PG_head_tail_mask) \ - == PG_head_tail_mask) +static inline int PageTail(struct page *page) +{ + return ((page->flags & PG_head_tail_mask) == PG_head_tail_mask); +} static inline void __SetPageTail(struct page *page) { @@ -279,33 +267,4 @@ static inline void __ClearPageTail(struc page->flags &= ~PG_head_tail_mask; } -#define PageHead(page) ((page->flags & PG_head_tail_mask) \ - == (1L << PG_compound)) -#define __SetPageHead(page) __SetPageCompound(page) -#define __ClearPageHead(page) __ClearPageCompound(page) - -#ifdef CONFIG_SWAP -#define PageSwapCache(page) test_bit(PG_swapcache, &(page)->flags) -#define SetPageSwapCache(page) set_bit(PG_swapcache, &(page)->flags) -#define ClearPageSwapCache(page) clear_bit(PG_swapcache, &(page)->flags) -#else -#define PageSwapCache(page) 0 -#endif - -#define PageUncached(page) test_bit(PG_uncached, &(page)->flags) -#define SetPageUncached(page) set_bit(PG_uncached, &(page)->flags) -#define ClearPageUncached(page) clear_bit(PG_uncached, &(page)->flags) - -struct page; /* forward declaration */ - -extern void cancel_dirty_page(struct page *page, unsigned int account_size); - -int test_clear_page_writeback(struct page *page); -int test_set_page_writeback(struct page *page); - -static inline void set_page_writeback(struct page *page) -{ - test_set_page_writeback(page); -} - #endif /* PAGE_FLAGS_H */ Index: linux-2.6/mm/page_alloc.c =================================================================== --- linux-2.6.orig/mm/page_alloc.c 2008-02-17 21:29:17.000000000 -0800 +++ linux-2.6/mm/page_alloc.c 2008-02-17 21:29:20.000000000 -0800 @@ -623,7 +623,7 @@ static int prep_new_page(struct page *pa if (PageReserved(page)) return 1; - page->flags &= ~(1 << PG_uptodate | 1 << PG_error | 1 << PG_readahead | + page->flags &= ~(1 << PG_uptodate | 1 << PG_error | 1 << PG_reclaim | 1 << PG_referenced | 1 << PG_arch_1 | 1 << PG_owner_priv_1 | 1 << PG_mappedtodisk); set_page_private(page, 0);