Skip to content

Commit 2b4cb4e

Browse files
fdmananakdave
authored andcommitted
btrfs: check for NULL root after calls to btrfs_csum_root()
btrfs_csum_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. 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 5024282 commit 2b4cb4e

7 files changed

Lines changed: 84 additions & 6 deletions

File tree

fs/btrfs/disk-io.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,6 +1627,10 @@ static int backup_super_roots(struct btrfs_fs_info *info)
16271627
btrfs_err(info, "missing extent root for extent at bytenr 0");
16281628
return -EUCLEAN;
16291629
}
1630+
if (unlikely(!csum_root)) {
1631+
btrfs_err(info, "missing csum root for extent at bytenr 0");
1632+
return -EUCLEAN;
1633+
}
16301634

16311635
btrfs_set_backup_extent_root(root_backup,
16321636
extent_root->node->start);

fs/btrfs/extent-tree.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,8 +1974,15 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
19741974
struct btrfs_root *csum_root;
19751975

19761976
csum_root = btrfs_csum_root(fs_info, head->bytenr);
1977-
ret = btrfs_del_csums(trans, csum_root, head->bytenr,
1978-
head->num_bytes);
1977+
if (unlikely(!csum_root)) {
1978+
btrfs_err(fs_info,
1979+
"missing csum root for extent at bytenr %llu",
1980+
head->bytenr);
1981+
ret = -EUCLEAN;
1982+
} else {
1983+
ret = btrfs_del_csums(trans, csum_root, head->bytenr,
1984+
head->num_bytes);
1985+
}
19791986
}
19801987
}
19811988

