[PATCH AUTOSEL 6.18-6.12] nvme: handle positive error codes in nuse_show()
Sasha Levin
sashal at kernel.org
Mon Oct 19 06:50:20 PDT 2026
From: John Garry <john.g.garry at oracle.com>
[ Upstream commit dd516cd7624648c71d338d99368587f10ecc9f0b ]
Function __nvme_submit_sync_cmd() returns a positive error code for NVMe
errors. Otherwise, we get 0 for success or a negative error code for a
kernel error.
In nuse_show() -> ns_{head}_update_nuse() -> nvme_identify_ns() ->
nvme_submit_sync_cmd() -> __nvme_submit_sync_cmd(), we then may get a
positive error code returned.
Function nuse_show() - being a device attr handler - should return the
number of bytes written to the buffer or a negative error code.
Convert any positive NVMe error code to -EIO.
Signed-off-by: John Garry <john.g.garry at oracle.com>
Reviewed-by: Christoph Hellwig <hch at lst.de>
Signed-off-by: Keith Busch <kbusch at kernel.org>
Signed-off-by: Sasha Levin <sashal at kernel.org>
---
LLM Generated explanations, may be completely bogus:
I have the mailing-list thread and the sysfs/NVMe return-code path. Next
I’ll confirm how a positive NVMe status is treated as a byte count, then
give the backport verdict for this tree.
---
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
Record: `[nvme] [handle] convert positive NVMe status codes from
nuse_show() into a proper sysfs errno`
- Subsystem: `nvme` (host sysfs)
- Verb: `handle` (bug-fix language: incorrect error handling)
- Intent: sysfs `nuse` show must not return a positive NVMe status as a
“bytes written” count
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
Record:
- `Fixes:` — absent (expected for this review pipeline)
- `Reported-by:` — none
- `Tested-by:` — none
- `Reviewed-by: Christoph Hellwig <hch at lst.de>` (core NVMe reviewer)
- `Acked-by:` — none
- `Link:` — none in the commit; lore found separately
- `Cc: stable at vger.kernel.org` — absent (not a negative signal)
- `Signed-off-by: John Garry <john.g.garry at oracle.com>` (author)
- `Signed-off-by: Keith Busch <kbusch at kernel.org>` (NVMe maintainer;
applied to nvme-7.3)
- Ignore pipeline `Signed-off-by: Sasha Levin` if present — not in this
commit
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
Record:
- **Bug:** `__nvme_submit_sync_cmd()` returns 0, a negative Linux errno,
or a **positive NVMe status**. That value is propagated `nuse_show() →
ns_{head}_update_nuse() → nvme_identify_ns() →
nvme_submit_sync_cmd()`.
- **Symptom:** `nuse_show()` is a device attribute handler; it must
return a byte count or a negative errno. A positive NVMe status is
neither.
- **Fix:** map `ret > 0` to `-EIO`; keep `ret < 0` as-is.
- **Version info in message:** none. Feature itself dates to v6.8
(`a1a825ab6a603` “nvme: add csi, ms and nuse to sysfs”).
- **Root cause:** treating any non-zero `ret` as a sysfs error, which is
wrong for positive NVMe codes (they are not negative, so they were
returned as a success length).
**Step 1.4: DETECT HIDDEN BUG FIXES**
Record: Not hidden. Explicit error-handling fix. Same class as “add
missing check” / “handle X properly.”
---
## PHASE 2: DIFF ANALYSIS - LINE BY LINE
**Step 2.1: INVENTORY THE CHANGES**
Record:
- File: `drivers/nvme/host/sysfs.c` — **+3 / −1**
- Function: `nuse_show()` only
- Scope: **single-file surgical fix**
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
Record:
- **Before:** `if (ret) return ret;` — negative errno returned
correctly; **positive NVMe status returned as the sysfs byte count**,
and `sysfs_emit()` is skipped so the buffer is never filled with the
NUSE value.
- **After:** `ret < 0` → pass through; `ret > 0` → `-EIO`; `ret == 0` →
`sysfs_emit()` of `head->nuse`.
- Path affected: **error path** of a sysfs read that issues Identify
Namespace (rate-limited).
**Step 2.3: IDENTIFY THE BUG MECHANISM**
Record:
- **Category:** logic/correctness of sysfs error conversion; can also
trip a kernel `WARN`.
- **Mechanism:** NVMe completion status is stored as
`le16_to_cpu(cqe->status) >> 1` (`nvme_try_complete_req()`).
`nvme_execute_rq()` returns that value when non-zero. Status often
includes `NVME_STATUS_DNR` (**0x4000 = 16384**).
- Sysfs (`sysfs_kf_seq_show` in `fs/sysfs/file.c`):
- `count < 0` → error
- `count >= PAGE_SIZE` → **`WARN(1, "OOB write or bad count ...")`**
then clamp
- otherwise `seq_commit(sf, count)` of a buffer that was `memset` to 0
but never written by `nuse_show()`
- On 4K pages (typical x86_64), DNR-tagged Identify failures (`status |
0x4000 >= 16384 > 4096`) **fire a kernel WARN**. Smaller statuses
become a short successful read of zeros instead of `-EIO`.
**Step 2.4: ASSESS THE FIX QUALITY**
Record:
- Obviously correct: matches `__nvme_submit_sync_cmd()` contract and the
existing `nvme_hwmon` pattern (`if (ret > 0) return -EIO`).
- Minimal; no unrelated edits; no API/struct changes.
- Regression risk **very low**: only the misclassified success path
becomes `-EIO`, which is the intended ABI.
---
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
Record:
- Buggy `if (ret) return ret;` introduced in **`a1a825ab6a603`** (Daniel
Wagner, 2023-12-18), “nvme: add csi, ms and nuse to sysfs”.
- First appeared: **v6.8-rc1** (`git describe --contains` →
`v6.8-rc1~121^2~25^2~4`).
- Present for a long time in this 7.3 lineage.
**Step 3.2: FOLLOW THE FIXES: TAG**
Record: No `Fixes:` tag. Buggy commit identified by blame:
`a1a825ab6a603`. That commit **is** an ancestor of this tree.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
Record:
- `8d0d2447394b1` — double-free of `nvme_id_ns` in `ns_update_nuse()`
(already in tree; different bug).
- `88c918d1ee2c88` — `nvme_disk_is_ns_head()` use in `nuse_show`.
- Standalone v1 patch; not “patch X/Y”.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
Record: John Garry is an active NVMe/block contributor (cdev lifetime,
multipath, sysfs). Nearby commits are unrelated lifetime/locking work,
not prerequisites of this hunk.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
Record: None. Touches only `nuse_show()` control flow. `nuse_show`,
`ns_update_nuse`, `ns_head_update_nuse`, and `nvme_identify_ns` all
exist here. **Applies standalone.**
---
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
Record:
- `b4 dig -c dd516cd762464` → https://patch.msgid.link/20260630102717.26
71475-1-john.g.garry at oracle.com
- **v1 only** (no v2/v3). Applied as submitted.
- Author note: could print `nvme_get_error_status_str()`; rejected as a
bad idea (keeps the fix small).
- Christoph: “Looks good:” + `Reviewed-by`
- Keith Busch: “Thanks, applied to nvme-7.3.”
- No NAKs, no stable nomination, no risk flags.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
Record (`b4 dig -w`): To/Cc **hch at lst.de, kbusch at kernel.org,
sagi at grimberg.me, axboe at fb.com, linux-nvme at lists.infradead.org**. Right
maintainers; Hellwig reviewed; Busch applied.
**Step 4.3: SEARCH FOR THE BUG REPORT**
Record: No `Reported-by`, syzbot, or bugzilla. Found by code inspection
of the Identify → sysfs return path. Still a real, reachable bug (sysfs
read issues Identify NS).
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
Record: Standalone single patch. Same conversion already used in
`drivers/nvme/host/hwmon.c`.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
Record: Direct lore stable search was blocked (bot/403). Thread mbox has
**no** `Cc: stable` and no stable-list discussion. **UNVERIFIED**
whether anyone later asked for it on stable@ — does not change the
technical verdict.
---
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS IN THE DIFF**
Record: `nuse_show` (modified). Callers of the bad return:
`ns_head_update_nuse`, `ns_update_nuse` → `nvme_identify_ns` →
`nvme_submit_sync_cmd` → `__nvme_submit_sync_cmd` → `nvme_execute_rq`.
**Step 5.2: TRACE CALLERS**
Record: `nuse_show` is `DEVICE_ATTR_RO(nuse)` (`0444`) on the NVMe
namespace disk. Reachable from userspace `read()` of
`/sys/block/nvmeXnY/nuse`. Documented in
`Documentation/ABI/stable/sysfs-nvme`; used so libnvme need not issue
Identify itself. **Not** IRQ/hot-path; process context, admin command.
**Step 5.3: TRACE CALLEES**
Record: Identify Namespace (admin), SRCU in the multipath helper, rate
limit 5s. On Identify failure, `nvme_identify_ns()` kfree’s the id
buffer and returns the status — no leak there.
**Step 5.4: FOLLOW THE CALL CHAIN**
Record: userspace `read` → sysfs/kernfs → `nuse_show` → Identify NS.
**Unprivileged users can trigger it** (world-readable). Failure of
Identify is uncommon on a healthy live NS, but expected during reset,
path loss, unmap, or device errors — exactly when libnvme/nvme-cli may
still read `nuse`.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
Record: Same `if (ret > 0) return -EIO` in `nvme_get_temp_thresh` /
`nvme_set_temp_thresh` (`hwmon.c`). Other `nuse_show`-style sysfs
readers in this file mostly format cached fields and do not submit
commands.
---
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
Record:
- `git describe HEAD` → **v7.3-rc4-27-gf0100363d8c37**
- `make kernelversion` → **7.3.0-rc4**
- `nuse_show` exists in `drivers/nvme/host/sysfs.c`
- Bug introduced **v6.8** (`a1a825ab6a603`); **is** ancestor of HEAD
- Candidate **`dd516cd762464` is already an ancestor of HEAD** (evaluate
on merit, not “already selected”)
- Current file already contains the `ret < 0` / `ret > 0` logic
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
Record: **Clean apply** on this tree (hunk matches current `nuse_show`).
No conflicting refactor of this function beyond the fix itself.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
Record: Double-free fix `8d0d2447394b1` is present and orthogonal. No
alternate conversion of positive NVMe status in `nuse_show` besides this
commit.
---
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
Record: **NVMe host sysfs** (`drivers/nvme/host/`). Criticality:
**IMPORTANT** (common storage stack; not mm/VFS core). Affects NVMe
users who read namespace sysfs (management tools).
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
Record: Actively developed (many recent sysfs/diag/timeout patches).
`nuse` itself is mature (since 6.8), not brand-new 7.3-only code.
---
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
Record: **Driver-specific** — NVMe namespace sysfs. Anyone with
`CONFIG_BLK_DEV_NVME` (default on most distros) and a namespace. Tools:
libnvme / nvme-cli discovery.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
Record:
- Trigger: `read` of `/sys/block/nvmeXnY/nuse` while Identify NS returns
a **non-zero NVMe status** (and the 5s ratelimit allows a command).
- Uncommon on a healthy device; realistic on reset, interconnect errors,
or a controller that fails Identify.
- Unprivileged readable (`DEVICE_ATTR_RO` = 0444).
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
Record:
- DNR (or any status ≥ `PAGE_SIZE`): **kernel WARN** in
`sysfs_kf_seq_show` (“OOB write or bad count”) — **HIGH** (WARNING;
panic if `panic_on_warn`).
- Smaller status: successful short read of zeros instead of an error —
**MEDIUM** (wrong ABI; tools may treat NUSE as 0 or fail to parse).
- Not UAF, not filesystem corruption, not a hard deadlock.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
Record:
- **Benefit:** medium–high — stops a real WARN and a bogus sysfs success
on a widely deployed driver.
- **Risk:** very low — 3 lines, error path only, established `-EIO`
mapping.
- **Ratio:** favorable.
---
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
**FOR backporting**
- Real bug: sysfs show returns a positive NVMe status as a byte count.
- Can `WARN` when status includes `NVME_STATUS_DNR` (0x4000) on 4K/16K
pages.
- Userspace can get a successful empty/short read instead of an error.
- 3-line, obviously correct; Hellwig reviewed; Busch applied.
- Same pattern already used in NVMe hwmon.
- Code and bug exist in this 7.3 tree (since v6.8).
- No new API/feature; no series dependencies.
**AGAINST backporting**
- No user/syzbot report; found by inspection.
- Identify NS rarely fails on a live healthy namespace.
- Not a UAF/panic/data-corruption class bug in the common success path.
**UNRESOLVED**
- Stable@ archives could not be fetched (403/bot). No evidence of a
prior rejection.
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — reviewed by Hellwig, applied
by Busch, matches documented return contract.
2. Fixes a real bug that affects users? **PASS** — wrong sysfs return;
WARN on DNR Identify failures.
3. Important issue? **PASS** — WARN_ON-class (and wrong userspace ABI).
Severity HIGH for the WARN path, MEDIUM otherwise.
4. Small and contained? **PASS** — +3/−1, one function.
5. No new features or APIs? **PASS**
6. Can apply to the local tree? **PASS** — `nuse_show` present; hunk
matches.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
Record: Not a device-ID/quirk/DT/build/docs exception. Ordinary small
driver bugfix.
**Step 9.4: MAKE YOUR DECISION**
This tree is **7.3.0-rc4**. The `nuse` sysfs attribute exists here. A
positive NVMe Identify status must not be returned as a sysfs byte
count; that can WARN and confuse management tools. The patch is tiny,
already the established NVMe conversion, and has maintainer review.
Benefit outweighs risk.
### What the commit solves for this tree
`nuse_show()` refreshes Namespace Utilization via Identify NS. Command
errors come back as **positive** NVMe status. Returning that from a
`DEVICE_ATTR_RO` show handler makes kernfs treat it as a length: zeros
to userspace, or a **sysfs “bad count” WARN** when the status is ≥
`PAGE_SIZE` (typical with DNR). Mapping `ret > 0` to `-EIO` restores the
sysfs contract.
### Risk vs benefit
Very low risk, clear correctness win on a user-visible NVMe sysfs file.
---
## Verification
- **[Phase 1]** Parsed message: no Fixes/Reported-by/stable Cc;
Reviewed-by Hellwig; SOB Garry + Busch.
- **[Phase 2]** Diff: +3/−1 in `nuse_show()` only; `if (ret)` → `ret <
0` / `ret > 0` → `-EIO`.
- **[Phase 2]** `__nvme_submit_sync_cmd()` comment and
`nvme_execute_rq()`: positive value is NVMe status
(`nvme_req(rq)->status`).
- **[Phase 2]** `nvme_try_complete_req()`: `rq->status =
le16_to_cpu(status) >> 1`; `NVME_STATUS_DNR = 0x4000`.
- **[Phase 2]** `fs/sysfs/file.c` `sysfs_kf_seq_show`: `count >=
PAGE_SIZE` → `WARN(1, "OOB write or bad count")`.
- **[Phase 2]** Same conversion in `drivers/nvme/host/hwmon.c` lines
31–32 and 54–55.
- **[Phase 3]** Blame: buggy `if (ret)` from `a1a825ab6a603` (v6.8); fix
is `dd516cd762464`.
- **[Phase 3]** `git merge-base --is-ancestor a1a825ab6a603 HEAD` — yes;
`dd516cd762464` also ancestor.
- **[Phase 3]** Related: `8d0d2447394b1` double-free in `ns_update_nuse`
— different bug, already here.
- **[Phase 3]** Author log: standalone; not a multi-patch series.
- **[Phase 4]** `b4 dig -c dd516cd762464`: lore msgid
`20260630102717.2671475-1-john.g.garry at oracle.com`.
- **[Phase 4]** `b4 dig -a`: v1 only.
- **[Phase 4]** `b4 dig -w`: linux-nvme + Hellwig, Busch, Grimberg,
Axboe.
- **[Phase 4]** mbox: Hellwig “Looks good”; Busch “applied to nvme-7.3”;
no NAK.
- **[Phase 4]** WebFetch lore/stable: 403/bot — UNVERIFIED stable@
traffic.
- **[Phase 5]** semcode MCP not available; used grep. Callers: sysfs RO
attr `nuse`.
- **[Phase 5]** ABI: `/sys/block/nvmeXnY/nuse` since 6.8; Identify on
read; `DEVICE_ATTR_RO` → 0444.
- **[Phase 6]** `git describe HEAD`: v7.3-rc4-27-gf0100363d8c37;
kernelversion 7.3.0-rc4.
- **[Phase 6]** Current `nuse_show` already has the fix; buggy pattern
exists in history of this file.
- **[Phase 8]** Failure: WARN (HIGH) or bogus short sysfs read (MEDIUM);
trigger = Identify NS error on nuse read.
The fix is small, surgical, and meets the stable criteria for this tree.
**YES**
drivers/nvme/host/sysfs.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/sysfs.c b/drivers/nvme/host/sysfs.c
index 16c6fea4b2db6..12478e0297356 100644
--- a/drivers/nvme/host/sysfs.c
+++ b/drivers/nvme/host/sysfs.c
@@ -239,8 +239,10 @@ static ssize_t nuse_show(struct device *dev, struct device_attribute *attr,
ret = ns_head_update_nuse(head);
else
ret = ns_update_nuse(disk->private_data);
- if (ret)
+ if (ret < 0)
return ret;
+ else if (ret > 0)
+ return -EIO;
return sysfs_emit(buf, "%llu\n", head->nuse);
}
--
2.53.0
More information about the Linux-nvme
mailing list