Commit 182741d2 authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba

btrfs: remove v0 extent handling

The v0 extent item has been deprecated for a long time, and we don't have
any report from the community either.

So it's time to remove the v0 extent specific error handling, and just
treat them as regular extent tree corruption.

This patch would remove the btrfs_print_v0_err() helper, and enhance the
involved error handling to treat them just as any extent tree
corruption. No reports regarding v0 extents have been seen since the
graceful handling was added in 2018.

This involves:

- btrfs_backref_add_tree_node()
  This change is a little tricky, the new code is changed to only handle
  BTRFS_TREE_BLOCK_REF_KEY and BTRFS_SHARED_BLOCK_REF_KEY.

  But this is safe, as we have rejected any unknown inline refs through
  btrfs_get_extent_inline_ref_type().
  For keyed backrefs, we're safe to skip anything we don't know (that's
  if it can pass tree-checker in the first place).

- btrfs_lookup_extent_info()
- lookup_inline_extent_backref()
- run_delayed_extent_op()
- __btrfs_free_extent()
- add_tree_block()
  Regular error handling of unexpected extent tree item, and abort
  transaction (if we have a trans handle).

- remove_extent_data_ref()
  It's pretty much the same as the regular rejection of unknown backref
  key.
  But for this particular case, we can also remove a BUG_ON().

- extent_data_ref_count()
  We can remove the BTRFS_EXTENT_REF_V0_KEY BUG_ON(), as it would be
  rejected by the only caller.

