Skip to content

Commit ba3c2b1

Browse files
lorddoskiaskdave
authored andcommitted
btrfs: Add graceful handling of V0 extents
Following the removal of the v0 handling code let's be courteous and print an error message when such extents are handled. In the cases where we have a transaction just abort it, otherwise just call btrfs_handle_fs_error. Both cases result in the FS being re-mounted RO. In case the error handling would be too intrusive, leave the BUG_ON in place, like extent_data_ref_count, other proper handling would catch that earlier. Signed-off-by: Nikolay Borisov <nborisov@suse.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent a79865c commit ba3c2b1

File tree

4 files changed

+72
-10
lines changed

4 files changed

+72
-10
lines changed

fs/btrfs/ctree.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3432,6 +3432,13 @@ static inline void assfail(char *expr, char *file, int line)
34323432
#define ASSERT(expr) ((void)0)
34333433
#endif
34343434

3435+
__cold
3436+
static inline void btrfs_print_v0_err(struct btrfs_fs_info *fs_info)
3437+
{
3438+
btrfs_err(fs_info,
3439+
"Unsupported V0 extent filesystem detected. Aborting. Please re-create your filesystem with a newer kernel");
3440+
}
3441+
34353442
__printf(5, 6)
34363443
__cold
34373444
void __btrfs_handle_fs_error(struct btrfs_fs_info *fs_info, const char *function,

fs/btrfs/extent-tree.c

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -867,8 +867,16 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
867867
num_refs = btrfs_extent_refs(leaf, ei);
868868
extent_flags = btrfs_extent_flags(leaf, ei);
869869
} else {
870-
BUG();
870+
ret = -EINVAL;
871+
btrfs_print_v0_err(fs_info);
872+
if (trans)
873+
btrfs_abort_transaction(trans, ret);
874+
else
875+
btrfs_handle_fs_error(fs_info, ret, NULL);
876+
877+
goto out_free;
871878
}
879+
872880
BUG_ON(num_refs == 0);
873881
} else {
874882
num_refs = 0;
@@ -1296,6 +1304,10 @@ static noinline int remove_extent_data_ref(struct btrfs_trans_handle *trans,
12961304
ref2 = btrfs_item_ptr(leaf, path->slots[0],
12971305
struct btrfs_shared_data_ref);
12981306
num_refs = btrfs_shared_data_ref_count(leaf, ref2);
1307+
} else if (key.type == BTRFS_EXTENT_REF_V0_KEY) {
1308+
btrfs_print_v0_err(trans->fs_info);
1309+
btrfs_abort_transaction(trans, -EINVAL);
1310+
return -EINVAL;
12991311
} else {
13001312
BUG();
13011313
}
@@ -1328,6 +1340,8 @@ static noinline u32 extent_data_ref_count(struct btrfs_path *path,
13281340

13291341
leaf = path->nodes[0];
13301342
btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
1343+
1344+
BUG_ON(key.type == BTRFS_EXTENT_REF_V0_KEY);
13311345
if (iref) {
13321346
/*
13331347
* If type is invalid, we should have bailed out earlier than
@@ -1541,7 +1555,12 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
15411555

15421556
leaf = path->nodes[0];
15431557
item_size = btrfs_item_size_nr(leaf, path->slots[0]);
1544-
BUG_ON(item_size < sizeof(*ei));
1558+
if (item_size < sizeof(*ei)) {
1559+
err = -EINVAL;
1560+
btrfs_print_v0_err(fs_info);
1561+
btrfs_abort_transaction(trans, err);
1562+
goto out;
1563+
}
15451564

15461565
ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
15471566
flags = btrfs_extent_flags(leaf, ei);
@@ -2265,7 +2284,14 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
22652284

22662285
leaf = path->nodes[0];
22672286
item_size = btrfs_item_size_nr(leaf, path->slots[0]);
2268-
BUG_ON(item_size < sizeof(*ei));
2287+
2288+
if (item_size < sizeof(*ei)) {
2289+
err = -EINVAL;
2290+
btrfs_print_v0_err(fs_info);
2291+
btrfs_abort_transaction(trans, err);
2292+
goto out;
2293+
}
2294+
22692295
ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
22702296
__run_delayed_extent_op(extent_op, leaf, ei);
22712297

@@ -6796,7 +6822,12 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
67966822

67976823
leaf = path->nodes[0];
67986824
item_size = btrfs_item_size_nr(leaf, extent_slot);
6799-
BUG_ON(item_size < sizeof(*ei));
6825+
if (item_size < sizeof(*ei)) {
6826+
ret = -EINVAL;
6827+
btrfs_print_v0_err(info);
6828+
btrfs_abort_transaction(trans, ret);
6829+
goto out;
6830+
}
68006831
ei = btrfs_item_ptr(leaf, extent_slot,
68016832
struct btrfs_extent_item);
68026833
if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID &&

fs/btrfs/print-tree.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@ static void print_extent_item(struct extent_buffer *eb, int slot, int type)
5252
u64 offset;
5353
int ref_index = 0;
5454

55-
if (item_size < sizeof(*ei))
56-
BUG();
55+
if (item_size < sizeof(*ei)) {
56+
btrfs_print_v0_err(eb->fs_info);
57+
btrfs_handle_fs_error(eb->fs_info, -EINVAL, NULL);
58+
}
5759

5860
ei = btrfs_item_ptr(eb, slot, struct btrfs_extent_item);
5961
flags = btrfs_extent_flags(eb, ei);
@@ -256,7 +258,8 @@ void btrfs_print_leaf(struct extent_buffer *l)
256258
btrfs_file_extent_ram_bytes(l, fi));
257259
break;
258260
case BTRFS_EXTENT_REF_V0_KEY:
259-
BUG();
261+
btrfs_print_v0_err(fs_info);
262+
btrfs_handle_fs_error(fs_info, -EINVAL, NULL);
260263
break;
261264
case BTRFS_BLOCK_GROUP_ITEM_KEY:
262265
bi = btrfs_item_ptr(l, i,

fs/btrfs/relocation.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,11 @@ int find_inline_backref(struct extent_buffer *leaf, int slot,
598598
btrfs_item_key_to_cpu(leaf, &key, slot);
599599

600600
item_size = btrfs_item_size_nr(leaf, slot);
601+
if (item_size < sizeof(*ei)) {
602+
btrfs_print_v0_err(leaf->fs_info);
603+
btrfs_handle_fs_error(leaf->fs_info, -EINVAL, NULL);
604+
return 1;
605+
}
601606
ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item);
602607
WARN_ON(!(btrfs_extent_flags(leaf, ei) &
603608
BTRFS_EXTENT_FLAG_TREE_BLOCK));
@@ -782,7 +787,6 @@ struct backref_node *build_backref_tree(struct reloc_control *rc,
782787
goto next;
783788
}
784789

785-
ASSERT(key.type != BTRFS_EXTENT_REF_V0_KEY);
786790
if (key.type == BTRFS_SHARED_BLOCK_REF_KEY) {
787791
if (key.objectid == key.offset) {
788792
/*
@@ -826,6 +830,12 @@ struct backref_node *build_backref_tree(struct reloc_control *rc,
826830
edge->node[UPPER] = upper;
827831

828832
goto next;
833+
} else if (key.type == BTRFS_EXTENT_REF_V0_KEY) {
834+
err = -EINVAL;
835+
btrfs_print_v0_err(rc->extent_root->fs_info);
836+
btrfs_handle_fs_error(rc->extent_root->fs_info, err,
837+
NULL);
838+
goto out;
829839
} else if (key.type != BTRFS_TREE_BLOCK_REF_KEY) {
830840
goto next;
831841
}
@@ -3315,6 +3325,10 @@ static int add_tree_block(struct reloc_control *rc,
33153325
level = (int)extent_key->offset;
33163326
}
33173327
generation = btrfs_extent_generation(eb, ei);
3328+
} else if (item_size == sizeof(struct btrfs_extent_item_v0)) {
3329+
btrfs_print_v0_err(eb->fs_info);
3330+
btrfs_handle_fs_error(eb->fs_info, -EINVAL, NULL);
3331+
return -EINVAL;
33183332
} else {
33193333
BUG();
33203334
}
@@ -3720,7 +3734,6 @@ int add_data_references(struct reloc_control *rc,
37203734
if (key.objectid != extent_key->objectid)
37213735
break;
37223736

3723-
BUG_ON(key.type == BTRFS_EXTENT_REF_V0_KEY);
37243737
if (key.type == BTRFS_SHARED_DATA_REF_KEY) {
37253738
ret = __add_tree_block(rc, key.offset, blocksize,
37263739
blocks);
@@ -3729,6 +3742,10 @@ int add_data_references(struct reloc_control *rc,
37293742
struct btrfs_extent_data_ref);
37303743
ret = find_data_references(rc, extent_key,
37313744
eb, dref, blocks);
3745+
} else if (key.type == BTRFS_EXTENT_REF_V0_KEY) {
3746+
btrfs_print_v0_err(eb->fs_info);
3747+
btrfs_handle_fs_error(eb->fs_info, -EINVAL, NULL);
3748+
ret = -EINVAL;
37323749
} else {
37333750
ret = 0;
37343751
}
@@ -3967,7 +3984,11 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
39673984
flags = btrfs_extent_flags(path->nodes[0], ei);
39683985
ret = check_extent_flags(flags);
39693986
BUG_ON(ret);
3970-
3987+
} else if (item_size == sizeof(struct btrfs_extent_item_v0)) {
3988+
err = -EINVAL;
3989+
btrfs_print_v0_err(trans->fs_info);
3990+
btrfs_abort_transaction(trans, err);
3991+
break;
39713992
} else {
39723993
BUG();
39733994
}

0 commit comments

Comments
 (0)