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

Sasha Levin <[email protected]>
Newsgroups org.infradead.lists.linux-nvme,dev.linux.lists.patches,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
From: Maurizio Lombardi <[email protected]>

[ 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 <[email protected]>
Signed-off-by: Keith Busch <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---

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/[email protected]
- 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 `[email protected]`, `[email protected]`, `linux-
[email protected]`, `[email protected]`. 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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.