diff options
author | Ingo Molnar <mingo@elte.hu> | 2011-07-01 12:28:42 +0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-07-01 12:28:46 +0400 |
commit | 10e6962765f8213941eaa1cbb9de425ff0689e2e (patch) | |
tree | c277e4ac5b2b7156152454578c39e90da5127dd8 /mm/truncate.c | |
parent | af07ce3e77d3b24ab1d71fcc5833d41800f23b2b (diff) | |
parent | b0af8dfdd67699e25083478c63eedef2e72ebd85 (diff) | |
download | linux-10e6962765f8213941eaa1cbb9de425ff0689e2e.tar.xz |
Merge commit 'v3.0-rc5' into perf/core
Merge reason: Pick up the latest fixes.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'mm/truncate.c')
-rw-r--r-- | mm/truncate.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/mm/truncate.c b/mm/truncate.c index 3a29a6180212..e13f22efaad7 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -304,6 +304,11 @@ EXPORT_SYMBOL(truncate_inode_pages_range); * @lstart: offset from which to truncate * * Called under (and serialised by) inode->i_mutex. + * + * Note: When this function returns, there can be a page in the process of + * deletion (inside __delete_from_page_cache()) in the specified range. Thus + * mapping->nrpages can be non-zero when this function returns even after + * truncation of the whole mapping. */ void truncate_inode_pages(struct address_space *mapping, loff_t lstart) { @@ -603,3 +608,27 @@ int vmtruncate(struct inode *inode, loff_t offset) return 0; } EXPORT_SYMBOL(vmtruncate); + +int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end) +{ + struct address_space *mapping = inode->i_mapping; + + /* + * If the underlying filesystem is not going to provide + * a way to truncate a range of blocks (punch a hole) - + * we should return failure right now. + */ + if (!inode->i_op->truncate_range) + return -ENOSYS; + + mutex_lock(&inode->i_mutex); + down_write(&inode->i_alloc_sem); + unmap_mapping_range(mapping, offset, (end - offset), 1); + inode->i_op->truncate_range(inode, offset, end); + /* unmap again to remove racily COWed private pages */ + unmap_mapping_range(mapping, offset, (end - offset), 1); + up_write(&inode->i_alloc_sem); + mutex_unlock(&inode->i_mutex); + + return 0; +} |