* [PATCH AUTOSEL 6.18] dm-raid: only requeue bios when dm is suspending
[not found] <20260831133314.4125787-1-sashal@kernel.org>
@ 2026-08-31 13:25 ` Sasha Levin
2026-08-31 13:30 ` [PATCH AUTOSEL 6.18-5.10] md/raid5: let stripe batch bm_seq comparison wrap-safe Sasha Levin
2026-08-31 13:31 ` [PATCH AUTOSEL 6.18-5.15] md/raid5: account discard IO Sasha Levin
2 siblings, 0 replies; 5+ messages in thread
From: Sasha Levin @ 2026-08-31 13:25 UTC (permalink / raw)
To: patches, stable
Cc: Benjamin Marzinski, Mikulas Patocka, Sasha Levin, agk, snitzer,
song, yukuai, dm-devel, linux-kernel, linux-raid
From: Benjamin Marzinski <bmarzins@redhat.com>
[ Upstream commit 97cb8be0fd4c50d310988e0822f7e91d1711e6f8 ]
returning DM_MAPIO_REQUEUE from the target map() function only requeues
the bio during noflush suspends. During regular operations or during
flushing suspends, it fails the bio. Failing the bio during flushing
suspends is the correct behavior here. We cannot handle the bio, and we
cannot suspends while it is outstanding. But during normal operations,
we should not push the bio back to dm. Instead, wait for the reshape
to be resumed.
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
# Stable Backport Analysis: `dm-raid: only requeue bios when dm is
suspending`
**Local tree:** Linux **6.18.43** (`v6.18.43-1-gc7f0dac02d232`)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[dm-raid]` `[fix/implied]` — Only requeue bios when DM is
suspending (reshape-interrupted I/O path).
### Step 1.2: Tags
**Record:**
- **Fixes:** — none
- **Reported-by:** — none
- **Tested-by:** — none
- **Reviewed-by:** — none
- **Acked-by:** — none
- **Link:** — none
- **Cc: stable:** — none (expected for manual review)
- **Signed-off-by:** Benjamin Marzinski `<bmarzins@redhat.com>`, Mikulas
Patocka `<mpatocka@redhat.com>`
No syzbot, no user bug reports in the message. Authors are dm/md
maintainers.
### Step 1.3: Body analysis
**Record:**
- **Bug:** `STRIPE_WAIT_RESHAPE` in raid456 causes `raid_map()` to
return `DM_MAPIO_REQUEUE`. That only requeues during **noflush**
suspend; otherwise DM fails the bio with `BLK_STS_IOERR`.
- **Symptom:** Spurious I/O failures on dm-raid456 when reshape is
interrupted and I/O crosses the reshape position during **normal**
operation (not suspend).
- **Correct behavior:** During normal ops, wait on `wait_for_reshape`
for reshape to resume. During suspend, abort/wake I/O so suspend can
complete (deadlock avoidance).
- **Root cause:** `STRIPE_WAIT_RESHAPE` is returned unconditionally when
`reshape_interrupted()`, without distinguishing suspend vs. normal
operation.
### Step 1.4: Hidden bug fix?
**Record:** No — explicitly described as correcting when bios are
requeued vs. failed. Real I/O-path bug fix, not cosmetic cleanup.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
| File | Change |
|------|--------|
| `drivers/md/md.h` | +1 enum flag `MD_DM_SUSPENDING`, doc comment |
| `drivers/md/dm-raid.c` | Set/clear `MD_DM_SUSPENDING` in
presuspend/postsuspend (+12 lines) |
| `drivers/md/raid5.c` | Gate `STRIPE_WAIT_RESHAPE` on dm+suspending (+4
lines net) |
**Functions:** `raid_presuspend`, `raid_presuspend_undo`,
`raid_postsuspend`, `make_stripe_request`
**Scope:** Small, 3-file surgical fix.
### Step 2.2: Code flow (per hunk)
**Hunk 1 — `raid_presuspend`:** Before → only set `RT_FLAG_RS_FROZEN`.
After → also `set_bit(MD_DM_SUSPENDING)` so raid5 knows DM suspend is in
progress.
**Hunk 2 — `raid_presuspend_undo`:** Clears `MD_DM_SUSPENDING` if
presuspend is rolled back.
**Hunk 3 — `raid_postsuspend`:** Clears `MD_DM_SUSPENDING` after suspend
completes.
**Hunk 4 — `make_stripe_request` out path:** Before → always convert
`STRIPE_SCHEDULE_AND_RETRY` + `reshape_interrupted()` to
`STRIPE_WAIT_RESHAPE`. After → only convert when **not** dm-raid, **or**
dm-raid **and** `MD_DM_SUSPENDING` is set. Otherwise keep
`STRIPE_SCHEDULE_AND_RETRY` → caller waits on `wait_for_reshape`.
### Step 2.3: Bug mechanism
**Record:** **Logic/correctness fix** in dm-raid456 reshape I/O
handling.
Broken path (present in 6.18.43):
1. Reshape interrupted; I/O crosses reshape position.
2. `make_stripe_request` → `STRIPE_WAIT_RESHAPE`.
3. `raid5_make_request` → `md_free_cloned_bio`, returns `false`.
4. `md_handle_request` (no `gendisk`, has `prepare_suspend`) → returns
`false`.
5. `raid_map` → `DM_MAPIO_REQUEUE`.
6. `dm_handle_requeue` — not noflush suspending → `BLK_STS_IOERR` (bio
failed).
Fix: During normal dm-raid ops, stay in `STRIPE_SCHEDULE_AND_RETRY` wait
loop. Only take abort path during actual DM suspend.
### Step 2.4: Fix quality
**Record:** Obviously correct, minimal, matches existing
`prepare_suspend`/`wait_for_reshape` design. Low regression risk — only
narrows when `STRIPE_WAIT_RESHAPE` fires for dm-raid. Complements
`ff6b93410192b` ("md: wake raid456 reshape waiters before suspend")
already in this tree.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:** Buggy lines at `raid5.c:6056-6059` blame to `19eef1d98eeda`
(tree import point; granular upstream history not available in this
stable checkout). `STRIPE_WAIT_RESHAPE` and `reshape_interrupted`
handling are present in 6.18.43.
### Step 3.2: Fixes: tag
**Record:** N/A — no `Fixes:` tag.
### Step 3.3: Related file history
**Record:**
- `ff6b93410192b` — related suspend deadlock fix for native md (already
in 6.18.43).
- `raid_presuspend` + `prepare_suspend` infrastructure present in
current `dm-raid.c`.
- Commit under review **not** in this tree (`MD_DM_SUSPENDING` absent).
### Step 3.4: Author context
**Record:** Marzinski/Patocka are dm/md maintainers. Web search found
prior dm-raid456 reshape deadlock/requeue discussion in the v6.7
regression series (Benjamin Marzinski proposing dm-raid requeue during
suspend).
### Step 3.5: Dependencies
**Record:** Self-contained. Requires existing `STRIPE_WAIT_RESHAPE`,
`reshape_interrupted()`, `raid_presuspend`/`prepare_suspend` — all
present in 6.18.43. No series dependency.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original discussion
**Record:** `b4 dig -c <hash>` — **failed** (commit not in local git).
`b4 dig` with author email — **failed**. No matching `.mbx` in
workspace. lore.kernel.org — **blocked** (Anubis bot protection).
### Step 4.2: Reviewers
**Record:** UNVERIFIED — could not fetch mailing list thread.
### Step 4.3: Bug reports
**Record:** No `Reported-by`/`Link` in commit. Web search found related
dm-raid456 reshape test failures (`lvconvert-raid-reshape-stripes-load-
reload.sh`, `lvconvert-repair-raid.sh`) in the v6.7 regression thread —
contextual, not a direct report for this exact patch.
### Step 4.4: Series context
**Record:** Part of ongoing dm-raid456 reshape I/O fixes. Standalone;
does not require other unmerged patches.
### Step 4.5: Stable list
**Record:** UNVERIFIED — lore stable list inaccessible.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `make_stripe_request`, `raid5_make_request`,
`md_handle_request`, `raid_map`, `dm_handle_requeue`, `raid_presuspend`,
`raid5_prepare_suspend`.
### Step 5.2: Callers
**Record:**
- `raid_map` ← dm target map (all dm-raid I/O)
- `raid5_make_request` ← `md_handle_request` ← `raid_map`
- `raid_presuspend` ← dm suspend path
All common block-I/O and device-mapper admin paths.
### Step 5.3: Callees
**Record:** `wait_woken(&wait_for_reshape)`, `prepare_suspend` →
`wake_up(&conf->wait_for_reshape)`, `dm_handle_requeue` →
`__noflush_suspending()`.
### Step 5.4: Reachability
**Record:** Triggered when dm-raid456 reshape is interrupted and I/O
hits the reshape boundary — realistic during `lvconvert`, table reload,
reshape freeze. Userspace block I/O is the trigger. Not obscure or init-
only.
### Step 5.5: Similar patterns
**Record:** `mddev_is_dm()` checks exist elsewhere in raid5.c.
`DM_MAPIO_REQUEUE` only requeues under noflush suspend (`dm.c:929-939`).
Same pattern as other dm-raid reshape fixes.
---
## PHASE 6: CROSS-REFERENCE WITH LOCAL TREE (6.18.43)
### Step 6.1: Buggy code present?
**Record:** **YES.** Current tree at `raid5.c:6056-6059`:
```6056:6059:drivers/md/raid5.c
if (ret == STRIPE_SCHEDULE_AND_RETRY &&
reshape_interrupted(mddev)) {
bi->bi_status = BLK_STS_RESOURCE;
ret = STRIPE_WAIT_RESHAPE;
pr_err_ratelimited("dm-raid456: io across reshape
position while reshape can't make progress");
```
`MD_DM_SUSPENDING` **not** present. `raid_presuspend` has
`prepare_suspend` call but no suspending flag.
### Step 6.2: Backport difficulty
**Record:** **Clean apply** expected — small additive change, no
conflicting refactors in these functions.
### Step 6.3: Duplicate fix?
**Record:** **None.** `ff6b93410192b` fixes native-md suspend deadlock;
does not fix dm-raid normal-operation I/O failure.
---
## PHASE 7: SUBSYSTEM CONTEXT
### Step 7.1: Subsystem
**Record:** `drivers/md` — device-mapper / md RAID. **Criticality:
IMPORTANT** (storage stack, LVM dm-raid users).
### Step 7.2: Activity
**Record:** Actively maintained; multiple recent stable backports in
this tree (raid5 hang fixes, dm-raid NULL deref, reshape suspend fix).
---
## PHASE 8: IMPACT AND RISK
### Step 8.1: Who is affected
**Record:** dm-raid456 users (LVM `raid` target, reshaping arrays).
Config-specific, but affects production storage setups.
### Step 8.2: Trigger conditions
**Record:** Reshape interrupted/frozen **and** I/O crosses reshape
position **and** not in DM suspend. Moderately common during reshape
admin operations. Unprivileged users can trigger via normal filesystem
I/O on the dm device.
### Step 8.3: Failure severity
**Record:** Spurious `BLK_STS_IOERR` on in-flight I/O → application
errors, possible failed LVM operations. **Severity: HIGH** for affected
workloads (incorrect I/O failure, not kernel crash). Suspend deadlock is
a separate issue addressed by related patches.
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** HIGH for dm-raid reshape users — prevents incorrect I/O
failure.
- **Risk:** LOW — ~15 lines, internal flag, narrow condition change.
- **Ratio:** Strong benefit, minimal risk.
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Real bug in 6.18.43 — verified in source
- Incorrect I/O failure on production storage path
- Small, surgical, maintainer-authored fix
- Complements existing reshape suspend fix already in tree
- Obviously correct logic: wait during normal ops, abort only during
suspend
- dm/md maintainers signed off
**AGAINST backport:**
- Affects dm-raid456 reshape edge case, not all kernel users
- No syzbot/user Reported-by in commit message
- Mailing list review not verified
**UNRESOLVED:**
- Original lore thread and explicit stable nomination not verified
- Exact upstream commit date/hash not in this checkout
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — logic verified in code;
maintainer SOBs; no Tested-by
2. Fixes real bug affecting users? **PASS** — spurious I/O errors on dm-
raid456 reshape
3. Important issue? **PASS** — incorrect I/O failure on storage path
(HIGH)
4. Small and contained? **PASS** — ~15 lines, 3 files
5. No new features/APIs? **PASS** — internal `MD_DM_SUSPENDING` flag
only
6. Can apply to local tree? **PASS** — all prerequisite code present;
clean apply expected
### Step 9.3: Exception categories
**Record:** N/A — standard bug fix, not device-ID/quirk/build/doc
exception.
### Step 9.4: Decision rationale
This commit fixes a real regression in dm-raid456: I/O that should block
waiting for reshape resume is instead failed because `DM_MAPIO_REQUEUE`
does not requeue outside noflush suspend. The buggy code exists in Linux
6.18.43, the fix is minimal and self-contained, and the failure mode
(spurious I/O errors during reshape operations) matters to stable users
running LVM dm-raid.
---
## Verification
- **[Phase 1]** Parsed subject, tags, body from user-provided commit
message
- **[Phase 2]** Read current `raid5.c:6056-6060`, `dm-
raid.c:3341-3360,3824-3867`, `md.c:395-426`, `dm.c:872-939,1446-1454`
- **[Phase 2]** Traced `STRIPE_WAIT_RESHAPE` → `md_free_cloned_bio` →
`false` → `DM_MAPIO_REQUEUE` → `BLK_STS_IOERR` path
- **[Phase 3]** `git describe HEAD` → v6.18.43
- **[Phase 3]** `git blame -L 6056,6060 drivers/md/raid5.c` → lines at
tree base
- **[Phase 3]** `git log --grep='only requeue bios'` → not in tree
- **[Phase 3]** `grep MD_DM_SUSPENDING` → not in tree (fix not applied)
- **[Phase 3]** `git log --oneline ff6b93410192b` → related suspend fix
present
- **[Phase 4]** `b4 dig -c <hash>` → failed (commit not local)
- **[Phase 4]** lore.kernel.org → blocked by Anubis
- **[Phase 4]** Web search → related dm-raid456 reshape context (v6.7
regression thread)
- **[Phase 5]** `grep md_handle_request, STRIPE_WAIT_RESHAPE,
prepare_suspend` → call chain verified
- **[Phase 6]** Buggy unconditional `STRIPE_WAIT_RESHAPE` confirmed in
6.18.43
- **[Phase 6]** `raid_presuspend`/`prepare_suspend` infrastructure
confirmed present
- **[Phase 8]** `dm_handle_requeue` noflush-only requeue behavior
confirmed at `dm.c:929-939`
- **UNVERIFIED:** Mailing list review thread; explicit stable
nomination; upstream commit SHA
**YES**The background searches finished and match what the earlier
analysis already used:
- **Commit not in this tree** — no match for `MD_DM_SUSPENDING` or the
subject line; the fix is still a candidate, not applied.
- **History** — `STRIPE_WAIT_RESHAPE` traces to the tree import point
(`19eef1d98eeda`); no finer-grained upstream history in this 6.18.43
checkout.
- **kernel.org search** — no useful commit hit from the web grep.
**Verdict unchanged: YES** for backport to this 6.18.43 tree. The buggy
path is present, and the patch is a small, low-risk fix for spurious I/O
errors on dm-raid456 during interrupted reshape outside of suspend.
drivers/md/dm-raid.c | 6 ++++++
drivers/md/md.h | 2 ++
drivers/md/raid5.c | 7 +++++--
3 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 4bacdc499984b..9eee490c029e7 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -3831,6 +3831,7 @@ static void raid_presuspend(struct dm_target *ti)
* resume, raid_postsuspend() is too late.
*/
set_bit(RT_FLAG_RS_FROZEN, &rs->runtime_flags);
+ set_bit(MD_DM_SUSPENDING, &mddev->flags);
if (!reshape_interrupted(mddev))
return;
@@ -3847,13 +3848,16 @@ static void raid_presuspend(struct dm_target *ti)
static void raid_presuspend_undo(struct dm_target *ti)
{
struct raid_set *rs = ti->private;
+ struct mddev *mddev = &rs->md;
+ clear_bit(MD_DM_SUSPENDING, &mddev->flags);
clear_bit(RT_FLAG_RS_FROZEN, &rs->runtime_flags);
}
static void raid_postsuspend(struct dm_target *ti)
{
struct raid_set *rs = ti->private;
+ struct mddev *mddev = &rs->md;
if (!test_and_set_bit(RT_FLAG_RS_SUSPENDED, &rs->runtime_flags)) {
/*
@@ -3864,6 +3868,8 @@ static void raid_postsuspend(struct dm_target *ti)
mddev_suspend(&rs->md, false);
rs->md.ro = MD_RDONLY;
}
+ clear_bit(MD_DM_SUSPENDING, &mddev->flags);
+
}
static void attempt_restore_of_faulty_devices(struct raid_set *rs)
diff --git a/drivers/md/md.h b/drivers/md/md.h
index 2960a98747607..2ece7788f9075 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -343,6 +343,7 @@ struct md_cluster_operations;
* @MD_HAS_SUPERBLOCK: There is persistence sb in member disks.
* @MD_FAILLAST_DEV: Allow last rdev to be removed.
* @MD_SERIALIZE_POLICY: Enforce write IO is not reordered, just used by raid1.
+ * @MD_DM_SUSPENDING: This DM raid device is suspending.
*
* change UNSUPPORTED_MDDEV_FLAGS for each array type if new flag is added
*/
@@ -362,6 +363,7 @@ enum mddev_flags {
MD_HAS_SUPERBLOCK,
MD_FAILLAST_DEV,
MD_SERIALIZE_POLICY,
+ MD_DM_SUSPENDING,
};
enum mddev_sb_flags {
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index b19d870e41719..0d83c4adf8e83 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -6054,8 +6054,11 @@ static enum stripe_result make_stripe_request(struct mddev *mddev,
raid5_release_stripe(sh);
out:
if (ret == STRIPE_SCHEDULE_AND_RETRY && reshape_interrupted(mddev)) {
- bi->bi_status = BLK_STS_RESOURCE;
- ret = STRIPE_WAIT_RESHAPE;
+ if (!mddev_is_dm(mddev) ||
+ test_bit(MD_DM_SUSPENDING, &mddev->flags)) {
+ bi->bi_status = BLK_STS_RESOURCE;
+ ret = STRIPE_WAIT_RESHAPE;
+ }
pr_err_ratelimited("dm-raid456: io across reshape position while reshape can't make progress");
}
return ret;
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH AUTOSEL 6.18-5.10] md/raid5: let stripe batch bm_seq comparison wrap-safe
[not found] <20260831133314.4125787-1-sashal@kernel.org>
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18] dm-raid: only requeue bios when dm is suspending Sasha Levin
@ 2026-08-31 13:30 ` Sasha Levin
2026-08-31 17:28 ` sashiko-bot
2026-08-31 13:31 ` [PATCH AUTOSEL 6.18-5.15] md/raid5: account discard IO Sasha Levin
2 siblings, 1 reply; 5+ messages in thread
From: Sasha Levin @ 2026-08-31 13:30 UTC (permalink / raw)
To: patches, stable
Cc: Chen Cheng, Yu Kuai, Sasha Levin, song, linux-raid, linux-kernel
From: Chen Cheng <chencheng@fnnas.com>
[ Upstream commit 00e93faf4cea9e8802ac5dfee0952d84fc95c40f ]
Once the 32-bit seq wraps, a newer bm_seq can look smaller
than old, so .. covert to wrap-safe calculate way.
Signed-off-by: Chen Cheng <chencheng@fnnas.com>
Link: https://patch.msgid.link/20260618025735.915113-1-chencheng@fnnas.com
Signed-off-by: Yu Kuai <yukuai@fygo.io>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
# Stable Backport Analysis: `md/raid5: let stripe batch bm_seq
comparison wrap-safe`
**Local tree:** `v6.18.44` (6.18.y) — `git describe HEAD` →
`v6.18.44-1-g2736c32da98b9`
**Commit analyzed:** `00e93faf4cea9` (mainline) / `13cb77aa61c3d`
(stable-queue variant)
**Status in this tree:** Buggy code is present; fix is **not** merged
(`git merge-base --is-ancestor 13cb77aa61c3d HEAD` → exit 1).
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[md/raid5]` `[let/fix]` — make stripe-batch `bm_seq`
comparison wrap-safe when merging bitmap sequence numbers during
batching.
### Step 1.2: Tags
**Record:**
- **Signed-off-by:** Chen Cheng `<chencheng@fnnas.com>` (author)
- **Signed-off-by:** Yu Kuai `<yukuai@fygo.io>` (md maintainer,
committer upstream)
- **Link:**
https://patch.msgid.link/20260618025735.915113-1-chencheng@fnnas.com
- **No** Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Cc:
stable@vger.kernel.org
- Notable: maintainer ack via commit + "Applied to md-7.2" on list; no
user/syzbot reports
### Step 1.3: Body analysis
**Record:**
- **Bug:** After 32-bit `bm_seq` wraps, plain `>` comparison can treat a
newer sequence as older.
- **Symptom:** Batch head may retain a stale (older) `bm_seq` instead of
the latest required bitmap batch.
- **Root cause:** `sh->batch_head->bm_seq > seq` is not wrap-safe;
should use subtraction idiom.
- **Versions:** No explicit version range; bug dates to 2015
introduction of this comparison.
### Step 1.4: Hidden bug fix?
**Record:** Yes — described as wrap-safety, but it is a real correctness
bug in RAID5 bitmap batch sequencing, not cosmetic cleanup.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- **Files:** `drivers/md/raid5.c` (+1/-1)
- **Function:** `stripe_add_to_batch_list()`
- **Scope:** Single-line, single-function, surgical fix
### Step 2.2: Code flow change
**Record:**
- **Before:** When merging `STRIPE_BIT_DELAY` state into `batch_head`,
take `batch_head->bm_seq` only if `batch_head->bm_seq > seq`.
- **After:** Use `batch_head->bm_seq - seq > 0` (wrap-safe “is a newer
than b?”).
- **Path:** Normal write/batching path when stripes with pending bitmap
updates are merged into a batch.
### Step 2.3: Bug mechanism
**Record:**
- **Category:** Logic/correctness — signed sequence-number comparison
across wrap boundary.
- **Mechanism:** After `bm_seq` (signed 32-bit `int`) wraps past
`INT_MAX`, a post-wrap value can be numerically less than a pre-wrap
value. The `>` check then fails to propagate the newer sequence to
`batch_head->bm_seq`, so the batch may proceed before all required
bitmap flushes complete.
### Step 2.4: Fix quality
**Record:**
- Obviously correct; mirrors existing raid5 idiom at line 259:
`sh->bm_seq - conf->seq_write > 0` (present since 2006).
- Minimal risk; no API/struct changes.
- Sashiko review noted theoretical UBSAN on signed subtraction — same
pattern already used in this file for 20 years; author and maintainer
accepted it.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:** Buggy comparison introduced in `2b6b24574256c` (Neil Brown,
2015-05-21): "md/raid5: ensure whole batch is delayed for all required
bitmap updates." Present in this 6.18.y tree.
### Step 3.2: Fixes: tag
**Record:** N/A — no Fixes: tag. Related context: `ae3c20ccf84c8` (2006)
introduced wrap-safe `sh->bm_seq - conf->seq_write > 0` in
`do_release_stripe()` path, but the 2015 batch-merge site was never
updated.
### Step 3.3: Related file history
**Record:** Recent raid5.c changes are unrelated (batch race fixes, IO
hangs, llbitmap). Standalone one-patch fix; not part of a series.
### Step 3.4: Author context
**Record:** Chen Cheng has recent md contributions (raid5 batch race
fixes). Yu Kuai is md maintainer and applied this to md-7.2.
### Step 3.5: Dependencies
**Record:** No prerequisites. Applies cleanly to current
`drivers/md/raid5.c` at lines 996–1002.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1: Original discussion
**Record:**
- **URL:**
https://patch.msgid.link/20260618025735.915113-1-chencheng@fnnas.com
- **Revisions:** v1 only
- **Feedback:** Sashiko AI flagged UBSAN concern and pre-existing
lockless `bm_seq` RMW race; author replied that `a - b > 0` is the
long-standing raid5 template (citing `do_release_stripe()`);
maintainer applied without requesting changes
- **Stable nomination:** None explicit in thread
### Step 4.2: Reviewers
**Record:** CC'd `linux-raid@vger.kernel.org`, `yukuai@fygo.io`. Yu Kuai
committed upstream and applied to md-7.2.
### Step 4.3: Bug reports
**Record:** No syzbot, bugzilla, or user crash reports.
Theoretical/latent correctness bug.
### Step 4.4: Related patches
**Record:** None in series.
### Step 4.5: Stable list history
**Record:** No stable-list discussion found.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `stripe_add_to_batch_list()` modified.
### Step 5.2: Callers
**Record:** Called from raid5 write path at line 6030
(`stripe_can_batch(sh)` branch) during `add_stripe_bio` processing —
common RAID5 write path with batching enabled.
### Step 5.3: Callees / context
**Record:** Manages `STRIPE_BIT_DELAY` and `bm_seq` on batch head; ties
into bitmap unplug sequencing (`conf->seq_flush`, `conf->seq_write`,
`activate_bit_delay()`).
### Step 5.4: Reachability
**Record:** Reachable on RAID5 arrays with writeback + bitmap enabled +
stripe batching. Enterprise NAS/server workloads on stable kernels are
in scope.
### Step 5.5: Similar patterns
**Record:** Same wrap-safe idiom at line 259; `dm-pcache` uses
`(s8)(seq1 - seq2) > 0`. The 2015 batch-merge site was the outlier still
using plain `>`.
---
## PHASE 6: CROSS-REFERENCE WITH LOCAL TREE
### Step 6.1: Buggy code present?
**Record:** Yes — at lines 998–999:
```996:1002:drivers/md/raid5.c
if (test_and_clear_bit(STRIPE_BIT_DELAY, &sh->state)) {
int seq = sh->bm_seq;
if (test_bit(STRIPE_BIT_DELAY, &sh->batch_head->state)
&&
sh->batch_head->bm_seq > seq)
seq = sh->batch_head->bm_seq;
set_bit(STRIPE_BIT_DELAY, &sh->batch_head->state);
sh->batch_head->bm_seq = seq;
```
Bug introduced 2015; predates 6.18 branch.
### Step 6.2: Backport complications
**Record:** Clean one-line apply expected; no structural conflicts
observed.
### Step 6.3: Related fixes already present?
**Record:** No equivalent fix in this tree (`git log --grep="stripe
batch bm_seq"` on HEAD → empty).
---
## PHASE 7: SUBSYSTEM CONTEXT
### Step 7.1: Subsystem criticality
**Record:** `drivers/md/raid5.c` — **IMPORTANT** (RAID5 + bitmap is
widely used in enterprise/storage on LTS kernels).
### Step 7.2: Activity
**Record:** md/raid5 actively maintained; recent stable-worthy fixes (IO
hangs, batch races) landed in 6.18.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
### Step 8.1: Who is affected
**Record:** Users of RAID5 with external/internal bitmap and stripe
write batching — config-specific but common on production md arrays.
### Step 8.2: Trigger conditions
**Record:**
- Requires `bm_seq`/`seq_flush` to wrap (~2³¹ bitmap batch increments).
- Bug manifests when comparing sequences on opposite sides of the wrap
boundary during batch merge.
- **Likelihood:** Low frequency, but realistic on long-uptime, write-
heavy arrays (exactly the stable/LTS profile).
### Step 8.3: Failure mode severity
**Record:** Stale `bm_seq` on batch head → stripe may write before
required bitmap batch is flushed → per raid5's own BITMAP UNPLUGGING
comments, missed dirty bits can cause **incorrect recovery after power
loss** (data integrity). Severity when triggered: **CRITICAL**; overall
exposure: **LOW** due to rare trigger.
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** Prevents latent bitmap sequencing corruption on long-
running RAID5 arrays.
- **Risk:** Very low — one line, established idiom, maintainer-accepted.
- **Ratio:** Favorable for stable.
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR backport:**
- Real correctness bug in bitmap sequencing (potential recovery/data
integrity issue)
- Bug present since 2015 in this tree
- One-line, obviously correct fix matching 20-year-old raid5 pattern
- Md maintainer committed and applied to md-7.2
- Small, contained, no new APIs/features
- Applies cleanly to v6.18.44
**AGAINST backport:**
- No user reports or fuzzer findings
- Trigger requires ~2³¹ bitmap batch increments (very rare)
- Not an immediate crash/hang; latent correctness issue
- Sashiko UBSAN note (mitigated: same pattern already in file since
2006)
**Unresolved:** No production incident reports confirming the wrap was
hit in the wild.
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — matches existing raid5 wrap-
safe idiom; maintainer applied.
2. Fixes a real bug? **PASS** — incorrect seq comparison after wrap.
3. Important issue? **PASS** — bitmap sequencing error can cause
recovery integrity failure (critical when triggered).
4. Small and contained? **PASS** — 1 line, 1 file.
5. No new features/APIs? **PASS**.
6. Can apply to local tree? **PASS** — buggy code confirmed present; fix
not yet applied.
### Step 9.3: Exception categories
**Record:** None (not device ID, quirk, DT, build, or docs). Standard
correctness bug fix.
### Step 9.4: Decision rationale
For **this** 6.18.y tree, the buggy comparison exists and has existed
for a decade. The fix is minimal, maintainer-vetted, and aligns with
established raid5 bitmap sequencing practice. While the trigger is rare,
stable kernels target long-lived, write-heavy storage systems where
counter wrap is a realistic eventual concern, and the failure mode
(bitmap bit not recorded before write) is exactly the class of issue
stable backports exist to prevent.
---
## Verification
- **[Phase 1]** `git show 00e93faf4cea9` / `13cb77aa61c3d`: parsed
message, tags, body
- **[Phase 1]** Ignored pipeline-only markers per instructions
- **[Phase 2]** Diff: 1-line change in `stripe_add_to_batch_list()`
- **[Phase 2]** Read `drivers/md/raid5.c` lines 13–30 (BITMAP UNPLUGGING
comment), 258–260, 996–1003, 6802–6811
- **[Phase 2]** `drivers/md/raid5.h` line 214: `bm_seq` is `int`; line
636: `seq_flush, seq_write`
- **[Phase 3]** `git blame -L 996,1003`: introduced `2b6b24574256c`
(2015)
- **[Phase 3]** `git show 2b6b24574256c`, `d0852df543e5a`,
`ae3c20ccf84c8`: history context
- **[Phase 3]** `git log --oneline -20 -- drivers/md/raid5.c`: recent
unrelated changes
- **[Phase 3]** `git merge-base --is-ancestor 2b6b24574256c HEAD`: buggy
code commit in tree
- **[Phase 3]** `git merge-base --is-ancestor 13cb77aa61c3d HEAD` → exit
1: fix NOT in tree
- **[Phase 4]** `b4 dig -c 13cb77aa61c3d`: found lore thread
- **[Phase 4]** `b4 dig -c 13cb77aa61c3d -w`: CC'd linux-raid,
yukuai@fygo.io
- **[Phase 4]** `b4 dig -c 13cb77aa61c3d -a`: single v1 revision
- **[Phase 4]** `b4 dig -m /tmp/bm_seq_thread.mbox`: read thread; Yu
Kuai "Applied to md-7.2"; Sashiko review + author reply
- **[Phase 5]** `grep stripe_add_to_batch_list`: caller at line 6030
- **[Phase 5]** `grep bm_seq` in raid5.c: wrap-safe pattern at line 259
since 2006
- **[Phase 6]** `git describe HEAD`: v6.18.44
- **[Phase 6]** Confirmed buggy `>` comparison at line 999 in working
tree
- **[Phase 6]** `git log --grep="stripe batch bm_seq" HEAD`: no fix
present
- **[Phase 8]** Assessed trigger rarity (~2³¹ `seq_flush` increments)
and failure mode via bitmap sequencing comments
**YES**
drivers/md/raid5.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 5c81dbac7eab5..f3951e162762c 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -996,7 +996,7 @@ static void stripe_add_to_batch_list(struct r5conf *conf,
if (test_and_clear_bit(STRIPE_BIT_DELAY, &sh->state)) {
int seq = sh->bm_seq;
if (test_bit(STRIPE_BIT_DELAY, &sh->batch_head->state) &&
- sh->batch_head->bm_seq > seq)
+ sh->batch_head->bm_seq - seq > 0)
seq = sh->batch_head->bm_seq;
set_bit(STRIPE_BIT_DELAY, &sh->batch_head->state);
sh->batch_head->bm_seq = seq;
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH AUTOSEL 6.18-5.10] md/raid5: let stripe batch bm_seq comparison wrap-safe
2026-08-31 13:30 ` [PATCH AUTOSEL 6.18-5.10] md/raid5: let stripe batch bm_seq comparison wrap-safe Sasha Levin
@ 2026-08-31 17:28 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-08-31 17:28 UTC (permalink / raw)
To: Sasha Levin; +Cc: yukuai, linux-raid
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Lockless Read-Modify-Write (RMW) race on batch_head->bm_seq could result in a stale bitmap sequence number.
--
commit ec929cd222791eadb056199cc433123ca41575a6
Author: Chen Cheng <chencheng@fnnas.com>
md/raid5: let stripe batch bm_seq comparison wrap-safe
This commit fixes a sequence number comparison bug in
stripe_add_to_batch_list() by changing a direct greater-than comparison to a
wrap-safe subtraction to ensure proper bitmap batch sequencing.
Link: https://patch.msgid.link/20260618025735.915113-1-chencheng@fnnas.com
> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -992,7 +992,7 @@ static void stripe_add_to_batch_list(struct r5conf *conf,
> if (test_and_clear_bit(STRIPE_BIT_DELAY, &sh->state)) {
> int seq = sh->bm_seq;
> if (test_bit(STRIPE_BIT_DELAY, &sh->batch_head->state) &&
> - sh->batch_head->bm_seq > seq)
> + sh->batch_head->bm_seq - seq > 0)
> seq = sh->batch_head->bm_seq;
> set_bit(STRIPE_BIT_DELAY, &sh->batch_head->state);
> sh->batch_head->bm_seq = seq;
[Severity: Critical]
This is a pre-existing issue, but could this lockless read-modify-write of
batch_head->bm_seq result in a stale bitmap sequence number?
During concurrent additions to a RAID5 stripe batch, threads handling disjoint
subordinate stripes (for example, sh1 and sh3) hold different stripe locks.
Because they do not contend for the same stripe locks, they can execute this
block concurrently on the same batch_head.
Could this concurrent access cause one thread to overwrite another thread's
newer bm_seq with an older one?
If a data race results in the batch head storing an older sequence number,
could the batch be written to disk before all required bitmap flushes have
completed? If a power failure occurs under these conditions, it appears the
dirty bits for some stripes in the batch might not be recorded in the bitmap,
which might lead to data corruption during array recovery.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831133314.4125787-624-sashal@kernel.org?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH AUTOSEL 6.18-5.15] md/raid5: account discard IO
[not found] <20260831133314.4125787-1-sashal@kernel.org>
2026-08-31 13:25 ` [PATCH AUTOSEL 6.18] dm-raid: only requeue bios when dm is suspending Sasha Levin
2026-08-31 13:30 ` [PATCH AUTOSEL 6.18-5.10] md/raid5: let stripe batch bm_seq comparison wrap-safe Sasha Levin
@ 2026-08-31 13:31 ` Sasha Levin
2026-08-31 17:50 ` sashiko-bot
2 siblings, 1 reply; 5+ messages in thread
From: Sasha Levin @ 2026-08-31 13:31 UTC (permalink / raw)
To: patches, stable; +Cc: Yu Kuai, Sasha Levin, song, linux-raid, linux-kernel
From: Yu Kuai <yukuai@fygo.io>
[ Upstream commit 74ddbf98e2db646ec58f7e7731c936b7a4a470fe ]
Raid5 handles discard bios internally through make_discard_request() and
never passes them through md_account_bio(). As a result, discard IO is
missing the md-device iostat accounting that normal raid5 IO and discard
IO in other raid levels get from md_account_bio().
Before accounting the bio, trim the request to the full data stripes that
raid5 will actually discard. The first full stripe is the ceiling of the
bio start divided by data-stripe sectors, and the last full stripe is the
floor of the bio end divided by data-stripe sectors. Account that exact
MD logical full-stripe range, then restore the original iterator so bio
completion and iostat still cover the original request.
Link: https://patch.msgid.link/20260605072639.2434847-2-yukuai@kernel.org
Signed-off-by: Yu Kuai <yukuai@fygo.io>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
# Stable Backport Analysis: `md/raid5: account discard IO`
**Local tree:** Linux **6.18.44** (`git describe HEAD` →
`v6.18.44-1-g2736c32da98b9`)
**Upstream commit:** `74ddbf98e2db6` (not yet in current HEAD; present
on `autosel` as `36d4b4a2d7925`)
---
## PHASE 1: COMMIT MESSAGE FORENSICS
### Step 1.1: Subject line
**Record:** `[md/raid5]` — missing verb "fix", but intent is clear —
`[account]` discard IO through `md_account_bio()` for iostat and unified
MD accounting.
### Step 1.2: Tags
**Record:**
- **Link:**
https://patch.msgid.link/20260605072639.2434847-2-yukuai@kernel.org
(patch 2 of a series)
- **Signed-off-by:** Yu Kuai `<yukuai@fygo.io>`
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Cc: stable@
- Message ID suffix `-2` implies a multi-patch series (patch 1 not
identified in this tree)
### Step 1.3: Body analysis
**Record:**
- **Bug:** RAID5 discard bios go through `make_discard_request()` and
bypass `md_account_bio()`, unlike normal RAID5 IO and discard on other
RAID levels.
- **Symptom:** MD device iostat does not reflect discard traffic
(`iostat` discard columns wrong).
- **Fix approach:** Temporarily trim bio iterator to the full data-
stripe range RAID5 will actually discard, call `md_account_bio()`,
restore original iterator for completion.
- **Root cause:** Discard has a dedicated code path that never
integrated with the `md_account_bio()` infrastructure added for other
IO.
### Step 1.4: Hidden bug fix?
**Record:** Yes — described as accounting, but `md_account_bio()` also:
- Holds `active_io` until bio completion (via cloned bio +
`md_end_clone_io`)
- Starts bitmap discard tracking via `md_bitmap_start()` when bitmap is
enabled (since `ac9dad8faaa7b`)
- Provides `bio_start_io_acct()` / `bio_end_io_acct()` for block-layer
statistics
The stripe-boundary refactor (`first_stripe`/`last_stripe` vs old align-
then-round-up) may also correct edge-case discard range selection.
---
## PHASE 2: DIFF ANALYSIS
### Step 2.1: Inventory
**Record:**
- **File:** `drivers/md/raid5.c` only (+23 / -10 lines)
- **Function:** `make_discard_request()`
- **Scope:** Single-file, surgical fix
### Step 2.2: Code flow per hunk
**Record:**
1. **Before:** Computed stripe range via align-to-`RAID5_STRIPE_SECTORS`
then `DIV_ROUND_UP`; no accounting; proceeded directly to stripe
loop.
2. **After:** Computes `first_stripe`/`last_stripe` directly from bio
sector range; early `bio_endio()` if no full stripes; temporarily
adjusts `bi_iter`, calls `md_account_bio()`, restores iterator, then
runs existing stripe loop.
3. **Affected path:** `raid5_make_request()` → `make_discard_request()`
for `REQ_OP_DISCARD` bios.
### Step 2.3: Bug mechanism
**Record:** **Missing integration with unified MD IO accounting
infrastructure** (category: logic/correctness + reference-counting side
effects)
- No `percpu_ref_get(&mddev->active_io)` for discard IO lifetime
- No iostat accounting (`bio_start_io_acct` / `bio_end_io_acct`)
- No bitmap `start_discard`/`end_discard` via `md_account_bio()` path
(relevant since `ac9dad8faaa7b` is in this tree)
### Step 2.4: Fix quality
**Record:** Fix is minimal and mirrors the already-merged `md/raid10:
fix missing discard IO accounting` (`d05af90d6218e`). Iterator
save/restore pattern is sound. Low regression risk; stripe-index
simplification is equivalent or more conservative at boundaries.
---
## PHASE 3: GIT HISTORY INVESTIGATION
### Step 3.1: Blame
**Record:** `make_discard_request()` introduced in `620125f2bf8ff`
(Shaohua Li, 2012) — discard support predates `md_account_bio()`.
Missing accounting since `10764815ff472` (2021) added `md_account_bio()`
to RAID5 read/write paths but not discard.
### Step 3.2: Fixes: tag
**Record:** N/A — no Fixes: tag. Logical regression point:
`10764815ff472` ("md: add io accounting for raid0 and raid5"), which is
an ancestor of this tree.
### Step 3.3: Related commits
**Record:**
- `d05af90d6218e` — raid10 discard accounting fix (in this tree)
- `05048cbccab79` — raid5 inflight counter leak fix via
`md_account_bio()`
- `ac9dad8faaa7b` — bitmap discard ops support (in this tree)
- `cc22b5407e9ca` — raid0 split-bio iostat accounting (backported to
stable 6.6.y)
- `74ddbf98e2db6` — this fix (mainline, not in HEAD)
### Step 3.4: Author context
**Record:** Yu Kuai is an active MD contributor; authored raid10 discard
fix, raid5 inflight accounting fix, and bitmap discard infrastructure.
### Step 3.5: Dependencies
**Record:** Standalone for backport purposes. Requires
`md_account_bio()` (present since 2021) and benefits from
`ac9dad8faaa7b` bitmap discard ops (present in 6.18.44). No other series
patches required for correctness.
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
### Step 4.1–4.2: Patch discussion
**Record:** `b4 dig -c 74ddbf98e2db6` returned no results. Lore search
blocked by Anubis bot protection. Link from commit message could not be
fetched. Patch is `2434847-2` (series context unknown).
### Step 4.3: Bug reports
**Record:** No syzbot, bugzilla, or user Reported-by tags. Raid10
parallel fix included before/after `iostat` measurements showing severe
under-reporting.
### Step 4.4: Series context
**Record:** Patch 2 of unknown series. No evidence other patches are
required for this fix to apply.
### Step 4.5: Stable list history
**Record:** `d05af90d6218e` (raid10 discard accounting) is already in
`stable/linux-6.18.y`. `cc22b5407e9ca` (raid0 iostat) was backported to
6.6.y. Strong precedent for this class of MD accounting fix in stable.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
### Step 5.1: Key functions
**Record:** `make_discard_request()`, `md_account_bio()`,
`raid5_make_request()`
### Step 5.2: Callers
**Record:** `raid5_make_request()` (line 6137) is the sole caller of
`make_discard_request()`. Reached from `md_handle_request()` →
`md_submit_bio()` on discard bios to `/dev/md*`.
### Step 5.3: Callees
**Record:** `md_account_bio()` → `percpu_ref_get(&active_io)` +
`md_clone_bio()` → `bio_start_io_acct()`, `md_bitmap_start()` (for
WRITE-direction ops including discard, since `REQ_OP_DISCARD=3` has
write bit set).
### Step 5.4: Reachability
**Record:** Reachable from userspace via `BLKDISCARD`/`fstrim` on RAID5
arrays. Common on systems using SSD-backed RAID5.
### Step 5.5: Similar patterns
**Record:** Raid10 fixed identically (`d05af90d6218e`). Raid0 discard
path (`raid0_handle_discard`) still lacks `md_account_bio()` —
inconsistency remains elsewhere, but raid5 is the subject here.
---
## PHASE 6: CROSS-REFERENCE WITH LOCAL TREE (6.18.44)
### Step 6.1: Buggy code present?
**Record:** **YES.** Current `make_discard_request()` at lines 5701–5782
has no `md_account_bio()` call. Normal RAID5 IO calls it at line 6163.
### Step 6.2: Backport difficulty
**Record:** Clean apply expected — upstream diff applies to current
`raid5.c` with only line-offset differences. No API conflicts.
### Step 6.3: Related fixes already present?
**Record:** Raid10 discard fix (`d05af90d6218e`) and bitmap discard ops
(`ac9dad8faaa7b`) are in tree. This raid5 fix is the remaining gap.
---
## PHASE 7: SUBSYSTEM CONTEXT
### Step 7.1: Subsystem criticality
**Record:** `drivers/md/` — **IMPORTANT** (block/MD RAID, used widely in
servers and NAS).
### Step 7.2: Activity
**Record:** Actively maintained; recent raid5 fixes for lockups, IO
hangs, and overlap races in this tree.
---
## PHASE 8: IMPACT AND RISK
### Step 8.1: Who is affected
**Record:** Users of RAID5/6 arrays who issue discard/trim (`fstrim`,
`BLKDISCARD`). Config-specific: RAID5/6 personality with discard
enabled.
### Step 8.2: Trigger conditions
**Record:** Any discard IO to a RAID5 device. Common during periodic
`fstrim` on SSD-backed arrays.
### Step 8.3: Failure mode severity
**Record:**
- **iostat under-reporting** — MEDIUM (monitoring/visibility; raid10
showed 16 MB/s vs 20462 MB/s)
- **Missing `active_io` tracking for in-flight discard** — MEDIUM-HIGH
(could affect suspend/quiesce timing; discard bios can complete
asynchronously via `bio_inc_remaining`)
- **Missing bitmap discard tracking** — MEDIUM (with bitmap-enabled
arrays, discard regions not tracked through unified path; raid5 has
stripe-level bitmap handling but `md_account_bio()` path is now the
canonical one since `ac9dad8faaa7b`)
- Not a direct crash/corruption fix, but functional accounting gap with
suspend/bitmap implications
### Step 8.4: Risk-benefit
**Record:**
- **Benefit:** HIGH for consistency (raid10 already fixed in this tree),
correct monitoring, proper `active_io`/bitmap lifecycle
- **Risk:** LOW — 23-line change, mirrors accepted raid10 pattern, no
API changes
- **Ratio:** Favorable
---
## PHASE 9: FINAL SYNTHESIS
### Step 9.1: Evidence summary
**FOR:**
- Direct parallel to `d05af90d6218e` already in 6.18.y stable
- Precedent: `cc22b5407e9ca` iostat fix backported to 6.6.y
- Bug confirmed present in 6.18.44 tree
- All prerequisites present (`md_account_bio`, bitmap discard ops)
- Small, obviously correct, low risk
- `md_account_bio()` provides more than iostat — `active_io` and bitmap
tracking
**AGAINST:**
- No syzbot/user crash reports
- Primary visible symptom is iostat inaccuracy
- Slight stripe-boundary calculation change (likely correction, but
unverified with tests)
- No maintainer Reviewed-by/Acked-by on this specific patch
- Lore discussion unavailable
### Step 9.2: Stable rules checklist
1. Obviously correct and tested? **PASS** — mirrors raid10 fix; author
is subsystem expert; no Tested-by but pattern proven
2. Fixes real bug affecting users? **PASS** — discard accounting gap
affects all RAID5 discard users
3. Important issue? **PASS (MEDIUM)** — not crash/corruption, but
functional accounting gap with suspend/bitmap implications; same
class accepted for raid10
4. Small and contained? **PASS** — 23 lines, one file
5. No new features/APIs? **PASS**
6. Can apply to local tree? **PASS** — prerequisites present, clean
apply expected
### Step 9.3: Exception category
**Record:** Not a device-ID/quirk/DT/build/docs exception. Standard bug
fix.
### Step 9.4: Decision rationale
This is the RAID5 counterpart to `d05af90d6218e`, which is already in
the 6.18.y tree. The MD subsystem has established stable precedent for
IO accounting fixes (`cc22b5407e9ca` on 6.6.y). The bug exists in
6.18.44, prerequisites are satisfied, and the fix is small with low
regression risk. While the most visible symptom is iostat inaccuracy,
`md_account_bio()` also provides `active_io` lifecycle tracking and
bitmap discard integration that RAID5 discard currently lacks.
---
## Verification
- [Phase 1] Parsed commit message from user query and `git show
74ddbf98e2db6`
- [Phase 1] Tags: Link only; no Fixes/Reported-by/Tested-by
- [Phase 2] Read current `make_discard_request()` at lines 5701–5782;
confirmed no `md_account_bio()`
- [Phase 2] Read `raid5_make_request()` discard path at lines 6137–6140
- [Phase 2] Read `md_account_bio()` at `md.c:9308–9312` and
`md_clone_bio()` at `md.c:9283–9306`
- [Phase 3] `git blame` on `make_discard_request()`: introduced
`620125f2bf8ff` (2012)
- [Phase 3] `git log -S md_account_bio -- drivers/md/raid5.c`: added
`10764815ff472`, not extended to discard
- [Phase 3] Found related commits: `d05af90d6218e`, `05048cbccab79`,
`ac9dad8faaa7b`, `cc22b5407e9ca`
- [Phase 3] `git merge-base --is-ancestor ac9dad8faaa7b 74ddbf98e2db6`:
bitmap discard prerequisite present
- [Phase 3] `git merge-base --is-ancestor d05af90d6218e HEAD`: raid10
fix in tree
- [Phase 4] `b4 dig -c 74ddbf98e2db6`: no results
- [Phase 4] Lore fetch blocked by Anubis
- [Phase 4] `git log stable/linux-6.18.y --grep raid10: fix missing
discard`: found `d05af90d6218e`
- [Phase 4] `git log stable/linux-6.18.y --grep raid0: account for
split`: found `cc22b5407e9ca` on 6.6.y
- [Phase 5] Traced call chain: `md_submit_bio` → `md_handle_request` →
`raid5_make_request` → `make_discard_request`
- [Phase 5] Verified `REQ_OP_DISCARD=3` → `op_is_write()` true →
`bio_data_dir()==WRITE` in `blk_types.h:336,441-444`
- [Phase 6] `git describe HEAD`: v6.18.44; `make kernelversion`: 6.18.44
- [Phase 6] `git merge-base --is-ancestor 74ddbf98e2db6 HEAD`: NOT in
HEAD (fix needed)
- [Phase 6] Buggy code confirmed at `drivers/md/raid5.c:5701-5782`
- [Phase 8] Read `mddev_suspend()` at `md.c:489-506`: waits on
`active_io` reaching zero
- [UNVERIFIED] Exact suspend+discard race reproduction — inferred from
code path, not from bug report
**YES**The background searches finished and match the earlier analysis:
- **Commit location:** `md/raid5: account discard IO` is upstream as
`74ddbf98e2db6` and on the `autosel` branch as `36d4b4a2d7925`, but it
is **not** in the current 6.18.44 HEAD.
- **Stable precedent:** `stable/linux-6.18.y` already has the parallel
raid10 fix (`d05af90d6218e`); this raid5 fix is not there yet.
That supports the **YES** backport recommendation for 6.18.y.
drivers/md/raid5.c | 33 +++++++++++++++++++++++----------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 0d83c4adf8e83..5c81dbac7eab5 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -5702,7 +5702,10 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi)
{
struct r5conf *conf = mddev->private;
sector_t logical_sector, last_sector;
+ sector_t first_stripe, last_stripe;
struct stripe_head *sh;
+ struct bvec_iter bi_iter;
+ struct bio *orig_bi = bi;
int stripe_sectors;
/* We need to handle this when io_uring supports discard/trim */
@@ -5713,19 +5716,29 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi)
/* Skip discard while reshape is happening */
return;
- logical_sector = bi->bi_iter.bi_sector & ~((sector_t)RAID5_STRIPE_SECTORS(conf)-1);
- last_sector = bio_end_sector(bi);
-
- bi->bi_next = NULL;
-
stripe_sectors = conf->chunk_sectors *
(conf->raid_disks - conf->max_degraded);
- logical_sector = DIV_ROUND_UP_SECTOR_T(logical_sector,
- stripe_sectors);
- sector_div(last_sector, stripe_sectors);
+ first_stripe = DIV_ROUND_UP_SECTOR_T(bi->bi_iter.bi_sector,
+ stripe_sectors);
+ last_stripe = bio_end_sector(bi);
+ sector_div(last_stripe, stripe_sectors);
+
+ if (first_stripe >= last_stripe) {
+ bio_endio(bi);
+ return;
+ }
+
+ bi_iter = bi->bi_iter;
+ bi->bi_iter.bi_sector = first_stripe * stripe_sectors;
+ bi->bi_iter.bi_size = ((last_stripe - first_stripe) *
+ stripe_sectors) << 9;
+ md_account_bio(mddev, &bi);
+ orig_bi->bi_iter = bi_iter;
+ bi->bi_iter = bi_iter;
+ bi->bi_next = NULL;
- logical_sector *= conf->chunk_sectors;
- last_sector *= conf->chunk_sectors;
+ logical_sector = first_stripe * conf->chunk_sectors;
+ last_sector = last_stripe * conf->chunk_sectors;
for (; logical_sector < last_sector;
logical_sector += RAID5_STRIPE_SECTORS(conf)) {
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH AUTOSEL 6.18-5.15] md/raid5: account discard IO
2026-08-31 13:31 ` [PATCH AUTOSEL 6.18-5.15] md/raid5: account discard IO Sasha Levin
@ 2026-08-31 17:50 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-08-31 17:50 UTC (permalink / raw)
To: Sasha Levin; +Cc: yukuai, linux-raid
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Discard bios are leaked (never completed) if REQ_NOWAIT is set or a reshape is in progress.
--
commit 411f7ab7bd6961f4f041d0cc04dc0f2c9fb67a13
Author: Yu Kuai <yukuai@fygo.io>
md/raid5: account discard IO
This commit adds discard IO to the md-device iostat accounting for RAID5,
which was previously bypassed. It trims the bio request to the full data
stripes before accounting it, then restores the iterator to ensure correct
bio completion and iostat coverage.
Link: https://patch.msgid.link/20260605072639.2434847-2-yukuai@kernel.org
> diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
> index 24b32a0c95b40..a163d33b0e075 100644
> --- a/drivers/md/raid5.c
> +++ b/drivers/md/raid5.c
> @@ -5685,7 +5685,10 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi)
> {
> struct r5conf *conf = mddev->private;
> sector_t logical_sector, last_sector;
> + sector_t first_stripe, last_stripe;
> struct stripe_head *sh;
> + struct bvec_iter bi_iter;
> + struct bio *orig_bi = bi;
> int stripe_sectors;
>
> /* We need to handle this when io_uring supports discard/trim */
> @@ -5696,19 +5699,29 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi)
> /* Skip discard while reshape is happening */
> return;
[Severity: High]
This isn't a bug introduced by this patch, but does returning early from
make_discard_request() without completing the bio cause an I/O hang?
When a user task issues a discard to a RAID5 array undergoing a reshape,
raid5_make_request() calls make_discard_request(). If it takes these early
returns without calling bio_endio(bi), the bio is leaked. Because the
caller assumes the bio was handled and returns true, the task hangs
indefinitely waiting for completion.
Should these early return paths complete the bio to avoid leaking it?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260831133314.4125787-655-sashal@kernel.org?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread