Commit 9264d004 authored by David Sterba's avatar David Sterba
Browse files

btrfs: add unlikely annotations to branches leading to EUCLEAN



The unlikely() annotation is a static prediction hint that compiler may
use to reorder code out of hot path. We use it elsewhere (namely
tree-checker.c) for error branches that almost never happen, where
EUCLEAN (a corruption) is one of them.

Reviewed-by: default avatarFilipe Manana <fdmanana@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 4ca6f24a
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
@@ -1062,7 +1062,7 @@ static int add_inline_refs(struct btrfs_backref_walk_ctx *ctx,
		iref = (struct btrfs_extent_inline_ref *)ptr;
		type = btrfs_get_extent_inline_ref_type(leaf, iref,
							BTRFS_REF_TYPE_ANY);
		if (type == BTRFS_REF_TYPE_INVALID)
		if (unlikely(type == BTRFS_REF_TYPE_INVALID))
			return -EUCLEAN;

		offset = btrfs_extent_inline_ref_offset(leaf, iref);
@@ -1422,7 +1422,7 @@ static int find_parent_nodes(struct btrfs_backref_walk_ctx *ctx,
	ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
	if (ret < 0)
		goto out;
	if (ret == 0) {
	if (unlikely(ret == 0)) {
		/*
		 * Key with offset -1 found, there would have to exist an extent
		 * item with such offset, but this is out of the valid range.
@@ -1652,7 +1652,7 @@ static int find_parent_nodes(struct btrfs_backref_walk_ctx *ctx,
				 * case.
				 */
				ASSERT(eie);
				if (!eie) {
				if (unlikely(!eie)) {
					ret = -EUCLEAN;
					goto out;
				}
@@ -2215,7 +2215,7 @@ int extent_from_logical(struct btrfs_fs_info *fs_info, u64 logical,
	ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
	if (ret < 0)
		return ret;
	if (ret == 0) {
	if (unlikely(ret == 0)) {
		/*
		 * Key with offset -1 found, there would have to exist an extent
		 * item with such offset, but this is out of the valid range.
@@ -2312,7 +2312,7 @@ static int get_extent_inline_ref(unsigned long *ptr,
	*out_eiref = (struct btrfs_extent_inline_ref *)(*ptr);
	*out_type = btrfs_get_extent_inline_ref_type(eb, *out_eiref,
						     BTRFS_REF_TYPE_ANY);
	if (*out_type == BTRFS_REF_TYPE_INVALID)
	if (unlikely(*out_type == BTRFS_REF_TYPE_INVALID))
		return -EUCLEAN;

	*ptr += btrfs_extent_inline_ref_size(*out_type);
@@ -2868,7 +2868,7 @@ int btrfs_backref_iter_start(struct btrfs_backref_iter *iter, u64 bytenr)
	ret = btrfs_search_slot(NULL, extent_root, &key, path, 0, 0);
	if (ret < 0)
		return ret;
	if (ret == 0) {
	if (unlikely(ret == 0)) {
		/*
		 * Key with offset -1 found, there would have to exist an extent
		 * item with such offset, but this is out of the valid range.
@@ -2876,7 +2876,7 @@ int btrfs_backref_iter_start(struct btrfs_backref_iter *iter, u64 bytenr)
		ret = -EUCLEAN;
		goto release;
	}
	if (path->slots[0] == 0) {
	if (unlikely(path->slots[0] == 0)) {
		DEBUG_WARN();
		ret = -EUCLEAN;
		goto release;
@@ -3457,7 +3457,7 @@ int btrfs_backref_add_tree_node(struct btrfs_trans_handle *trans,
		if (ret < 0)
			goto out;
		/* No extra backref? This means the tree block is corrupted */
		if (ret > 0) {
		if (unlikely(ret > 0)) {
			ret = -EUCLEAN;
			goto out;
		}
@@ -3500,7 +3500,7 @@ int btrfs_backref_add_tree_node(struct btrfs_trans_handle *trans,
				((unsigned long)iter->cur_ptr);
			type = btrfs_get_extent_inline_ref_type(eb, iref,
							BTRFS_REF_TYPE_BLOCK);
			if (type == BTRFS_REF_TYPE_INVALID) {
			if (unlikely(type == BTRFS_REF_TYPE_INVALID)) {
				ret = -EUCLEAN;
				goto out;
			}
@@ -3612,7 +3612,7 @@ int btrfs_backref_finish_upper_links(struct btrfs_backref_cache *cache,
		}

		/* Sanity check, we shouldn't have any unchecked nodes */
		if (!upper->checked) {
		if (unlikely(!upper->checked)) {
			DEBUG_WARN("we should not have any unchecked nodes");
			return -EUCLEAN;
		}
+7 −7
Original line number Diff line number Diff line
@@ -2071,7 +2071,7 @@ static int read_bg_from_eb(struct btrfs_fs_info *fs_info, const struct btrfs_key
		return -ENOENT;
	}

	if (map->start != key->objectid || map->chunk_len != key->offset) {
	if (unlikely(map->start != key->objectid || map->chunk_len != key->offset)) {
		btrfs_err(fs_info,
			"block group %llu len %llu mismatch with chunk %llu len %llu",
			  key->objectid, key->offset, map->start, map->chunk_len);
@@ -2084,7 +2084,7 @@ static int read_bg_from_eb(struct btrfs_fs_info *fs_info, const struct btrfs_key
	flags = btrfs_stack_block_group_flags(&bg) &
		BTRFS_BLOCK_GROUP_TYPE_MASK;

	if (flags != (map->type & BTRFS_BLOCK_GROUP_TYPE_MASK)) {
	if (unlikely(flags != (map->type & BTRFS_BLOCK_GROUP_TYPE_MASK))) {
		btrfs_err(fs_info,
"block group %llu len %llu type flags 0x%llx mismatch with chunk type flags 0x%llx",
			  key->objectid, key->offset, flags,
@@ -2245,7 +2245,7 @@ static int exclude_super_stripes(struct btrfs_block_group *cache)
			return ret;

		/* Shouldn't have super stripes in sequential zones */
		if (zoned && nr) {
		if (unlikely(zoned && nr)) {
			kfree(logical);
			btrfs_err(fs_info,
			"zoned: block group %llu must not contain super block",
@@ -2336,7 +2336,7 @@ static int check_chunk_block_group_mappings(struct btrfs_fs_info *fs_info)
			break;

		bg = btrfs_lookup_block_group(fs_info, map->start);
		if (!bg) {
		if (unlikely(!bg)) {
			btrfs_err(fs_info,
	"chunk start=%llu len=%llu doesn't have corresponding block group",
				     map->start, map->chunk_len);
@@ -2344,9 +2344,9 @@ static int check_chunk_block_group_mappings(struct btrfs_fs_info *fs_info)
			btrfs_free_chunk_map(map);
			break;
		}
		if (bg->start != map->start || bg->length != map->chunk_len ||
		if (unlikely(bg->start != map->start || bg->length != map->chunk_len ||
			     (bg->flags & BTRFS_BLOCK_GROUP_TYPE_MASK) !=
		    (map->type & BTRFS_BLOCK_GROUP_TYPE_MASK)) {
			     (map->type & BTRFS_BLOCK_GROUP_TYPE_MASK))) {
			btrfs_err(fs_info,
"chunk start=%llu len=%llu flags=0x%llx doesn't match block group start=%llu len=%llu flags=0x%llx",
				map->start, map->chunk_len,
+5 −5
Original line number Diff line number Diff line
@@ -1499,7 +1499,7 @@ read_block_for_search(struct btrfs_root *root, struct btrfs_path *p,
			 * being cached, read from scrub, or have multiple
			 * parents (shared tree blocks).
			 */
			if (btrfs_verify_level_key(tmp, &check)) {
			if (unlikely(btrfs_verify_level_key(tmp, &check))) {
				ret = -EUCLEAN;
				goto out;
			}
@@ -2731,7 +2731,7 @@ static int push_node_left(struct btrfs_trans_handle *trans,
		push_items = min(src_nritems - 8, push_items);

	/* dst is the left eb, src is the middle eb */
	if (check_sibling_keys(dst, src)) {
	if (unlikely(check_sibling_keys(dst, src))) {
		ret = -EUCLEAN;
		btrfs_abort_transaction(trans, ret);
		return ret;
@@ -2805,7 +2805,7 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
		push_items = max_push;

	/* dst is the right eb, src is the middle eb */
	if (check_sibling_keys(src, dst)) {
	if (unlikely(check_sibling_keys(src, dst))) {
		ret = -EUCLEAN;
		btrfs_abort_transaction(trans, ret);
		return ret;
@@ -3287,7 +3287,7 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
	if (left_nritems == 0)
		goto out_unlock;

	if (check_sibling_keys(left, right)) {
	if (unlikely(check_sibling_keys(left, right))) {
		ret = -EUCLEAN;
		btrfs_abort_transaction(trans, ret);
		btrfs_tree_unlock(right);
@@ -3503,7 +3503,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
		goto out;
	}

	if (check_sibling_keys(left, right)) {
	if (unlikely(check_sibling_keys(left, right))) {
		ret = -EUCLEAN;
		btrfs_abort_transaction(trans, ret);
		goto out;
+2 −2
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
		 * We don't have a replace item or it's corrupted.  If there is
		 * a replace target, fail the mount.
		 */
		if (btrfs_find_device(fs_info->fs_devices, &args)) {
		if (unlikely(btrfs_find_device(fs_info->fs_devices, &args))) {
			btrfs_err(fs_info,
			"found replace target device without a valid replace item");
			return -EUCLEAN;
@@ -158,7 +158,7 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
		 * We don't have an active replace item but if there is a
		 * replace target, fail the mount.
		 */
		if (btrfs_find_device(fs_info->fs_devices, &args)) {
		if (unlikely(btrfs_find_device(fs_info->fs_devices, &args))) {
			btrfs_err(fs_info,
"replace without active item, run 'device scan --forget' on the target device");
			ret = -EUCLEAN;
+14 −14
Original line number Diff line number Diff line
@@ -404,7 +404,7 @@ int btrfs_validate_extent_buffer(struct extent_buffer *eb,
			      CSUM_FMT_VALUE(csum_size, result),
			      btrfs_header_level(eb),
			      ignore_csum ? ", ignored" : "");
		if (!ignore_csum) {
		if (unlikely(!ignore_csum)) {
			ret = -EUCLEAN;
			goto out;
		}
@@ -1055,10 +1055,10 @@ static struct btrfs_root *read_tree_root_path(struct btrfs_root *tree_root,
	 * For real fs, and not log/reloc trees, root owner must
	 * match its root node owner
	 */
	if (!btrfs_is_testing(fs_info) &&
	if (unlikely(!btrfs_is_testing(fs_info) &&
		     btrfs_root_id(root) != BTRFS_TREE_LOG_OBJECTID &&
		     btrfs_root_id(root) != BTRFS_TREE_RELOC_OBJECTID &&
	    btrfs_root_id(root) != btrfs_header_owner(root->node)) {
		     btrfs_root_id(root) != btrfs_header_owner(root->node))) {
		btrfs_crit(fs_info,
"root=%llu block=%llu, tree root owner mismatch, have %llu expect %llu",
			   btrfs_root_id(root), root->node->start,
@@ -2324,7 +2324,7 @@ static int validate_sys_chunk_array(const struct btrfs_fs_info *fs_info,
	const u32 sectorsize = btrfs_super_sectorsize(sb);
	u32 sys_array_size = btrfs_super_sys_array_size(sb);

	if (sys_array_size > BTRFS_SYSTEM_CHUNK_ARRAY_SIZE) {
	if (unlikely(sys_array_size > BTRFS_SYSTEM_CHUNK_ARRAY_SIZE)) {
		btrfs_err(fs_info, "system chunk array too big %u > %u",
			  sys_array_size, BTRFS_SYSTEM_CHUNK_ARRAY_SIZE);
		return -EUCLEAN;
@@ -2342,12 +2342,12 @@ static int validate_sys_chunk_array(const struct btrfs_fs_info *fs_info,
		disk_key = (struct btrfs_disk_key *)(sb->sys_chunk_array + cur);
		len = sizeof(*disk_key);

		if (cur + len > sys_array_size)
		if (unlikely(cur + len > sys_array_size))
			goto short_read;
		cur += len;

		btrfs_disk_key_to_cpu(&key, disk_key);
		if (key.type != BTRFS_CHUNK_ITEM_KEY) {
		if (unlikely(key.type != BTRFS_CHUNK_ITEM_KEY)) {
			btrfs_err(fs_info,
			    "unexpected item type %u in sys_array at offset %u",
				  key.type, cur);
@@ -2355,10 +2355,10 @@ static int validate_sys_chunk_array(const struct btrfs_fs_info *fs_info,
		}
		chunk = (struct btrfs_chunk *)(sb->sys_chunk_array + cur);
		num_stripes = btrfs_stack_chunk_num_stripes(chunk);
		if (cur + btrfs_chunk_item_size(num_stripes) > sys_array_size)
		if (unlikely(cur + btrfs_chunk_item_size(num_stripes) > sys_array_size))
			goto short_read;
		type = btrfs_stack_chunk_type(chunk);
		if (!(type & BTRFS_BLOCK_GROUP_SYSTEM)) {
		if (unlikely(!(type & BTRFS_BLOCK_GROUP_SYSTEM))) {
			btrfs_err(fs_info,
			"invalid chunk type %llu in sys_array at offset %u",
				  type, cur);
@@ -2605,13 +2605,13 @@ static int btrfs_validate_write_super(struct btrfs_fs_info *fs_info,
	ret = btrfs_validate_super(fs_info, sb, -1);
	if (ret < 0)
		goto out;
	if (!btrfs_supported_super_csum(btrfs_super_csum_type(sb))) {
	if (unlikely(!btrfs_supported_super_csum(btrfs_super_csum_type(sb)))) {
		ret = -EUCLEAN;
		btrfs_err(fs_info, "invalid csum type, has %u want %u",
			  btrfs_super_csum_type(sb), BTRFS_CSUM_TYPE_CRC32);
		goto out;
	}
	if (btrfs_super_incompat_flags(sb) & ~BTRFS_FEATURE_INCOMPAT_SUPP) {
	if (unlikely(btrfs_super_incompat_flags(sb) & ~BTRFS_FEATURE_INCOMPAT_SUPP)) {
		ret = -EUCLEAN;
		btrfs_err(fs_info,
		"invalid incompat flags, has 0x%llx valid mask 0x%llx",
@@ -4065,7 +4065,7 @@ int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors)
		btrfs_set_super_flags(sb, flags | BTRFS_HEADER_FLAG_WRITTEN);

		ret = btrfs_validate_write_super(fs_info, sb);
		if (ret < 0) {
		if (unlikely(ret < 0)) {
			mutex_unlock(&fs_info->fs_devices->device_list_mutex);
			btrfs_handle_fs_error(fs_info, -EUCLEAN,
				"unexpected superblock corruption detected");
@@ -4881,7 +4881,7 @@ int btrfs_init_root_free_objectid(struct btrfs_root *root)
	ret = btrfs_search_slot(NULL, root, &search_key, path, 0, 0);
	if (ret < 0)
		return ret;
	if (ret == 0) {
	if (unlikely(ret == 0)) {
		/*
		 * Key with offset -1 found, there would have to exist a root
		 * with such id, but this is out of valid range.
Loading