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,
static void free_huge_page(struct page *page)
{
BUG_ON(page_count(page));
BUG_ON(page->mapping);
INIT_LIST_HEAD(&page->lru);
......
......@@ -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)
{
BUG_ON(page_count(page));
BUG_ON(page->mapping);
INIT_LIST_HEAD(&page->lru);
......
......@@ -450,7 +450,6 @@ follow_huge_pmd(struct mm_struct *mm, unsigned long address,
static void free_huge_page(struct page *page)
{
BUG_ON(page_count(page));
BUG_ON(page->mapping);
INIT_LIST_HEAD(&page->lru);
......
......@@ -248,7 +248,6 @@ struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address,
static void free_huge_page(struct page *page)
{
BUG_ON(page_count(page));
BUG_ON(page->mapping);
INIT_LIST_HEAD(&page->lru);
......
......@@ -242,24 +242,24 @@ extern void FASTCALL(__page_cache_release(struct page *));
static inline int page_count(struct page *p)
{
if (PageCompound(p))
p = (struct page *)p->lru.next;
p = (struct page *)p->private;
return atomic_read(&(p)->count);
}
static inline void get_page(struct page *page)
{
if (PageCompound(page))
page = (struct page *)page->lru.next;
page = (struct page *)page->private;
atomic_inc(&page->count);
}
static inline void put_page(struct page *page)
{
if (PageCompound(page)) {
page = (struct page *)page->lru.next;
page = (struct page *)page->private;
if (put_page_testzero(page)) {
if (page->lru.prev) { /* destructor? */
(*(void (*)(struct page *))page->lru.prev)(page);
if (page[1].mapping) { /* destructor? */
(*(void (*)(struct page *))page[1].mapping)(page);
} else {
__page_cache_release(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)
{
printk("Bad page state at %s (in process '%s', page %p)\n", function, current->comm, page);
printk("flags:0x%08lx mapping:%p mapped:%d count:%d\n",
printk(KERN_EMERG "Bad page state at %s (in process '%s', page %p)\n",
function, current->comm, page);
printk(KERN_EMERG "flags:0x%08lx mapping:%p mapped:%d count:%d\n",
(unsigned long)page->flags, page->mapping,
page_mapped(page), page_count(page));
printk("Backtrace:\n");
printk(KERN_EMERG "Backtrace:\n");
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 |
1 << PG_locked |
1 << PG_lru |
......@@ -99,13 +100,13 @@ static void bad_page(const char *function, struct page *page)
*
* 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's lru.prev, if non-zero, holds the address of the compound
* page's put_page() function.
* The first tail page's ->mapping, if non-zero, holds the address of the
* 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
* may not be compound.
*/
......@@ -114,13 +115,13 @@ static void prep_compound_page(struct page *page, unsigned long order)
int i;
int nr_pages = 1 << order;
page->lru.prev = NULL;
page[1].lru.prev = (void *)order;
page[1].mapping = 0;
page[1].index = order;
for (i = 0; i < nr_pages; i++) {
struct page *p = page + i;
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)
int i;
int nr_pages = 1 << order;
if (page[1].lru.prev != (void *)order)
if (page[1].index != order)
bad_page(__FUNCTION__, page);
for (i = 0; i < nr_pages; i++) {
......@@ -137,7 +138,7 @@ static void destroy_compound_page(struct page *page, unsigned long order)
if (!PageCompound(p))
bad_page(__FUNCTION__, page);
if (p->lru.next != (void *)page)
if (p->private != (unsigned long)page)
bad_page(__FUNCTION__, page);
ClearPageCompound(p);
}
......@@ -512,14 +513,14 @@ static struct page *buffered_rmqueue(struct zone *zone, int order, int cold)
spin_lock_irqsave(&zone->lock, flags);
page = __rmqueue(zone, order);
spin_unlock_irqrestore(&zone->lock, flags);
if (order && page)
prep_compound_page(page, order);
}
if (page != NULL) {
BUG_ON(bad_range(zone, page));
mod_page_state_zone(zone, pgalloc, 1 << order);
prep_new_page(page, order);
if (order)
prep_compound_page(page, order);
}
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