Index: linux-2.6.20-git11/include/linux/page-flags.h =================================================================== --- linux-2.6.20-git11.orig/include/linux/page-flags.h 2007-02-15 11:24:03.000000000 -0800 +++ linux-2.6.20-git11/include/linux/page-flags.h 2007-02-16 01:00:01.000000000 -0800 @@ -8,51 +8,6 @@ #include /* - * Various page->flags bits: - * - * PG_reserved is set for special pages, which can never be swapped out. Some - * of them might not even exist (eg empty_bad_page)... - * - * The PG_private bitflag is set on pagecache pages if they contain filesystem - * specific data (which is normally at page->private). It can be used by - * private allocations for its own usage. - * - * During initiation of disk I/O, PG_locked is set. This bit is set before I/O - * and cleared when writeback _starts_ or when read _completes_. PG_writeback - * is set before writeback starts and cleared when it finishes. - * - * PG_locked also pins a page in pagecache, and blocks truncation of the file - * while it is held. - * - * page_waitqueue(page) is a wait queue of all tasks waiting for the page - * to become unlocked. - * - * PG_uptodate tells whether the page's contents is valid. When a read - * completes, the page becomes uptodate, unless a disk I/O error happened. - * - * PG_referenced, PG_reclaim are used for page reclaim for anonymous and - * file-backed pagecache (see mm/vmscan.c). - * - * PG_error is set to indicate that an I/O error occurred on this page. - * - * PG_arch_1 is an architecture specific page state bit. The generic code - * guarantees that this bit is cleared for a page when it first is entered into - * the page cache. - * - * PG_highmem pages are not permanently mapped into the kernel virtual address - * space, they need to be kmapped separately for doing IO on the pages. The - * struct page (these bits with information) are always mapped into kernel - * address space... - * - * PG_buddy is set to indicate that the page is free and in the buddy system - * (see mm/page_alloc.c). - * - */ - -/* - * Don't use the *_dontuse flags. Use the macros. Otherwise you'll break - * locked- and dirty-page accounting. - * * The page flags field is split into two parts, the main flags area * which extends from the low bits upwards, and the fields area which * extends from the high bits downwards. @@ -65,7 +20,55 @@ * section. The boundry between these two areas is defined by * FLAGS_RESERVED which defines the width of the fields section * (see linux/mmzone.h). New flags must _not_ overlap with this area. +* + * 64-bit-only flags build down from bit 31 + * + * 32 bit -------------------------------| FIELDS | FLAGS | + * 64 bit | FIELDS | ?????? FLAGS | + * 63 32 0 + * + * The description of the exact nature of the flags is given with the + * definition of the operations on the flag. */ +enum page_flag_items = { + /* Unstable */ + PG_locked, + PG_referenced, + PG_dirty, + PG_arch_1, + /* Modified under PageLock */ + PG_error, + PG_uptodate, + PG_private, + PG_writeback, + PG_mappedtodisk, + PG_checked, + /* Modified under zone->lru_lock */ + PG_lru, + PG_active, + PG_swapcache, + PG_reclaim, + PG_mlocked, + /* + * Modified after allocation and before freeing never + * in between + */ + PG_slab, + PG_compound, + PG_buddy, + /* Set up on boot */ + PG_reserved, + /* Who knows */ + PG_nosave, + PG_nosave_free + +#if (BITS_PER_LONG > 32) + PG_uncached = 31, +#endif + + NR_PAGE_FLAG_ITEMS +} + #define PG_locked 0 /* Page is locked. Don't touch. */ #define PG_error 1 #define PG_referenced 2 @@ -93,20 +96,36 @@ #define PG_mlocked 20 /* Page is mlocked */ -#if (BITS_PER_LONG > 32) /* - * 64-bit-only flags build down from bit 31 + * Various page->flags bits: * - * 32 bit -------------------------------| FIELDS | FLAGS | - * 64 bit | FIELDS | ?????? FLAGS | - * 63 32 0 +* */ -#define PG_uncached 31 /* Page has been mapped as uncached */ -#endif /* * Manipulation of page state flags */ + +/* + * Page locking + * + * Page locking is used to limit the operations on the page. If PageLocked + * is set then no additonal mappings may be established to the page. + * + * Page locking pins a page in pagecache, and blocks truncation of the file + * while it is held. + * + * page_waitqueue(page) is a wait queue of all tasks waiting for the page + * to become unlocked. On unlock processes on the waitqueue wake up. + * + * When stable: Never. PageLocked() can only be used for optimizations. + * + * PageLocked is handled like a spinlock. The state transitions must be used to + * detect successful locking and unlocking. + * + * SetPageLocked may only be used if we know for some other reasons that + * the page is not accessible from elsewhere (f.e. a newly allocated page). + */ #define PageLocked(page) \ test_bit(PG_locked, &(page)->flags) #define SetPageLocked(page) \ @@ -118,15 +137,41 @@ #define TestClearPageLocked(page) \ test_and_clear_bit(PG_locked, &(page)->flags) +/* + * PageError + * + * PageError is set to indicate that an I/O error occurred on this page. + * + * When stable: If PageLocked(page) + */ #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) +/* + * PageReferenced + * + * Indicates that a page was recently used for Page reclaim. See + * mm/vmscan.c + * + * When stable: Never. PageReferenced does not have to be accurate. + * The referenced state may be updated in a racy way. + */ #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) +/* + * PageUptodate + * + * PageUptodate indicates that the page's contents are valid. F.e. when a + * read completes, the page becomes uptodate, unless a disk I/O error happened. + * If PageUptodate is not set then the contents of the page are invalid + * and should not be accessed. + * + * When stable: If PageLocked(page) + */ #define PageUptodate(page) test_bit(PG_uptodate, &(page)->flags) #ifdef CONFIG_S390 static inline void SetPageUptodate(struct page *page) @@ -139,6 +184,16 @@ static inline void SetPageUptodate(struc #endif #define ClearPageUptodate(page) clear_bit(PG_uptodate, &(page)->flags) +/* + * PageDirty + * + * Indicates that the page has been modified and that the changes + * have not been written back. + * + * When stable: Never, the state transitions must be used to determine + * the state. It seems that sometimes the PageLock is used to + * attempt to stabilize it but that is not followed strictly. + */ #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) @@ -146,41 +201,82 @@ static inline void SetPageUptodate(struc #define __ClearPageDirty(page) __clear_bit(PG_dirty, &(page)->flags) #define TestClearPageDirty(page) test_and_clear_bit(PG_dirty, &(page)->flags) +/* + * PageLRU + * + * Indicates that a page is on the active or inactive list in a zone. + * + * When stable: If zone->lru_lock is held. + */ #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) +/* + * PageActive + * + * Indicates that a page is on the active list. + * + * When stable: If zone->lru_lock is held. + */ #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) +/* + * PageSlab + * + * Indicates that a page is used for storing slab data. + * + * When stable: Always. PageSlab is set on allocation and cleared + * when the page is freed. + */ #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) -#ifdef CONFIG_HIGHMEM -#define PageHighMem(page) is_highmem(page_zone(page)) -#else -#define PageHighMem(page) 0 /* needed to optimize away at compile time */ -#endif - +/* + * PageChecked + * + * Usable for filesystems to mark pages (?) + */ #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) +/* + * PageReserved + * + * Marks pages that are not to be touched by the VM code. These + * are typically ZERO_PAGEs, other special pages (empty_bad_page) and + * memory areas that were determined to be unusable on bootup. + * + * When stable: Always. PageReserved is set during bootup. + */ #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) +/* + * PagePrivate + * + * PagePrivate is set on pagecache pages if they contain filesystem + * specific data (which is normally at page->private). It can be used by + * private allocations for other purposes. + * + * When stable: If PageLocked(page) + */ #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) + + #define PageWriteback(page) test_bit(PG_writeback, &(page)->flags) #define SetPageWriteback(page) \ do { \ @@ -223,6 +319,14 @@ static inline void SetPageUptodate(struc #define SetPageNosaveFree(page) set_bit(PG_nosave_free, &(page)->flags) #define ClearPageNosaveFree(page) clear_bit(PG_nosave_free, &(page)->flags) +/* + * PageBuddy + * + * PageBuddy is set to indicate that the page is free and in the buddy system + * (see mm/page_alloc.c). + * + * When stable: If zone->lru_lock taken + */ #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) @@ -274,4 +378,18 @@ static inline void set_page_writeback(st test_set_page_writeback(page); } +/* + * PG_highmem pages are not permanently mapped into the kernel virtual address + * space, they need to be kmapped separately for doing IO on the pages. The + * struct page (these bits with information) are always mapped into kernel + * address space... + */ + +#ifdef CONFIG_HIGHMEM +#define PageHighMem(page) is_highmem(page_zone(page)) +#else +#define PageHighMem(page) 0 /* needed to optimize away at compile time */ +#endif + + #endif /* PAGE_FLAGS_H */