From: Matthew Wilcox Subject: [PATCH v3 2/3] xip: Add xip_zero_page_range Date: Tue, 17 Dec 2013 14:18:27 -0500 Message-ID: <6cef8baf3fa1e7f891b7d7252b3e9b37dda5f011.1387307259.git.matthew.r.wilcox@intel.com> References: Cc: Matthew Wilcox , Ross Zwisler To: linux-ext4@vger.kernel.org, linux-fsdevel@vger.kernel.org Return-path: In-Reply-To: In-Reply-To: References: Sender: linux-fsdevel-owner@vger.kernel.org List-Id: linux-ext4.vger.kernel.org This new function allows us to support hole-punch for XIP files by zeroing a partial page, as opposed to the xip_truncate_page() function which can only truncate to the end of the page. Reimplement xip_truncate_page() as a caller of xip_zero_page_range(). Signed-off-by: Matthew Wilcox [ported to 3.13-rc2] Signed-off-by: Ross Zwisler --- include/linux/fs.h | 8 ++++++++ mm/filemap_xip.c | 31 +++++++++++++++---------------- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 121f11f..a063bff 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2509,11 +2509,19 @@ extern int xip_file_mmap(struct file * file, struct vm_area_struct * vma); extern ssize_t xip_file_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos); extern int xip_truncate_page(struct address_space *mapping, loff_t from); +extern int xip_zero_page_range(struct address_space *, loff_t from, + unsigned length); #else static inline int xip_truncate_page(struct address_space *mapping, loff_t from) { return 0; } + +static inline int xip_zero_page_range(struct address_space *mapping, + loff_t from, unsigned length) +{ + return 0; +} #endif #ifdef CONFIG_BLOCK diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index c8d23e9..d808b72 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c @@ -461,33 +461,19 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len, } EXPORT_SYMBOL_GPL(xip_file_write); -/* - * truncate a page used for execute in place - * functionality is analog to block_truncate_page but does use get_xip_mem - * to get the page instead of page cache - */ -int -xip_truncate_page(struct address_space *mapping, loff_t from) +int xip_zero_page_range(struct address_space *mapping, loff_t from, + unsigned length) { pgoff_t index = from >> PAGE_CACHE_SHIFT; unsigned offset = from & (PAGE_CACHE_SIZE-1); - unsigned blocksize; - unsigned length; void *xip_mem; unsigned long xip_pfn; int err; - BUG_ON(!mapping->a_ops->get_xip_mem); - - blocksize = 1 << mapping->host->i_blkbits; - length = offset & (blocksize - 1); - /* Block boundary? Nothing to do */ if (!length) return 0; - length = blocksize - length; - err = mapping->a_ops->get_xip_mem(mapping, index, 0, &xip_mem, &xip_pfn); if (unlikely(err)) { @@ -497,7 +483,20 @@ xip_truncate_page(struct address_space *mapping, loff_t from) else return err; } + memset(xip_mem + offset, 0, length); return 0; } +EXPORT_SYMBOL_GPL(xip_zero_page_range); + +/* + * truncate a page used for execute in place + * functionality is analog to block_truncate_page but does use get_xip_mem + * to get the page instead of page cache + */ +int xip_truncate_page(struct address_space *mapping, loff_t from) +{ + unsigned length = PAGE_CACHE_ALIGN(from) - from; + return xip_zero_page_range(mapping, from, length); +} EXPORT_SYMBOL_GPL(xip_truncate_page); -- 1.8.4.rc3