@@ -3147,6 +3154,15 @@ static int do_free_extent_accounting(struct btrfs_trans_handle *trans,
31473154
struct btrfs_root *csum_root;
31483155

31493156
csum_root = btrfs_csum_root(trans->fs_info, bytenr);
3157+
if (unlikely(!csum_root)) {
3158+
ret = -EUCLEAN;
3159+
btrfs_abort_transaction(trans, ret);
3160+
btrfs_err(trans->fs_info,
3161+
"missing csum root for extent at bytenr %llu",
3162+
bytenr);
3163+
return ret;
3164+
}
3165+
31503166
ret = btrfs_del_csums(trans, csum_root, bytenr, num_bytes);
31513167
if (unlikely(ret)) {
31523168
btrfs_abort_transaction(trans, ret);

fs/btrfs/file-item.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,13 @@ static int search_csum_tree(struct btrfs_fs_info *fs_info,
308308
/* Current item doesn't contain the desired range, search again */
309309
btrfs_release_path(path);
310310
csum_root = btrfs_csum_root(fs_info, disk_bytenr);
311+
if (unlikely(!csum_root)) {
312+
btrfs_err(fs_info,
313+
"missing csum root for extent at bytenr %llu",
314+
disk_bytenr);
315+
return -EUCLEAN;
316+
}
317+
311318
item = btrfs_lookup_csum(NULL, csum_root, path, disk_bytenr, 0);
312319
if (IS_ERR(item)) {
313320
ret = PTR_ERR(item);

fs/btrfs/inode.c

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2012,6 +2012,13 @@ static int can_nocow_file_extent(struct btrfs_path *path,
20122012
*/
20132013

20142014
csum_root = btrfs_csum_root(root->fs_info, io_start);
2015+
if (unlikely(!csum_root)) {
2016+
btrfs_err(root->fs_info,
2017+
"missing csum root for extent at bytenr %llu", io_start);
2018+
ret = -EUCLEAN;
2019+
goto out;
2020+
}
2021+
20152022
ret = btrfs_lookup_csums_list(csum_root, io_start,
20162023
io_start + args->file_extent.num_bytes - 1,
20172024
NULL, nowait);
@@ -2749,10 +2756,17 @@ static int add_pending_csums(struct btrfs_trans_handle *trans,
27492756
int ret;
27502757

27512758
list_for_each_entry(sum, list, list) {
2752-
trans->adding_csums = true;
2753-
if (!csum_root)
2759+
if (!csum_root) {
27542760
csum_root = btrfs_csum_root(trans->fs_info,
27552761
sum->logical);
2762+
if (unlikely(!csum_root)) {
2763+
btrfs_err(trans->fs_info,
2764+
"missing csum root for extent at bytenr %llu",
2765+
sum->logical);
2766+
return -EUCLEAN;
2767+
}
2768+
}
2769+
trans->adding_csums = true;
27562770
ret = btrfs_csum_file_blocks(trans, csum_root, sum);
27572771
trans->adding_csums = false;
27582772
if (ret)

fs/btrfs/raid56.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2295,8 +2295,7 @@ void raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc,
22952295
static void fill_data_csums(struct btrfs_raid_bio *rbio)
22962296
{
22972297
struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
2298-
struct btrfs_root *csum_root = btrfs_csum_root(fs_info,
2299-
rbio->bioc->full_stripe_logical);
2298+
struct btrfs_root *csum_root;
23002299
const u64 start = rbio->bioc->full_stripe_logical;
23012300
const u32 len = (rbio->nr_data * rbio->stripe_nsectors) <<
23022301
fs_info->sectorsize_bits;
@@ -2329,6 +2328,15 @@ static void fill_data_csums(struct btrfs_raid_bio *rbio)
23292328
goto error;
23302329
}
23312330

2331+
csum_root = btrfs_csum_root(fs_info, rbio->bioc->full_stripe_logical);
2332+
if (unlikely(!csum_root)) {
2333+
btrfs_err(fs_info,
2334+
"missing csum root for extent at bytenr %llu",
2335+
rbio->bioc->full_stripe_logical);
2336+
ret = -EUCLEAN;
2337+
goto error;
2338+
}
2339+
23322340
ret = btrfs_lookup_csums_bitmap(csum_root, NULL, start, start + len - 1,
23332341
rbio->csum_buf, rbio->csum_bitmap);
23342342
if (ret < 0)

fs/btrfs/relocation.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5654,6 +5654,14 @@ int btrfs_reloc_clone_csums(struct btrfs_ordered_extent *ordered)
56545654
LIST_HEAD(list);
56555655
int ret;
56565656

5657+
if (unlikely(!csum_root)) {
5658+
btrfs_mark_ordered_extent_error(ordered);
5659+
btrfs_err(fs_info,
5660+
"missing csum root for extent at bytenr %llu",
5661+
disk_bytenr);
5662+
return -EUCLEAN;
5663+
}
5664+
56575665
ret = btrfs_lookup_csums_list(csum_root, disk_bytenr,
56585666
disk_bytenr + ordered->num_bytes - 1,
56595667
&list, false);

fs/btrfs/tree-log.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,13 @@ static noinline int replay_one_extent(struct walk_control *wc)
984984

985985
sums = list_first_entry(&ordered_sums, struct btrfs_ordered_sum, list);
986986
csum_root = btrfs_csum_root(fs_info, sums->logical);
987+
if (unlikely(!csum_root)) {
988+
btrfs_err(fs_info,
989+
"missing csum root for extent at bytenr %llu",
990+
sums->logical);
991+
ret = -EUCLEAN;
992+
}
993+
987994
if (!ret) {
988995
ret = btrfs_del_csums(trans, csum_root, sums->logical,
989996
sums->len);
@@ -4890,6 +4897,13 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
48904897
}
48914898

48924899
csum_root = btrfs_csum_root(trans->fs_info, disk_bytenr);
4900+
if (unlikely(!csum_root)) {
4901+
btrfs_err(trans->fs_info,
4902+
"missing csum root for extent at bytenr %llu",
4903+
disk_bytenr);
4904+
return -EUCLEAN;
4905+
}
4906+
48934907
disk_bytenr += extent_offset;
48944908
ret = btrfs_lookup_csums_list(csum_root, disk_bytenr,
48954909
disk_bytenr + extent_num_bytes - 1,
@@ -5086,6 +5100,13 @@ static int log_extent_csums(struct btrfs_trans_handle *trans,
50865100
/* block start is already adjusted for the file extent offset. */
50875101
block_start = btrfs_extent_map_block_start(em);
50885102
csum_root = btrfs_csum_root(trans->fs_info, block_start);
5103+
if (unlikely(!csum_root)) {
5104+
btrfs_err(trans->fs_info,
5105+
"missing csum root for extent at bytenr %llu",
5106+
block_start);
5107+
return -EUCLEAN;
5108+
}
5109+
50895110
ret = btrfs_lookup_csums_list(csum_root, block_start + csum_offset,
50905111
block_start + csum_offset + csum_len - 1,
50915112
&ordered_sums, false);

0 commit comments

Comments
 (0)