diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-20 12:52:35 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-05-20 12:52:35 -0400 |
commit | f49aa1de98363b6c5fba4637678d6b0ba3d18065 (patch) | |
tree | f02df2090c2d5baf0276ab6fa53c80db783c4765 /fs/btrfs/tree-checker.c | |
parent | 78e03651849fd3e8aa9ab3288bc1d3726c4c6129 (diff) | |
parent | 4e9845eff5a8027b5181d5bff56a02991fe46d48 (diff) |
Merge tag 'for-5.2-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba:
"Notable highlights:
- fixes for some long-standing bugs in fsync that were quite hard to
catch but now finaly fixed
- some fixups to error handling paths that did not properly clean up
(locking, memory)
- fix to space reservation for inheriting properties"
* tag 'for-5.2-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
Btrfs: tree-checker: detect file extent items with overlapping ranges
Btrfs: fix race between ranged fsync and writeback of adjacent ranges
Btrfs: avoid fallback to transaction commit during fsync of files with holes
btrfs: extent-tree: Fix a bug that btrfs is unable to add pinned bytes
btrfs: sysfs: don't leak memory when failing add fsid
btrfs: sysfs: Fix error path kobject memory leak
Btrfs: do not abort transaction at btrfs_update_root() after failure to COW path
btrfs: use the existing reserved items for our first prop for inheritance
btrfs: don't double unlock on error in btrfs_punch_hole
btrfs: Check the compression level before getting a workspace
Diffstat (limited to 'fs/btrfs/tree-checker.c')
-rw-r--r-- | fs/btrfs/tree-checker.c | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c index 748cd1598255..96fce4bef4e7 100644 --- a/fs/btrfs/tree-checker.c +++ b/fs/btrfs/tree-checker.c | |||
@@ -107,8 +107,26 @@ static void file_extent_err(const struct extent_buffer *eb, int slot, | |||
107 | (!IS_ALIGNED(btrfs_file_extent_##name((leaf), (fi)), (alignment))); \ | 107 | (!IS_ALIGNED(btrfs_file_extent_##name((leaf), (fi)), (alignment))); \ |
108 | }) | 108 | }) |
109 | 109 | ||
110 | static u64 file_extent_end(struct extent_buffer *leaf, | ||
111 | struct btrfs_key *key, | ||
112 | struct btrfs_file_extent_item *extent) | ||
113 | { | ||
114 | u64 end; | ||
115 | u64 len; | ||
116 | |||
117 | if (btrfs_file_extent_type(leaf, extent) == BTRFS_FILE_EXTENT_INLINE) { | ||
118 | len = btrfs_file_extent_ram_bytes(leaf, extent); | ||
119 | end = ALIGN(key->offset + len, leaf->fs_info->sectorsize); | ||
120 | } else { | ||
121 | len = btrfs_file_extent_num_bytes(leaf, extent); | ||
122 | end = key->offset + len; | ||
123 | } | ||
124 | return end; | ||
125 | } | ||
126 | |||
110 | static int check_extent_data_item(struct extent_buffer *leaf, | 127 | static int check_extent_data_item(struct extent_buffer *leaf, |
111 | struct btrfs_key *key, int slot) | 128 | struct btrfs_key *key, int slot, |
129 | struct btrfs_key *prev_key) | ||
112 | { | 130 | { |
113 | struct btrfs_fs_info *fs_info = leaf->fs_info; | 131 | struct btrfs_fs_info *fs_info = leaf->fs_info; |
114 | struct btrfs_file_extent_item *fi; | 132 | struct btrfs_file_extent_item *fi; |
@@ -188,6 +206,28 @@ static int check_extent_data_item(struct extent_buffer *leaf, | |||
188 | CHECK_FE_ALIGNED(leaf, slot, fi, offset, sectorsize) || | 206 | CHECK_FE_ALIGNED(leaf, slot, fi, offset, sectorsize) || |
189 | CHECK_FE_ALIGNED(leaf, slot, fi, num_bytes, sectorsize)) | 207 | CHECK_FE_ALIGNED(leaf, slot, fi, num_bytes, sectorsize)) |
190 | return -EUCLEAN; | 208 | return -EUCLEAN; |
209 | |||
210 | /* | ||
211 | * Check that no two consecutive file extent items, in the same leaf, | ||
212 | * present ranges that overlap each other. | ||
213 | */ | ||
214 | if (slot > 0 && | ||
215 | prev_key->objectid == key->objectid && | ||
216 | prev_key->type == BTRFS_EXTENT_DATA_KEY) { | ||
217 | struct btrfs_file_extent_item *prev_fi; | ||
218 | u64 prev_end; | ||
219 | |||
220 | prev_fi = btrfs_item_ptr(leaf, slot - 1, | ||
221 | struct btrfs_file_extent_item); | ||
222 | prev_end = file_extent_end(leaf, prev_key, prev_fi); | ||
223 | if (prev_end > key->offset) { | ||
224 | file_extent_err(leaf, slot - 1, | ||
225 | "file extent end range (%llu) goes beyond start offset (%llu) of the next file extent", | ||
226 | prev_end, key->offset); | ||
227 | return -EUCLEAN; | ||
228 | } | ||
229 | } | ||
230 | |||
191 | return 0; | 231 | return 0; |
192 | } | 232 | } |
193 | 233 | ||
@@ -774,14 +814,15 @@ static int check_inode_item(struct extent_buffer *leaf, | |||
774 | * Common point to switch the item-specific validation. | 814 | * Common point to switch the item-specific validation. |
775 | */ | 815 | */ |
776 | static int check_leaf_item(struct extent_buffer *leaf, | 816 | static int check_leaf_item(struct extent_buffer *leaf, |
777 | struct btrfs_key *key, int slot) | 817 | struct btrfs_key *key, int slot, |
818 | struct btrfs_key *prev_key) | ||
778 | { | 819 | { |
779 | int ret = 0; | 820 | int ret = 0; |
780 | struct btrfs_chunk *chunk; | 821 | struct btrfs_chunk *chunk; |
781 | 822 | ||
782 | switch (key->type) { | 823 | switch (key->type) { |
783 | case BTRFS_EXTENT_DATA_KEY: | 824 | case BTRFS_EXTENT_DATA_KEY: |
784 | ret = check_extent_data_item(leaf, key, slot); | 825 | ret = check_extent_data_item(leaf, key, slot, prev_key); |
785 | break; | 826 | break; |
786 | case BTRFS_EXTENT_CSUM_KEY: | 827 | case BTRFS_EXTENT_CSUM_KEY: |
787 | ret = check_csum_item(leaf, key, slot); | 828 | ret = check_csum_item(leaf, key, slot); |
@@ -928,7 +969,7 @@ static int check_leaf(struct extent_buffer *leaf, bool check_item_data) | |||
928 | * Check if the item size and content meet other | 969 | * Check if the item size and content meet other |
929 | * criteria | 970 | * criteria |
930 | */ | 971 | */ |
931 | ret = check_leaf_item(leaf, &key, slot); | 972 | ret = check_leaf_item(leaf, &key, slot, &prev_key); |
932 | if (ret < 0) | 973 | if (ret < 0) |
933 | return ret; | 974 | return ret; |
934 | } | 975 | } |