Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
422 | giacomo | 1 | /* |
2 | * Macros for manipulating and testing page->flags |
||
3 | */ |
||
4 | |||
5 | #ifndef PAGE_FLAGS_H |
||
6 | #define PAGE_FLAGS_H |
||
7 | |||
8 | #include <linux/percpu.h> |
||
9 | #include <linux/cache.h> |
||
10 | #include <asm/pgtable.h> |
||
11 | |||
12 | /* |
||
13 | * Various page->flags bits: |
||
14 | * |
||
15 | * PG_reserved is set for special pages, which can never be swapped out. Some |
||
16 | * of them might not even exist (eg empty_bad_page)... |
||
17 | * |
||
18 | * The PG_private bitflag is set if page->private contains a valid value. |
||
19 | * |
||
20 | * During disk I/O, PG_locked is used. This bit is set before I/O and |
||
21 | * reset when I/O completes. page_waitqueue(page) is a wait queue of all tasks |
||
22 | * waiting for the I/O on this page to complete. |
||
23 | * |
||
24 | * PG_uptodate tells whether the page's contents is valid. When a read |
||
25 | * completes, the page becomes uptodate, unless a disk I/O error happened. |
||
26 | * |
||
27 | * For choosing which pages to swap out, inode pages carry a PG_referenced bit, |
||
28 | * which is set any time the system accesses that page through the (mapping, |
||
29 | * index) hash table. This referenced bit, together with the referenced bit |
||
30 | * in the page tables, is used to manipulate page->age and move the page across |
||
31 | * the active, inactive_dirty and inactive_clean lists. |
||
32 | * |
||
33 | * Note that the referenced bit, the page->lru list_head and the active, |
||
34 | * inactive_dirty and inactive_clean lists are protected by the |
||
35 | * zone->lru_lock, and *NOT* by the usual PG_locked bit! |
||
36 | * |
||
37 | * PG_error is set to indicate that an I/O error occurred on this page. |
||
38 | * |
||
39 | * PG_arch_1 is an architecture specific page state bit. The generic code |
||
40 | * guarantees that this bit is cleared for a page when it first is entered into |
||
41 | * the page cache. |
||
42 | * |
||
43 | * PG_highmem pages are not permanently mapped into the kernel virtual address |
||
44 | * space, they need to be kmapped separately for doing IO on the pages. The |
||
45 | * struct page (these bits with information) are always mapped into kernel |
||
46 | * address space... |
||
47 | */ |
||
48 | |||
49 | /* |
||
50 | * Don't use the *_dontuse flags. Use the macros. Otherwise you'll break |
||
51 | * locked- and dirty-page accounting. The top eight bits of page->flags are |
||
52 | * used for page->zone, so putting flag bits there doesn't work. |
||
53 | */ |
||
54 | #define PG_locked 0 /* Page is locked. Don't touch. */ |
||
55 | #define PG_error 1 |
||
56 | #define PG_referenced 2 |
||
57 | #define PG_uptodate 3 |
||
58 | |||
59 | #define PG_dirty 4 |
||
60 | #define PG_lru 5 |
||
61 | #define PG_active 6 |
||
62 | #define PG_slab 7 /* slab debug (Suparna wants this) */ |
||
63 | |||
64 | #define PG_highmem 8 |
||
65 | #define PG_checked 9 /* kill me in 2.5.<early>. */ |
||
66 | #define PG_arch_1 10 |
||
67 | #define PG_reserved 11 |
||
68 | |||
69 | #define PG_private 12 /* Has something at ->private */ |
||
70 | #define PG_writeback 13 /* Page is under writeback */ |
||
71 | #define PG_nosave 14 /* Used for system suspend/resume */ |
||
72 | #define PG_chainlock 15 /* lock bit for ->pte_chain */ |
||
73 | |||
74 | #define PG_direct 16 /* ->pte_chain points directly at pte */ |
||
75 | #define PG_mappedtodisk 17 /* Has blocks allocated on-disk */ |
||
76 | #define PG_reclaim 18 /* To be reclaimed asap */ |
||
77 | #define PG_compound 19 /* Part of a compound page */ |
||
78 | |||
79 | |||
80 | /* |
||
81 | * Global page accounting. One instance per CPU. Only unsigned longs are |
||
82 | * allowed. |
||
83 | */ |
||
84 | struct page_state { |
||
85 | unsigned long nr_dirty; /* Dirty writeable pages */ |
||
86 | unsigned long nr_writeback; /* Pages under writeback */ |
||
87 | unsigned long nr_unstable; /* NFS unstable pages */ |
||
88 | unsigned long nr_page_table_pages;/* Pages used for pagetables */ |
||
89 | unsigned long nr_mapped; /* mapped into pagetables */ |
||
90 | unsigned long nr_slab; /* In slab */ |
||
91 | #define GET_PAGE_STATE_LAST nr_slab |
||
92 | |||
93 | /* |
||
94 | * The below are zeroed by get_page_state(). Use get_full_page_state() |
||
95 | * to add up all these. |
||
96 | */ |
||
97 | unsigned long pgpgin; /* Disk reads */ |
||
98 | unsigned long pgpgout; /* Disk writes */ |
||
99 | unsigned long pswpin; /* swap reads */ |
||
100 | unsigned long pswpout; /* swap writes */ |
||
101 | unsigned long pgalloc; /* page allocations */ |
||
102 | |||
103 | unsigned long pgfree; /* page freeings */ |
||
104 | unsigned long pgactivate; /* pages moved inactive->active */ |
||
105 | unsigned long pgdeactivate; /* pages moved active->inactive */ |
||
106 | unsigned long pgfault; /* faults (major+minor) */ |
||
107 | unsigned long pgmajfault; /* faults (major only) */ |
||
108 | |||
109 | unsigned long pgscan; /* pages scanned by page reclaim */ |
||
110 | unsigned long pgrefill; /* inspected in refill_inactive_zone */ |
||
111 | unsigned long pgsteal; /* total pages reclaimed */ |
||
112 | unsigned long pginodesteal; /* pages reclaimed via inode freeing */ |
||
113 | unsigned long kswapd_steal; /* pages reclaimed by kswapd */ |
||
114 | |||
115 | unsigned long kswapd_inodesteal;/* reclaimed via kswapd inode freeing */ |
||
116 | unsigned long pageoutrun; /* kswapd's calls to page reclaim */ |
||
117 | unsigned long allocstall; /* direct reclaim calls */ |
||
118 | unsigned long pgrotated; /* pages rotated to tail of the LRU */ |
||
119 | } ____cacheline_aligned; |
||
120 | |||
121 | DECLARE_PER_CPU(struct page_state, page_states); |
||
122 | |||
123 | extern void get_page_state(struct page_state *ret); |
||
124 | extern void get_full_page_state(struct page_state *ret); |
||
125 | |||
126 | #define mod_page_state(member, delta) \ |
||
127 | do { \ |
||
128 | unsigned long flags; \ |
||
129 | local_irq_save(flags); \ |
||
130 | __get_cpu_var(page_states).member += (delta); \ |
||
131 | local_irq_restore(flags); \ |
||
132 | } while (0) |
||
133 | |||
134 | #define inc_page_state(member) mod_page_state(member, 1UL) |
||
135 | #define dec_page_state(member) mod_page_state(member, 0UL - 1) |
||
136 | #define sub_page_state(member,delta) mod_page_state(member, 0UL - (delta)) |
||
137 | |||
138 | |||
139 | /* |
||
140 | * Manipulation of page state flags |
||
141 | */ |
||
142 | #define PageLocked(page) \ |
||
143 | test_bit(PG_locked, &(page)->flags) |
||
144 | #define SetPageLocked(page) \ |
||
145 | set_bit(PG_locked, &(page)->flags) |
||
146 | #define TestSetPageLocked(page) \ |
||
147 | test_and_set_bit(PG_locked, &(page)->flags) |
||
148 | #define ClearPageLocked(page) \ |
||
149 | clear_bit(PG_locked, &(page)->flags) |
||
150 | #define TestClearPageLocked(page) \ |
||
151 | test_and_clear_bit(PG_locked, &(page)->flags) |
||
152 | |||
153 | #define PageError(page) test_bit(PG_error, &(page)->flags) |
||
154 | #define SetPageError(page) set_bit(PG_error, &(page)->flags) |
||
155 | #define ClearPageError(page) clear_bit(PG_error, &(page)->flags) |
||
156 | |||
157 | #define PageReferenced(page) test_bit(PG_referenced, &(page)->flags) |
||
158 | #define SetPageReferenced(page) set_bit(PG_referenced, &(page)->flags) |
||
159 | #define ClearPageReferenced(page) clear_bit(PG_referenced, &(page)->flags) |
||
160 | #define TestClearPageReferenced(page) test_and_clear_bit(PG_referenced, &(page)->flags) |
||
161 | |||
162 | #ifndef arch_set_page_uptodate |
||
163 | #define arch_set_page_uptodate(page) do { } while (0) |
||
164 | #endif |
||
165 | |||
166 | #define PageUptodate(page) test_bit(PG_uptodate, &(page)->flags) |
||
167 | #define SetPageUptodate(page) \ |
||
168 | do { \ |
||
169 | arch_set_page_uptodate(page); \ |
||
170 | set_bit(PG_uptodate, &(page)->flags); \ |
||
171 | } while (0) |
||
172 | #define ClearPageUptodate(page) clear_bit(PG_uptodate, &(page)->flags) |
||
173 | |||
174 | #define PageDirty(page) test_bit(PG_dirty, &(page)->flags) |
||
175 | #define SetPageDirty(page) set_bit(PG_dirty, &(page)->flags) |
||
176 | #define TestSetPageDirty(page) test_and_set_bit(PG_dirty, &(page)->flags) |
||
177 | #define ClearPageDirty(page) clear_bit(PG_dirty, &(page)->flags) |
||
178 | #define TestClearPageDirty(page) test_and_clear_bit(PG_dirty, &(page)->flags) |
||
179 | |||
180 | #define SetPageLRU(page) set_bit(PG_lru, &(page)->flags) |
||
181 | #define PageLRU(page) test_bit(PG_lru, &(page)->flags) |
||
182 | #define TestSetPageLRU(page) test_and_set_bit(PG_lru, &(page)->flags) |
||
183 | #define TestClearPageLRU(page) test_and_clear_bit(PG_lru, &(page)->flags) |
||
184 | |||
185 | #define PageActive(page) test_bit(PG_active, &(page)->flags) |
||
186 | #define SetPageActive(page) set_bit(PG_active, &(page)->flags) |
||
187 | #define ClearPageActive(page) clear_bit(PG_active, &(page)->flags) |
||
188 | #define TestClearPageActive(page) test_and_clear_bit(PG_active, &(page)->flags) |
||
189 | #define TestSetPageActive(page) test_and_set_bit(PG_active, &(page)->flags) |
||
190 | |||
191 | #define PageSlab(page) test_bit(PG_slab, &(page)->flags) |
||
192 | #define SetPageSlab(page) set_bit(PG_slab, &(page)->flags) |
||
193 | #define ClearPageSlab(page) clear_bit(PG_slab, &(page)->flags) |
||
194 | #define TestClearPageSlab(page) test_and_clear_bit(PG_slab, &(page)->flags) |
||
195 | #define TestSetPageSlab(page) test_and_set_bit(PG_slab, &(page)->flags) |
||
196 | |||
197 | #ifdef CONFIG_HIGHMEM |
||
198 | #define PageHighMem(page) test_bit(PG_highmem, &(page)->flags) |
||
199 | #else |
||
200 | #define PageHighMem(page) 0 /* needed to optimize away at compile time */ |
||
201 | #endif |
||
202 | |||
203 | #define PageChecked(page) test_bit(PG_checked, &(page)->flags) |
||
204 | #define SetPageChecked(page) set_bit(PG_checked, &(page)->flags) |
||
205 | #define ClearPageChecked(page) clear_bit(PG_checked, &(page)->flags) |
||
206 | |||
207 | #define PageReserved(page) test_bit(PG_reserved, &(page)->flags) |
||
208 | #define SetPageReserved(page) set_bit(PG_reserved, &(page)->flags) |
||
209 | #define ClearPageReserved(page) clear_bit(PG_reserved, &(page)->flags) |
||
210 | |||
211 | #define SetPagePrivate(page) set_bit(PG_private, &(page)->flags) |
||
212 | #define ClearPagePrivate(page) clear_bit(PG_private, &(page)->flags) |
||
213 | #define PagePrivate(page) test_bit(PG_private, &(page)->flags) |
||
214 | |||
215 | #define PageWriteback(page) test_bit(PG_writeback, &(page)->flags) |
||
216 | #define SetPageWriteback(page) \ |
||
217 | do { \ |
||
218 | if (!test_and_set_bit(PG_writeback, \ |
||
219 | &(page)->flags)) \ |
||
220 | inc_page_state(nr_writeback); \ |
||
221 | } while (0) |
||
222 | #define TestSetPageWriteback(page) \ |
||
223 | ({ \ |
||
224 | int ret; \ |
||
225 | ret = test_and_set_bit(PG_writeback, \ |
||
226 | &(page)->flags); \ |
||
227 | if (!ret) \ |
||
228 | inc_page_state(nr_writeback); \ |
||
229 | ret; \ |
||
230 | }) |
||
231 | #define ClearPageWriteback(page) \ |
||
232 | do { \ |
||
233 | if (test_and_clear_bit(PG_writeback, \ |
||
234 | &(page)->flags)) \ |
||
235 | dec_page_state(nr_writeback); \ |
||
236 | } while (0) |
||
237 | #define TestClearPageWriteback(page) \ |
||
238 | ({ \ |
||
239 | int ret; \ |
||
240 | ret = test_and_clear_bit(PG_writeback, \ |
||
241 | &(page)->flags); \ |
||
242 | if (ret) \ |
||
243 | dec_page_state(nr_writeback); \ |
||
244 | ret; \ |
||
245 | }) |
||
246 | |||
247 | #define PageNosave(page) test_bit(PG_nosave, &(page)->flags) |
||
248 | #define SetPageNosave(page) set_bit(PG_nosave, &(page)->flags) |
||
249 | #define TestSetPageNosave(page) test_and_set_bit(PG_nosave, &(page)->flags) |
||
250 | #define ClearPageNosave(page) clear_bit(PG_nosave, &(page)->flags) |
||
251 | #define TestClearPageNosave(page) test_and_clear_bit(PG_nosave, &(page)->flags) |
||
252 | |||
253 | #define PageDirect(page) test_bit(PG_direct, &(page)->flags) |
||
254 | #define SetPageDirect(page) set_bit(PG_direct, &(page)->flags) |
||
255 | #define TestSetPageDirect(page) test_and_set_bit(PG_direct, &(page)->flags) |
||
256 | #define ClearPageDirect(page) clear_bit(PG_direct, &(page)->flags) |
||
257 | #define TestClearPageDirect(page) test_and_clear_bit(PG_direct, &(page)->flags) |
||
258 | |||
259 | #define PageMappedToDisk(page) test_bit(PG_mappedtodisk, &(page)->flags) |
||
260 | #define SetPageMappedToDisk(page) set_bit(PG_mappedtodisk, &(page)->flags) |
||
261 | #define ClearPageMappedToDisk(page) clear_bit(PG_mappedtodisk, &(page)->flags) |
||
262 | |||
263 | #define PageReclaim(page) test_bit(PG_reclaim, &(page)->flags) |
||
264 | #define SetPageReclaim(page) set_bit(PG_reclaim, &(page)->flags) |
||
265 | #define ClearPageReclaim(page) clear_bit(PG_reclaim, &(page)->flags) |
||
266 | #define TestClearPageReclaim(page) test_and_clear_bit(PG_reclaim, &(page)->flags) |
||
267 | |||
268 | #define PageCompound(page) test_bit(PG_compound, &(page)->flags) |
||
269 | #define SetPageCompound(page) set_bit(PG_compound, &(page)->flags) |
||
270 | #define ClearPageCompound(page) clear_bit(PG_compound, &(page)->flags) |
||
271 | |||
272 | /* |
||
273 | * The PageSwapCache predicate doesn't use a PG_flag at this time, |
||
274 | * but it may again do so one day. |
||
275 | */ |
||
276 | #ifdef CONFIG_SWAP |
||
277 | extern struct address_space swapper_space; |
||
278 | #define PageSwapCache(page) ((page)->mapping == &swapper_space) |
||
279 | #else |
||
280 | #define PageSwapCache(page) 0 |
||
281 | #endif |
||
282 | |||
283 | struct page; /* forward declaration */ |
||
284 | |||
285 | int test_clear_page_dirty(struct page *page); |
||
286 | |||
287 | static inline void clear_page_dirty(struct page *page) |
||
288 | { |
||
289 | test_clear_page_dirty(page); |
||
290 | } |
||
291 | |||
292 | #endif /* PAGE_FLAGS_H */ |