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 | 12 ++++++++++++ include/linux/pagemap.h | 25 +++++++++++++++++++++++++ mm/filemap.c | 4 ++-- 4 files changed, 41 insertions(+), 4 deletions(-) Index: linux-2.6.21-rc7/include/linux/pagemap.h =================================================================== --- linux-2.6.21-rc7.orig/include/linux/pagemap.h 2007-04-24 11:41:35.000000000 -0700 +++ linux-2.6.21-rc7/include/linux/pagemap.h 2007-04-24 11:41:51.000000000 -0700 @@ -291,6 +291,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/fs/libfs.c =================================================================== --- linux-2.6.21-rc7.orig/fs/libfs.c 2007-04-24 11:41:37.000000000 -0700 +++ linux-2.6.21-rc7/fs/libfs.c 2007-04-24 11:41:51.000000000 -0700 @@ -320,8 +320,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/include/linux/highmem.h =================================================================== --- linux-2.6.21-rc7.orig/include/linux/highmem.h 2007-04-24 11:42:52.000000000 -0700 +++ linux-2.6.21-rc7/include/linux/highmem.h 2007-04-24 11:59:31.000000000 -0700 @@ -81,6 +81,17 @@ static inline void clear_highpage(struct kunmap_atomic(kaddr, KM_USER0); } +#ifdef CONFIG_LARGE_BLOCKSIZE +/* + * Macro needed because flush_mapping_page definition is not available yet + * CONFIG_LARGE_BLOCKSIZE means !HIGHMEM + */ +#define memclear_highpage_flush(__page,__offset,__size) \ +{ \ + memset(page_address(__page), (__offset), (__size)); \ + flush_mapping_page(__page); \ +} +#else /* * Same but also flushes aliased cache contents to RAM. */ @@ -95,6 +106,7 @@ static inline void memclear_highpage_flu flush_dcache_page(page); kunmap_atomic(kaddr, KM_USER0); } +#endif #ifndef __HAVE_ARCH_COPY_USER_HIGHPAGE Index: linux-2.6.21-rc7/mm/filemap.c =================================================================== --- linux-2.6.21-rc7.orig/mm/filemap.c 2007-04-24 11:41:37.000000000 -0700 +++ linux-2.6.21-rc7/mm/filemap.c 2007-04-24 11:59:36.000000000 -0700 @@ -925,7 +925,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 (part of) the same page is read multiple times @@ -2139,7 +2139,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); -- - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/