btrfs-progs: Get rid of the confusing btrfs_file_extent_inline_len()

[BUG]
If one uncompressed inline extent has incorrect ram_bytes, neither btrfs
check nor dump-tree could detect such corruption.

[CAUSE]
Every caller tries to read inline extent ram_bytes is using
btrfs_file_extent_inline_len(), other than directly calling
btrfs_file_extent_ram_bytes().

For compressed extent, it's just calling btrfs_file_extent_ram_bytes().
However for uncompressed extent, it falls back to
btrfs_file_extent_inline_item_len(), makes us unable to detect anything
wrong in ram_bytes.

[FIX]
Just get rid of such confusing btrfs_file_extent_inline_len() function.

Reported-by: Steve Leung <sjleung@shaw.ca>
Tested-by: Steve Leung <sjleung@shaw.ca>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Qu Wenruo 2018-06-06 15:27:13 +08:00 committed by David Sterba
parent 90b677a2d7
commit 3c042605db
6 changed files with 6 additions and 29 deletions

View File

@ -1472,7 +1472,7 @@ static int process_file_extent(struct btrfs_root *root,
u8 compression = btrfs_file_extent_compression(eb, fi);
struct btrfs_item *item = btrfs_item_nr(slot);
num_bytes = btrfs_file_extent_inline_len(eb, slot, fi);
num_bytes = btrfs_file_extent_ram_bytes(eb, fi);
if (num_bytes == 0)
rec->errors |= I_ERR_BAD_FILE_EXTENT;
if (compression) {

View File

@ -1776,7 +1776,7 @@ static int check_file_extent(struct btrfs_root *root, struct btrfs_key *fkey,
u32 item_inline_len;
item_inline_len = btrfs_file_extent_inline_item_len(node, e);
extent_num_bytes = btrfs_file_extent_inline_len(node, slot, fi);
extent_num_bytes = btrfs_file_extent_ram_bytes(node, fi);
compressed = btrfs_file_extent_compression(node, fi);
if (extent_num_bytes == 0) {
error(

View File

@ -302,7 +302,7 @@ static int copy_one_inline(struct btrfs_root *root, int fd,
fi = btrfs_item_ptr(leaf, path->slots[0],
struct btrfs_file_extent_item);
ptr = btrfs_file_extent_inline_start(fi);
len = btrfs_file_extent_inline_len(leaf, path->slots[0], fi);
len = btrfs_file_extent_ram_bytes(leaf, fi);
inline_item_len = btrfs_file_extent_inline_item_len(leaf, btrfs_item_nr(path->slots[0]));
read_extent_buffer(leaf, buf, ptr, inline_item_len);

22
ctree.h
View File

@ -2443,28 +2443,6 @@ static inline u32 btrfs_search_header_len(struct btrfs_ioctl_search_header *sh)
return get_unaligned_32(&sh->len);
}
/* this returns the number of file bytes represented by the inline item.
* If an item is compressed, this is the uncompressed size
*/
static inline u32 btrfs_file_extent_inline_len(struct extent_buffer *eb,
int slot,
struct btrfs_file_extent_item *fi)
{
/*
* return the space used on disk if this item isn't
* compressed or encoded
*/
if (btrfs_file_extent_compression(eb, fi) == 0 &&
btrfs_file_extent_encryption(eb, fi) == 0 &&
btrfs_file_extent_other_encoding(eb, fi) == 0) {
return btrfs_file_extent_inline_item_len(eb,
btrfs_item_nr(slot));
}
/* otherwise use the ram bytes field */
return btrfs_file_extent_ram_bytes(eb, fi);
}
#define btrfs_fs_incompat(fs_info, opt) \
__btrfs_fs_incompat((fs_info), BTRFS_FEATURE_INCOMPAT_##opt)

3
file.c
View File

@ -255,8 +255,7 @@ int btrfs_read_file(struct btrfs_root *root, u64 ino, u64 start, int len,
/* Inline extent, one inode should only one inline extent */
if (btrfs_file_extent_type(leaf, fi) ==
BTRFS_FILE_EXTENT_INLINE) {
extent_len = btrfs_file_extent_inline_len(leaf, slot,
fi);
extent_len = btrfs_file_extent_ram_bytes(leaf, fi);
if (extent_start + extent_len <= start)
goto next;
read_extent_buffer(leaf, dest,

View File

@ -357,9 +357,9 @@ static void print_file_extent_item(struct extent_buffer *eb,
extent_type, file_extent_type_to_str(extent_type));
if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
printf("\t\tinline extent data size %u ram_bytes %u compression %hhu (%s)\n",
printf("\t\tinline extent data size %u ram_bytes %llu compression %hhu (%s)\n",
btrfs_file_extent_inline_item_len(eb, item),
btrfs_file_extent_inline_len(eb, slot, fi),
btrfs_file_extent_ram_bytes(eb, fi),
btrfs_file_extent_compression(eb, fi),
compress_str);
return;