Skip to content

Commit 5024282

Browse files
fdmananakdave
authored andcommitted
btrfs: check for NULL root after calls to btrfs_extent_root()
btrfs_extent_root() can return a NULL pointer in case the root we are looking for is not in the rb tree that tracks roots. So add checks to every caller that is missing such check to log a message and return an error. The same applies to callers of btrfs_block_group_root(), since it calls btrfs_extent_root(). Reported-by: Chris Mason <[email protected]> Link: https://lore.kernel.org/linux-btrfs/[email protected]/ Reviewed-by: Boris Burkov <[email protected]> Signed-off-by: Filipe Manana <[email protected]> Reviewed-by: David Sterba <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent fc1cd1f commit 5024282

8 files changed

Lines changed: 195 additions & 9 deletions

File tree

fs/btrfs/backref.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1393,6 +1393,13 @@ static int find_parent_nodes(struct btrfs_backref_walk_ctx *ctx,
13931393
.indirect_missing_keys = PREFTREE_INIT
13941394
};
13951395

1396+
if (unlikely(!root)) {
1397+
btrfs_err(ctx->fs_info,
1398+
"missing extent root for extent at bytenr %llu",
1399+
ctx->bytenr);
1400+
return -EUCLEAN;
1401+
}
1402+
13961403
/* Roots ulist is not needed when using a sharedness check context. */
13971404
if (sc)
13981405
ASSERT(ctx->roots == NULL);
@@ -2204,6 +2211,13 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
22042211
struct btrfs_extent_item *ei;
22052212
struct btrfs_key key;
22062213

2214+
if (unlikely(!extent_root)) {
2215+
btrfs_err(fs_info,
2216+
"missing extent root for extent at bytenr %llu",
2217+
logical);
2218+
return -EUCLEAN;
2219+
}
2220+
22072221
key.objectid = logical;
22082222
if (btrfs_fs_incompat(fs_info, SKINNY_METADATA))
22092223
key.type = BTRFS_METADATA_ITEM_KEY;
@@ -2851,6 +2865,13 @@ int btrfs_backref_iter_start(struct btrfs_backref_iter *iter, u64 bytenr)
28512865
struct btrfs_key key;
28522866
int ret;
28532867

2868+
if (unlikely(!extent_root)) {
2869+
btrfs_err(fs_info,
2870+
"missing extent root for extent at bytenr %llu",
2871+
bytenr);
2872+
return -EUCLEAN;
2873+
}
2874+
28542875
key.objectid = bytenr;
28552876
key.type = BTRFS_METADATA_ITEM_KEY;
28562877
key.offset = (u64)-1;
@@ -2987,6 +3008,13 @@ int btrfs_backref_iter_next(struct btrfs_backref_iter *iter)
29873008

29883009
/* We're at keyed items, there is no inline item, go to the next one */
29893010
extent_root = btrfs_extent_root(iter->fs_info, iter->bytenr);
3011+
if (unlikely(!extent_root)) {
3012+
btrfs_err(iter->fs_info,
3013+
"missing extent root for extent at bytenr %llu",
3014+
iter->bytenr);
3015+
return -EUCLEAN;
3016+
}
3017+
29903018
ret = btrfs_next_item(extent_root, iter->path);
29913019
if (ret)
29923020
return ret;

fs/btrfs/block-group.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -739,6 +739,12 @@ static int load_extent_tree_free(struct btrfs_caching_control *caching_ctl)
739739

740740
last = max_t(u64, block_group->start, BTRFS_SUPER_INFO_OFFSET);
741741
extent_root = btrfs_extent_root(fs_info, last);
742+
if (unlikely(!extent_root)) {
743+
btrfs_err(fs_info,
744+
"missing extent root for block group at offset %llu",
745+
block_group->start);
746+
return -EUCLEAN;
747+
}
742748

