Variable Order Page Cache: Add clearing and flushing function Add a flushing and clearing function for higher order pages. These are provisional and will likely have to be optimized. Signed-off-by: Christoph Lameter --- fs/libfs.c | 4 ++-- include/linux/highmem.h | 9 +++------ include/linux/pagemap.h | 25 +++++++++++++++++++++++++ mm/filemap.c | 4 ++-- 4 files changed, 32 insertions(+), 10 deletions(-) Index: linux-2.6.21-rc7-mm1/include/linux/pagemap.h =================================================================== --- linux-2.6.21-rc7-mm1.orig/include/linux/pagemap.h 2007-04-25 07:38:59.000000000 -0700 +++ linux-2.6.21-rc7-mm1/include/linux/pagemap.h 2007-04-25 07:58:43.000000000 -0700 @@ -315,6 +315,31 @@ static inline void wait_on_page_writebac extern void end_page_writeback(struct page *page); +/* Support for clearing higher order pages */ +static inline void clear_mapping_page(struct page *page) +{ + int nr_pages = compound_pages(page); + int i; + + for (i = 0; i < nr_pages; i++) + clear_highpage(page + i); +} + +/* + * Support for flushing higher order pages. + * + * A bit stupid: On many platforms flushing the first page + * will flush any TLB starting there + */ +static inline void flush_mapping_page(struct page *page) +{ + int nr_pages = compound_pages(page); + int i; + + for (i = 0; i < nr_pages; i++) + flush_dcache_page(page + i); +} + /* * Fault a userspace page into pagetables. Return non-zero on a fault. * Index: linux-2.6.21-rc7-mm1/fs/libfs.c =================================================================== --- linux-2.6.21-rc7-mm1.orig/fs/libfs.c 2007-04-25 07:48:53.000000000 -0700 +++ linux-2.6.21-rc7-mm1/fs/libfs.c 2007-04-25 07:58:43.000000000 -0700 @@ -326,8 +326,8 @@ int simple_rename(struct inode *old_dir, int simple_readpage(struct file *file, struct page *page) { - clear_highpage(page); - flush_dcache_page(page); + clear_mapping_page(page); + flush_mapping_page(page); SetPageUptodate(page); unlock_page(page); return 0; Index: linux-2.6.21-rc7-mm1/include/linux/highmem.h =================================================================== --- linux-2.6.21-rc7-mm1.orig/include/linux/highmem.h 2007-04-25 07:59:32.000000000 -0700 +++ linux-2.6.21-rc7-mm1/include/linux/highmem.h 2007-04-25 08:13:22.000000000 -0700 @@ -148,15 +148,12 @@ static inline void clear_highpage(struct \ kaddr = kmap_atomic(page, km_type); \ memset((char *)kaddr + (offset), 0, (size)); \ - flush_dcache_page(page); \ + flush_mapping_page(page); \ kunmap_atomic(kaddr, (km_type)); \ } while (0) -static inline void __deprecated memclear_highpage_flush(struct page *page, - unsigned int offset, unsigned int size) -{ - zero_user_page(page, offset, size, KM_USER0); -} +#define memclear_highpage_flush(__p, __o, __s) \ + zero_user_page(__p, __o, __s, KM_USER0) #ifndef __HAVE_ARCH_COPY_USER_HIGHPAGE Index: linux-2.6.21-rc7-mm1/mm/filemap.c =================================================================== --- linux-2.6.21-rc7-mm1.orig/mm/filemap.c 2007-04-25 07:53:23.000000000 -0700 +++ linux-2.6.21-rc7-mm1/mm/filemap.c 2007-04-25 08:45:07.000000000 -0700 @@ -974,7 +974,7 @@ page_ok: * before reading the page on the kernel side. */ if (mapping_writably_mapped(mapping)) - flush_dcache_page(page); + flush_mapping_page(page); /* * When a sequential read accesses a page several times, @@ -2044,7 +2044,7 @@ generic_file_buffered_write(struct kiocb else copied = filemap_copy_from_user_iovec(page, offset, cur_iov, iov_base, bytes); - flush_dcache_page(page); + flush_mapping_page(page); status = a_ops->commit_write(file, page, offset, offset+bytes); if (status == AOP_TRUNCATED_PAGE) { page_cache_release(page);