aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorFilipe Manana <fdmanana@suse.com>2015-03-12 19:23:13 -0400
committerChris Mason <clm@fb.com>2015-03-26 20:55:52 -0400
commit3d850dd44889d3aa67d0b8007c2cdd259bff7da4 (patch)
treea21c9d47c7cb1a7392008954494d49154d3a80dd /fs/btrfs/file.c
parent5f806c3ae2ff6263a10a6901f97abb74dac03d36 (diff)
Btrfs: add missing inode item update in fallocate()
If we fallocate(), without the keep size flag, into an area already covered by an extent previously fallocated, we were updating the inode's i_size but we weren't updating the inode item in the fs/subvol tree. A following umount + mount would result in a loss of the inode's size (and an fsync would miss too the fact that the inode changed). Reproducer: $ mkfs.btrfs -f /dev/sdd $ mount /dev/sdd /mnt $ fallocate -n -l 1M /mnt/foobar $ fallocate -l 512K /mnt/foobar $ umount /mnt $ mount /dev/sdd /mnt $ od -t x1 /mnt/foobar 0000000 The expected result is: $ od -t x1 /mnt/foobar 0000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 * 2000000 A test case for fstests follows soon. Signed-off-by: Filipe Manana <fdmanana@suse.com> Reviewed-by: Liu Bo <bo.li.liu@oracle.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 7d4bb3b6fbc2..150db5e50c2d 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -2669,23 +2669,34 @@ static long btrfs_fallocate(struct file *file, int mode,
2669 1 << inode->i_blkbits, 2669 1 << inode->i_blkbits,
2670 offset + len, 2670 offset + len,
2671 &alloc_hint); 2671 &alloc_hint);
2672
2673 if (ret < 0) {
2674 free_extent_map(em);
2675 break;
2676 }
2677 } else if (actual_end > inode->i_size && 2672 } else if (actual_end > inode->i_size &&
2678 !(mode & FALLOC_FL_KEEP_SIZE)) { 2673 !(mode & FALLOC_FL_KEEP_SIZE)) {
2674 struct btrfs_trans_handle *trans;
2675
2679 /* 2676 /*
2680 * We didn't need to allocate any more space, but we 2677 * We didn't need to allocate any more space, but we
2681 * still extended the size of the file so we need to 2678 * still extended the size of the file so we need to
2682 * update i_size. 2679 * update i_size and the inode item.
2683 */ 2680 */
2684 inode->i_ctime = CURRENT_TIME; 2681 trans = btrfs_start_transaction(root, 1);
2685 i_size_write(inode, actual_end); 2682 if (IS_ERR(trans)) {
2686 btrfs_ordered_update_i_size(inode, actual_end, NULL); 2683 ret = PTR_ERR(trans);
2684 } else {
2685 inode->i_ctime = CURRENT_TIME;
2686 i_size_write(inode, actual_end);
2687 btrfs_ordered_update_i_size(inode, actual_end,
2688 NULL);
2689 ret = btrfs_update_inode(trans, root, inode);
2690 if (ret)
2691 btrfs_end_transaction(trans, root);
2692 else
2693 ret = btrfs_end_transaction(trans,
2694 root);
2695 }
2687 } 2696 }
2688 free_extent_map(em); 2697 free_extent_map(em);
2698 if (ret < 0)
2699 break;
2689 2700
2690 cur_offset = last_byte; 2701 cur_offset = last_byte;
2691 if (cur_offset >= alloc_end) { 2702 if (cur_offset >= alloc_end) {