743749
#ifdef CONFIG_BTRFS_DEBUG
744750
/*
@@ -1061,6 +1067,11 @@ static int remove_block_group_item(struct btrfs_trans_handle *trans,
10611067
int ret;
10621068

10631069
root = btrfs_block_group_root(fs_info);
1070+
if (unlikely(!root)) {
1071+
btrfs_err(fs_info, "missing block group root");
1072+
return -EUCLEAN;
1073+
}
1074+
10641075
key.objectid = block_group->start;
10651076
key.type = BTRFS_BLOCK_GROUP_ITEM_KEY;
10661077
key.offset = block_group->length;
@@ -1349,6 +1360,11 @@ struct btrfs_trans_handle *btrfs_start_trans_remove_block_group(
13491360
struct btrfs_chunk_map *map;
13501361
unsigned int num_items;
13511362

1363+
if (unlikely(!root)) {
1364+
btrfs_err(fs_info, "missing block group root");
1365+
return ERR_PTR(-EUCLEAN);
1366+
}
1367+
13521368
map = btrfs_find_chunk_map(fs_info, chunk_offset, 1);
13531369
ASSERT(map != NULL);
13541370
ASSERT(map->start == chunk_offset);
@@ -2140,6 +2156,11 @@ static int find_first_block_group(struct btrfs_fs_info *fs_info,
21402156
int ret;
21412157
struct btrfs_key found_key;
21422158

2159+
if (unlikely(!root)) {
2160+
btrfs_err(fs_info, "missing block group root");
2161+
return -EUCLEAN;
2162+
}
2163+
21432164
btrfs_for_each_slot(root, key, &found_key, path, ret) {
21442165
if (found_key.objectid >= key->objectid &&
21452166
found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) {
@@ -2714,6 +2735,11 @@ static int insert_block_group_item(struct btrfs_trans_handle *trans,
27142735
size_t size;
27152736
int ret;
27162737

2738+
if (unlikely(!root)) {
2739+
btrfs_err(fs_info, "missing block group root");
2740+
return -EUCLEAN;
2741+
}
2742+
27172743
spin_lock(&block_group->lock);
27182744
btrfs_set_stack_block_group_v2_used(&bgi, block_group->used);
27192745
btrfs_set_stack_block_group_v2_chunk_objectid(&bgi, block_group->global_root_id);
@@ -3049,6 +3075,11 @@ int btrfs_inc_block_group_ro(struct btrfs_block_group *cache,
30493075
int ret;
30503076
bool dirty_bg_running;
30513077

3078+
if (unlikely(!root)) {
3079+
btrfs_err(fs_info, "missing block group root");
3080+
return -EUCLEAN;
3081+
}
3082+
30523083
/*
30533084
* This can only happen when we are doing read-only scrub on read-only
30543085
* mount.
@@ -3193,6 +3224,11 @@ static int update_block_group_item(struct btrfs_trans_handle *trans,
31933224
u64 used, remap_bytes;
31943225
u32 identity_remap_count;
31953226

3227+
if (unlikely(!root)) {
3228+
btrfs_err(fs_info, "missing block group root");
3229+
return -EUCLEAN;
3230+
}
3231+
31963232
/*
31973233
* Block group items update can be triggered out of commit transaction
31983234
* critical section, thus we need a consistent view of used bytes.

fs/btrfs/disk-io.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,7 +1591,7 @@ static int find_newest_super_backup(struct btrfs_fs_info *info)
15911591
* this will bump the backup pointer by one when it is
15921592
* done
15931593
*/
1594-
static void backup_super_roots(struct btrfs_fs_info *info)
1594+
static int backup_super_roots(struct btrfs_fs_info *info)
15951595
{
15961596
const int next_backup = info->backup_root_index;
15971597
struct btrfs_root_backup *root_backup;
@@ -1623,6 +1623,11 @@ static void backup_super_roots(struct btrfs_fs_info *info)
16231623
struct btrfs_root *extent_root = btrfs_extent_root(info, 0);
16241624
struct btrfs_root *csum_root = btrfs_csum_root(info, 0);
16251625

1626+
if (unlikely(!extent_root)) {
1627+
btrfs_err(info, "missing extent root for extent at bytenr 0");
1628+
return -EUCLEAN;
1629+
}
1630+
16261631
btrfs_set_backup_extent_root(root_backup,
16271632
extent_root->node->start);
16281633
btrfs_set_backup_extent_root_gen(root_backup,
@@ -1670,6 +1675,8 @@ static void backup_super_roots(struct btrfs_fs_info *info)
16701675
memcpy(&info->super_copy->super_roots,
16711676
&info->super_for_commit->super_roots,
16721677
sizeof(*root_backup) * BTRFS_NUM_BACKUP_ROOTS);
1678+
1679+
return 0;
16731680
}
16741681

16751682
/*
@@ -4051,8 +4058,11 @@ int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors)
40514058
* not from fsync where the tree roots in fs_info have not
40524059
* been consistent on disk.
40534060
*/
4054-
if (max_mirrors == 0)
4055-
backup_super_roots(fs_info);
4061+
if (max_mirrors == 0) {
4062+
ret = backup_super_roots(fs_info);
4063+
if (ret < 0)
4064+
return ret;
4065+
}
40564066

40574067
sb = fs_info->super_for_commit;
40584068
dev_item = &sb->dev_item;

fs/btrfs/extent-tree.c

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,12 @@ int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len)
7575
struct btrfs_key key;
7676
BTRFS_PATH_AUTO_FREE(path);
7777

