[26/36] compound pages: Allow freeing of compound pages via pagevec

clameter
2007-08-28T19:21:06Z

[-- Attachment #1: 0026-compound-pages-Allow-freeing-of-compound-pages-via.patch --]
[-- Type: text/plain, Size: 2492 bytes --]

Allow the freeing of compound pages via pagevec.

In release_pages() we currently special case for compound pages in order to
be sure to always decrement the page count of the head page and not the
tail page. However that redirection to the head page is only necessary for
tail pages. So we can actually use PageTail instead of PageCompound there
by avoiding the redirection to the first page. Tail page handling is
not changed.

The head page of a compound pages now represents single page large page.
We do the usual processing including checking if its on the LRU
and removing it (not useful right now but later when compound pages are
on the LRU this will work). Then we add the compound page to the pagevec.
Only head pages will end up on the pagevec not tail pages.

In __pagevec_free() we then check if we are freeing a head page and if
so call the destructor for the compound page.

Signed-off-by: Christoph Lameter <clameter@sgi.com>
---
mm/page_alloc.c | 13 +++++++++++--
mm/swap.c | 8 +++++++-
2 files changed, 18 insertions(+), 3 deletions(-)

Index: linux-2.6/mm/page_alloc.c
===================================================================
--- linux-2.6.orig/mm/page_alloc.c 2007-08-27 20:59:38.000000000 -0700
+++ linux-2.6/mm/page_alloc.c 2007-08-27 21:05:34.000000000 -0700
@@ -1441,8 +1441,17 @@ void __pagevec_free(struct pagevec *pvec
{
int i = pagevec_count(pvec);

- while (--i >= 0)
- free_hot_cold_page(pvec->pages[i], pvec->cold);
+ while (--i >= 0) {
+ struct page *page = pvec->pages[i];
+
+ if (PageHead(page)) {
+ compound_page_dtor *dtor;
+
+ dtor = get_compound_page_dtor(page);
+ (*dtor)(page);
+ } else
+ free_hot_cold_page(page, pvec->cold);
+ }
}

fastcall void __free_pages(struct page *page, unsigned int order)
Index: linux-2.6/mm/swap.c
===================================================================
--- linux-2.6.orig/mm/swap.c 2007-08-27 19:22:13.000000000 -0700
+++ linux-2.6/mm/swap.c 2007-08-27 21:05:34.000000000 -0700
@@ -263,7 +263,13 @@ void release_pages(struct page **pages,
for (i = 0; i < nr; i++) {
struct page *page = pages[i];

- if (unlikely(PageCompound(page))) {
+ /*
+ * If we have a tail page on the LRU then we need to
+ * decrement the page count of the head page. There
+ * is no further need to do anything since tail pages
+ * cannot be on the LRU.
+ */
+ if (unlikely(PageTail(page))) {
if (zone) {
spin_unlock_irq(&zone->lru_lock);
zone = NULL;

--