Commit 2b4cb4e5 authored by Filipe Manana's avatar Filipe Manana Committed by David Sterba
Browse files

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: default avatarChris Mason <clm@meta.com>
Link: https://lore.kernel.org/linux-btrfs/20260208161657.3972997-1-clm@meta.com/


Reviewed-by: default avatarBoris Burkov <boris@bur.io>
Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 50242828
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1627,6 +1627,10 @@ static int backup_super_roots(struct btrfs_fs_info *info)
			btrfs_err(info, "missing extent root for extent at bytenr 0");
			return -EUCLEAN;
		}
		if (unlikely(!csum_root)) {
			btrfs_err(info, "missing csum root for extent at bytenr 0");
			return -EUCLEAN;
		}

		btrfs_set_backup_extent_root(root_backup,
					     extent_root->node->start);
+18 −2
Original line number Diff line number Diff line
@@ -1974,10 +1974,17 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
			struct btrfs_root *csum_root;

			csum_root = btrfs_csum_root(fs_info, head->bytenr);
			if (unlikely(!csum_root)) {
				btrfs_err(fs_info,
					  "missing csum root for extent at bytenr %llu",
					  head->bytenr);
				ret = -EUCLEAN;
			} else {
				ret = btrfs_del_csums(trans, csum_root, head->bytenr,
						      head->num_bytes);
			}
		}
	}

	*bytes_released += btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);

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

		csum_root = btrfs_csum_root(trans->fs_info, bytenr);
		if (unlikely(!csum_root)) {
			ret = -EUCLEAN;
			btrfs_abort_transaction(trans, ret);
			btrfs_err(trans->fs_info,
				  "missing csum root for extent at bytenr %llu",
				  bytenr);
			return ret;
		}

		ret = btrfs_del_csums(trans, csum_root, bytenr, num_bytes);
		if (unlikely(ret)) {
			btrfs_abort_transaction(trans, ret);
+7 −0
Original line number Diff line number Diff line
@@ -308,6 +308,13 @@ static int search_csum_tree(struct btrfs_fs_info *fs_info,
	/* Current item doesn't contain the desired range, search again */
	btrfs_release_path(path);
	csum_root = btrfs_csum_root(fs_info, disk_bytenr);
	if (unlikely(!csum_root)) {
		btrfs_err(fs_info,
			  "missing csum root for extent at bytenr %llu",
			  disk_bytenr);
		return -EUCLEAN;
	}

	item = btrfs_lookup_csum(NULL, csum_root, path, disk_bytenr, 0);
	if (IS_ERR(item)) {
		ret = PTR_ERR(item);
+16 −2
Original line number Diff line number Diff line
@@ -2012,6 +2012,13 @@ static int can_nocow_file_extent(struct btrfs_path *path,
	 */

	csum_root = btrfs_csum_root(root->fs_info, io_start);
	if (unlikely(!csum_root)) {
		btrfs_err(root->fs_info,
			  "missing csum root for extent at bytenr %llu", io_start);
		ret = -EUCLEAN;
		goto out;
	}

	ret = btrfs_lookup_csums_list(csum_root, io_start,
				      io_start + args->file_extent.num_bytes - 1,
				      NULL, nowait);
@@ -2749,10 +2756,17 @@ static int add_pending_csums(struct btrfs_trans_handle *trans,
	int ret;

	list_for_each_entry(sum, list, list) {
		trans->adding_csums = true;
		if (!csum_root)
		if (!csum_root) {
			csum_root = btrfs_csum_root(trans->fs_info,
						    sum->logical);
			if (unlikely(!csum_root)) {
				btrfs_err(trans->fs_info,
				  "missing csum root for extent at bytenr %llu",
					  sum->logical);
				return -EUCLEAN;
			}
		}
		trans->adding_csums = true;
		ret = btrfs_csum_file_blocks(trans, csum_root, sum);
		trans->adding_csums = false;
		if (ret)
+10 −2
Original line number Diff line number Diff line
@@ -2295,8 +2295,7 @@ void raid56_parity_recover(struct bio *bio, struct btrfs_io_context *bioc,
static void fill_data_csums(struct btrfs_raid_bio *rbio)
{
	struct btrfs_fs_info *fs_info = rbio->bioc->fs_info;
	struct btrfs_root *csum_root = btrfs_csum_root(fs_info,
						       rbio->bioc->full_stripe_logical);
	struct btrfs_root *csum_root;
	const u64 start = rbio->bioc->full_stripe_logical;
	const u32 len = (rbio->nr_data * rbio->stripe_nsectors) <<
			fs_info->sectorsize_bits;
@@ -2329,6 +2328,15 @@ static void fill_data_csums(struct btrfs_raid_bio *rbio)
		goto error;
	}

	csum_root = btrfs_csum_root(fs_info, rbio->bioc->full_stripe_logical);
	if (unlikely(!csum_root)) {
		btrfs_err(fs_info,
			  "missing csum root for extent at bytenr %llu",
			  rbio->bioc->full_stripe_logical);
		ret = -EUCLEAN;
		goto error;
	}

	ret = btrfs_lookup_csums_bitmap(csum_root, NULL, start, start + len - 1,
					rbio->csum_buf, rbio->csum_bitmap);
	if (ret < 0)
Loading