Commit 835d974f authored by Josef Bacik's avatar Josef Bacik Committed by Chris Mason

Btrfs: handle a bogus chunk tree nicely

If you restore a btrfs-image file system and try to mount that file system we'll
panic.  That's because btrfs-image restores and just makes one big chunk to
envelope the whole disk, since they are really only meant to be messed with by
our btrfs-progs.  So fix up btrfs_rmap_block and the callers of it for mount so
that we no longer panic but instead just return an error and fail to mount.
Thanks,
Signed-off-by: default avatarJosef Bacik <jbacik@fusionio.com>
Signed-off-by: default avatarChris Mason <chris.mason@fusionio.com>
parent d7634482
...@@ -257,7 +257,8 @@ static int exclude_super_stripes(struct btrfs_root *root, ...@@ -257,7 +257,8 @@ static int exclude_super_stripes(struct btrfs_root *root,
cache->bytes_super += stripe_len; cache->bytes_super += stripe_len;
ret = add_excluded_extent(root, cache->key.objectid, ret = add_excluded_extent(root, cache->key.objectid,
stripe_len); stripe_len);
BUG_ON(ret); /* -ENOMEM */ if (ret)
return ret;
} }
for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
...@@ -265,13 +266,17 @@ static int exclude_super_stripes(struct btrfs_root *root, ...@@ -265,13 +266,17 @@ static int exclude_super_stripes(struct btrfs_root *root,
ret = btrfs_rmap_block(&root->fs_info->mapping_tree, ret = btrfs_rmap_block(&root->fs_info->mapping_tree,
cache->key.objectid, bytenr, cache->key.objectid, bytenr,
0, &logical, &nr, &stripe_len); 0, &logical, &nr, &stripe_len);
BUG_ON(ret); /* -ENOMEM */ if (ret)
return ret;
while (nr--) { while (nr--) {
cache->bytes_super += stripe_len; cache->bytes_super += stripe_len;
ret = add_excluded_extent(root, logical[nr], ret = add_excluded_extent(root, logical[nr],
stripe_len); stripe_len);
BUG_ON(ret); /* -ENOMEM */ if (ret) {
kfree(logical);
return ret;
}
} }
kfree(logical); kfree(logical);
...@@ -7964,7 +7969,17 @@ int btrfs_read_block_groups(struct btrfs_root *root) ...@@ -7964,7 +7969,17 @@ int btrfs_read_block_groups(struct btrfs_root *root)
* info has super bytes accounted for, otherwise we'll think * info has super bytes accounted for, otherwise we'll think
* we have more space than we actually do. * we have more space than we actually do.
*/ */
exclude_super_stripes(root, cache); ret = exclude_super_stripes(root, cache);
if (ret) {
/*
* We may have excluded something, so call this just in
* case.
*/
free_excluded_extents(root, cache);
kfree(cache->free_space_ctl);
kfree(cache);
goto error;
}
/* /*
* check for two cases, either we are full, and therefore * check for two cases, either we are full, and therefore
...@@ -8106,7 +8121,17 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans, ...@@ -8106,7 +8121,17 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
cache->last_byte_to_unpin = (u64)-1; cache->last_byte_to_unpin = (u64)-1;
cache->cached = BTRFS_CACHE_FINISHED; cache->cached = BTRFS_CACHE_FINISHED;
exclude_super_stripes(root, cache); ret = exclude_super_stripes(root, cache);
if (ret) {
/*
* We may have excluded something, so call this just in
* case.
*/
free_excluded_extents(root, cache);
kfree(cache->free_space_ctl);
kfree(cache);
return ret;
}
add_new_free_space(cache, root->fs_info, chunk_offset, add_new_free_space(cache, root->fs_info, chunk_offset,
chunk_offset + size); chunk_offset + size);
......
...@@ -4935,7 +4935,18 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree, ...@@ -4935,7 +4935,18 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
em = lookup_extent_mapping(em_tree, chunk_start, 1); em = lookup_extent_mapping(em_tree, chunk_start, 1);
read_unlock(&em_tree->lock); read_unlock(&em_tree->lock);
BUG_ON(!em || em->start != chunk_start); if (!em) {
printk(KERN_ERR "btrfs: couldn't find em for chunk %Lu\n",
chunk_start);
return -EIO;
}
if (em->start != chunk_start) {
printk(KERN_ERR "btrfs: bad chunk start, em=%Lu, wanted=%Lu\n",
em->start, chunk_start);
free_extent_map(em);
return -EIO;
}
map = (struct map_lookup *)em->bdev; map = (struct map_lookup *)em->bdev;
length = em->len; length = em->len;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment