Skip to content

Commit f1d7497

Browse files
committed
btrfs: add hybrid latency-rr read policy
This mode combines latency and round-robin modes by considering all stripes within 120% of the minimum latency. It falls back to round-robin if all stripes have no latency recorded yet. Signed-off-by: Kai Krakow <[email protected]>
1 parent 4426a9c commit f1d7497

File tree

3 files changed

+51
-2
lines changed

3 files changed

+51
-2
lines changed

fs/btrfs/sysfs.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,6 +1310,7 @@ static const char *btrfs_read_policy_name[] = {
13101310
#ifdef CONFIG_BTRFS_EXPERIMENTAL
13111311
"round-robin",
13121312
"latency",
1313+
"latency-rr",
13131314
"devid",
13141315
#endif
13151316
};
@@ -1325,7 +1326,7 @@ char *btrfs_get_mod_read_policy(void)
13251326
/* Set perm 0, disable sys/module/btrfs/parameter/read_policy interface */
13261327
module_param(read_policy, charp, 0);
13271328
MODULE_PARM_DESC(read_policy,
1328-
"Global read policy; pid (default), round-robin[:min_contig_read], latency, devid[:devid]");
1329+
"Global read policy; pid (default), round-robin[:min_contig_read], latency, latency-rr[:min_contig_read], devid[:devid]");
13291330
#endif
13301331

13311332
int btrfs_read_policy_to_enum(const char *str, s64 *value)
@@ -1383,6 +1384,10 @@ static ssize_t btrfs_read_policy_show(struct kobject *kobj,
13831384
ret += sysfs_emit_at(buf, ret, "%s", btrfs_read_policy_name[i]);
13841385

13851386
#ifdef CONFIG_BTRFS_EXPERIMENTAL
1387+
if (i == BTRFS_READ_POLICY_LATENCY_RR)
1388+
ret += sysfs_emit_at(buf, ret, ":%d",
1389+
READ_ONCE(fs_devices->rr_min_contig_read));
1390+
13861391
if (i == BTRFS_READ_POLICY_RR)
13871392
ret += sysfs_emit_at(buf, ret, ":%d",
13881393
READ_ONCE(fs_devices->rr_min_contig_read));
@@ -1418,7 +1423,11 @@ static ssize_t btrfs_read_policy_store(struct kobject *kobj,
14181423
index != BTRFS_READ_POLICY_RR)
14191424
fs_devices->fs_stats = false;
14201425

1421-
if (index == BTRFS_READ_POLICY_RR) {
1426+
if (fs_devices->read_policy == BTRFS_READ_POLICY_LATENCY_RR &&
1427+
index != BTRFS_READ_POLICY_LATENCY_RR)
1428+
fs_devices->fs_stats = false;
1429+
1430+
if ((index == BTRFS_READ_POLICY_RR) || (index == BTRFS_READ_POLICY_LATENCY_RR)) {
14221431
if (value != -1) {
14231432
u32 sectorsize = fs_devices->fs_info->sectorsize;
14241433

fs/btrfs/volumes.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6143,6 +6143,40 @@ static int btrfs_read_rr(struct btrfs_chunk_map *map, int first, int num_stripes
61436143

61446144
return ret_stripe;
61456145
}
6146+
6147+
/*
6148+
* btrfs_read_fastest_rr.
6149+
*
6150+
* Select a stripe for reading using a hybrid algorithm:
6151+
*
6152+
* 1. Determine the fastest stripe using btrfs_best_stripe.
6153+
* 2. Add 20% headroom to the selected latency.
6154+
* 3. Select a stripe using btrfs_read_rr filtered by latency.
6155+
*/
6156+
static int btrfs_read_fastest_rr(struct btrfs_fs_info *fs_info,
6157+
struct btrfs_chunk_map *map, int first,
6158+
int num_stripes)
6159+
{
6160+
u64 min_latency;
6161+
int ret_stripe = -1;
6162+
6163+
btrfs_best_stripe(fs_info, map, first, num_stripes, &min_latency,
6164+
&ret_stripe);
6165+
6166+
/* min_latency will be 0 if no latency has been recorded yet,
6167+
* add 20% headroom otherwise.
6168+
*/
6169+
if (likely(min_latency)) {
6170+
min_latency = min_latency * 6;
6171+
min_latency = div_u64(min_latency, 5);
6172+
ret_stripe = btrfs_read_rr(map, first, num_stripes, min_latency);
6173+
}
6174+
6175+
if (ret_stripe < 0)
6176+
ret_stripe = btrfs_read_rr(map, first, num_stripes, 0);
6177+
6178+
return ret_stripe;
6179+
}
61466180
#endif
61476181

61486182
static int find_live_mirror(struct btrfs_fs_info *fs_info,
@@ -6185,6 +6219,10 @@ static int find_live_mirror(struct btrfs_fs_info *fs_info,
61856219
preferred_mirror = btrfs_read_fastest(fs_info, map, first,
61866220
num_stripes);
61876221
break;
6222+
case BTRFS_READ_POLICY_LATENCY_RR:
6223+
preferred_mirror = btrfs_read_fastest_rr(fs_info, map, first,
6224+
num_stripes);
6225+
break;
61886226
#endif
61896227
}
61906228

fs/btrfs/volumes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,8 @@ enum btrfs_read_policy {
310310
BTRFS_READ_POLICY_RR,
311311
/* Use the lowest-latency device dynamically */
312312
BTRFS_READ_POLICY_LATENCY,
313+
/* Use hybrid approach of lowest-latency and round-robin */
314+
BTRFS_READ_POLICY_LATENCY_RR,
313315
/* Read from the specific device */
314316
BTRFS_READ_POLICY_DEVID,
315317
#endif

0 commit comments

Comments
 (0)