diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-01-22 16:47:59 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:59 -0400 |
commit | 5f56406aabdf5444d040c5955effc665b1d0dbaf (patch) | |
tree | 59c82cc7f5d5de3b65b6eba24b505684eb7941d6 /fs/btrfs/inode.c | |
parent | c1e32da616a17813f11b701a7a87775d35c12e3a (diff) |
Btrfs: Fix hole insertion corner cases
There were a few places that could cause duplicate extent insertion,
this adjusts the code that creates holes to avoid it.
lookup_extent_map is changed to correctly return all of the extents in a
range, even when there are none matching at the start of the range.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 51fc06dc4a5d..67005480e139 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -133,6 +133,7 @@ static int cow_file_range(struct inode *inode, u64 start, u64 end) | |||
133 | ret = btrfs_insert_file_extent(trans, root, inode->i_ino, | 133 | ret = btrfs_insert_file_extent(trans, root, inode->i_ino, |
134 | start, ins.objectid, ins.offset, | 134 | start, ins.objectid, ins.offset, |
135 | ins.offset); | 135 | ins.offset); |
136 | btrfs_check_file(root, inode); | ||
136 | num_bytes -= cur_alloc_size; | 137 | num_bytes -= cur_alloc_size; |
137 | alloc_hint = ins.objectid + ins.offset; | 138 | alloc_hint = ins.objectid + ins.offset; |
138 | start += cur_alloc_size; | 139 | start += cur_alloc_size; |
@@ -965,12 +966,18 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
965 | u64 mask = root->sectorsize - 1; | 966 | u64 mask = root->sectorsize - 1; |
966 | u64 pos = (inode->i_size + mask) & ~mask; | 967 | u64 pos = (inode->i_size + mask) & ~mask; |
967 | u64 block_end = attr->ia_size | mask; | 968 | u64 block_end = attr->ia_size | mask; |
969 | u64 hole_start; | ||
968 | u64 hole_size; | 970 | u64 hole_size; |
969 | u64 alloc_hint = 0; | 971 | u64 alloc_hint = 0; |
970 | 972 | ||
971 | if (attr->ia_size <= pos) | 973 | if (attr->ia_size <= pos) |
972 | goto out; | 974 | goto out; |
973 | 975 | ||
976 | if (pos != inode->i_size) | ||
977 | hole_start = pos + root->sectorsize; | ||
978 | else | ||
979 | hole_start = pos; | ||
980 | |||
974 | mutex_lock(&root->fs_info->fs_mutex); | 981 | mutex_lock(&root->fs_info->fs_mutex); |
975 | err = btrfs_check_free_space(root, 1, 0); | 982 | err = btrfs_check_free_space(root, 1, 0); |
976 | mutex_unlock(&root->fs_info->fs_mutex); | 983 | mutex_unlock(&root->fs_info->fs_mutex); |
@@ -980,19 +987,21 @@ static int btrfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
980 | btrfs_truncate_page(inode->i_mapping, inode->i_size); | 987 | btrfs_truncate_page(inode->i_mapping, inode->i_size); |
981 | 988 | ||
982 | lock_extent(em_tree, pos, block_end, GFP_NOFS); | 989 | lock_extent(em_tree, pos, block_end, GFP_NOFS); |
983 | hole_size = (attr->ia_size - pos + mask) & ~mask; | 990 | hole_size = block_end - hole_start; |
984 | 991 | ||
985 | mutex_lock(&root->fs_info->fs_mutex); | 992 | mutex_lock(&root->fs_info->fs_mutex); |
986 | trans = btrfs_start_transaction(root, 1); | 993 | trans = btrfs_start_transaction(root, 1); |
987 | btrfs_set_trans_block_group(trans, inode); | 994 | btrfs_set_trans_block_group(trans, inode); |
988 | err = btrfs_drop_extents(trans, root, inode, | 995 | err = btrfs_drop_extents(trans, root, inode, |
989 | pos, pos + hole_size, pos, | 996 | pos, block_end, pos, |
990 | &alloc_hint); | 997 | &alloc_hint); |
991 | 998 | ||
992 | if (alloc_hint != EXTENT_MAP_INLINE) { | 999 | if (alloc_hint != EXTENT_MAP_INLINE) { |
993 | err = btrfs_insert_file_extent(trans, root, | 1000 | err = btrfs_insert_file_extent(trans, root, |
994 | inode->i_ino, | 1001 | inode->i_ino, |
995 | pos, 0, 0, hole_size); | 1002 | hole_start, 0, 0, |
1003 | hole_size); | ||
1004 | btrfs_check_file(root, inode); | ||
996 | } | 1005 | } |
997 | btrfs_end_transaction(trans, root); | 1006 | btrfs_end_transaction(trans, root); |
998 | mutex_unlock(&root->fs_info->fs_mutex); | 1007 | mutex_unlock(&root->fs_info->fs_mutex); |