aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorChristoph Lameter <clameter@sgi.com>2007-05-06 17:49:39 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-07 15:12:53 -0400
commitd85f33855c303acfa87fa457157cef755b6087df (patch)
treef1184a1a24b432727b0399594ede37c7539db888 /mm/page_alloc.c
parent30520864839dc796fd314812e7036e754880b47d (diff)
Make page->private usable in compound pages
If we add a new flag so that we can distinguish between the first page and the tail pages then we can avoid to use page->private in the first page. page->private == page for the first page, so there is no real information in there. Freeing up page->private makes the use of compound pages more transparent. They become more usable like real pages. Right now we have to be careful f.e. if we are going beyond PAGE_SIZE allocations in the slab on i386 because we can then no longer use the private field. This is one of the issues that cause us not to support debugging for page size slabs in SLAB. Having page->private available for SLUB would allow more meta information in the page struct. I can probably avoid the 16 bit ints that I have in there right now. Also if page->private is available then a compound page may be equipped with buffer heads. This may free up the way for filesystems to support larger blocks than page size. We add PageTail as an alias of PageReclaim. Compound pages cannot currently be reclaimed. Because of the alias one needs to check PageCompound first. The RFC for the this approach was discussed at http://marc.info/?t=117574302800001&r=1&w=2 [nacc@us.ibm.com: fix hugetlbfs] Signed-off-by: Christoph Lameter <clameter@sgi.com> Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 542fc088ff50..fc241fe295ab 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -225,7 +225,7 @@ static void bad_page(struct page *page)
225 225
226static void free_compound_page(struct page *page) 226static void free_compound_page(struct page *page)
227{ 227{
228 __free_pages_ok(page, (unsigned long)page[1].lru.prev); 228 __free_pages_ok(page, compound_order(page));
229} 229}
230 230
231static void prep_compound_page(struct page *page, unsigned long order) 231static void prep_compound_page(struct page *page, unsigned long order)
@@ -234,12 +234,14 @@ static void prep_compound_page(struct page *page, unsigned long order)
234 int nr_pages = 1 << order; 234 int nr_pages = 1 << order;
235 235
236 set_compound_page_dtor(page, free_compound_page); 236 set_compound_page_dtor(page, free_compound_page);
237 page[1].lru.prev = (void *)order; 237 set_compound_order(page, order);
238 for (i = 0; i < nr_pages; i++) { 238 __SetPageCompound(page);
239 for (i = 1; i < nr_pages; i++) {
239 struct page *p = page + i; 240 struct page *p = page + i;
240 241
242 __SetPageTail(p);
241 __SetPageCompound(p); 243 __SetPageCompound(p);
242 set_page_private(p, (unsigned long)page); 244 p->first_page = page;
243 } 245 }
244} 246}
245 247
@@ -248,15 +250,19 @@ static void destroy_compound_page(struct page *page, unsigned long order)
248 int i; 250 int i;
249 int nr_pages = 1 << order; 251 int nr_pages = 1 << order;
250 252
251 if (unlikely((unsigned long)page[1].lru.prev != order)) 253 if (unlikely(compound_order(page) != order))
252 bad_page(page); 254 bad_page(page);
253 255
254 for (i = 0; i < nr_pages; i++) { 256 if (unlikely(!PageCompound(page)))
257 bad_page(page);
258 __ClearPageCompound(page);
259 for (i = 1; i < nr_pages; i++) {
255 struct page *p = page + i; 260 struct page *p = page + i;
256 261
257 if (unlikely(!PageCompound(p) | 262 if (unlikely(!PageCompound(p) | !PageTail(p) |
258 (page_private(p) != (unsigned long)page))) 263 (p->first_page != page)))
259 bad_page(page); 264 bad_page(page);
265 __ClearPageTail(p);
260 __ClearPageCompound(p); 266 __ClearPageCompound(p);
261 } 267 }
262} 268}
@@ -429,13 +435,18 @@ static inline int free_pages_check(struct page *page)
429 1 << PG_private | 435 1 << PG_private |
430 1 << PG_locked | 436 1 << PG_locked |
431 1 << PG_active | 437 1 << PG_active |
432 1 << PG_reclaim |
433 1 << PG_slab | 438 1 << PG_slab |
434 1 << PG_swapcache | 439 1 << PG_swapcache |
435 1 << PG_writeback | 440 1 << PG_writeback |
436 1 << PG_reserved | 441 1 << PG_reserved |
437 1 << PG_buddy )))) 442 1 << PG_buddy ))))
438 bad_page(page); 443 bad_page(page);
444 /*
445 * PageReclaim == PageTail. It is only an error
446 * for PageReclaim to be set if PageCompound is clear.
447 */
448 if (unlikely(!PageCompound(page) && PageReclaim(page)))
449 bad_page(page);
439 if (PageDirty(page)) 450 if (PageDirty(page))
440 __ClearPageDirty(page); 451 __ClearPageDirty(page);
441 /* 452 /*