Skip to content

Commit

Permalink
Btrfs: fixup error handling in btrfs_reloc_cow
Browse files Browse the repository at this point in the history
If we failed to actually allocate the correct size of the extent to relocate we
will end up in an infinite loop because we won't return an error, we'll just
move on to the next extent.  So fix this up by returning an error, and then fix
all the callers to return an error up the stack rather than BUG_ON()'ing.
Thanks,

Signed-off-by: Josef Bacik <jbacik@fusionio.com>
Signed-off-by: Chris Mason <chris.mason@fusionio.com>
  • Loading branch information
Josef Bacik authored and Chris Mason committed Sep 21, 2013
1 parent 07f0e62 commit 83d4cfd
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 22 deletions.
7 changes: 5 additions & 2 deletions fs/btrfs/ctree.c
Original file line number Diff line number Diff line change
Expand Up @@ -1005,8 +1005,11 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
return ret;
}

if (root->ref_cows)
btrfs_reloc_cow_block(trans, root, buf, cow);
if (root->ref_cows) {
ret = btrfs_reloc_cow_block(trans, root, buf, cow);
if (ret)
return ret;
}

if (buf == root->node) {
WARN_ON(parent && parent != buf);
Expand Down
6 changes: 3 additions & 3 deletions fs/btrfs/ctree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3939,9 +3939,9 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
struct btrfs_root *root);
int btrfs_recover_relocation(struct btrfs_root *root);
int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len);
void btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct extent_buffer *buf,
struct extent_buffer *cow);
int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct extent_buffer *buf,
struct extent_buffer *cow);
void btrfs_reloc_pre_snapshot(struct btrfs_trans_handle *trans,
struct btrfs_pending_snapshot *pending,
u64 *bytes_to_reserve);
Expand Down
41 changes: 24 additions & 17 deletions fs/btrfs/relocation.c
Original file line number Diff line number Diff line change
Expand Up @@ -1548,7 +1548,7 @@ static int get_new_location(struct inode *reloc_inode, u64 *new_bytenr,
btrfs_file_extent_other_encoding(leaf, fi));

if (num_bytes != btrfs_file_extent_disk_num_bytes(leaf, fi)) {
ret = 1;
ret = -EINVAL;
goto out;
}

Expand Down Expand Up @@ -1579,7 +1579,7 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
u64 end;
u32 nritems;
u32 i;
int ret;
int ret = 0;
int first = 1;
int dirty = 0;

Expand Down Expand Up @@ -1642,11 +1642,13 @@ int replace_file_extents(struct btrfs_trans_handle *trans,

ret = get_new_location(rc->data_inode, &new_bytenr,
bytenr, num_bytes);
if (ret > 0) {
WARN_ON(1);
continue;
if (ret) {
/*
* Don't have to abort since we've not changed anything
* in the file extent yet.
*/
break;
}
BUG_ON(ret < 0);

btrfs_set_file_extent_disk_bytenr(leaf, fi, new_bytenr);
dirty = 1;
Expand All @@ -1656,18 +1658,24 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
num_bytes, parent,
btrfs_header_owner(leaf),
key.objectid, key.offset, 1);
BUG_ON(ret);
if (ret) {
btrfs_abort_transaction(trans, root, ret);
break;
}

ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
parent, btrfs_header_owner(leaf),
key.objectid, key.offset, 1);
BUG_ON(ret);
if (ret) {
btrfs_abort_transaction(trans, root, ret);
break;
}
}
if (dirty)
btrfs_mark_buffer_dirty(leaf);
if (inode)
btrfs_add_delayed_iput(inode);
return 0;
return ret;
}

static noinline_for_stack
Expand Down Expand Up @@ -4499,19 +4507,19 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len)
return ret;
}

void btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct extent_buffer *buf,
struct extent_buffer *cow)
int btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
struct btrfs_root *root, struct extent_buffer *buf,
struct extent_buffer *cow)
{
struct reloc_control *rc;
struct backref_node *node;
int first_cow = 0;
int level;
int ret;
int ret = 0;

rc = root->fs_info->reloc_ctl;
if (!rc)
return;
return 0;

BUG_ON(rc->stage == UPDATE_DATA_PTRS &&
root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID);
Expand Down Expand Up @@ -4547,10 +4555,9 @@ void btrfs_reloc_cow_block(struct btrfs_trans_handle *trans,
rc->nodes_relocated += buf->len;
}

if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS) {
if (level == 0 && first_cow && rc->stage == UPDATE_DATA_PTRS)
ret = replace_file_extents(trans, rc, root, cow);
BUG_ON(ret);
}
return ret;
}

/*
Expand Down

0 comments on commit 83d4cfd

Please sign in to comment.