diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/page_alloc.c | 44 |
1 files changed, 20 insertions, 24 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e12154d9c4ed..b9fd2c238f13 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -132,16 +132,16 @@ static inline int bad_range(struct zone *zone, struct page *page) | |||
132 | } | 132 | } |
133 | #endif | 133 | #endif |
134 | 134 | ||
135 | static void bad_page(const char *function, struct page *page) | 135 | static void bad_page(struct page *page) |
136 | { | 136 | { |
137 | printk(KERN_EMERG "Bad page state at %s (in process '%s', page %p)\n", | 137 | printk(KERN_EMERG "Bad page state in process '%s'\n" |
138 | function, current->comm, page); | 138 | "page:%p flags:0x%0*lx mapping:%p mapcount:%d count:%d\n" |
139 | printk(KERN_EMERG "flags:0x%0*lx mapping:%p mapcount:%d count:%d\n", | 139 | "Trying to fix it up, but a reboot is needed\n" |
140 | (int)(2*sizeof(unsigned long)), (unsigned long)page->flags, | 140 | "Backtrace:\n", |
141 | page->mapping, page_mapcount(page), page_count(page)); | 141 | current->comm, page, (int)(2*sizeof(unsigned long)), |
142 | printk(KERN_EMERG "Backtrace:\n"); | 142 | (unsigned long)page->flags, page->mapping, |
143 | page_mapcount(page), page_count(page)); | ||
143 | dump_stack(); | 144 | dump_stack(); |
144 | printk(KERN_EMERG "Trying to fix it up, but a reboot is needed\n"); | ||
145 | page->flags &= ~(1 << PG_lru | | 145 | page->flags &= ~(1 << PG_lru | |
146 | 1 << PG_private | | 146 | 1 << PG_private | |
147 | 1 << PG_locked | | 147 | 1 << PG_locked | |
@@ -194,19 +194,15 @@ static void destroy_compound_page(struct page *page, unsigned long order) | |||
194 | int i; | 194 | int i; |
195 | int nr_pages = 1 << order; | 195 | int nr_pages = 1 << order; |
196 | 196 | ||
197 | if (!PageCompound(page)) | 197 | if (unlikely(page[1].index != order)) |
198 | return; | 198 | bad_page(page); |
199 | |||
200 | if (page[1].index != order) | ||
201 | bad_page(__FUNCTION__, page); | ||
202 | 199 | ||
203 | for (i = 0; i < nr_pages; i++) { | 200 | for (i = 0; i < nr_pages; i++) { |
204 | struct page *p = page + i; | 201 | struct page *p = page + i; |
205 | 202 | ||
206 | if (!PageCompound(p)) | 203 | if (unlikely(!PageCompound(p) | |
207 | bad_page(__FUNCTION__, page); | 204 | (page_private(p) != (unsigned long)page))) |
208 | if (page_private(p) != (unsigned long)page) | 205 | bad_page(page); |
209 | bad_page(__FUNCTION__, page); | ||
210 | ClearPageCompound(p); | 206 | ClearPageCompound(p); |
211 | } | 207 | } |
212 | } | 208 | } |
@@ -316,7 +312,7 @@ static inline void __free_pages_bulk (struct page *page, | |||
316 | unsigned long page_idx; | 312 | unsigned long page_idx; |
317 | int order_size = 1 << order; | 313 | int order_size = 1 << order; |
318 | 314 | ||
319 | if (unlikely(order)) | 315 | if (unlikely(PageCompound(page))) |
320 | destroy_compound_page(page, order); | 316 | destroy_compound_page(page, order); |
321 | 317 | ||
322 | page_idx = page_to_pfn(page) & ((1 << MAX_ORDER) - 1); | 318 | page_idx = page_to_pfn(page) & ((1 << MAX_ORDER) - 1); |
@@ -348,7 +344,7 @@ static inline void __free_pages_bulk (struct page *page, | |||
348 | zone->free_area[order].nr_free++; | 344 | zone->free_area[order].nr_free++; |
349 | } | 345 | } |
350 | 346 | ||
351 | static inline int free_pages_check(const char *function, struct page *page) | 347 | static inline int free_pages_check(struct page *page) |
352 | { | 348 | { |
353 | if (unlikely(page_mapcount(page) | | 349 | if (unlikely(page_mapcount(page) | |
354 | (page->mapping != NULL) | | 350 | (page->mapping != NULL) | |
@@ -363,7 +359,7 @@ static inline int free_pages_check(const char *function, struct page *page) | |||
363 | 1 << PG_swapcache | | 359 | 1 << PG_swapcache | |
364 | 1 << PG_writeback | | 360 | 1 << PG_writeback | |
365 | 1 << PG_reserved )))) | 361 | 1 << PG_reserved )))) |
366 | bad_page(function, page); | 362 | bad_page(page); |
367 | if (PageDirty(page)) | 363 | if (PageDirty(page)) |
368 | __ClearPageDirty(page); | 364 | __ClearPageDirty(page); |
369 | /* | 365 | /* |
@@ -422,7 +418,7 @@ void __free_pages_ok(struct page *page, unsigned int order) | |||
422 | #endif | 418 | #endif |
423 | 419 | ||
424 | for (i = 0 ; i < (1 << order) ; ++i) | 420 | for (i = 0 ; i < (1 << order) ; ++i) |
425 | reserved += free_pages_check(__FUNCTION__, page + i); | 421 | reserved += free_pages_check(page + i); |
426 | if (reserved) | 422 | if (reserved) |
427 | return; | 423 | return; |
428 | 424 | ||
@@ -517,7 +513,7 @@ static int prep_new_page(struct page *page, int order) | |||
517 | 1 << PG_swapcache | | 513 | 1 << PG_swapcache | |
518 | 1 << PG_writeback | | 514 | 1 << PG_writeback | |
519 | 1 << PG_reserved )))) | 515 | 1 << PG_reserved )))) |
520 | bad_page(__FUNCTION__, page); | 516 | bad_page(page); |
521 | 517 | ||
522 | /* | 518 | /* |
523 | * For now, we report if PG_reserved was found set, but do not | 519 | * For now, we report if PG_reserved was found set, but do not |
@@ -716,7 +712,7 @@ static void fastcall free_hot_cold_page(struct page *page, int cold) | |||
716 | 712 | ||
717 | if (PageAnon(page)) | 713 | if (PageAnon(page)) |
718 | page->mapping = NULL; | 714 | page->mapping = NULL; |
719 | if (free_pages_check(__FUNCTION__, page)) | 715 | if (free_pages_check(page)) |
720 | return; | 716 | return; |
721 | 717 | ||
722 | inc_page_state(pgfree); | 718 | inc_page_state(pgfree); |