Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cb44921a authored by Chris Mason's avatar Chris Mason
Browse files

Btrfs: don't loop forever on bad btree blocks



When btrfs discovers the generation number in a btree block is
incorrect, it can loop forever without forcing the RAID
code to try a valid mirror, and without returning EIO.

This changes things to properly kick out the EIO.

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 6b5b817f
Loading
Loading
Loading
Loading
+28 −9
Original line number Diff line number Diff line
@@ -1577,14 +1577,34 @@ read_block_for_search(struct btrfs_trans_handle *trans,
	blocksize = btrfs_level_size(root, level - 1);

	tmp = btrfs_find_tree_block(root, blocknr, blocksize);
	if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
	if (tmp) {
		if (btrfs_buffer_uptodate(tmp, 0)) {
			if (btrfs_buffer_uptodate(tmp, gen)) {
				/*
		 * we found an up to date block without sleeping, return
				 * we found an up to date block without
				 * sleeping, return
				 * right away
				 */
				*eb_ret = tmp;
				return 0;
			}
			/* the pages were up to date, but we failed
			 * the generation number check.  Do a full
			 * read for the generation number that is correct.
			 * We must do this without dropping locks so
			 * we can trust our generation number
			 */
			free_extent_buffer(tmp);
			tmp = read_tree_block(root, blocknr, blocksize, gen);
			if (tmp && btrfs_buffer_uptodate(tmp, gen)) {
				*eb_ret = tmp;
				return 0;
			}
			free_extent_buffer(tmp);
			btrfs_release_path(NULL, p);
			return -EIO;
		}
	}

	/*
	 * reduce lock contention at high levels
@@ -1596,7 +1616,6 @@ read_block_for_search(struct btrfs_trans_handle *trans,
	btrfs_unlock_up_safe(p, level + 1);
	btrfs_set_path_blocking(p);

	if (tmp)
	free_extent_buffer(tmp);
	if (p->reada)
		reada_for_search(root, p, level, slot, key->objectid);