page-flags.h 14.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9
/*
 * Macros for manipulating and testing page->flags
 */

#ifndef PAGE_FLAGS_H
#define PAGE_FLAGS_H

#include <linux/percpu.h>
#include <linux/cache.h>
A
Andrew Morton 已提交
10 11
#include <linux/types.h>

L
Linus Torvalds 已提交
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#include <asm/pgtable.h>

/*
 * 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 if page->private contains a valid value.
 *
 * During disk I/O, PG_locked is used. This bit is set before I/O and
 * reset when I/O completes. page_waitqueue(page) is a wait queue of all tasks
 * waiting for the I/O on this page to complete.
 *
 * 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.
 *
 * For choosing which pages to swap out, inode pages carry a PG_referenced bit,
 * which is set any time the system accesses that page through the (mapping,
 * index) hash table.  This referenced bit, together with the referenced bit
 * in the page tables, is used to manipulate page->age and move the page across
 * the active, inactive_dirty and inactive_clean lists.
 *
 * Note that the referenced bit, the page->lru list_head and the active,
 * inactive_dirty and inactive_clean lists are protected by the
 * zone->lru_lock, and *NOT* by the usual PG_locked bit!
 *
 * 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...
 */

/*
 * Don't use the *_dontuse flags.  Use the macros.  Otherwise you'll break
53 54 55 56 57 58 59 60 61 62 63 64 65 66
 * 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.
 *
 *  | FIELD | ... | FLAGS |
 *  N-1     ^             0
 *          (N-FLAGS_RESERVED)
 *
 * The fields area is reserved for fields mapping zone, node and SPARSEMEM
 * 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.
L
Linus Torvalds 已提交
67 68 69 70 71 72 73 74 75 76 77
 */
#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) */

B
Badari Pulavarty 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90
#define PG_checked		 8	/* kill me in 2.5.<early>. */
#define PG_arch_1		 9
#define PG_reserved		10
#define PG_private		11	/* Has something at ->private */

#define PG_writeback		12	/* Page is under writeback */
#define PG_nosave		13	/* Used for system suspend/resume */
#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_nosave_free		18	/* Free, should not be written */
91 92
#define PG_buddy		19	/* Page is free, on buddy lists */

A
Andrew Morton 已提交
93 94 95 96 97 98 99 100 101 102 103

#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
 */
#define PG_uncached		31	/* Page has been mapped as uncached */
#endif
L
Linus Torvalds 已提交
104 105 106 107

/*
 * Global page accounting.  One instance per CPU.  Only unsigned longs are
 * allowed.
N
Nick Piggin 已提交
108 109 110 111 112 113 114
 *
 * - Fields can be modified with xxx_page_state and xxx_page_state_zone at
 * any time safely (which protects the instance from modification by
 * interrupt.
 * - The __xxx_page_state variants can be used safely when interrupts are
 * disabled.
 * - The __xxx_page_state variants can be used if the field is only
115 116 117
 * modified from process context and protected from preemption, or only
 * modified from interrupt context.  In this case, the field should be
 * commented here.
L
Linus Torvalds 已提交
118 119 120 121 122 123
 */
struct page_state {
	unsigned long nr_dirty;		/* Dirty writeable pages */
	unsigned long nr_writeback;	/* Pages under writeback */
	unsigned long nr_unstable;	/* NFS unstable pages */
	unsigned long nr_page_table_pages;/* Pages used for pagetables */
N
Nick Piggin 已提交
124 125
	unsigned long nr_mapped;	/* mapped into pagetables.
					 * only modified from process context */
L
Linus Torvalds 已提交
126 127 128 129 130 131 132 133 134 135 136 137
	unsigned long nr_slab;		/* In slab */
#define GET_PAGE_STATE_LAST nr_slab

	/*
	 * The below are zeroed by get_page_state().  Use get_full_page_state()
	 * to add up all these.
	 */
	unsigned long pgpgin;		/* Disk reads */
	unsigned long pgpgout;		/* Disk writes */
	unsigned long pswpin;		/* swap reads */
	unsigned long pswpout;		/* swap writes */

N
Nick Piggin 已提交
138
	unsigned long pgalloc_high;	/* page allocations */
L
Linus Torvalds 已提交
139
	unsigned long pgalloc_normal;
N
Nick Piggin 已提交
140
	unsigned long pgalloc_dma32;
L
Linus Torvalds 已提交
141
	unsigned long pgalloc_dma;
N
Nick Piggin 已提交
142

L
Linus Torvalds 已提交
143 144 145 146 147 148
	unsigned long pgfree;		/* page freeings */
	unsigned long pgactivate;	/* pages moved inactive->active */
	unsigned long pgdeactivate;	/* pages moved active->inactive */

