Skip to content

Commit 7dfb8be

Browse files
lorddoskiaskdave
authored andcommitted
btrfs: Round down values which are written for total_bytes_size
We got an internal report about a file system not wanting to mount following 99e3ecf ("Btrfs: add more validation checks for superblock"). BTRFS error (device sdb1): super_total_bytes 1000203816960 mismatch with fs_devices total_rw_bytes 1000203820544 Subtracting the numbers we get a difference of less than a 4kb. Upon closer inspection it became apparent that mkfs actually rounds down the size of the device to a multiple of sector size. However, the same cannot be said for various functions which modify the total size and are called from btrfs_balance as well as when adding a new device. So this patch ensures that values being saved into on-disk data structures are always rounded down to a multiple of sectorsize. Signed-off-by: Nikolay Borisov <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent eca152e commit 7dfb8be

File tree

2 files changed

+14
-5
lines changed

2 files changed

+14
-5
lines changed

fs/btrfs/ctree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,6 +1556,7 @@ static inline void btrfs_set_device_total_bytes(struct extent_buffer *eb,
15561556
{
15571557
BUILD_BUG_ON(sizeof(u64) !=
15581558
sizeof(((struct btrfs_dev_item *)0))->total_bytes);
1559+
WARN_ON(!IS_ALIGNED(val, eb->fs_info->sectorsize));
15591560
btrfs_set_64(eb, s, offsetof(struct btrfs_dev_item, total_bytes), val);
15601561
}
15611562

fs/btrfs/volumes.c

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2385,7 +2385,8 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
23852385
device->io_width = fs_info->sectorsize;
23862386
device->io_align = fs_info->sectorsize;
23872387
device->sector_size = fs_info->sectorsize;
2388-
device->total_bytes = i_size_read(bdev->bd_inode);
2388+
device->total_bytes = round_down(i_size_read(bdev->bd_inode),
2389+
fs_info->sectorsize);
23892390
device->disk_total_bytes = device->total_bytes;
23902391
device->commit_total_bytes = device->total_bytes;
23912392
device->fs_info = fs_info;
@@ -2422,7 +2423,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
24222423

24232424
tmp = btrfs_super_total_bytes(fs_info->super_copy);
24242425
btrfs_set_super_total_bytes(fs_info->super_copy,
2425-
tmp + device->total_bytes);
2426+
round_down(tmp + device->total_bytes, fs_info->sectorsize));
24262427

24272428
tmp = btrfs_super_num_devices(fs_info->super_copy);
24282429
btrfs_set_super_num_devices(fs_info->super_copy, tmp + 1);
@@ -2685,6 +2686,8 @@ int btrfs_grow_device(struct btrfs_trans_handle *trans,
26852686
if (!device->writeable)
26862687
return -EACCES;
26872688

2689+
new_size = round_down(new_size, fs_info->sectorsize);
2690+
26882691
mutex_lock(&fs_info->chunk_mutex);
26892692
old_total = btrfs_super_total_bytes(super_copy);
26902693
diff = new_size - device->total_bytes;
@@ -2697,7 +2700,8 @@ int btrfs_grow_device(struct btrfs_trans_handle *trans,
26972700

26982701
fs_devices = fs_info->fs_devices;
26992702

2700-
btrfs_set_super_total_bytes(super_copy, old_total + diff);
2703+
btrfs_set_super_total_bytes(super_copy,
2704+
round_down(old_total + diff, fs_info->sectorsize));
27012705
device->fs_devices->total_rw_bytes += diff;
27022706

27032707
btrfs_device_set_total_bytes(device, new_size);
@@ -4387,7 +4391,10 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
43874391
struct btrfs_super_block *super_copy = fs_info->super_copy;
43884392
u64 old_total = btrfs_super_total_bytes(super_copy);
43894393
u64 old_size = btrfs_device_get_total_bytes(device);
4390-
u64 diff = old_size - new_size;
4394+
u64 diff;
4395+
4396+
new_size = round_down(new_size, fs_info->sectorsize);
4397+
diff = old_size - new_size;
43914398

43924399
if (device->is_tgtdev_for_dev_replace)
43934400
return -EINVAL;
@@ -4514,7 +4521,8 @@ int btrfs_shrink_device(struct btrfs_device *device, u64 new_size)
45144521
&fs_info->fs_devices->resized_devices);
45154522

45164523
WARN_ON(diff > old_total);
4517-
btrfs_set_super_total_bytes(super_copy, old_total - diff);
4524+
btrfs_set_super_total_bytes(super_copy,
4525+
round_down(old_total - diff, fs_info->sectorsize));
45184526
mutex_unlock(&fs_info->chunk_mutex);
45194527

45204528
/* Now btrfs_update_device() will change the on-disk size. */

0 commit comments

Comments
 (0)