aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/file.c
diff options
context:
space:
mode:
authorJosef Bacik <jbacik@fb.com>2016-11-14 14:06:22 -0500
committerDavid Sterba <dsterba@suse.com>2016-11-30 07:45:19 -0500
commitf94480bd7be6bb1b0823d1036f3ee4ebe7450172 (patch)
tree185626f23c4cf4c5be566f9984d2ede1137904e7 /fs/btrfs/file.c
parent62fe51c1d0100ff07a761cd077872e01f2a2b8ca (diff)
Btrfs: abort transaction if fill_holes() fails
At this point we will have dropped extent entries from the file, so if we fail to insert the new hole entries then we are leaving the fs in a corrupt state (albeit an easily fixed one). Abort the transaciton if this happens so we can avoid corrupting the fs. Thanks, Signed-off-by: Josef Bacik <jbacik@fb.com> Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/file.c')
-rw-r--r--fs/btrfs/file.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index f5288fa0aad0..3c1f4be36f16 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -2232,9 +2232,15 @@ static int fill_holes(struct btrfs_trans_handle *trans, struct inode *inode,
2232 key.offset = offset; 2232 key.offset = offset;
2233 2233
2234 ret = btrfs_search_slot(trans, root, &key, path, 0, 1); 2234 ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
2235 if (ret < 0) 2235 if (ret <= 0) {
2236 /*
2237 * We should have dropped this offset, so if we find it then
2238 * something has gone horribly wrong.
2239 */
2240 if (ret == 0)
2241 ret = -EINVAL;
2236 return ret; 2242 return ret;
2237 BUG_ON(!ret); 2243 }
2238 2244
2239 leaf = path->nodes[0]; 2245 leaf = path->nodes[0];
2240 if (hole_mergeable(inode, leaf, path->slots[0]-1, offset, end)) { 2246 if (hole_mergeable(inode, leaf, path->slots[0]-1, offset, end)) {
@@ -2537,6 +2543,13 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
2537 ret = fill_holes(trans, inode, path, cur_offset, 2543 ret = fill_holes(trans, inode, path, cur_offset,
2538 drop_end); 2544 drop_end);
2539 if (ret) { 2545 if (ret) {
2546 /*
2547 * If we failed then we didn't insert our hole
2548 * entries for the area we dropped, so now the
2549 * fs is corrupted, so we must abort the
2550 * transaction.
2551 */
2552 btrfs_abort_transaction(trans, ret);
2540 err = ret; 2553 err = ret;
2541 break; 2554 break;
2542 } 2555 }
@@ -2601,6 +2614,8 @@ static int btrfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
2601 if (cur_offset < ino_size && cur_offset < drop_end) { 2614 if (cur_offset < ino_size && cur_offset < drop_end) {
2602 ret = fill_holes(trans, inode, path, cur_offset, drop_end); 2615 ret = fill_holes(trans, inode, path, cur_offset, drop_end);
2603 if (ret) { 2616 if (ret) {
2617 /* Same comment as above. */
2618 btrfs_abort_transaction(trans, ret);
2604 err = ret; 2619 err = ret;
2605 goto out_trans; 2620 goto out_trans;
2606 } 2621 }