	unsigned long pgfault;		/* faults (major+minor) */
	unsigned long pgmajfault;	/* faults (major only) */
N
Nick Piggin 已提交
149

L
Linus Torvalds 已提交
150 151
	unsigned long pgrefill_high;	/* inspected in refill_inactive_zone */
	unsigned long pgrefill_normal;
N
Nick Piggin 已提交
152
	unsigned long pgrefill_dma32;
L
Linus Torvalds 已提交
153 154 155 156
	unsigned long pgrefill_dma;

	unsigned long pgsteal_high;	/* total highmem pages reclaimed */
	unsigned long pgsteal_normal;
N
Nick Piggin 已提交
157
	unsigned long pgsteal_dma32;
L
Linus Torvalds 已提交
158
	unsigned long pgsteal_dma;
N
Nick Piggin 已提交
159

L
Linus Torvalds 已提交
160 161
	unsigned long pgscan_kswapd_high;/* total highmem pages scanned */
	unsigned long pgscan_kswapd_normal;
N
Nick Piggin 已提交
162
	unsigned long pgscan_kswapd_dma32;
L
Linus Torvalds 已提交
163
	unsigned long pgscan_kswapd_dma;
N
Nick Piggin 已提交
164

L
Linus Torvalds 已提交
165 166
	unsigned long pgscan_direct_high;/* total highmem pages scanned */
	unsigned long pgscan_direct_normal;
N
Nick Piggin 已提交
167
	unsigned long pgscan_direct_dma32;
L
Linus Torvalds 已提交
168 169
	unsigned long pgscan_direct_dma;

N
Nick Piggin 已提交
170
	unsigned long pginodesteal;	/* pages reclaimed via inode freeing */
L
Linus Torvalds 已提交
171 172 173 174 175 176 177
	unsigned long slabs_scanned;	/* slab objects scanned */
	unsigned long kswapd_steal;	/* pages reclaimed by kswapd */
	unsigned long kswapd_inodesteal;/* reclaimed via kswapd inode freeing */
	unsigned long pageoutrun;	/* kswapd's calls to page reclaim */
	unsigned long allocstall;	/* direct reclaim calls */

	unsigned long pgrotated;	/* pages rotated to tail of the LRU */
178
	unsigned long nr_bounce;	/* pages for bounce buffers */
L
Linus Torvalds 已提交
179 180 181
};

extern void get_page_state(struct page_state *ret);
182
extern void get_page_state_node(struct page_state *ret, int node);
L
Linus Torvalds 已提交
183
extern void get_full_page_state(struct page_state *ret);
N
Nick Piggin 已提交
184 185 186
extern unsigned long read_page_state_offset(unsigned long offset);
extern void mod_page_state_offset(unsigned long offset, unsigned long delta);
extern void __mod_page_state_offset(unsigned long offset, unsigned long delta);
L
Linus Torvalds 已提交
187 188

#define read_page_state(member) \
N
Nick Piggin 已提交
189
	read_page_state_offset(offsetof(struct page_state, member))
L
Linus Torvalds 已提交
190 191

#define mod_page_state(member, delta)	\
N
Nick Piggin 已提交
192
	mod_page_state_offset(offsetof(struct page_state, member), (delta))
L
Linus Torvalds 已提交
193

N
Nick Piggin 已提交
194 195
#define __mod_page_state(member, delta)	\
	__mod_page_state_offset(offsetof(struct page_state, member), (delta))
L
Linus Torvalds 已提交
196

N
Nick Piggin 已提交
197 198 199 200 201 202 203 204 205 206 207 208 209 210
#define inc_page_state(member)		mod_page_state(member, 1UL)
#define dec_page_state(member)		mod_page_state(member, 0UL - 1)
#define add_page_state(member,delta)	mod_page_state(member, (delta))
#define sub_page_state(member,delta)	mod_page_state(member, 0UL - (delta))

#define __inc_page_state(member)	__mod_page_state(member, 1UL)
#define __dec_page_state(member)	__mod_page_state(member, 0UL - 1)
#define __add_page_state(member,delta)	__mod_page_state(member, (delta))
#define __sub_page_state(member,delta)	__mod_page_state(member, 0UL - (delta))

#define page_state(member) (*__page_state(offsetof(struct page_state, member)))

