Skip to content

Commit 7e81d2c

Browse files
committed
btrfs: add in-flight queue read policy
Select the preferred stripe based on the mirror with the least in-flight requests. Signed-off-by: Kai Krakow <kai@kaishome.de>
1 parent 8f86b12 commit 7e81d2c

File tree

3 files changed

+50
-1
lines changed

3 files changed

+50
-1
lines changed

fs/btrfs/sysfs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,7 @@ static const char *btrfs_read_policy_name[] = {
13251325
"pid",
13261326
#ifdef CONFIG_BTRFS_READ_POLICIES
13271327
"round-robin",
1328+
"queue",
13281329
"devid",
13291330
#endif
13301331
};
@@ -1341,7 +1342,7 @@ char *btrfs_get_mod_read_policy(void)
13411342
/* Set perms to 0, disable /sys/module/btrfs/parameter/read_policy interface. */
13421343
module_param(read_policy, charp, 0);
13431344
MODULE_PARM_DESC(read_policy,
1344-
"Global read policy: pid (default), round-robin[:<min_contig_read>], devid[:<devid>]");
1345+
"Global read policy: pid (default), round-robin[:<min_contig_read>], queue, devid[:<devid>]");
13451346
#endif
13461347

13471348
int btrfs_read_policy_to_enum(const char *str, s64 *value_ret)

fs/btrfs/volumes.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
#include "super.h"
3535
#include "raid-stripe-tree.h"
3636

37+
#ifdef CONFIG_BTRFS_READ_POLICIES
38+
#include <linux/part_stat.h>
39+
#endif
40+
3741
#define BTRFS_BLOCK_GROUP_STRIPE_MASK (BTRFS_BLOCK_GROUP_RAID0 | \
3842
BTRFS_BLOCK_GROUP_RAID10 | \
3943
BTRFS_BLOCK_GROUP_RAID56_MASK)
@@ -6051,6 +6055,44 @@ unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info,
60516055
}
60526056

60536057
#ifdef CONFIG_BTRFS_READ_POLICIES
6058+
static unsigned int part_in_flight(struct block_device *part)
6059+
{
6060+
unsigned int inflight = 0;
6061+
int cpu;
6062+
6063+
for_each_possible_cpu(cpu) {
6064+
inflight += part_stat_local_read_cpu(part, in_flight[READ], cpu) +
6065+
part_stat_local_read_cpu(part, in_flight[WRITE], cpu);
6066+
}
6067+
if ((int)inflight < 0)
6068+
inflight = 0;
6069+
6070+
return inflight;
6071+
}
6072+
6073+
/*
6074+
* btrfs_earliest_stripe
6075+
*
6076+
* Select a stripe from the device with shortest in-flight requests.
6077+
*/
6078+
static int btrfs_read_earliest(struct btrfs_fs_info *fs_info,
6079+
struct btrfs_chunk_map *map, int first,
6080+
int num_stripes)
6081+
{
6082+
u64 best_in_flight = U64_MAX;
6083+
int best_stripe = 0;
6084+
6085+
for (int index = first; index < first + num_stripes; index++) {
6086+
u64 in_flight = part_in_flight(map->stripes[index].dev->bdev);
6087+
if (best_in_flight > in_flight) {
6088+
best_in_flight = in_flight;
6089+
best_stripe = index;
6090+
}
6091+
}
6092+
6093+
return best_stripe;
6094+
}
6095+
60546096
static int btrfs_read_preferred(struct btrfs_chunk_map *map, int first, int num_stripes)
60556097
{
60566098
for (int index = first; index < first + num_stripes; index++) {
@@ -6162,6 +6204,10 @@ static int find_live_mirror(struct btrfs_fs_info *fs_info,
61626204
case BTRFS_READ_POLICY_RR:
61636205
preferred_mirror = btrfs_read_rr(map, first, num_stripes);
61646206
break;
6207+
case BTRFS_READ_POLICY_QUEUE:
6208+
preferred_mirror = btrfs_read_earliest(fs_info, map, first,
6209+
num_stripes);
6210+
break;
61656211
case BTRFS_READ_POLICY_DEVID:
61666212
preferred_mirror = btrfs_read_preferred(map, first, num_stripes);
61676213
break;

fs/btrfs/volumes.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,8 @@ enum btrfs_read_policy {
321321
#ifdef CONFIG_BTRFS_READ_POLICIES
322322
/* Balancing RAID1 reads across all striped devices (round-robin). */
323323
BTRFS_READ_POLICY_RR,
324+
/* Read from the device with the least in-flight requests */
325+
BTRFS_READ_POLICY_QUEUE,
324326
/* Read from a specific device. */
325327
BTRFS_READ_POLICY_DEVID,
326328
#endif

0 commit comments

Comments
 (0)