linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] btrfs: reduce the width of devices counter
@ 2023-09-19  2:21 Qu Wenruo
  2023-09-19  2:21 ` [PATCH 1/2] btrfs: reject a superblock with over 65536 devices Qu Wenruo
  2023-09-19  2:21 ` [PATCH 2/2] btrfs: reduce the width of device counters Qu Wenruo
  0 siblings, 2 replies; 3+ messages in thread
From: Qu Wenruo @ 2023-09-19  2:21 UTC (permalink / raw)
  To: linux-btrfs

Currently btrfs_super_block::num_devices is u64, thus all of our
internal devices counters are also u64.

But the truth is, it's really impractical to have that many devices, one
of two dozens of devices may be the upper limit in the real world.

In fact we already have a sanity check for
btrfs_super_block::num_devices, if the value is beyond 1<<31, we would
consider it insane and reject the superblock.

Now let's go a step further, by reducing the limit to U16_MAX (65536),
and with that change, we can also reduce the width from 64 to 16 for all
our internal devices counters.
(superblock num_devices still stay u64 though).

Such reduce would slightly reduce the memory usage per-btrfs.

Also with the new device number limit, the 2nd patch would do extra
device number check to avoid overflow u16.

Qu Wenruo (2):
  btrfs: reject a superblock with over 65536 devices
  btrfs: reduce the width of device counters

 fs/btrfs/dev-replace.c |  9 +++++++++
 fs/btrfs/disk-io.c     |  3 ++-
 fs/btrfs/volumes.c     | 11 ++++++++++-
 fs/btrfs/volumes.h     | 12 ++++++------
 4 files changed, 27 insertions(+), 8 deletions(-)

-- 
2.42.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 1/2] btrfs: reject a superblock with over 65536 devices
  2023-09-19  2:21 [PATCH 0/2] btrfs: reduce the width of devices counter Qu Wenruo
@ 2023-09-19  2:21 ` Qu Wenruo
  2023-09-19  2:21 ` [PATCH 2/2] btrfs: reduce the width of device counters Qu Wenruo
  1 sibling, 0 replies; 3+ messages in thread
From: Qu Wenruo @ 2023-09-19  2:21 UTC (permalink / raw)
  To: linux-btrfs

The btrfs superblock uses u64 for num_devices (including both read-write
and read-only devices).

The real-world value should be way smaller, dozens of devices would
already be a little too many, not to mention anything beyond U16_MAX
(65535).

So here we just reject any superblock with a num_devices beyond U16_MAX.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/disk-io.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 163f37ad1b27..beb35a0187f4 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2431,7 +2431,8 @@ int btrfs_validate_super(struct btrfs_fs_info *fs_info,
 			  btrfs_super_stripesize(sb));
 		ret = -EINVAL;
 	}
-	if (btrfs_super_num_devices(sb) > (1UL << 31))
+	/* 65536 devices already doesn't sound sane. */
+	if (btrfs_super_num_devices(sb) > U16_MAX)
 		btrfs_warn(fs_info, "suspicious number of devices: %llu",
 			   btrfs_super_num_devices(sb));
 	if (btrfs_super_num_devices(sb) == 0) {
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] btrfs: reduce the width of device counters
  2023-09-19  2:21 [PATCH 0/2] btrfs: reduce the width of devices counter Qu Wenruo
  2023-09-19  2:21 ` [PATCH 1/2] btrfs: reject a superblock with over 65536 devices Qu Wenruo
@ 2023-09-19  2:21 ` Qu Wenruo
  1 sibling, 0 replies; 3+ messages in thread
From: Qu Wenruo @ 2023-09-19  2:21 UTC (permalink / raw)
  To: linux-btrfs

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(-)

diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index d3998cad62c2..1a7a8caf1e51 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -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!");
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 2f05d38980ce..96bfa86d7371 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -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;
 		}
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index b513b2846793..045e9eadd025 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -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;
 
-- 
2.42.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-09-19  2:21 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-09-19  2:21 [PATCH 0/2] btrfs: reduce the width of devices counter Qu Wenruo
2023-09-19  2:21 ` [PATCH 1/2] btrfs: reject a superblock with over 65536 devices Qu Wenruo
2023-09-19  2:21 ` [PATCH 2/2] btrfs: reduce the width of device counters Qu Wenruo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).