diff options
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); | |||
304 | * @lstart: offset from which to truncate | 304 | * @lstart: offset from which to truncate |
305 | * | 305 | * |
306 | * Called under (and serialised by) inode->i_mutex. | 306 | * Called under (and serialised by) inode->i_mutex. |
307 | * | ||
308 | * Note: When this function returns, there can be a page in the process of | ||
309 | * deletion (inside __delete_from_page_cache()) in the specified range. Thus | ||
310 | * mapping->nrpages can be non-zero when this function returns even after | ||
311 | * truncation of the whole mapping. | ||
307 | */ | 312 | */ |
308 | void truncate_inode_pages(struct address_space *mapping, loff_t lstart) | 313 | void truncate_inode_pages(struct address_space *mapping, loff_t lstart) |
309 | { | 314 | { |
@@ -603,3 +608,27 @@ int vmtruncate(struct inode *inode, loff_t offset) | |||
603 | return 0; | 608 | return 0; |
604 | } | 609 | } |
605 | EXPORT_SYMBOL(vmtruncate); | 610 | EXPORT_SYMBOL(vmtruncate); |
611 | |||
612 | int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end) | ||
613 | { | ||
614 | struct address_space *mapping = inode->i_mapping; | ||
615 | |||
616 | /* | ||
617 | * If the underlying filesystem is not going to provide | ||
618 | * a way to truncate a range of blocks (punch a hole) - | ||
619 | * we should return failure right now. | ||
620 | */ | ||
621 | if (!inode->i_op->truncate_range) | ||
622 | return -ENOSYS; | ||
623 | |||
624 | mutex_lock(&inode->i_mutex); | ||
625 | down_write(&inode->i_alloc_sem); | ||
626 | unmap_mapping_range(mapping, offset, (end - offset), 1); | ||
627 | inode->i_op->truncate_range(inode, offset, end); | ||
628 | /* unmap again to remove racily COWed private pages */ | ||
629 | unmap_mapping_range(mapping, offset, (end - offset), 1); | ||
630 | up_write(&inode->i_alloc_sem); | ||
631 | mutex_unlock(&inode->i_mutex); | ||
632 | |||
633 | return 0; | ||
634 | } | ||