[PATCH AUTOSEL 6.18] nvme: fix crash and memory leak during invalid cdev teardown

From: Sasha Levin

Date: Mon Aug 31 2026 - 12:34:45 EST


From: Maurizio Lombardi <mlombard@xxxxxxxxxx>

[ Upstream commit 26acdaa357cded33a37f575cd5f6bae1033b3a5d ]

In the NVMe multipath code, if nvme_add_ns_head_cdev() fails during
nvme_mpath_set_live(), the error is ignored. However, during teardown,
nvme_remove_head() unconditionally calls nvme_cdev_del(). This teardown
asymmetry leads to a kernel panic if the character device was never
successfully initialized.

BUG: kernel NULL pointer dereference, address: 00000000000000d0
device_del+0x39/0x3c0
cdev_device_del+0x15/0x50
nvme_cdev_del+0xe/0x20 [nvme_core]
nvme_mpath_shutdown_disk+0x38/0x60 [nvme_core]
nvme_ns_remove+0x177/0x1f0 [nvme_core]
nvme_remove_namespaces+0xdc/0x130 [nvme_core]
nvme_do_delete_ctrl+0x71/0xd0 [nvme_core]

Additionally, a memory leak exists in the nvme_cdev_add() failure path.
Previously, dev_set_name() was called before ida_alloc(). If ida_alloc()
subsequently failed, device_initialize() was never called, meaning
put_device() could not be used to clean up the kobject, leaking the
memory allocated by dev_set_name().

* Introduces the NVME_NSHEAD_CDEV_LIVE and NVME_NS_CDEV_LIVE bits to track
the successful creation of the character devices. Teardown routines now
check these bits before attempting deletion.
* Refactor nvme_cdev_add() to accept the formatted device name as a
parameter, moving dev_set_name() after the IDA allocation and
immediately before device_initialize(). This ensures any internally
allocated strings are safely cleaned up by put_device() upon failure.

Signed-off-by: Maurizio Lombardi <mlombard@xxxxxxxxxx>
Signed-off-by: Keith Busch <kbusch@xxxxxxxxxx>
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---

LLM Generated explanations, may be completely bogus:

