diff options
author | Qu Wenruo <wqu@suse.com> | 2018-06-06 03:41:49 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2018-08-06 07:12:38 -0400 |
commit | e41ca5897489b1c18af75ff0cc8f5c80260b3281 (patch) | |
tree | dc20051c4be3bb6f4b47bb1823364ae345d75809 /fs/btrfs | |
parent | bc877d285ca3dba24c52406946a4a69847cc7422 (diff) |
btrfs: Get rid of the confusing btrfs_file_extent_inline_len
We used to call btrfs_file_extent_inline_len() to get the uncompressed
data size of an inlined extent.
However this function is hiding evil, for compressed extent, it has no
choice but to directly read out ram_bytes from btrfs_file_extent_item.
While for uncompressed extent, it uses item size to calculate the real
data size, and ignoring ram_bytes completely.
In fact, for corrupted ram_bytes, due to above behavior kernel
btrfs_print_leaf() can't even print correct ram_bytes to expose the bug.
Since we have the tree-checker to verify all EXTENT_DATA, such mismatch
can be detected pretty easily, thus we can trust ram_bytes without the
evil btrfs_file_extent_inline_len().
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.h | 26 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 2 | ||||
-rw-r--r-- | fs/btrfs/file.c | 3 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 12 | ||||
-rw-r--r-- | fs/btrfs/print-tree.c | 4 | ||||
-rw-r--r-- | fs/btrfs/send.c | 17 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 12 |
7 files changed, 21 insertions, 55 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 12cb327cd16e..41ba770b9db9 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -2428,32 +2428,6 @@ static inline u32 btrfs_file_extent_inline_item_len( | |||
2428 | return btrfs_item_size(eb, e) - BTRFS_FILE_EXTENT_INLINE_DATA_START; | 2428 | return btrfs_item_size(eb, e) - BTRFS_FILE_EXTENT_INLINE_DATA_START; |
2429 | } | 2429 | } |
2430 | 2430 | ||
2431 | /* this returns the number of file bytes represented by the inline item. | ||
2432 | * If an item is compressed, this is the uncompressed size | ||
2433 | */ | ||
2434 | static inline u32 btrfs_file_extent_inline_len(const struct extent_buffer *eb, | ||
2435 | int slot, | ||
2436 | const struct btrfs_file_extent_item *fi) | ||
2437 | { | ||
2438 | struct btrfs_map_token token; | ||
2439 | |||
2440 | btrfs_init_map_token(&token); | ||
2441 | /* | ||
2442 | * return the space used on disk if this item isn't | ||
2443 | * compressed or encoded | ||
2444 | */ | ||
2445 | if (btrfs_token_file_extent_compression(eb, fi, &token) == 0 && | ||
2446 | btrfs_token_file_extent_encryption(eb, fi, &token) == 0 && | ||
2447 | btrfs_token_file_extent_other_encoding(eb, fi, &token) == 0) { | ||
2448 | return btrfs_file_extent_inline_item_len(eb, | ||
2449 | btrfs_item_nr(slot)); | ||
2450 | } | ||
2451 | |||
2452 | /* otherwise use the ram bytes field */ | ||
2453 | return btrfs_token_file_extent_ram_bytes(eb, fi, &token); | ||
2454 | } | ||
2455 | |||
2456 | |||
2457 | /* btrfs_dev_stats_item */ | 2431 | /* btrfs_dev_stats_item */ |
2458 | static inline u64 btrfs_dev_stats_value(const struct extent_buffer *eb, | 2432 | static inline u64 btrfs_dev_stats_value(const struct extent_buffer *eb, |
2459 | const struct btrfs_dev_stats_item *ptr, | 2433 | const struct btrfs_dev_stats_item *ptr, |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index f9dd6d1836a3..8c3cd7072caf 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -942,7 +942,7 @@ void btrfs_extent_item_to_extent_map(struct btrfs_inode *inode, | |||
942 | btrfs_file_extent_num_bytes(leaf, fi); | 942 | btrfs_file_extent_num_bytes(leaf, fi); |
943 | } else if (type == BTRFS_FILE_EXTENT_INLINE) { | 943 | } else if (type == BTRFS_FILE_EXTENT_INLINE) { |
944 | size_t size; | 944 | size_t size; |
945 | size = btrfs_file_extent_inline_len(leaf, slot, fi); | 945 | size = btrfs_file_extent_ram_bytes(leaf, fi); |
946 | extent_end = ALIGN(extent_start + size, | 946 | extent_end = ALIGN(extent_start + size, |
947 | fs_info->sectorsize); | 947 | fs_info->sectorsize); |
948 | } | 948 | } |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 975c590c50d8..4cd8af14f915 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
@@ -833,8 +833,7 @@ next_slot: | |||
833 | btrfs_file_extent_num_bytes(leaf, fi); | 833 | btrfs_file_extent_num_bytes(leaf, fi); |
834 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | 834 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { |
835 | extent_end = key.offset + | 835 | extent_end = key.offset + |
836 | btrfs_file_extent_inline_len(leaf, | 836 | btrfs_file_extent_ram_bytes(leaf, fi); |
837 | path->slots[0], fi); | ||
838 | } else { | 837 | } else { |
839 | /* can't happen */ | 838 | /* can't happen */ |
840 | BUG(); | 839 | BUG(); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index eba61bcb9bb3..1ade43c02b81 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1443,8 +1443,7 @@ next_slot: | |||
1443 | nocow = 1; | 1443 | nocow = 1; |
1444 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | 1444 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { |
1445 | extent_end = found_key.offset + | 1445 | extent_end = found_key.offset + |
1446 | btrfs_file_extent_inline_len(leaf, | 1446 | btrfs_file_extent_ram_bytes(leaf, fi); |
1447 | path->slots[0], fi); | ||
1448 | extent_end = ALIGN(extent_end, | 1447 | extent_end = ALIGN(extent_end, |
1449 | fs_info->sectorsize); | 1448 | fs_info->sectorsize); |
1450 | } else { | 1449 | } else { |
@@ -4643,8 +4642,8 @@ search_again: | |||
4643 | BTRFS_I(inode), leaf, fi, | 4642 | BTRFS_I(inode), leaf, fi, |
4644 | found_key.offset); | 4643 | found_key.offset); |
4645 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | 4644 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { |
4646 | item_end += btrfs_file_extent_inline_len(leaf, | 4645 | item_end += btrfs_file_extent_ram_bytes(leaf, |
4647 | path->slots[0], fi); | 4646 | fi); |
4648 | 4647 | ||
4649 | trace_btrfs_truncate_show_fi_inline( | 4648 | trace_btrfs_truncate_show_fi_inline( |
4650 | BTRFS_I(inode), leaf, fi, path->slots[0], | 4649 | BTRFS_I(inode), leaf, fi, path->slots[0], |
@@ -6943,7 +6942,8 @@ struct extent_map *btrfs_get_extent(struct btrfs_inode *inode, | |||
6943 | extent_start); | 6942 | extent_start); |
6944 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | 6943 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { |
6945 | size_t size; | 6944 | size_t size; |
6946 | size = btrfs_file_extent_inline_len(leaf, path->slots[0], item); | 6945 | |
6946 | size = btrfs_file_extent_ram_bytes(leaf, item); | ||
6947 | extent_end = ALIGN(extent_start + size, | 6947 | extent_end = ALIGN(extent_start + size, |
6948 | fs_info->sectorsize); | 6948 | fs_info->sectorsize); |
6949 | 6949 | ||
@@ -6994,7 +6994,7 @@ next: | |||
6994 | if (new_inline) | 6994 | if (new_inline) |
6995 | goto out; | 6995 | goto out; |
6996 | 6996 | ||
6997 | size = btrfs_file_extent_inline_len(leaf, path->slots[0], item); | 6997 | size = btrfs_file_extent_ram_bytes(leaf, item); |
6998 | extent_offset = page_offset(page) + pg_offset - extent_start; | 6998 | extent_offset = page_offset(page) + pg_offset - extent_start; |
6999 | copy_size = min_t(u64, PAGE_SIZE - pg_offset, | 6999 | copy_size = min_t(u64, PAGE_SIZE - pg_offset, |
7000 | size - extent_offset); | 7000 | size - extent_offset); |
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index a4e11cf04671..59efcf2e0de8 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c | |||
@@ -267,8 +267,8 @@ void btrfs_print_leaf(struct extent_buffer *l) | |||
267 | struct btrfs_file_extent_item); | 267 | struct btrfs_file_extent_item); |
268 | if (btrfs_file_extent_type(l, fi) == | 268 | if (btrfs_file_extent_type(l, fi) == |
269 | BTRFS_FILE_EXTENT_INLINE) { | 269 | BTRFS_FILE_EXTENT_INLINE) { |
270 | pr_info("\t\tinline extent data size %u\n", | 270 | pr_info("\t\tinline extent data size %llu\n", |
271 | btrfs_file_extent_inline_len(l, i, fi)); | 271 | btrfs_file_extent_ram_bytes(l, fi)); |
272 | break; | 272 | break; |
273 | } | 273 | } |
274 | pr_info("\t\textent data disk bytenr %llu nr %llu\n", | 274 | pr_info("\t\textent data disk bytenr %llu nr %llu\n", |
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index c47f62b19226..6ff7a1315e52 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
@@ -1500,7 +1500,7 @@ static int read_symlink(struct btrfs_root *root, | |||
1500 | BUG_ON(compression); | 1500 | BUG_ON(compression); |
1501 | 1501 | ||
1502 | off = btrfs_file_extent_inline_start(ei); | 1502 | off = btrfs_file_extent_inline_start(ei); |
1503 | len = btrfs_file_extent_inline_len(path->nodes[0], path->slots[0], ei); | 1503 | len = btrfs_file_extent_ram_bytes(path->nodes[0], ei); |
1504 | 1504 | ||
1505 | ret = fs_path_add_from_extent_buffer(dest, path->nodes[0], off, len); | 1505 | ret = fs_path_add_from_extent_buffer(dest, path->nodes[0], off, len); |
1506 | 1506 | ||
@@ -5160,7 +5160,7 @@ static int clone_range(struct send_ctx *sctx, | |||
5160 | ei = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); | 5160 | ei = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); |
5161 | type = btrfs_file_extent_type(leaf, ei); | 5161 | type = btrfs_file_extent_type(leaf, ei); |
5162 | if (type == BTRFS_FILE_EXTENT_INLINE) { | 5162 | if (type == BTRFS_FILE_EXTENT_INLINE) { |
5163 | ext_len = btrfs_file_extent_inline_len(leaf, slot, ei); | 5163 | ext_len = btrfs_file_extent_ram_bytes(leaf, ei); |
5164 | ext_len = PAGE_ALIGN(ext_len); | 5164 | ext_len = PAGE_ALIGN(ext_len); |
5165 | } else { | 5165 | } else { |
5166 | ext_len = btrfs_file_extent_num_bytes(leaf, ei); | 5166 | ext_len = btrfs_file_extent_num_bytes(leaf, ei); |
@@ -5236,8 +5236,7 @@ static int send_write_or_clone(struct send_ctx *sctx, | |||
5236 | struct btrfs_file_extent_item); | 5236 | struct btrfs_file_extent_item); |
5237 | type = btrfs_file_extent_type(path->nodes[0], ei); | 5237 | type = btrfs_file_extent_type(path->nodes[0], ei); |
5238 | if (type == BTRFS_FILE_EXTENT_INLINE) { | 5238 | if (type == BTRFS_FILE_EXTENT_INLINE) { |
5239 | len = btrfs_file_extent_inline_len(path->nodes[0], | 5239 | len = btrfs_file_extent_ram_bytes(path->nodes[0], ei); |
5240 | path->slots[0], ei); | ||
5241 | /* | 5240 | /* |
5242 | * it is possible the inline item won't cover the whole page, | 5241 | * it is possible the inline item won't cover the whole page, |
5243 | * but there may be items after this page. Make | 5242 | * but there may be items after this page. Make |
@@ -5375,7 +5374,7 @@ static int is_extent_unchanged(struct send_ctx *sctx, | |||
5375 | } | 5374 | } |
5376 | 5375 | ||
5377 | if (right_type == BTRFS_FILE_EXTENT_INLINE) { | 5376 | if (right_type == BTRFS_FILE_EXTENT_INLINE) { |
5378 | right_len = btrfs_file_extent_inline_len(eb, slot, ei); | 5377 | right_len = btrfs_file_extent_ram_bytes(eb, ei); |
5379 | right_len = PAGE_ALIGN(right_len); | 5378 | right_len = PAGE_ALIGN(right_len); |
5380 | } else { | 5379 | } else { |
5381 | right_len = btrfs_file_extent_num_bytes(eb, ei); | 5380 | right_len = btrfs_file_extent_num_bytes(eb, ei); |
@@ -5496,8 +5495,7 @@ static int get_last_extent(struct send_ctx *sctx, u64 offset) | |||
5496 | struct btrfs_file_extent_item); | 5495 | struct btrfs_file_extent_item); |
5497 | type = btrfs_file_extent_type(path->nodes[0], fi); | 5496 | type = btrfs_file_extent_type(path->nodes[0], fi); |
5498 | if (type == BTRFS_FILE_EXTENT_INLINE) { | 5497 | if (type == BTRFS_FILE_EXTENT_INLINE) { |
5499 | u64 size = btrfs_file_extent_inline_len(path->nodes[0], | 5498 | u64 size = btrfs_file_extent_ram_bytes(path->nodes[0], fi); |
5500 | path->slots[0], fi); | ||
5501 | extent_end = ALIGN(key.offset + size, | 5499 | extent_end = ALIGN(key.offset + size, |
5502 | sctx->send_root->fs_info->sectorsize); | 5500 | sctx->send_root->fs_info->sectorsize); |
5503 | } else { | 5501 | } else { |
@@ -5560,7 +5558,7 @@ static int range_is_hole_in_parent(struct send_ctx *sctx, | |||
5560 | fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); | 5558 | fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); |
5561 | if (btrfs_file_extent_type(leaf, fi) == | 5559 | if (btrfs_file_extent_type(leaf, fi) == |
5562 | BTRFS_FILE_EXTENT_INLINE) { | 5560 | BTRFS_FILE_EXTENT_INLINE) { |
5563 | u64 size = btrfs_file_extent_inline_len(leaf, slot, fi); | 5561 | u64 size = btrfs_file_extent_ram_bytes(leaf, fi); |
5564 | 5562 | ||
5565 | extent_end = ALIGN(key.offset + size, | 5563 | extent_end = ALIGN(key.offset + size, |
5566 | root->fs_info->sectorsize); | 5564 | root->fs_info->sectorsize); |
@@ -5606,8 +5604,7 @@ static int maybe_send_hole(struct send_ctx *sctx, struct btrfs_path *path, | |||
5606 | struct btrfs_file_extent_item); | 5604 | struct btrfs_file_extent_item); |
5607 | type = btrfs_file_extent_type(path->nodes[0], fi); | 5605 | type = btrfs_file_extent_type(path->nodes[0], fi); |
5608 | if (type == BTRFS_FILE_EXTENT_INLINE) { | 5606 | if (type == BTRFS_FILE_EXTENT_INLINE) { |
5609 | u64 size = btrfs_file_extent_inline_len(path->nodes[0], | 5607 | u64 size = btrfs_file_extent_ram_bytes(path->nodes[0], fi); |
5610 | path->slots[0], fi); | ||
5611 | extent_end = ALIGN(key->offset + size, | 5608 | extent_end = ALIGN(key->offset + size, |
5612 | sctx->send_root->fs_info->sectorsize); | 5609 | sctx->send_root->fs_info->sectorsize); |
5613 | } else { | 5610 | } else { |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index b3b1d424f2d8..6bca8f88ade0 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -597,7 +597,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
597 | if (btrfs_file_extent_disk_bytenr(eb, item) == 0) | 597 | if (btrfs_file_extent_disk_bytenr(eb, item) == 0) |
598 | nbytes = 0; | 598 | nbytes = 0; |
599 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | 599 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { |
600 | size = btrfs_file_extent_inline_len(eb, slot, item); | 600 | size = btrfs_file_extent_ram_bytes(eb, item); |
601 | nbytes = btrfs_file_extent_ram_bytes(eb, item); | 601 | nbytes = btrfs_file_extent_ram_bytes(eb, item); |
602 | extent_end = ALIGN(start + size, | 602 | extent_end = ALIGN(start + size, |
603 | fs_info->sectorsize); | 603 | fs_info->sectorsize); |
@@ -3920,9 +3920,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, | |||
3920 | struct btrfs_file_extent_item); | 3920 | struct btrfs_file_extent_item); |
3921 | if (btrfs_file_extent_type(src, extent) == | 3921 | if (btrfs_file_extent_type(src, extent) == |
3922 | BTRFS_FILE_EXTENT_INLINE) { | 3922 | BTRFS_FILE_EXTENT_INLINE) { |
3923 | len = btrfs_file_extent_inline_len(src, | 3923 | len = btrfs_file_extent_ram_bytes(src, extent); |
3924 | src_path->slots[0], | ||
3925 | extent); | ||
3926 | *last_extent = ALIGN(key.offset + len, | 3924 | *last_extent = ALIGN(key.offset + len, |
3927 | fs_info->sectorsize); | 3925 | fs_info->sectorsize); |
3928 | } else { | 3926 | } else { |
@@ -3987,7 +3985,7 @@ fill_holes: | |||
3987 | extent = btrfs_item_ptr(src, i, struct btrfs_file_extent_item); | 3985 | extent = btrfs_item_ptr(src, i, struct btrfs_file_extent_item); |
3988 | if (btrfs_file_extent_type(src, extent) == | 3986 | if (btrfs_file_extent_type(src, extent) == |
3989 | BTRFS_FILE_EXTENT_INLINE) { | 3987 | BTRFS_FILE_EXTENT_INLINE) { |
3990 | len = btrfs_file_extent_inline_len(src, i, extent); | 3988 | len = btrfs_file_extent_ram_bytes(src, extent); |
3991 | extent_end = ALIGN(key.offset + len, | 3989 | extent_end = ALIGN(key.offset + len, |
3992 | fs_info->sectorsize); | 3990 | fs_info->sectorsize); |
3993 | } else { | 3991 | } else { |
@@ -4572,9 +4570,7 @@ static int btrfs_log_trailing_hole(struct btrfs_trans_handle *trans, | |||
4572 | 4570 | ||
4573 | if (btrfs_file_extent_type(leaf, extent) == | 4571 | if (btrfs_file_extent_type(leaf, extent) == |
4574 | BTRFS_FILE_EXTENT_INLINE) { | 4572 | BTRFS_FILE_EXTENT_INLINE) { |
4575 | len = btrfs_file_extent_inline_len(leaf, | 4573 | len = btrfs_file_extent_ram_bytes(leaf, extent); |
4576 | path->slots[0], | ||
4577 | extent); | ||
4578 | ASSERT(len == i_size || | 4574 | ASSERT(len == i_size || |
4579 | (len == fs_info->sectorsize && | 4575 | (len == fs_info->sectorsize && |
4580 | btrfs_file_extent_compression(leaf, extent) != | 4576 | btrfs_file_extent_compression(leaf, extent) != |