- btrfs_print_leaf()
  Remove the handling for BTRFS_EXTENT_REF_V0_KEY.
Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 7f72f505
...@@ -3373,7 +3373,6 @@ int btrfs_backref_add_tree_node(struct btrfs_backref_cache *cache, ...@@ -3373,7 +3373,6 @@ int btrfs_backref_add_tree_node(struct btrfs_backref_cache *cache,
struct btrfs_key *node_key, struct btrfs_key *node_key,
struct btrfs_backref_node *cur) struct btrfs_backref_node *cur)
{ {
struct btrfs_fs_info *fs_info = cache->fs_info;
struct btrfs_backref_edge *edge; struct btrfs_backref_edge *edge;
struct btrfs_backref_node *exist; struct btrfs_backref_node *exist;
int ret; int ret;
...@@ -3462,25 +3461,21 @@ int btrfs_backref_add_tree_node(struct btrfs_backref_cache *cache, ...@@ -3462,25 +3461,21 @@ int btrfs_backref_add_tree_node(struct btrfs_backref_cache *cache,
ret = handle_direct_tree_backref(cache, &key, cur); ret = handle_direct_tree_backref(cache, &key, cur);
if (ret < 0) if (ret < 0)
goto out; goto out;
continue; } else if (key.type == BTRFS_TREE_BLOCK_REF_KEY) {
} else if (unlikely(key.type == BTRFS_EXTENT_REF_V0_KEY)) { /*
ret = -EINVAL; * key.type == BTRFS_TREE_BLOCK_REF_KEY, inline ref
btrfs_print_v0_err(fs_info); * offset means the root objectid. We need to search
btrfs_handle_fs_error(fs_info, ret, NULL); * the tree to get its parent bytenr.
goto out; */
} else if (key.type != BTRFS_TREE_BLOCK_REF_KEY) { ret = handle_indirect_tree_backref(cache, path, &key, node_key,
continue; cur);
if (ret < 0)
goto out;
} }
/* /*
* key.type == BTRFS_TREE_BLOCK_REF_KEY, inline ref offset * Unrecognized tree backref items (if it can pass tree-checker)
* means the root objectid. We need to search the tree to get * would be ignored.
* its parent bytenr.
*/ */
ret = handle_indirect_tree_backref(cache, path, &key, node_key,
cur);
if (ret < 0)
goto out;
} }
ret = 0; ret = 0;
cur->checked = 1; cur->checked = 1;
......
...@@ -166,8 +166,10 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans, ...@@ -166,8 +166,10 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
num_refs = btrfs_extent_refs(leaf, ei); num_refs = btrfs_extent_refs(leaf, ei);
extent_flags = btrfs_extent_flags(leaf, ei); extent_flags = btrfs_extent_flags(leaf, ei);
} else { } else {
ret = -EINVAL; ret = -EUCLEAN;
btrfs_print_v0_err(fs_info); btrfs_err(fs_info,
"unexpected extent item size, has %u expect >= %zu",
item_size, sizeof(*ei));
if (trans) if (trans)
btrfs_abort_transaction(trans, ret); btrfs_abort_transaction(trans, ret);
else else
...@@ -603,12 +605,12 @@ static noinline int remove_extent_data_ref(struct btrfs_trans_handle *trans, ...@@ -603,12 +605,12 @@ static noinline int remove_extent_data_ref(struct btrfs_trans_handle *trans,
ref2 = btrfs_item_ptr(leaf, path->slots[0], ref2 = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_shared_data_ref); struct btrfs_shared_data_ref);
num_refs = btrfs_shared_data_ref_count(leaf, ref2); num_refs = btrfs_shared_data_ref_count(leaf, ref2);
} else if (unlikely(key.type == BTRFS_EXTENT_REF_V0_KEY)) {
btrfs_print_v0_err(trans->fs_info);
btrfs_abort_transaction(trans, -EINVAL);
return -EINVAL;
} else { } else {
BUG(); btrfs_err(trans->fs_info,
"unrecognized backref key (%llu %u %llu)",
key.objectid, key.type, key.offset);
btrfs_abort_transaction(trans, -EUCLEAN);
return -EUCLEAN;
} }
BUG_ON(num_refs < refs_to_drop); BUG_ON(num_refs < refs_to_drop);
...@@ -639,7 +641,6 @@ static noinline u32 extent_data_ref_count(struct btrfs_path *path, ...@@ -639,7 +641,6 @@ static noinline u32 extent_data_ref_count(struct btrfs_path *path,
leaf = path->nodes[0]; leaf = path->nodes[0];
btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
BUG_ON(key.type == BTRFS_EXTENT_REF_V0_KEY);
if (iref) { if (iref) {
/* /*
* If type is invalid, we should have bailed out earlier than * If type is invalid, we should have bailed out earlier than
...@@ -860,8 +861,10 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans, ...@@ -860,8 +861,10 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
leaf = path->nodes[0]; leaf = path->nodes[0];
item_size = btrfs_item_size(leaf, path->slots[0]); item_size = btrfs_item_size(leaf, path->slots[0]);
if (unlikely(item_size < sizeof(*ei))) { if (unlikely(item_size < sizeof(*ei))) {
err = -EINVAL; err = -EUCLEAN;
btrfs_print_v0_err(fs_info); btrfs_err(fs_info,
"unexpected extent item size, has %llu expect >= %zu",
item_size, sizeof(*ei));
btrfs_abort_transaction(trans, err); btrfs_abort_transaction(trans, err);
goto out; goto out;
} }
...@@ -1662,8 +1665,10 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans, ...@@ -1662,8 +1665,10 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
item_size = btrfs_item_size(leaf, path->slots[0]); item_size = btrfs_item_size(leaf, path->slots[0]);
if (unlikely(item_size < sizeof(*ei))) { if (unlikely(item_size < sizeof(*ei))) {
err = -EINVAL; err = -EUCLEAN;
btrfs_print_v0_err(fs_info); btrfs_err(fs_info,
"unexpected extent item size, has %u expect >= %zu",
item_size, sizeof(*ei));
btrfs_abort_transaction(trans, err); btrfs_abort_transaction(trans, err);
goto out; goto out;
} }
...@@ -3091,8 +3096,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans, ...@@ -3091,8 +3096,10 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
leaf = path->nodes[0]; leaf = path->nodes[0];
item_size = btrfs_item_size(leaf, extent_slot); item_size = btrfs_item_size(leaf, extent_slot);
if (unlikely(item_size < sizeof(*ei))) { if (unlikely(item_size < sizeof(*ei))) {
ret = -EINVAL; ret = -EUCLEAN;
btrfs_print_v0_err(info); btrfs_err(trans->fs_info,
"unexpected extent item size, has %u expect >= %zu",
item_size, sizeof(*ei));
btrfs_abort_transaction(trans, ret); btrfs_abort_transaction(trans, ret);
goto out; goto out;
} }
......
...@@ -256,12 +256,6 @@ void __cold _btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...@@ -256,12 +256,6 @@ void __cold _btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt,
} }
#endif #endif
void __cold btrfs_print_v0_err(struct btrfs_fs_info *fs_info)
{
btrfs_err(fs_info,
"Unsupported V0 extent filesystem detected. Aborting. Please re-create your filesystem with a newer kernel");
}
#if BITS_PER_LONG == 32 #if BITS_PER_LONG == 32
void __cold btrfs_warn_32bit_limit(struct btrfs_fs_info *fs_info) void __cold btrfs_warn_32bit_limit(struct btrfs_fs_info *fs_info)
{ {
......
...@@ -181,8 +181,6 @@ do { \ ...@@ -181,8 +181,6 @@ do { \
#define ASSERT(expr) (void)(expr) #define ASSERT(expr) (void)(expr)
#endif #endif
void __cold btrfs_print_v0_err(struct btrfs_fs_info *fs_info);
__printf(5, 6) __printf(5, 6)
__cold __cold
void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function, void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function,
......
...@@ -95,8 +95,10 @@ static void print_extent_item(const struct extent_buffer *eb, int slot, int type ...@@ -95,8 +95,10 @@ static void print_extent_item(const struct extent_buffer *eb, int slot, int type
int ref_index = 0; int ref_index = 0;
if (unlikely(item_size < sizeof(*ei))) { if (unlikely(item_size < sizeof(*ei))) {
btrfs_print_v0_err(eb->fs_info); btrfs_err(eb->fs_info,
btrfs_handle_fs_error(eb->fs_info, -EINVAL, NULL); "unexpected extent item size, has %u expect >= %zu",
item_size, sizeof(*ei));
btrfs_handle_fs_error(eb->fs_info, -EUCLEAN, NULL);
} }
ei = btrfs_item_ptr(eb, slot, struct btrfs_extent_item); ei = btrfs_item_ptr(eb, slot, struct btrfs_extent_item);
...@@ -291,10 +293,6 @@ void btrfs_print_leaf(const struct extent_buffer *l) ...@@ -291,10 +293,6 @@ void btrfs_print_leaf(const struct extent_buffer *l)
btrfs_file_extent_num_bytes(l, fi), btrfs_file_extent_num_bytes(l, fi),
btrfs_file_extent_ram_bytes(l, fi)); btrfs_file_extent_ram_bytes(l, fi));
break; break;
case BTRFS_EXTENT_REF_V0_KEY:
btrfs_print_v0_err(fs_info);
btrfs_handle_fs_error(fs_info, -EINVAL, NULL);
break;
case BTRFS_BLOCK_GROUP_ITEM_KEY: case BTRFS_BLOCK_GROUP_ITEM_KEY:
bi = btrfs_item_ptr(l, i, bi = btrfs_item_ptr(l, i,
struct btrfs_block_group_item); struct btrfs_block_group_item);
......
...@@ -3256,12 +3256,13 @@ static int add_tree_block(struct reloc_control *rc, ...@@ -3256,12 +3256,13 @@ static int add_tree_block(struct reloc_control *rc,
if (type == BTRFS_TREE_BLOCK_REF_KEY) if (type == BTRFS_TREE_BLOCK_REF_KEY)
owner = btrfs_extent_inline_ref_offset(eb, iref); owner = btrfs_extent_inline_ref_offset(eb, iref);
} }
} else if (unlikely(item_size == sizeof(struct btrfs_extent_item_v0))) {
btrfs_print_v0_err(eb->fs_info);
btrfs_handle_fs_error(eb->fs_info, -EINVAL, NULL);
return -EINVAL;
} else { } else {
BUG(); btrfs_print_leaf(eb);
btrfs_err(rc->block_group->fs_info,
"unrecognized tree backref at tree block %llu slot %u",
eb->start, path->slots[0]);
btrfs_release_path(path);
return -EUCLEAN;
} }
btrfs_release_path(path); btrfs_release_path(path);
......
...@@ -38,7 +38,6 @@ struct find_free_extent_ctl; ...@@ -38,7 +38,6 @@ struct find_free_extent_ctl;
__print_symbolic(type, \ __print_symbolic(type, \
{ BTRFS_TREE_BLOCK_REF_KEY, "TREE_BLOCK_REF" }, \ { BTRFS_TREE_BLOCK_REF_KEY, "TREE_BLOCK_REF" }, \
{ BTRFS_EXTENT_DATA_REF_KEY, "EXTENT_DATA_REF" }, \ { BTRFS_EXTENT_DATA_REF_KEY, "EXTENT_DATA_REF" }, \
{ BTRFS_EXTENT_REF_V0_KEY, "EXTENT_REF_V0" }, \
{ BTRFS_SHARED_BLOCK_REF_KEY, "SHARED_BLOCK_REF" }, \ { BTRFS_SHARED_BLOCK_REF_KEY, "SHARED_BLOCK_REF" }, \
{ BTRFS_SHARED_DATA_REF_KEY, "SHARED_DATA_REF" }) { BTRFS_SHARED_DATA_REF_KEY, "SHARED_DATA_REF" })
......
...@@ -220,7 +220,11 @@ ...@@ -220,7 +220,11 @@
#define BTRFS_EXTENT_DATA_REF_KEY 178 #define BTRFS_EXTENT_DATA_REF_KEY 178
#define BTRFS_EXTENT_REF_V0_KEY 180 /*
* Obsolete key. Defintion removed in 6.6, value may be reused in the future.
*
* #define BTRFS_EXTENT_REF_V0_KEY 180
*/
#define BTRFS_SHARED_BLOCK_REF_KEY 182 #define BTRFS_SHARED_BLOCK_REF_KEY 182
......
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