@@ -250,6 +250,15 @@ static int btrfs_init_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
u64 devid = BTRFS_DEV_REPLACE_DEVID;
int ret = 0;
+ mutex_lock(&fs_devices->device_list_mutex);
+ if (unlikely(fs_devices->num_devices >= U16_MAX)) {
+ mutex_unlock(&fs_devices->device_list_mutex);
+ btrfs_err(fs_info,
+ "too many devices, has %u devices, up limit is %u",
+ fs_devices->num_devices, U16_MAX);
+ return -EINVAL;
+ }
+ mutex_unlock(&fs_devices->device_list_mutex);
*device_out = NULL;
if (srcdev->fs_devices->seeding) {
btrfs_err(fs_info, "the filesystem is a seed filesystem!");
@@ -2652,6 +2652,15 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
if (sb_rdonly(sb) && !fs_devices->seeding)
return -EROFS;
+ mutex_lock(&fs_info->chunk_mutex);
+ if (unlikely(fs_devices->num_devices >= U16_MAX)) {
+ btrfs_err(fs_info, "too many devices, has %u devices, up limit is %u",
+ fs_devices->num_devices, U16_MAX);
+ mutex_unlock(&fs_info->chunk_mutex);
+ return -EINVAL;
+ }
+ mutex_unlock(&fs_info->chunk_mutex);
+
bdev = blkdev_get_by_path(device_path, BLK_OPEN_WRITE,
fs_info->bdev_holder, NULL);
if (IS_ERR(bdev))
@@ -5263,7 +5272,7 @@ static int gather_device_info(struct btrfs_fs_devices *fs_devices,
}
if (ndevs == fs_devices->rw_devices) {
- WARN(1, "%s: found more than %llu devices\n",
+ WARN(1, "%s: found more than %u devices\n",
__func__, fs_devices->rw_devices);
break;
}
@@ -308,28 +308,28 @@ struct btrfs_fs_devices {
* Number of devices under this fsid including missing and
* replace-target device and excludes seed devices.
*/
- u64 num_devices;
+ u16 num_devices;
/*
* The number of devices that successfully opened, including
* replace-target, excludes seed devices.
*/
- u64 open_devices;
+ u16 open_devices;
/* The number of devices that are under the chunk allocation list. */
- u64 rw_devices;
+ u16 rw_devices;
/* Count of missing devices under this fsid excluding seed device. */
- u64 missing_devices;
- u64 total_rw_bytes;
+ u16 missing_devices;
/*
* Count of devices from btrfs_super_block::num_devices for this fsid,
* which includes the seed device, excludes the transient replace-target
* device.
*/
- u64 total_devices;
+ u16 total_devices;
+ u64 total_rw_bytes;
/* Highest generation number of seen devices */
u64 latest_generation;
Since we will reject the super block if its num_devices is beyond U16_MAX, there is no need to go u64 to count the devices. We can shrink the width of the following members: - num_devices - open_devices - rw_devices - missing_devices - total_devices And for the ioctls which will add a new device, always make sure the existing num_devices (the real total number of devices, including missing and replace-source) would never go beyond U16_MAX. Signed-off-by: Qu Wenruo <wqu@suse.com> --- fs/btrfs/dev-replace.c | 9 +++++++++ fs/btrfs/volumes.c | 11 ++++++++++- fs/btrfs/volumes.h | 12 ++++++------ 3 files changed, 25 insertions(+), 7 deletions(-)