[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 <sjle...@shaw.ca> Signed-off-by: Qu Wenruo <w...@suse.com> --- check/main.c | 2 +- check/mode-lowmem.c | 2 +- cmds-restore.c | 2 +- ctree.h | 22 ---------------------- file.c | 3 +-- print-tree.c | 4 ++-- 6 files changed, 6 insertions(+), 29 deletions(-) diff --git a/check/main.c b/check/main.c index 235db373a86c..52ef181add61 100644 --- a/check/main.c +++ b/check/main.c @@ -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) { diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index c42dfcc50352..b3198fffa250 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -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( diff --git a/cmds-restore.c b/cmds-restore.c index 29a329a397c2..9542221fd265 100644 --- a/cmds-restore.c +++ b/cmds-restore.c @@ -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); diff --git a/ctree.h b/ctree.h index de4b1b7e6416..04a77550c715 100644 --- a/ctree.h +++ b/ctree.h @@ -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) diff --git a/file.c b/file.c index f5e645c47bda..056be1045814 100644 --- a/file.c +++ b/file.c @@ -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, diff --git a/print-tree.c b/print-tree.c index dfa7bb6b676f..a09ecfbb28f0 100644 --- a/print-tree.c +++ b/print-tree.c @@ -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; -- 2.17.1 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html