btrfs-progs: convert: ensure the data chunks size never exceed device size
[BUG] The following script could lead to corrupted btrfs fs after btrfs-convert: fallocate -l 1G test.img mkfs.ext4 test.img mount test.img $mnt fallocate -l 200m $mnt/file1 fallocate -l 200m $mnt/file2 fallocate -l 200m $mnt/file3 fallocate -l 200m $mnt/file4 fallocate -l 205m $mnt/file1 fallocate -l 205m $mnt/file2 fallocate -l 205m $mnt/file3 fallocate -l 205m $mnt/file4 umount $mnt btrfs-convert test.img The result btrfs will have a device extent beyond its boundary: pening filesystem to check... Checking filesystem on test.img UUID: bbcd7399-fd5b-41a7-81ae-d48bc6935e43 [1/7] checking root items [2/7] checking extents ERROR: dev extent devid 1 physical offset 993198080 len 85786624 is beyond device boundary 1073741824 ERROR: errors found in extent allocation tree or chunk allocation [3/7] checking free space cache [4/7] checking fs roots [5/7] checking only csums items (without verifying data) [6/7] checking root refs [7/7] checking quota groups skipped (not enabled on this FS) found 913960960 bytes used, error(s) found total csum bytes: 891500 total tree bytes: 1064960 total fs tree bytes: 49152 total extent tree bytes: 16384 btree space waste bytes: 144885 file data blocks allocated: 2129063936 referenced 1772728320 [CAUSE] Btrfs-convert first collect all used blocks in the original fs, then slightly enlarge the used blocks range as new btrfs data chunks. However the enlarge part has a problem, that it doesn't take the device boundary into consideration. Thus it caused device extents and data chunks to go beyond device boundary. [FIX] Just to extra check before inserting data chunks into btrfs_convert_context::data_chunk. Reported-by: Jiachen YANG <farseerfc@gmail.com> Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
2eb48d8c81
commit
0ff7a9b521
|
@ -669,6 +669,8 @@ static int calculate_available_space(struct btrfs_convert_context *cctx)
|
|||
cur_off = cache->start;
|
||||
cur_len = max(cache->start + cache->size - cur_off,
|
||||
min_stripe_size);
|
||||
/* data chunks should never exceed device boundary */
|
||||
cur_len = min(cctx->total_bytes - cur_off, cur_len);
|
||||
ret = add_merge_cache_extent(data_chunks, cur_off, cur_len);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
|
Loading…
Reference in New Issue