diff mbox series

[v5,05/10] btrfs: add read count tracking for filesystem stats

Message ID c4010cee5398e35a695def3ad97d4de6f136ae2c.1735748715.git.anand.jain@oracle.com (mailing list archive)
State New
Headers show
Series raid1 balancing methods | expand

Commit Message

Anand Jain Jan. 1, 2025, 6:06 p.m. UTC
Add fs_devices::read_cnt_blocks to track read blocks, initialize it in
open_fs_devices() and clean it up in close_fs_devices().
btrfs_submit_dev_bio() increments it for reads when stats tracking is
enabled. Stats tracking is disabled by default and is enabled through
fs_devices::fs_stats when required.

The code is not under the EXPERIMENTAL define, as stats can be expanded
to include write counts and other performance counters, with the user
interface independent of its internal use.

This is an in-memory-only feature, different to the dev error stats.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
 fs/btrfs/bio.c     | 8 ++++++++
 fs/btrfs/disk-io.c | 3 +++
 fs/btrfs/volumes.c | 8 +++++++-
 fs/btrfs/volumes.h | 7 ++++++-
 4 files changed, 24 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c
index 1f216d07eff6..faefb18010fc 100644
--- a/fs/btrfs/bio.c
+++ b/fs/btrfs/bio.c
@@ -450,6 +450,14 @@  static void btrfs_submit_dev_bio(struct btrfs_device *dev, struct bio *bio)
 		(unsigned long)dev->bdev->bd_dev, btrfs_dev_name(dev),
 		dev->devid, bio->bi_iter.bi_size);
 
+	/*
+	 * Track reads if tracking is enabled; ignore I/O operations before
+	 * fully initialized.
+	 */
+	if (dev->fs_devices->fs_stats && bio_op(bio) == REQ_OP_READ && dev->fs_info)
+		percpu_counter_add(&dev->fs_devices->read_cnt_blocks,
+				   bio->bi_iter.bi_size >> dev->fs_info->sectorsize_bits);
+
 	if (bio->bi_opf & REQ_BTRFS_CGROUP_PUNT)
 		blkcg_punt_bio_submit(bio);
 	else
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index ab45b02df957..79b859790e8c 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3481,6 +3481,9 @@  int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
 		goto fail_sysfs;
 	}
 
+	/* Disable filesystem stats tracking unless required by a feature. */
+	fs_devices->fs_stats = false;
+
 	ret = btrfs_read_block_groups(fs_info);
 	if (ret) {
 		btrfs_err(fs_info, "failed to read block groups: %d", ret);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index fe5ceea2ba0b..1fa40bf6f708 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1254,6 +1254,7 @@  static void close_fs_devices(struct btrfs_fs_devices *fs_devices)
 	list_for_each_entry_safe(device, tmp, &fs_devices->devices, dev_list)
 		btrfs_close_one_device(device);
 
+	percpu_counter_destroy(&fs_devices->read_cnt_blocks);
 	WARN_ON(fs_devices->open_devices);
 	WARN_ON(fs_devices->rw_devices);
 	fs_devices->opened = 0;
@@ -1300,6 +1301,11 @@  static int open_fs_devices(struct btrfs_fs_devices *fs_devices,
 	struct btrfs_device *tmp_device;
 	int ret = 0;
 
+	/* Initialize the in-memory record of filesystem read count */
+	ret = percpu_counter_init(&fs_devices->read_cnt_blocks, 0, GFP_KERNEL);
+	if (ret)
+		return ret;
+
 	list_for_each_entry_safe(device, tmp_device, &fs_devices->devices,
 				 dev_list) {
 		int ret2;
@@ -7669,7 +7675,7 @@  int btrfs_init_dev_stats(struct btrfs_fs_info *fs_info)
 	list_for_each_entry(device, &fs_devices->devices, dev_list) {
 		ret = btrfs_device_init_dev_stats(device, path);
 		if (ret)
-			goto out;
+			return ret;
 	}
 	list_for_each_entry(seed_devs, &fs_devices->seed_list, seed_list) {
 		list_for_each_entry(device, &seed_devs->devices, dev_list) {
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 3a416b1bc24c..45d0eb3429c6 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -185,7 +185,7 @@  struct btrfs_device {
 	 * enum btrfs_dev_stat_values in ioctl.h */
 	int dev_stats_valid;
 
-	/* Counter to record the change of device stats */
+	/* Counter to record of the change of device stats */
 	atomic_t dev_stats_ccnt;
 	atomic_t dev_stat_values[BTRFS_DEV_STAT_VALUES_MAX];
 
@@ -417,6 +417,8 @@  struct btrfs_fs_devices {
 	bool seeding;
 	/* The mount needs to use a randomly generated fsid. */
 	bool temp_fsid;
+	/* Enable/disable the filesystem stats tracking */
+	bool fs_stats;
 
 	struct btrfs_fs_info *fs_info;
 	/* sysfs kobjects */
@@ -427,6 +429,9 @@  struct btrfs_fs_devices {
 
 	enum btrfs_chunk_allocation_policy chunk_alloc_policy;
 
+	/* Tracks the number of blocks (sectors) read from the filesystem. */
+	struct percpu_counter read_cnt_blocks;
+
 	/* Policy used to read the mirrored stripes. */
 	enum btrfs_read_policy read_policy;