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

Commit e2406a6f authored by Qu Wenruo's avatar Qu Wenruo Committed by David Sterba
Browse files

btrfs: tree-checker: Add simple keyed refs check



For TREE_BLOCK_REF, SHARED_DATA_REF and SHARED_BLOCK_REF we need to
check:
              | TREE_BLOCK_REF | SHARED_BLOCK_REF | SHARED_BLOCK_REF
--------------+----------------+-----------------+------------------
key->objectid |    Alignment   |     Alignment    |    Alignment
key->offset   |    Any value   |     Alignment    |    Alignment
item_size     |        0       |        0         |   sizeof(le32) (*)

*: sizeof(struct btrfs_shared_data_ref)

So introduce a check to check all these 3 key types together.

Signed-off-by: default avatarQu Wenruo <wqu@suse.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent f82d1c7c
Loading
Loading
Loading
Loading
+39 −1
Original line number Original line Diff line number Diff line
@@ -923,7 +923,9 @@ static void extent_err(const struct extent_buffer *eb, int slot,


	btrfs_item_key_to_cpu(eb, &key, slot);
	btrfs_item_key_to_cpu(eb, &key, slot);
	bytenr = key.objectid;
	bytenr = key.objectid;
	if (key.type == BTRFS_METADATA_ITEM_KEY)
	if (key.type == BTRFS_METADATA_ITEM_KEY ||
	    key.type == BTRFS_TREE_BLOCK_REF_KEY ||
	    key.type == BTRFS_SHARED_BLOCK_REF_KEY)
		len = eb->fs_info->nodesize;
		len = eb->fs_info->nodesize;
	else
	else
		len = key.offset;
		len = key.offset;
@@ -1154,6 +1156,37 @@ static int check_extent_item(struct extent_buffer *leaf,
	return 0;
	return 0;
}
}


static int check_simple_keyed_refs(struct extent_buffer *leaf,
				   struct btrfs_key *key, int slot)
{
	u32 expect_item_size = 0;

	if (key->type == BTRFS_SHARED_DATA_REF_KEY)
		expect_item_size = sizeof(struct btrfs_shared_data_ref);

	if (btrfs_item_size_nr(leaf, slot) != expect_item_size) {
		generic_err(leaf, slot,
		"invalid item size, have %u expect %u for key type %u",
			    btrfs_item_size_nr(leaf, slot),
			    expect_item_size, key->type);
		return -EUCLEAN;
	}
	if (!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize)) {
		generic_err(leaf, slot,
"invalid key objectid for shared block ref, have %llu expect aligned to %u",
			    key->objectid, leaf->fs_info->sectorsize);
		return -EUCLEAN;
	}
	if (key->type != BTRFS_TREE_BLOCK_REF_KEY &&
	    !IS_ALIGNED(key->offset, leaf->fs_info->sectorsize)) {
		extent_err(leaf, slot,
		"invalid tree parent bytenr, have %llu expect aligned to %u",
			   key->offset, leaf->fs_info->sectorsize);
		return -EUCLEAN;
	}
	return 0;
}

/*
/*
 * Common point to switch the item-specific validation.
 * Common point to switch the item-specific validation.
 */
 */
@@ -1196,6 +1229,11 @@ static int check_leaf_item(struct extent_buffer *leaf,
	case BTRFS_METADATA_ITEM_KEY:
	case BTRFS_METADATA_ITEM_KEY:
		ret = check_extent_item(leaf, key, slot);
		ret = check_extent_item(leaf, key, slot);
		break;
		break;
	case BTRFS_TREE_BLOCK_REF_KEY:
	case BTRFS_SHARED_DATA_REF_KEY:
	case BTRFS_SHARED_BLOCK_REF_KEY:
		ret = check_simple_keyed_refs(leaf, key, slot);
		break;
	}
	}
	return ret;
	return ret;
}
}