aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fusionio.com>2012-08-29 14:27:18 -0400
committerChris Mason <chris.mason@fusionio.com>2012-10-01 15:19:07 -0400
commit2aaa66558172b017f36bf38ae69372813dedee9d (patch)
treed6150a615935d36166cd06d69e3252451e62e724 /fs/btrfs/inode.c
parent2671485d395c07fca104c972785898d7c52fc942 (diff)
Btrfs: add hole punching
This patch adds hole punching via fallocate. Thanks, Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index f0a4792492ed..8cb272c84089 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3475,12 +3475,20 @@ error:
3475} 3475}
3476 3476
3477/* 3477/*
3478 * taken from block_truncate_page, but does cow as it zeros out 3478 * btrfs_truncate_page - read, zero a chunk and write a page
3479 * any bytes left in the last page in the file. 3479 * @inode - inode that we're zeroing
3480 * @from - the offset to start zeroing
3481 * @len - the length to zero, 0 to zero the entire range respective to the
3482 * offset
3483 * @front - zero up to the offset instead of from the offset on
3484 *
3485 * This will find the page for the "from" offset and cow the page and zero the
3486 * part we want to zero. This is used with truncate and hole punching.
3480 */ 3487 */
3481static int btrfs_truncate_page(struct address_space *mapping, loff_t from) 3488int btrfs_truncate_page(struct inode *inode, loff_t from, loff_t len,
3489 int front)
3482{ 3490{
3483 struct inode *inode = mapping->host; 3491 struct address_space *mapping = inode->i_mapping;
3484 struct btrfs_root *root = BTRFS_I(inode)->root; 3492 struct btrfs_root *root = BTRFS_I(inode)->root;
3485 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; 3493 struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
3486 struct btrfs_ordered_extent *ordered; 3494 struct btrfs_ordered_extent *ordered;
@@ -3495,7 +3503,8 @@ static int btrfs_truncate_page(struct address_space *mapping, loff_t from)
3495 u64 page_start; 3503 u64 page_start;
3496 u64 page_end; 3504 u64 page_end;
3497 3505
3498 if ((offset & (blocksize - 1)) == 0) 3506 if ((offset & (blocksize - 1)) == 0 &&
3507 (!len || ((len & (blocksize - 1)) == 0)))
3499 goto out; 3508 goto out;
3500 ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE); 3509 ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE);
3501 if (ret) 3510 if (ret)
@@ -3555,8 +3564,13 @@ again:
3555 3564
3556 ret = 0; 3565 ret = 0;
3557 if (offset != PAGE_CACHE_SIZE) { 3566 if (offset != PAGE_CACHE_SIZE) {
3567 if (!len)
3568 len = PAGE_CACHE_SIZE - offset;
3558 kaddr = kmap(page); 3569 kaddr = kmap(page);
3559 memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset); 3570 if (front)
3571 memset(kaddr, 0, offset);
3572 else
3573 memset(kaddr + offset, 0, len);
3560 flush_dcache_page(page); 3574 flush_dcache_page(page);
3561 kunmap(page); 3575 kunmap(page);
3562 } 3576 }
@@ -6796,7 +6810,7 @@ static int btrfs_truncate(struct inode *inode)
6796 u64 mask = root->sectorsize - 1; 6810 u64 mask = root->sectorsize - 1;
6797 u64 min_size = btrfs_calc_trunc_metadata_size(root, 1); 6811 u64 min_size = btrfs_calc_trunc_metadata_size(root, 1);
6798 6812
6799 ret = btrfs_truncate_page(inode->i_mapping, inode->i_size); 6813 ret = btrfs_truncate_page(inode, inode->i_size, 0, 0);
6800 if (ret) 6814 if (ret)
6801 return ret; 6815 return ret;
6802 6816