Commit 0fcb51fd authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] stop using page->lru in compound pages

The compound page logic is using page->lru, and these get will scribbled on
in various places so switch the Compound page logic over to using ->mapping
and ->private.
parent bd64f049
...@@ -278,7 +278,6 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address, ...@@ -278,7 +278,6 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
static void free_huge_page(struct page *page) static void free_huge_page(struct page *page)
{ {
BUG_ON(page_count(page)); BUG_ON(page_count(page));
BUG_ON(page->mapping);
INIT_LIST_HEAD(&page->lru); INIT_LIST_HEAD(&page->lru);
......
...@@ -246,7 +246,6 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int wri ...@@ -246,7 +246,6 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int wri
void free_huge_page(struct page *page) void free_huge_page(struct page *page)
{ {
BUG_ON(page_count(page)); BUG_ON(page_count(page));
BUG_ON(page->mapping);
INIT_LIST_HEAD(&page->lru); INIT_LIST_HEAD(&page->lru);
......
...@@ -450,7 +450,6 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address, ...@@ -450,7 +450,6 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
static void free_huge_page(struct page *page) static void free_huge_page(struct page *page)
{ {
BUG_ON(page_count(page)); BUG_ON(page_count(page));
BUG_ON(page->mapping);
INIT_LIST_HEAD(&page->lru); INIT_LIST_HEAD(&page->lru);
......
...@@ -248,7 +248,6 @@ struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, ...@@ -248,7 +248,6 @@ struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
static void free_huge_page(struct page *page) static void free_huge_page(struct page *page)
{ {
BUG_ON(page_count(page)); BUG_ON(page_count(page));
BUG_ON(page->mapping);
INIT_LIST_HEAD(&page->lru); INIT_LIST_HEAD(&page->lru);
......
...@@ -242,24 +242,24 @@ extern void FASTCALL(__page_cache_release(struct page *)); ...@@ -242,24 +242,24 @@ extern void FASTCALL(__page_cache_release(struct page *));
static inline int page_count(struct page *p) static inline int page_count(struct page *p)
{ {
if (PageCompound(p)) if (PageCompound(p))
p = (struct page *)p->lru.next; p = (struct page *)p->private;
return atomic_read(&(p)->count); return atomic_read(&(p)->count);
} }
static inline void get_page(struct page *page) static inline void get_page(struct page *page)
{ {
if (PageCompound(page)) if (PageCompound(page))
page = (struct page *)page->lru.next; page = (struct page *)page->private;
atomic_inc(&page->count); atomic_inc(&page->count);
} }
static inline void put_page(struct page *page) static inline void put_page(struct page *page)
{ {
if (PageCompound(page)) { if (PageCompound(page)) {
page = (struct page *)page->lru.next; page = (struct page *)page->private;
if (put_page_testzero(page)) { if (put_page_testzero(page)) {
if (page->lru.prev) { /* destructor? */ if (page[1].mapping) { /* destructor? */
(*(void (*)(struct page *))page->lru.prev)(page); (*(void (*)(struct page *))page[1].mapping)(page);
} else { } else {
__page_cache_release(page); __page_cache_release(page);
} }
......
...@@ -71,13 +71,14 @@ static int bad_range(struct zone *zone, struct page *page) ...@@ -71,13 +71,14 @@ static int bad_range(struct zone *zone, struct page *page)
static void bad_page(const char *function, struct page *page) static void bad_page(const char *function, struct page *page)
{ {
printk("Bad page state at %s (in process '%s', page %p)\n", function, current->comm, page); printk(KERN_EMERG "Bad page state at %s (in process '%s', page %p)\n",
printk("flags:0x%08lx mapping:%p mapped:%d count:%d\n", function, current->comm, page);
printk(KERN_EMERG "flags:0x%08lx mapping:%p mapped:%d count:%d\n",
(unsigned long)page->flags, page->mapping, (unsigned long)page->flags, page->mapping,
page_mapped(page), page_count(page)); page_mapped(page), page_count(page));
printk("Backtrace:\n"); printk(KERN_EMERG "Backtrace:\n");
dump_stack(); dump_stack();
printk("Trying to fix it up, but a reboot is needed\n"); printk(KERN_EMERG "Trying to fix it up, but a reboot is needed\n");
page->flags &= ~(1 << PG_private | page->flags &= ~(1 << PG_private |
1 << PG_locked | 1 << PG_locked |
1 << PG_lru | 1 << PG_lru |
...@@ -99,13 +100,13 @@ static void bad_page(const char *function, struct page *page) ...@@ -99,13 +100,13 @@ static void bad_page(const char *function, struct page *page)
* *
* The remaining PAGE_SIZE pages are called "tail pages". * The remaining PAGE_SIZE pages are called "tail pages".
* *
* All pages have PG_compound set. All pages have their lru.next pointing at * All pages have PG_compound set. All pages have their ->private pointing at
* the head page (even the head page has this). * the head page (even the head page has this).
* *
* The head page's lru.prev, if non-zero, holds the address of the compound * The first tail page's ->mapping, if non-zero, holds the address of the
* page's put_page() function. * compound page's put_page() function.
* *
* The order of the allocation is stored in the first tail page's lru.prev. * The order of the allocation is stored in the first tail page's ->index
* This is only for debug at present. This usage means that zero-order pages * This is only for debug at present. This usage means that zero-order pages
* may not be compound. * may not be compound.
*/ */
...@@ -114,13 +115,13 @@ static void prep_compound_page(struct page *page, unsigned long order) ...@@ -114,13 +115,13 @@ static void prep_compound_page(struct page *page, unsigned long order)
int i; int i;
int nr_pages = 1 << order; int nr_pages = 1 << order;
page->lru.prev = NULL; page[1].mapping = 0;
page[1].lru.prev = (void *)order; page[1].index = order;
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
struct page *p = page + i; struct page *p = page + i;
SetPageCompound(p); SetPageCompound(p);
p->lru.next = (void *)page; p->private = (unsigned long)page;
} }
} }
...@@ -129,7 +130,7 @@ static void destroy_compound_page(struct page *page, unsigned long order) ...@@ -129,7 +130,7 @@ 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 (page[1].lru.prev != (void *)order) if (page[1].index != order)
bad_page(__FUNCTION__, page); bad_page(__FUNCTION__, page);
for (i = 0; i < nr_pages; i++) { for (i = 0; i < nr_pages; i++) {
...@@ -137,7 +138,7 @@ static void destroy_compound_page(struct page *page, unsigned long order) ...@@ -137,7 +138,7 @@ static void destroy_compound_page(struct page *page, unsigned long order)
if (!PageCompound(p)) if (!PageCompound(p))
bad_page(__FUNCTION__, page); bad_page(__FUNCTION__, page);
if (p->lru.next != (void *)page) if (p->private != (unsigned long)page)
bad_page(__FUNCTION__, page); bad_page(__FUNCTION__, page);
ClearPageCompound(p); ClearPageCompound(p);
} }
...@@ -512,14 +513,14 @@ static struct page *buffered_rmqueue(struct zone *zone, int order, int cold) ...@@ -512,14 +513,14 @@ static struct page *buffered_rmqueue(struct zone *zone, int order, int cold)
spin_lock_irqsave(&zone->lock, flags); spin_lock_irqsave(&zone->lock, flags);
page = __rmqueue(zone, order); page = __rmqueue(zone, order);
spin_unlock_irqrestore(&zone->lock, flags); spin_unlock_irqrestore(&zone->lock, flags);
if (order && page)
prep_compound_page(page, order);
} }
if (page != NULL) { if (page != NULL) {
BUG_ON(bad_range(zone, page)); BUG_ON(bad_range(zone, page));
mod_page_state_zone(zone, pgalloc, 1 << order); mod_page_state_zone(zone, pgalloc, 1 << order);
prep_new_page(page, order); prep_new_page(page, order);
if (order)
prep_compound_page(page, order);
} }
return page; return page;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment