* [PATCH 1/1 RFC] btrfs: add read_policy heuristic
2022-07-21 11:52 [PATCH 0/1 RFC] read_policy type heuristic Anand Jain
@ 2022-07-21 11:52 ` Anand Jain
0 siblings, 0 replies; 2+ messages in thread
From: Anand Jain @ 2022-07-21 11:52 UTC (permalink / raw)
To: linux-btrfs
Read_policy type Heuristic provides the low latency device-type if
read_policy type PID fails. The read policy heuristic retains the
advantages of the PID-based read_policy and has no dependency on
block layer iostats. This policy can be a default policy.
This patch depends on the patches[1], which provides device types
in the order of their latency.
[1]
btrfs: create chunk device type aware
btrfs: keep device type in the struct btrfs_device
Usage:
$ echo heuristic > /sys/fs/btrfs/4b74dc57-526c-42c0-882a-8be30e1b8933/read_policy
Signed-off-by: Anand Jain <anand.jain@oracle.com>
---
fs/btrfs/sysfs.c | 2 +-
fs/btrfs/volumes.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++
fs/btrfs/volumes.h | 2 ++
3 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index d5d0717fd09a..501c216009fb 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -1169,7 +1169,7 @@ static bool strmatch(const char *buffer, const char *string)
return false;
}
-static const char * const btrfs_read_policy_name[] = { "pid" };
+static const char * const btrfs_read_policy_name[] = { "pid", "heuristic" };
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 ad053c2a63a5..7efdd1dabf7b 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -5896,6 +5896,54 @@ int btrfs_is_parity_mirror(struct btrfs_fs_info *fs_info, u64 logical, u64 len)
return ret;
}
+static int btrfs_read_heuristic(struct btrfs_fs_info *fs_info,
+ struct map_lookup *map, int first,
+ int num_stripes)
+{
+ int cur;
+ int new;
+ int stripe;
+ int latency;
+ int curlatency;
+
+ /*
+ * First get the preferred mirror as per current pid and check its
+ * latency
+ */
+ stripe = first + (current->pid % num_stripes);
+ latency = btrfs_dev_type_to_latency(map->stripes[stripe].dev->dev_type);
+
+ /* If the device selected already has the lowest latency then return */
+ if (latency == 0)
+ return stripe;
+
+ cur = stripe;
+ curlatency = latency;
+
+ /* Find if any other stripes have lower latency */
+ for (new = first; new < first + num_stripes; new++) {
+ struct btrfs_device *device = map->stripes[new].dev;
+ int newlatency;
+
+ newlatency = btrfs_dev_type_to_latency(device->dev_type);
+
+ if (newlatency < curlatency) {
+ cur = new;
+ curlatency = newlatency;
+ }
+ }
+
+ /*
+ * If the PID chosen device also has the same latency, then use that
+ * device.
+ */
+ if (curlatency == latency)
+ return stripe;
+
+ return cur;
+}
+
+
static int find_live_mirror(struct btrfs_fs_info *fs_info,
struct map_lookup *map, int first,
int dev_replace_is_ongoing)
@@ -5925,6 +5973,10 @@ static int find_live_mirror(struct btrfs_fs_info *fs_info,
case BTRFS_READ_POLICY_PID:
preferred_mirror = first + (current->pid % num_stripes);
break;
+ case BTRFS_READ_POLICY_HEURISTIC:
+ preferred_mirror = btrfs_read_heuristic(fs_info, map, first,
+ num_stripes);
+ break;
}
if (dev_replace_is_ongoing &&
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 0fe20eb4087a..c8a73722bf60 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -277,6 +277,8 @@ enum btrfs_chunk_allocation_policy {
enum btrfs_read_policy {
/* Use process PID to choose the stripe */
BTRFS_READ_POLICY_PID,
+ /* Find and use device with the lowest latency */
+ BTRFS_READ_POLICY_HEURISTIC,
BTRFS_NR_READ_POLICY,
};
--
2.33.1
^ permalink raw reply related [flat|nested] 2+ messages in thread