aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
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 /*