# Stable Backport Analysis: `nvme: fix crash and memory leak during
invalid cdev teardown`

**Local tree:** Linux **6.18.44** (`stable/linux-6.18.y`, `HEAD`
detached at `1efe5d048a391`)

**Commit under review:** `26acdaa357cde` (on `master`, **not** in this
tree)

---

## PHASE 1: COMMIT MESSAGE FORENSICS

### Step 1.1: Subject Line
**Record:** `[nvme]` `[fix]` — crash and memory leak during invalid
character-device teardown in NVMe namespace cdev paths.

### 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:** Maurizio Lombardi, Keith Busch (NVMe maintainer)

Notable: commit includes a concrete **BUG:** stack trace (NULL pointer
dereference). No syzbot report.

### Step 1.3: Body Analysis
**Record:**
- **Bug:** Teardown asymmetry in NVMe multipath — if
`nvme_add_ns_head_cdev()` fails during `nvme_mpath_set_live()`, the
error is ignored, but `nvme_remove_head()` unconditionally calls
`nvme_cdev_del()`.
- **Symptom:** Kernel panic — NULL pointer dereference in `device_del()`
during controller/namespace removal (`nvme_do_delete_ctrl` →
`nvme_remove_namespaces` → `nvme_ns_remove` → multipath head removal).
- **Secondary bug:** Memory leak when `dev_set_name()` runs before
`ida_alloc()` in the cdev-add path; if `ida_alloc()` fails,
`device_initialize()` never runs and `put_device()` cannot free the
kobject name.
- **Root cause:** No tracking of whether cdev creation actually
succeeded; teardown assumes it did.
- **Version info:** None explicit in message.

### Step 1.4: Hidden Bug Fix Detection
**Record:** Not disguised — explicitly labeled as crash + memory leak
fix. The `nvme_cdev_add()` refactor is a real resource-management fix,
not cosmetic cleanup.

---

## PHASE 2: DIFF ANALYSIS

### Step 2.1: Inventory
**Record:**
| File | Changes |
|------|---------|
| `drivers/nvme/host/core.c` | ~33 lines changed |
| `drivers/nvme/host/multipath.c` | ~19 lines changed |
| `drivers/nvme/host/nvme.h` | ~5 lines changed |

**Functions modified:** `nvme_cdev_add()`, `nvme_add_ns_cdev()`,
`nvme_ns_remove()`, `nvme_add_ns_head_cdev()`, `nvme_remove_head()`

**Scope:** Single-subsystem, surgical fix across 3 files (~57 lines
total). Not a refactor.

### Step 2.2: Code Flow Changes
**Record:**

| Hunk | Before | After |
|------|--------|-------|
| `nvme_cdev_add()` | `ida_alloc` only; callers set name separately |
Accepts `name`, calls `dev_set_name()` after `ida_alloc`, before
`device_initialize()` |
| `nvme_add_ns_cdev()` / `nvme_add_ns_head_cdev()` | `dev_set_name()`
then `nvme_cdev_add()`; no success tracking | `snprintf` name, call
refactored `nvme_cdev_add()`, set `NVME_NS_CDEV_LIVE` /
`NVME_NSHEAD_CDEV_LIVE` on success |
| `nvme_ns_remove()` | Unconditionally `nvme_cdev_del()` for non-
multipath | Only if `NVME_NS_CDEV_LIVE` bit set |
| `nvme_remove_head()` | Unconditionally `nvme_cdev_del()` | Only if
`NVME_NSHEAD_CDEV_LIVE` bit set |

### Step 2.3: Bug Mechanism
**Record:**
- **Category (a):** Resource leak on error path — `dev_set_name()`
before `ida_alloc()`/`device_initialize()`.
- **Category (d):** NULL pointer dereference — `nvme_cdev_del()` →
`cdev_device_del()` → `device_del()` on uninitialized/failed cdev.
- **Category (g):** Logic/correctness — teardown does not match setup;
success bit flags align init and teardown.

**Specific mechanism:** In current 6.18.44 code at
`multipath.c:794-801`, `NVME_NSHEAD_DISK_LIVE` is set after
`device_add_disk()` succeeds, then `nvme_add_ns_head_cdev(head)` is
called with **return value ignored**. On failure, `nvme_remove_head()`
at line 698 still calls `nvme_cdev_del()`.

### Step 2.4: Fix Quality
**Record:**
- Fix is obviously correct: only delete cdev when creation succeeded.
- Minimal, surgical; uses existing `flags` bitfields with free bit
positions (2 and 6).
- Low regression risk: adds guards on teardown paths only; does not
change successful init behavior.
- `nvme_cdev_add()` signature change is internal to `nvme_core` (no new
userspace API).

---

## PHASE 3: GIT HISTORY INVESTIGATION

### Step 3.1: Blame
**Record:**
- `nvme_cdev_add()` / `nvme_add_ns_head_cdev()`: introduced in
`2637baed7801` (Apr 2021, "introduce generic per-namespace chardev") —
**present in this tree**.
- `nvme_remove_head()` unconditional `nvme_cdev_del`: `62188639ec160`
(May 2025, delayed multipath head removal) — **present in this tree**.
- Stack trace references `nvme_mpath_shutdown_disk`; renamed to
`nvme_mpath_remove_disk` in `9e221d8cf90b8` — **this tree uses
`nvme_mpath_remove_disk`**.

### Step 3.2: Fixes: Tag
**Record:** N/A — no `Fixes:` tag. Bug latent since cdev introduction
(2021); exposed by multipath head lifecycle code (2025).

### Step 3.3: Related File History
**Record:**
- Recent related fix: `3d8f35e182c80` "nvme-multipath: fix leak on
try_module_get failure" — separate issue.
- Follow-up on master: `869567bcbe2dc` makes cdev-add functions return
`void` (cleanup after this fix; **not a prerequisite**).
- Standalone fix; not part of a multi-patch dependency series.

### Step 3.4: Author Context
**Record:** Maurizio Lombardi — active NVMe contributor (nvme-tcp, nvme-
pci fixes). Keith Busch committed as NVMe maintainer. No indication this
is experimental.

### Step 3.5: Dependencies
**Record:** No prerequisites. All touched code exists in 6.18.44. `git
apply --check --3way` succeeds on this tree. Plain `git apply --check`
fails on `nvme.h` line offsets only (struct layout drift vs. mainline);
3-way merge applies cleanly.

---

## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH

### Step 4.1: Original Discussion
**Record:**
- `b4 dig -c 26acdaa357cde`:
https://patch.msgid.link/20260608155357.256966-1-mlombard@xxxxxxxxxx
- Series: v1 (Jun 5) → v2 (Jun 8) → v3 (Jun 8); committed version
matches v3.
- Lore thread content could not be fetched (Anubis bot protection on
lore.kernel.org and patch.msgid.link).

### Step 4.2: Reviewers
**Record:** `b4 dig -w`: CC'd `kbusch@xxxxxxxxxx`, `hch@xxxxxx`, `linux-
nvme@xxxxxxxxxxxxxxxxxxx`, `dwagner@xxxxxxx`. Keith Busch committed the
patch.

### Step 4.3: Bug Report
**Record:** Stack trace in commit message only. No external
bugzilla/syzbot link. Reproducible via cdev-add failure during multipath
namespace bring-up followed by controller removal.

### Step 4.4: Related Patches
**Record:** `869567bcbe2dc` on master is optional follow-up cleanup, not
required for correctness.

### Step 4.5: Stable List History
**Record:** UNVERIFIED — could not search lore stable archive due to
fetch blocking. No evidence in this tree that the fix was already
backported.

---

## PHASE 5: CODE SEMANTIC ANALYSIS

### Step 5.1: Key Functions
**Record:** `nvme_mpath_set_live()`, `nvme_add_ns_head_cdev()`,
`nvme_remove_head()`, `nvme_mpath_remove_disk()`, `nvme_ns_remove()`,
`nvme_add_ns_cdev()`, `nvme_cdev_add()`, `nvme_cdev_del()`.

### Step 5.2: Callers
**Record:**
- `nvme_mpath_set_live()` ← `nvme_mpath_add_disk()` ← namespace
scan/alloc path (`core.c:4186`)
- `nvme_remove_head()` ← `nvme_mpath_remove_disk()` ← `nvme_ns_remove()`
when last path removed (`core.c:4275-4276`)
- `nvme_ns_remove()` ← `nvme_remove_namespaces()` ←
`nvme_do_delete_ctrl()` (controller delete/hot-unplug)
- `nvme_add_ns_cdev()` ← namespace alloc when not multipath
(`core.c:4183-4184`)

### Step 5.3: Callees
**Record:** `device_add_disk()`, `dev_set_name()`, `ida_alloc()`,
`device_initialize()`, `cdev_device_add()`, `cdev_device_del()`,
`put_device()`, `del_gendisk()`.

### Step 5.4: Reachability
**Record:**
- **Crash path:** Controller removal / namespace teardown — common
during driver unload, device hot-unplug, reset, or error recovery.
- Trigger requires `nvme_add_ns_head_cdev()` or `nvme_add_ns_cdev()`
failure (memory pressure, `ida_alloc` exhaustion, `cdev_device_add`
failure).
- Multipath crash path: `CONFIG_NVME_MULTIPATH=y`.
- Memory-leak fix: all configs using NVMe namespace cdevs.

### Step 5.5: Similar Patterns
**Record:** Same asymmetry in both multipath head cdev (`multipath.c`)
and per-namespace cdev (`core.c`). Fix addresses both consistently.

---

## PHASE 6: CROSS-REFERENCE WITH LOCAL TREE (6.18.44)

### Step 6.1: Buggy Code Present?
**Record:** **YES.** Verified in checkout:
- `multipath.c:801` — `nvme_add_ns_head_cdev(head)` with ignored return
- `multipath.c:698` — unconditional `nvme_cdev_del()`
- `core.c:4184` — `nvme_add_ns_cdev(ns)` with ignored return
- `core.c:4264` — unconditional `nvme_cdev_del()` for non-multipath
- `core.c:3876-3877` — `dev_set_name()` before `nvme_cdev_add()` (which
does `ida_alloc` first internally, but caller already set name)

Bug introduced with cdev code in 2021; present throughout 6.18.y.

### Step 6.2: Backport Complications
**Record:** Minor line-offset drift in `nvme.h` vs. mainline (missing
`io_requeue_*` counters in 6.18). `git apply --check --3way` applies
cleanly. Expected difficulty: **clean apply with minor context
adjustment** if needed.

### Step 6.3: Fix Already Present?
**Record:** **NO.** `git merge-base --is-ancestor 26acdaa357cde HEAD`
returns exit code 1. No grep hits for `NVME_NSHEAD_CDEV_LIVE` or
`NVME_NS_CDEV_LIVE` in tree.

---

## PHASE 7: SUBSYSTEM CONTEXT

### Step 7.1: Subsystem Criticality
**Record:** `drivers/nvme/` — **IMPORTANT** (block storage, widely
deployed; multipath used in enterprise/high-availability setups).

### Step 7.2: Activity
**Record:** Actively maintained in 6.18.y (recent multipath fixes in
2025–2026). Mature subsystem with ongoing lifecycle bug fixes.

---

## PHASE 8: IMPACT AND RISK

### Step 8.1: Who Is Affected
**Record:**
- **Crash:** Users with `CONFIG_NVME_MULTIPATH` who hit cdev creation
failure during namespace bring-up, then remove controller/namespace.
- **Leak:** Any NVMe user where `dev_set_name` succeeds but subsequent
`ida_alloc` or `cdev_device_add` fails.
- Population: storage/multipath deployments (RHEL, SLES, cloud block
storage with multipath).

### Step 8.2: Trigger Conditions
**Record:**
- `ida_alloc()` failure under memory pressure (realistic).
- `cdev_device_add()` failure (less common but possible).
- Followed by controller delete / namespace removal (normal admin or
error-recovery path).
- Unprivileged direct trigger: **no** (requires device admin/removal),
but failure during init can be triggered by kernel memory pressure.

### Step 8.3: Failure Severity
**Record:**
- **Crash:** NULL pointer dereference → kernel oops/panic during
teardown — **CRITICAL**
- **Leak:** kmemleak-reported kobject name leak on error path — **HIGH**
(contributes to memory pressure)

### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** HIGH — prevents kernel panic on realistic error+teardown
path; fixes resource leak.
- **Risk:** LOW — ~57 lines, guarded teardown only, no API changes,
applies cleanly with 3-way merge.
- **Ratio:** Strongly favors backport.

---

## PHASE 9: FINAL SYNTHESIS

### Step 9.1: Evidence Summary

**FOR backport:**
- Fixes verified kernel panic (NULL deref) with stack trace
- Fixes memory leak on cdev-add error path
- Small, contained, obviously correct
- Buggy code confirmed present in 6.18.44
- Patch applies cleanly (3-way) to this tree
- NVMe maintainer (Keith Busch) committed
- Longstanding latent bug in production cdev/multipath code

**AGAINST backport:**
- Requires `CONFIG_NVME_MULTIPATH` for the primary crash scenario (but
leak fix is broader)
- Trigger needs cdev-add failure (not everyday, but realistic under
memory pressure)
- No explicit stable nomination found (UNVERIFIED due to lore fetch
failure)

**Unresolved:** Full lore review thread content; whether distros already
carry an equivalent private fix.

### Step 9.2: Stable Rules Checklist
| Criterion | Result |
|-----------|--------|
| 1. Obviously correct and tested? | **PASS** — logic is clear; v1→v3
review series; maintainer commit |
| 2. Fixes real bug affecting users? | **PASS** — panic + leak on NVMe
teardown |
| 3. Important issue? | **PASS** — CRITICAL crash, HIGH leak |
| 4. Small and contained? | **PASS** — 3 files, ~57 lines |
| 5. No new features/APIs? | **PASS** — internal flags + error-path fix
only |
| 6. Can apply to local tree? | **PASS** — 3-way apply clean |

### Step 9.3: Exception Categories
**Record:** None (standard bug fix, not device ID/quirk/DT/docs).

### Step 9.4: Decision Rationale
This commit fixes a real teardown asymmetry in NVMe multipath cdev
handling that causes a **kernel panic** when cdev creation fails but the
namespace head disk is live, plus a **memory leak** in the cdev-add
error path. The buggy code is present in Linux 6.18.44, the fix is small
and surgical, and it meets all stable-kernel criteria. The follow-up
commit making cdev functions return `void` is optional cleanup and not
required.

---

## Verification

- **[Phase 1]** Parsed subject, tags, body; no Fixes/Reported-
by/Cc:stable tags
- **[Phase 1]** Identified explicit BUG stack trace in commit message
- **[Phase 2]** Diff: 3 files, ~57 lines; flag bits + guarded teardown +
`nvme_cdev_add()` refactor
- **[Phase 2]** Read current `multipath.c:689-703`,
`multipath.c:794-801`, `core.c:3829-3883`, `core.c:4183-4184`,
`core.c:4263-4264`
- **[Phase 3]** `git describe HEAD`: v6.18.44
- **[Phase 3]** `git blame`: cdev code from `2637baed7801` (2021);
`nvme_remove_head` from `62188639ec160` (2025)
- **[Phase 3]** `git log`: `9e221d8cf90b8` renamed
`nvme_mpath_shutdown_disk` → `nvme_mpath_remove_disk`
- **[Phase 3]** `git merge-base --is-ancestor 26acdaa357cde HEAD`: exit
1 (fix NOT in tree)
- **[Phase 3]** Related commit `3596a06583a16` (2021 put_device leak
fix) is separate/prior issue
- **[Phase 3]** Follow-up `869567bcbe2dc` on master is optional, not
prerequisite
- **[Phase 4]** `b4 dig -c 26acdaa357cde`: lore URL found
- **[Phase 4]** `b4 dig -a`: v1/v2/v3 series; v3 committed
- **[Phase 4]** `b4 dig -w`: NVMe maintainers CC'd
- **[Phase 4]** UNVERIFIED: lore thread content (Anubis blocked fetch)
- **[Phase 5]** Traced call chain: `nvme_mpath_set_live` → ignored
failure → `nvme_ns_remove` → `nvme_mpath_remove_disk` →
`nvme_remove_head` → `nvme_cdev_del`
- **[Phase 6]** Buggy code confirmed present in 6.18.44 checkout
- **[Phase 6]** `git apply --check --3way` on `26acdaa357cde`: applies
cleanly
- **[Phase 6]** No `NVME_NSHEAD_CDEV_LIVE` / `NVME_NS_CDEV_LIVE` in
current tree
- **[Phase 8]** Failure mode: NULL deref panic — CRITICAL; memory leak —
HIGH

**YES**

drivers/nvme/host/core.c | 33 ++++++++++++++++++++++++---------
drivers/nvme/host/multipath.c | 19 +++++++++++++------
drivers/nvme/host/nvme.h | 5 ++++-
3 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 5ea331e933c55..de2f47d7ffd3d 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -3838,7 +3838,8 @@ void nvme_cdev_del(struct cdev *cdev, struct device *cdev_device)
put_device(cdev_device);
}

-int nvme_cdev_add(struct cdev *cdev, struct device *cdev_device,
+int nvme_cdev_add(const char *name, struct cdev *cdev,
+ struct device *cdev_device,
const struct file_operations *fops, struct module *owner)
{
int minor, ret;
@@ -3846,6 +3847,12 @@ int nvme_cdev_add(struct cdev *cdev, struct device *cdev_device,
minor = ida_alloc(&nvme_ns_chr_minor_ida, GFP_KERNEL);
if (minor < 0)
return minor;
+
+ ret = dev_set_name(cdev_device, name);
+ if (ret) {
+ ida_free(&nvme_ns_chr_minor_ida, minor);
+ return ret;
+ }
cdev_device->devt = MKDEV(MAJOR(nvme_ns_chr_devt), minor);
cdev_device->class = &nvme_ns_chr_class;
cdev_device->release = nvme_cdev_rel;
@@ -3883,15 +3890,21 @@ static const struct file_operations nvme_ns_chr_fops = {
static int nvme_add_ns_cdev(struct nvme_ns *ns)
{
int ret;
+ char name[32];

ns->cdev_device.parent = ns->ctrl->device;
- ret = dev_set_name(&ns->cdev_device, "ng%dn%d",
- ns->ctrl->instance, ns->head->instance);
- if (ret)
- return ret;
+ snprintf(name, sizeof(name), "ng%dn%d", ns->ctrl->instance,
+ ns->head->instance);

- return nvme_cdev_add(&ns->cdev, &ns->cdev_device, &nvme_ns_chr_fops,
- ns->ctrl->ops->module);
+ ret = nvme_cdev_add(name, &ns->cdev, &ns->cdev_device,
+ &nvme_ns_chr_fops, ns->ctrl->ops->module);
+ if (ret) {
+ dev_err(ns->ctrl->device, "Unable to create the %s device\n",
+ name);
+ } else {
+ set_bit(NVME_NS_CDEV_LIVE, &ns->flags);
+ }
+ return ret;
}

static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
@@ -4272,8 +4285,10 @@ static void nvme_ns_remove(struct nvme_ns *ns)
/* guarantee not available in head->list */
synchronize_srcu(&ns->head->srcu);

- if (!nvme_ns_head_multipath(ns->head))
- nvme_cdev_del(&ns->cdev, &ns->cdev_device);
+ if (!nvme_ns_head_multipath(ns->head)) {
+ if (test_and_clear_bit(NVME_NS_CDEV_LIVE, &ns->flags))
+ nvme_cdev_del(&ns->cdev, &ns->cdev_device);
+ }

nvme_mpath_remove_sysfs_link(ns);

diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index 616d1ce6b8e5c..d61c4e9543040 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -643,14 +643,20 @@ static const struct file_operations nvme_ns_head_chr_fops = {
static int nvme_add_ns_head_cdev(struct nvme_ns_head *head)
{
int ret;
+ char name[32];

head->cdev_device.parent = &head->subsys->dev;
- ret = dev_set_name(&head->cdev_device, "ng%dn%d",
- head->subsys->instance, head->instance);
- if (ret)
- return ret;
- ret = nvme_cdev_add(&head->cdev, &head->cdev_device,
+ snprintf(name, sizeof(name), "ng%dn%d", head->subsys->instance,
+ head->instance);
+
+ ret = nvme_cdev_add(name, &head->cdev, &head->cdev_device,
&nvme_ns_head_chr_fops, THIS_MODULE);
+ if (ret) {
+ dev_err(disk_to_dev(head->disk),
+ "Unable to create the %s device\n", name);
+ } else {
+ set_bit(NVME_NSHEAD_CDEV_LIVE, &head->flags);
+ }
return ret;
}

@@ -695,7 +701,8 @@ static void nvme_remove_head(struct nvme_ns_head *head)
*/
kblockd_schedule_work(&head->requeue_work);

- nvme_cdev_del(&head->cdev, &head->cdev_device);
+ if (test_and_clear_bit(NVME_NSHEAD_CDEV_LIVE, &head->flags))
+ nvme_cdev_del(&head->cdev, &head->cdev_device);
synchronize_srcu(&head->srcu);
del_gendisk(head->disk);
}
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 102fae6a231c5..2708003e5b40f 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -510,6 +510,7 @@ struct nvme_ns_head {
unsigned int delayed_removal_secs;
#define NVME_NSHEAD_DISK_LIVE 0
#define NVME_NSHEAD_QUEUE_IF_NO_PATH 1
+#define NVME_NSHEAD_CDEV_LIVE 2
struct nvme_ns __rcu *current_path[];
#endif
};
@@ -545,6 +546,7 @@ struct nvme_ns {
#define NVME_NS_FORCE_RO 3
#define NVME_NS_READY 4
#define NVME_NS_SYSFS_ATTR_LINK 5
+#define NVME_NS_CDEV_LIVE 6

struct cdev cdev;
struct device cdev_device;
@@ -916,7 +918,8 @@ int nvme_get_log(struct nvme_ctrl *ctrl, u32 nsid, u8 log_page, u8 lsp, u8 csi,
void *log, size_t size, u64 offset);
bool nvme_tryget_ns_head(struct nvme_ns_head *head);
void nvme_put_ns_head(struct nvme_ns_head *head);
-int nvme_cdev_add(struct cdev *cdev, struct device *cdev_device,
+int nvme_cdev_add(const char *name, struct cdev *cdev,
+ struct device *cdev_device,
const struct file_operations *fops, struct module *owner);
void nvme_cdev_del(struct cdev *cdev, struct device *cdev_device);
int nvme_ioctl(struct block_device *bdev, blk_mode_t mode,
--
2.53.0