diff options
author | Josef Bacik <jbacik@fusionio.com> | 2012-08-29 14:27:18 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@fusionio.com> | 2012-10-01 15:19:07 -0400 |
commit | 2aaa66558172b017f36bf38ae69372813dedee9d (patch) | |
tree | d6150a615935d36166cd06d69e3252451e62e724 /fs/btrfs/inode.c | |
parent | 2671485d395c07fca104c972785898d7c52fc942 (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.c | 28 |
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 | */ |
3481 | static int btrfs_truncate_page(struct address_space *mapping, loff_t from) | 3488 | int 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 | ||