diff mbox series

[RFC,7/7] btrfs: introduce new read_policy round-robin

Message ID 4c4dd72374fdd51674cd1c909fe48fb6f3853d71.1603751876.git.anand.jain@oracle.com
State New
Headers show
Series [RFC,1/7] block: export part_stat_read_all | expand

Commit Message

Anand Jain Oct. 26, 2020, 11:55 p.m. UTC
Add round-robin read policy to route the read IO to the next device in the
round-robin order. The chunk allocation and thus the stripe-index follows
the order of free space available on devices. So to make the round-robin
effective it shall follow the devid order instead of the stripe-index
order.

Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
 fs/btrfs/sysfs.c   |  2 +-
 fs/btrfs/volumes.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++
 fs/btrfs/volumes.h |  2 ++
 3 files changed, 71 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index 677070bab1e0..45efc9755336 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -876,7 +876,7 @@  static int btrfs_strmatch(const char *given, const char *golden)
 
 /* Must follow the order as in enum btrfs_read_policy */
 static const char * const btrfs_read_policy_name[] = { "pid", "latency",
-						       "device" };
+						       "device", "roundrobin" };
 
 static ssize_t btrfs_read_policy_show(struct kobject *kobj,
 				      struct kobj_attribute *a, char *buf)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index e71af8ab4ad8..d3023879bdf6 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -5466,6 +5466,69 @@  int btrfs_is_parity_mirror(struct btrfs_fs_info *fs_info, u64 logical, u64 len)
 	return ret;
 }
 
+struct stripe_mirror {
+	u64 devid;
+	int map;
+};
+
+static int btrfs_cmp_devid(const void *a, const void *b)
+{
+	struct stripe_mirror *s1 = (struct stripe_mirror *)a;
+	struct stripe_mirror *s2 = (struct stripe_mirror *)b;
+
+	if (s1->devid < s2->devid)
+		return -1;
+	if (s1->devid > s2->devid)
+		return 1;
+	return 0;
+}
+
+static int btrfs_find_read_round_robin(struct map_lookup *map, int first,
+				       int num_stripe, char *log, int logsz)
+{
+	struct stripe_mirror stripes[4] = {0}; //4: for testing, works for now.
+	struct btrfs_fs_devices *fs_devices;
+	u64 devid;
+	int index, j, cnt;
+	int lognr = 0;
+	int next_stripe;
+
+	index = 0;
+	lognr += scnprintf(log + lognr, logsz - lognr, "index=map:devid [");
+	for (j = first; j < first + num_stripe; j++) {
+		devid = map->stripes[j].dev->devid;
+
+		stripes[index].devid = devid;
+		stripes[index].map = j;
+
+		lognr += scnprintf(log + lognr, logsz - lognr, "%d=%d:%llu, ",
+				  index, j, devid);
+
+		index++;
+	}
+
+	sort(stripes, num_stripe, sizeof(struct stripe_mirror),
+	     btrfs_cmp_devid, NULL);
+
+	lognr += scnprintf(log + lognr, logsz - lognr, "] sorted=[");
+	for (index = 0; index < num_stripe; index++) {
+		j = stripes[index].map;
+		devid = stripes[index].devid;
+
+		lognr += scnprintf(log + lognr, logsz - lognr, "%d=%d:%llu, ",
+				  index, j, devid);
+	}
+
+	fs_devices = map->stripes[first].dev->fs_devices;
+	cnt = atomic_inc_return(&fs_devices->total_reads);
+	next_stripe = stripes[cnt % num_stripe].map;
+
+	lognr += scnprintf(log + lognr, logsz - lognr, "] next_stripe %d",
+			  next_stripe);
+
+	return next_stripe;
+}
+
 static u64 btrfs_estimate_read(struct btrfs_device *device,
 			       unsigned long *inflight)
 {
@@ -5608,6 +5671,11 @@  static int find_live_mirror(struct btrfs_fs_info *fs_info,
 			  first, num_stripes, current->comm, task_pid_nr(current),
 			  preferred_mirror);
 		break;
+	case BTRFS_READ_POLICY_ROUND_ROBIN:
+		preferred_mirror = btrfs_find_read_round_robin(map, first,
+							       num_stripes, log,
+							       logsz);
+		break;
 	}
 
 	/*
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 40e56287204a..571b52afcaa1 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -220,6 +220,7 @@  enum btrfs_read_policy {
 	BTRFS_READ_POLICY_PID,
 	BTRFS_READ_POLICY_LATENCY,
 	BTRFS_READ_POLICY_DEVICE,
+	BTRFS_READ_POLICY_ROUND_ROBIN,
 	BTRFS_NR_READ_POLICY,
 };
 
@@ -281,6 +282,7 @@  struct btrfs_fs_devices {
 	 * policy used to read the mirrored stripes
 	 */
 	enum btrfs_read_policy read_policy;
+	atomic_t total_reads;
 };
 
 #define BTRFS_BIO_INLINE_CSUM_SIZE	64