78+
if (unlikely(!root)) {
79+
btrfs_err(fs_info,
80+
"missing extent root for extent at bytenr %llu", start);
81+
return -EUCLEAN;
82+
}
83+
7884
path = btrfs_alloc_path();
7985
if (!path)
8086
return -ENOMEM;
@@ -131,6 +137,12 @@ int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
131137
key.offset = offset;
132138

133139
extent_root = btrfs_extent_root(fs_info, bytenr);
140+
if (unlikely(!extent_root)) {
141+
btrfs_err(fs_info,
142+
"missing extent root for extent at bytenr %llu", bytenr);
143+
return -EUCLEAN;
144+
}
145+
134146
ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
135147
if (ret < 0)
136148
return ret;
@@ -436,6 +448,12 @@ static noinline int lookup_extent_data_ref(struct btrfs_trans_handle *trans,
436448
int recow;
437449
int ret;
438450

451+
if (unlikely(!root)) {
452+
btrfs_err(trans->fs_info,
453+
"missing extent root for extent at bytenr %llu", bytenr);
454+
return -EUCLEAN;
455+
}
456+
439457
key.objectid = bytenr;
440458
if (parent) {
441459
key.type = BTRFS_SHARED_DATA_REF_KEY;
@@ -510,6 +528,12 @@ static noinline int insert_extent_data_ref(struct btrfs_trans_handle *trans,
510528
u32 num_refs;
511529
int ret;
512530

531+
if (unlikely(!root)) {
532+
btrfs_err(trans->fs_info,
533+
"missing extent root for extent at bytenr %llu", bytenr);
534+
return -EUCLEAN;
535+
}
536+
513537
key.objectid = bytenr;
514538
if (node->parent) {
515539
key.type = BTRFS_SHARED_DATA_REF_KEY;
@@ -668,6 +692,12 @@ static noinline int lookup_tree_block_ref(struct btrfs_trans_handle *trans,
668692
struct btrfs_key key;
669693
int ret;
670694

695+
if (unlikely(!root)) {
696+
btrfs_err(trans->fs_info,
697+
"missing extent root for extent at bytenr %llu", bytenr);
698+
return -EUCLEAN;
699+
}
700+
671701
key.objectid = bytenr;
672702
if (parent) {
673703
key.type = BTRFS_SHARED_BLOCK_REF_KEY;
@@ -692,6 +722,12 @@ static noinline int insert_tree_block_ref(struct btrfs_trans_handle *trans,
692722
struct btrfs_key key;
693723
int ret;
694724

725+
if (unlikely(!root)) {
726+
btrfs_err(trans->fs_info,
727+
"missing extent root for extent at bytenr %llu", bytenr);
728+
return -EUCLEAN;
729+
}
730+
695731
key.objectid = bytenr;
696732
if (node->parent) {
697733
key.type = BTRFS_SHARED_BLOCK_REF_KEY;
@@ -782,6 +818,12 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
782818
bool skinny_metadata = btrfs_fs_incompat(fs_info, SKINNY_METADATA);
783819
int needed;
784820

821+
if (unlikely(!root)) {
822+
btrfs_err(fs_info,
823+
"missing extent root for extent at bytenr %llu", bytenr);
824+
return -EUCLEAN;
825+
}
826+
785827
key.objectid = bytenr;
786828
key.type = BTRFS_EXTENT_ITEM_KEY;
787829
key.offset = num_bytes;
@@ -1680,6 +1722,12 @@ static int run_delayed_extent_op(struct btrfs_trans_handle *trans,
16801722
}
16811723

16821724
root = btrfs_extent_root(fs_info, key.objectid);
1725+
if (unlikely(!root)) {
1726+
btrfs_err(fs_info,
1727+
"missing extent root for extent at bytenr %llu",
1728+
key.objectid);
1729+
return -EUCLEAN;
1730+
}
16831731
again:
16841732
ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
16851733
if (ret < 0) {
@@ -2379,6 +2427,12 @@ static noinline int check_committed_ref(struct btrfs_inode *inode,
23792427
int type;
23802428
int ret;
23812429

2430+
if (unlikely(!extent_root)) {
2431+
btrfs_err(fs_info,
2432+
"missing extent root for extent at bytenr %llu", bytenr);
2433+
return -EUCLEAN;
2434+
}
2435+
23822436
key.objectid = bytenr;
23832437
key.type = BTRFS_EXTENT_ITEM_KEY;
23842438
key.offset = (u64)-1;
@@ -3222,7 +3276,11 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
32223276
u64 delayed_ref_root = href->owning_root;
32233277

32243278
extent_root = btrfs_extent_root(info, bytenr);
3225-
ASSERT(extent_root);
3279+
if (unlikely(!extent_root)) {
3280+
btrfs_err(info,
3281+
"missing extent root for extent at bytenr %llu", bytenr);
3282+
return -EUCLEAN;
3283+
}
32263284

32273285
path = btrfs_alloc_path();
32283286
if (!path)
@@ -4939,11 +4997,18 @@ static int alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
49394997
size += btrfs_extent_inline_ref_size(BTRFS_EXTENT_OWNER_REF_KEY);
49404998
size += btrfs_extent_inline_ref_size(type);
49414999

5000+
extent_root = btrfs_extent_root(fs_info, ins->objectid);
5001+
if (unlikely(!extent_root)) {
5002+
btrfs_err(fs_info,
5003+
"missing extent root for extent at bytenr %llu",
5004+
ins->objectid);
5005+
return -EUCLEAN;
5006+
}
5007+
49425008
path = btrfs_alloc_path();
49435009
if (!path)
49445010
return -ENOMEM;
49455011

4946-
extent_root = btrfs_extent_root(fs_info, ins->objectid);
49475012
ret = btrfs_insert_empty_item(trans, extent_root, path, ins, size);
49485013
if (ret) {
49495014
btrfs_free_path(path);
@@ -5019,11 +5084,18 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
50195084
size += sizeof(*block_info);
50205085
}
50215086

5087+
extent_root = btrfs_extent_root(fs_info, extent_key.objectid);
5088+
if (unlikely(!extent_root)) {
5089+
btrfs_err(fs_info,
5090+
"missing extent root for extent at bytenr %llu",
5091+
extent_key.objectid);
5092+
return -EUCLEAN;
5093+
}
5094+
50225095
path = btrfs_alloc_path();
50235096
if (!path)
50245097
return -ENOMEM;
50255098

5026-
extent_root = btrfs_extent_root(fs_info, extent_key.objectid);
50275099
ret = btrfs_insert_empty_item(trans, extent_root, path, &extent_key,
50285100
size);
50295101
if (ret) {

fs/btrfs/free-space-tree.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,6 +1073,14 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
10731073
if (ret)
10741074
return ret;
10751075

1076+
extent_root = btrfs_extent_root(trans->fs_info, block_group->start);
1077+
if (unlikely(!extent_root)) {
1078+
btrfs_err(trans->fs_info,
1079+
"missing extent root for block group at offset %llu",
1080+
block_group->start);
1081+
return -EUCLEAN;
1082+
}
1083+
10761084
mutex_lock(&block_group->free_space_lock);
10771085

10781086
/*
@@ -1086,7 +1094,6 @@ static int populate_free_space_tree(struct btrfs_trans_handle *trans,
10861094
key.type = BTRFS_EXTENT_ITEM_KEY;
10871095
key.offset = 0;
10881096

1089-
extent_root = btrfs_extent_root(trans->fs_info, key.objectid);
10901097
ret = btrfs_search_slot_for_read(extent_root, &key, path, 1, 0);
10911098
if (ret < 0)
10921099
goto out_locked;

fs/btrfs/qgroup.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3740,6 +3740,14 @@ static int qgroup_rescan_leaf(struct btrfs_trans_handle *trans,
37403740
mutex_lock(&fs_info->qgroup_rescan_lock);
37413741
extent_root = btrfs_extent_root(fs_info,
37423742
fs_info->qgroup_rescan_progress.objectid);
3743+
if (unlikely(!extent_root)) {
3744+
btrfs_err(fs_info,
3745+
"missing extent root for extent at bytenr %llu",
3746+
fs_info->qgroup_rescan_progress.objectid);
3747+
mutex_unlock(&fs_info->qgroup_rescan_lock);
3748+
return -EUCLEAN;
3749+
}
3750+
37433751
ret = btrfs_search_slot_for_read(extent_root,
37443752
&fs_info->qgroup_rescan_progress,
37453753
path, 1, 0);

0 commit comments

Comments
 (0)