|
@@ -225,7 +225,7 @@ static void bad_page(struct page *page)
|
|
|
|
|
|
static void free_compound_page(struct page *page)
|
|
static void free_compound_page(struct page *page)
|
|
{
|
|
{
|
|
- __free_pages_ok(page, (unsigned long)page[1].lru.prev);
|
|
|
|
|
|
+ __free_pages_ok(page, compound_order(page));
|
|
}
|
|
}
|
|
|
|
|
|
static void prep_compound_page(struct page *page, unsigned long order)
|
|
static 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)
|
|
int nr_pages = 1 << order;
|
|
int nr_pages = 1 << order;
|
|
|
|
|
|
set_compound_page_dtor(page, free_compound_page);
|
|
set_compound_page_dtor(page, free_compound_page);
|
|
- page[1].lru.prev = (void *)order;
|
|
|
|
- for (i = 0; i < nr_pages; i++) {
|
|
|
|
|
|
+ set_compound_order(page, order);
|
|
|
|
+ __SetPageCompound(page);
|
|
|
|
+ for (i = 1; i < nr_pages; i++) {
|
|
struct page *p = page + i;
|
|
struct page *p = page + i;
|
|
|
|
|
|
|
|
+ __SetPageTail(p);
|
|
__SetPageCompound(p);
|
|
__SetPageCompound(p);
|
|
- set_page_private(p, (unsigned long)page);
|
|
|
|
|
|
+ p->first_page = page;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -248,15 +250,19 @@ static void destroy_compound_page(struct page *page, unsigned long order)
|
|
int i;
|
|
int i;
|
|
int nr_pages = 1 << order;
|
|
int nr_pages = 1 << order;
|
|
|
|
|
|
- if (unlikely((unsigned long)page[1].lru.prev != order))
|
|
|
|
|
|
+ if (unlikely(compound_order(page) != order))
|
|
bad_page(page);
|
|
bad_page(page);
|
|
|
|
|
|
- for (i = 0; i < nr_pages; i++) {
|
|
|
|
|
|
+ if (unlikely(!PageCompound(page)))
|
|
|
|
+ bad_page(page);
|
|
|
|
+ __ClearPageCompound(page);
|
|
|
|
+ for (i = 1; i < nr_pages; i++) {
|
|
struct page *p = page + i;
|
|
struct page *p = page + i;
|
|
|
|
|
|
- if (unlikely(!PageCompound(p) |
|
|
|
|
- (page_private(p) != (unsigned long)page)))
|
|
|
|
|
|
+ if (unlikely(!PageCompound(p) | !PageTail(p) |
|
|
|
|
+ (p->first_page != page)))
|
|
bad_page(page);
|
|
bad_page(page);
|
|
|
|
+ __ClearPageTail(p);
|
|
__ClearPageCompound(p);
|
|
__ClearPageCompound(p);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -429,13 +435,18 @@ static inline int free_pages_check(struct page *page)
|
|
1 << PG_private |
|
|
1 << PG_private |
|
|
1 << PG_locked |
|
|
1 << PG_locked |
|
|
1 << PG_active |
|
|
1 << PG_active |
|
|
- 1 << PG_reclaim |
|
|
|
|
1 << PG_slab |
|
|
1 << PG_slab |
|
|
1 << PG_swapcache |
|
|
1 << PG_swapcache |
|
|
1 << PG_writeback |
|
|
1 << PG_writeback |
|
|
1 << PG_reserved |
|
|
1 << PG_reserved |
|
|
1 << PG_buddy ))))
|
|
1 << PG_buddy ))))
|
|
bad_page(page);
|
|
bad_page(page);
|
|
|
|
+ /*
|
|
|
|
+ * PageReclaim == PageTail. It is only an error
|
|
|
|
+ * for PageReclaim to be set if PageCompound is clear.
|
|
|
|
+ */
|
|
|
|
+ if (unlikely(!PageCompound(page) && PageReclaim(page)))
|
|
|
|
+ bad_page(page);
|
|
if (PageDirty(page))
|
|
if (PageDirty(page))
|
|
__ClearPageDirty(page);
|
|
__ClearPageDirty(page);
|
|
/*
|
|
/*
|