aboutsummaryrefslogtreecommitdiff
path: root/mm/truncate.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2011-07-01 10:28:42 +0200
committerIngo Molnar <mingo@elte.hu>2011-07-01 10:28:46 +0200
commit10e6962765f8213941eaa1cbb9de425ff0689e2e (patch)
treec277e4ac5b2b7156152454578c39e90da5127dd8 /mm/truncate.c
parentaf07ce3e77d3b24ab1d71fcc5833d41800f23b2b (diff)
parentb0af8dfdd67699e25083478c63eedef2e72ebd85 (diff)
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.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/mm/truncate.c b/mm/truncate.c
index 3a29a618021..e13f22efaad 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;
+}