From 5677d7ec2710e762a24f6b60cd173f2e26f2a62c Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 3 Oct 2007 20:42:43 -0700 Subject: [PATCH] vcompound: page_address() support Make page_address() correctly determine the address of a potentially virtually mapped compound page. There are 3 cases to consider: 1. !HASHED_PAGE_VIRTUAL && !WANT_PAGE_VIRTUAL Call vmalloc_address() directly from the page_address function defined in mm.h. 2. HASHED_PAGE_VIRTUAL Modify page_address() in highmem.c to call vmalloc_address(). 3. WANT_PAGE_VIRTUAL set_page_address() is used to set up the virtual addresses of all pages that are part of the virtual compound. Cc: apw@shadowen.org Signed-off-by: Christoph Lameter --- include/linux/mm.h | 9 ++++++++- mm/highmem.c | 10 ++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) Index: linux-2.6.25-rc5-mm1/include/linux/mm.h =================================================================== --- linux-2.6.25-rc5-mm1.orig/include/linux/mm.h 2008-03-19 18:25:11.881378660 -0700 +++ linux-2.6.25-rc5-mm1/include/linux/mm.h 2008-03-19 18:27:38.126566085 -0700 @@ -579,7 +579,14 @@ void page_address_init(void); #endif #if !defined(HASHED_PAGE_VIRTUAL) && !defined(WANT_PAGE_VIRTUAL) -#define page_address(page) lowmem_page_address(page) + +static inline void *page_address(struct page *page) +{ + if (unlikely(PageVcompound(page))) + return vmalloc_address(page); + return lowmem_page_address(page); +} + #define set_page_address(page, address) do { } while(0) #define page_address_init() do { } while(0) #endif Index: linux-2.6.25-rc5-mm1/mm/highmem.c =================================================================== --- linux-2.6.25-rc5-mm1.orig/mm/highmem.c 2008-03-18 12:20:10.391825814 -0700 +++ linux-2.6.25-rc5-mm1/mm/highmem.c 2008-03-19 18:27:38.138566219 -0700 @@ -265,8 +265,11 @@ void *page_address(struct page *page) void *ret; struct page_address_slot *pas; - if (!PageHighMem(page)) + if (!PageHighMem(page)) { + if (PageVcompound(page)) + return vmalloc_address(page); return lowmem_page_address(page); + } pas = page_slot(page); ret = NULL; @@ -294,7 +297,10 @@ void set_page_address(struct page *page, struct page_address_slot *pas; struct page_address_map *pam; - BUG_ON(!PageHighMem(page)); + if (!PageHighMem(page)) { + BUG_ON(!PageVcompound(page)); + return; + } pas = page_slot(page); if (virtual) { /* Add */