From: "Chen Cheng" <chencheng@fnnas.com>
To: <linux-raid@vger.kernel.org>, <yukuai@fygo.io>, <xiaon@kernel.org>
Cc: <chencheng@fnnas.com>, <linux-kernel@vger.kernel.org>
Subject: [RFC PATCH 5/5] md/raid1: clarify choose_best_rdev comments
Date: Tue, 18 Aug 2026 15:06:46 +0800 [thread overview]
Message-ID: <20260818070646.1029149-6-chencheng@fnnas.com> (raw)
In-Reply-To: <20260818070646.1029149-1-chencheng@fnnas.com>
From: Chen Cheng <chencheng@fnnas.com>
Write the rot/nonrot read policy in short comments next to the code.
No functional change.
Signed-off-by: Chen Cheng <chencheng@fnnas.com>
---
drivers/md/raid1.c | 48 +++++++++++++++++++++++++++++++++-------------
1 file changed, 35 insertions(+), 13 deletions(-)
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index f476d4dea4be..897eef3a022d 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -788,15 +788,17 @@ struct read_balance_ctl {
int readable_disks;
bool min_pending_nonrot;
bool sequential_nonrot;
};
+/* Offset from rr start. Replacement uses the same slot as primary. */
static int raid1_rr_pos(int disk, int start, int n)
{
return ((disk % n) - start + n) % n;
}
+/* True if some readable member is nonrot. */
static bool raid1_has_readable_nonrot(struct r1conf *conf,
struct r1bio *r1_bio)
{
int disk;
@@ -811,10 +813,11 @@ static bool raid1_has_readable_nonrot(struct r1conf *conf,
return true;
}
return false;
}
+/* Lower pending wins. Same pending: prefer nonrot, then rr order. */
static bool is_better_disk(unsigned int pending, int disk, bool nonrot,
const struct read_balance_ctl *ctl,
int rr_start, int n)
{
if (ctl->min_pending_disk < 0)
@@ -828,10 +831,24 @@ static bool is_better_disk(unsigned int pending, int disk, bool nonrot,
return nonrot && ctl->min_pending_nonrot &&
raid1_rr_pos(disk, rr_start, n) <
raid1_rr_pos(ctl->min_pending_disk, rr_start, n);
}
+/*
+ * Choose a readable disk for this read.
+ *
+ * Prefer nonrot. Use rot only if no nonrot disk is readable.
+ *
+ * Sequential idle: keep this disk. Mixed array: do not keep a
+ * rot disk (after a write every disk looks sequential).
+ * Sequential busy: try an idle disk of the same class. If none
+ * is idle, keep the sequential disk.
+ *
+ * Else fewest pending I/Os among disks we may pick. Same
+ * pending: nonrot, then round-robin. Rot-only with no idle
+ * disk: closest head.
+ */
static int choose_best_rdev(struct r1conf *conf, struct r1bio *r1_bio)
{
int disk;
int rr_start = 0;
bool has_nonrot = raid1_has_readable_nonrot(conf, r1_bio);
@@ -867,26 +884,32 @@ static int choose_best_rdev(struct r1conf *conf, struct r1bio *r1_bio)
pending = atomic_read(&rdev->nr_pending);
dist = abs(r1_bio->sector -
READ_ONCE(conf->mirrors[disk].head_position));
nonrot = test_bit(Nonrot, &rdev->flags);
+ /*
+ * If a nonrot disk is readable, pick only nonrot.
+ * Else we must use rot.
+ */
can_pick = nonrot || !has_nonrot;
- /* Don't change to another disk for sequential reads */
+ /*
+ * Idle sequential disk: return it now, unless
+ * should_choose_next() wants another disk.
+ * Mixed array: do not return a rot disk.
+ */
if (is_sequential(conf, disk, r1_bio)) {
if (!should_choose_next(conf, disk) && !pending &&
can_pick)
return disk;
- /*
- * Add 'pending' to avoid choosing this disk if
- * there is other idle disk.
- */
+ /* Make an idle disk win over this busy one. */
pending++;
/*
- * If there is no other idle disk, this disk
- * will be chosen.
+ * Remember the first sequential disk.
+ * A nonrot disk may replace a rot disk.
+ * A later nonrot disk may not replace an earlier one.
*/
if (ctl.sequential_disk < 0 ||
(nonrot && !ctl.sequential_nonrot)) {
ctl.sequential_disk = disk;
ctl.sequential_nonrot = nonrot;
@@ -906,22 +929,21 @@ static int choose_best_rdev(struct r1conf *conf, struct r1bio *r1_bio)
ctl.closest_dist_disk = disk;
}
}
/*
- * sequential IO size exceeds optimal iosize, however, there is no other
- * idle disk, so choose the sequential disk.
+ * Keep the sequential disk if no idle peer should take it.
+ * If a nonrot disk is readable: keep only a nonrot sequential disk.
+ * If not: an idle rot disk may take it.
*/
if (ctl.sequential_disk != -1 && ctl.min_pending != 0 &&
(ctl.sequential_nonrot || !has_nonrot))
return ctl.sequential_disk;
/*
- * If all disks are rotational, choose the closest disk. If any disk is
- * non-rotational, choose the disk with less pending request even the
- * disk is rotational, which might/might not be optimal for raids with
- * mixed ratation/non-rotational disks depending on workload.
+ * No readable nonrot disk: closest disk, unless some disk is idle.
+ * Some readable nonrot disk: that nonrot disk with fewest pending I/Os.
*/
if (ctl.min_pending_disk != -1 &&
(has_nonrot || ctl.min_pending == 0))
return ctl.min_pending_disk;
else
--
2.55.0
prev parent reply other threads:[~2026-08-18 7:07 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-18 7:06 [RFC PATCH 0/5] md/raid1: improve choose_best_rdev read balance Chen Cheng
2026-08-18 7:06 ` [RFC PATCH 1/5] md/raid1: balance reads across non-rotational disks Chen Cheng
2026-08-18 7:16 ` sashiko-bot
2026-08-18 7:06 ` [RFC PATCH 2/5] md/raid1: do not move nonrot reads onto a rot disk Chen Cheng
2026-08-18 7:26 ` sashiko-bot
2026-08-18 7:06 ` [RFC PATCH 3/5] md/raid1: do not send random reads to " Chen Cheng
2026-08-18 7:06 ` [RFC PATCH 4/5] md/raid1: use rot policy when no nonrot disk is readable Chen Cheng
2026-08-18 7:34 ` sashiko-bot
2026-08-18 7:06 ` Chen Cheng [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260818070646.1029149-6-chencheng@fnnas.com \
--to=chencheng@fnnas.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-raid@vger.kernel.org \
--cc=xiaon@kernel.org \
--cc=yukuai@fygo.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.