#define state_zone_offset(zone, member)					\
({									\
N
Nick Piggin 已提交
211 212 213 214 215 216 217 218 219
	unsigned offset;						\
	if (is_highmem(zone))						\
		offset = offsetof(struct page_state, member##_high);	\
	else if (is_normal(zone))					\
		offset = offsetof(struct page_state, member##_normal);	\
	else if (is_dma32(zone))					\
		offset = offsetof(struct page_state, member##_dma32);	\
	else								\
		offset = offsetof(struct page_state, member##_dma);	\
N
Nick Piggin 已提交
220 221 222 223 224 225 226 227 228 229 230
	offset;								\
})

#define __mod_page_state_zone(zone, member, delta)			\
 do {									\
	__mod_page_state_offset(state_zone_offset(zone, member), (delta)); \
 } while (0)

#define mod_page_state_zone(zone, member, delta)			\
 do {									\
	mod_page_state_offset(state_zone_offset(zone, member), (delta)); \
N
Nick Piggin 已提交
231
 } while (0)
L
Linus Torvalds 已提交
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265

/*
 * Manipulation of page state flags
 */
#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)

#define PageUptodate(page)	test_bit(PG_uptodate, &(page)->flags)
#ifndef SetPageUptodate
#define SetPageUptodate(page)	set_bit(PG_uptodate, &(page)->flags)
#endif
#define ClearPageUptodate(page)	clear_bit(PG_uptodate, &(page)->flags)

#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)
N
Nick Piggin 已提交
266
#define __ClearPageDirty(page)	__clear_bit(PG_dirty, &(page)->flags)
L
Linus Torvalds 已提交
267 268 269
#define TestClearPageDirty(page) test_and_clear_bit(PG_dirty, &(page)->flags)

#define PageLRU(page)		test_bit(PG_lru, &(page)->flags)
N
Nick Piggin 已提交
270 271
#define SetPageLRU(page)	set_bit(PG_lru, &(page)->flags)
#define ClearPageLRU(page)	clear_bit(PG_lru, &(page)->flags)
N
Nick Piggin 已提交
272
#define __ClearPageLRU(page)	__clear_bit(PG_lru, &(page)->flags)
L
Linus Torvalds 已提交
273 274 275 276

#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)
N
Nick Piggin 已提交
277
#define __ClearPageActive(page)	__clear_bit(PG_active, &(page)->flags)
L
Linus Torvalds 已提交
278 279

#define PageSlab(page)		test_bit(PG_slab, &(page)->flags)
N
Nick Piggin 已提交
280 281
#define __SetPageSlab(page)	__set_bit(PG_slab, &(page)->flags)
#define __ClearPageSlab(page)	__clear_bit(PG_slab, &(page)->flags)
L
Linus Torvalds 已提交
282 283

#ifdef CONFIG_HIGHMEM
B
Badari Pulavarty 已提交
284
#define PageHighMem(page)	is_highmem(page_zone(page))
L
Linus Torvalds 已提交
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
#else
#define PageHighMem(page)	0 /* needed to optimize away at compile time */
#endif

#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 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)

#define PageWriteback(page)	test_bit(PG_writeback, &(page)->flags)
#define SetPageWriteback(page)						\
	do {								\
		if (!test_and_set_bit(PG_writeback,			\
				&(page)->flags))			\
			inc_page_state(nr_writeback);			\
	} while (0)
#define TestSetPageWriteback(page)					\
	({								\
		int ret;						\
		ret = test_and_set_bit(PG_writeback,			\
					&(page)->flags);		\
		if (!ret)						\
			inc_page_state(nr_writeback);			\
		ret;							\
	})
#define ClearPageWriteback(page)					\
	do {								\
		if (test_and_clear_bit(PG_writeback,			\
				&(page)->flags))			\
			dec_page_state(nr_writeback);			\
	} while (0)
#define TestClearPageWriteback(page)					\
	({								\
		int ret;						\
		ret = test_and_clear_bit(PG_writeback,			\
				&(page)->flags);			\
		if (ret)						\
			dec_page_state(nr_writeback);			\
		ret;							\
	})

#define PageNosave(page)	test_bit(PG_nosave, &(page)->flags)
#define SetPageNosave(page)	set_bit(PG_nosave, &(page)->flags)
#define TestSetPageNosave(page)	test_and_set_bit(PG_nosave, &(page)->flags)
#define ClearPageNosave(page)		clear_bit(PG_nosave, &(page)->flags)
#define TestClearPageNosave(page)	test_and_clear_bit(PG_nosave, &(page)->flags)

#define PageNosaveFree(page)	test_bit(PG_nosave_free, &(page)->flags)
#define SetPageNosaveFree(page)	set_bit(PG_nosave_free, &(page)->flags)
#define ClearPageNosaveFree(page)		clear_bit(PG_nosave_free, &(page)->flags)

346 347 348 349
#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)

L
Linus Torvalds 已提交
350 351 352 353 354 355 356 357 358 359
#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 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)
360 361
#define __SetPageCompound(page)	__set_bit(PG_compound, &(page)->flags)
#define __ClearPageCompound(page) __clear_bit(PG_compound, &(page)->flags)
L
Linus Torvalds 已提交
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391

#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 */

int test_clear_page_dirty(struct page *page);
int test_clear_page_writeback(struct page *page);
int test_set_page_writeback(struct page *page);

static inline void clear_page_dirty(struct page *page)
{
	test_clear_page_dirty(page);
}

static inline void set_page_writeback(struct page *page)
{
	test_set_page_writeback(page);
}

#endif	/* PAGE_FLAGS_H */