Skip to content

Commit 5990b77

Browse files
committed
Merge tag 'nvme-6.16-2025-06-26' of git://git.infradead.org/nvme into block-6.16
Pull NVMe fixes from Christoph: " - reset delayed remove_work after reconnect (Keith Busch) - fix atomic write size validation (Christoph Hellwig)" * tag 'nvme-6.16-2025-06-26' of git://git.infradead.org/nvme: nvme: fix atomic write size validation nvme: refactor the atomic write unit detection nvme: reset delayed remove_work after reconnect
2 parents 969127b + f46d273 commit 5990b77

File tree

3 files changed

+44
-48
lines changed

3 files changed

+44
-48
lines changed

drivers/nvme/host/core.c

Lines changed: 42 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,21 +2015,41 @@ static void nvme_configure_metadata(struct nvme_ctrl *ctrl,
20152015
}
20162016

20172017

2018-
static void nvme_update_atomic_write_disk_info(struct nvme_ns *ns,
2019-
struct nvme_id_ns *id, struct queue_limits *lim,
2020-
u32 bs, u32 atomic_bs)
2018+
static u32 nvme_configure_atomic_write(struct nvme_ns *ns,
2019+
struct nvme_id_ns *id, struct queue_limits *lim, u32 bs)
20212020
{
2022-
unsigned int boundary = 0;
2021+
u32 atomic_bs, boundary = 0;
20232022

2024-
if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf) {
2025-
if (le16_to_cpu(id->nabspf))
2023+
/*
2024+
* We do not support an offset for the atomic boundaries.
2025+
*/
2026+
if (id->nabo)
2027+
return bs;
2028+
2029+
if ((id->nsfeat & NVME_NS_FEAT_ATOMICS) && id->nawupf) {
2030+
/*
2031+
* Use the per-namespace atomic write unit when available.
2032+
*/
2033+
atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs;
2034+
if (id->nabspf)
20262035
boundary = (le16_to_cpu(id->nabspf) + 1) * bs;
2036+
} else {
2037+
/*
2038+
* Use the controller wide atomic write unit. This sucks
2039+
* because the limit is defined in terms of logical blocks while
2040+
* namespaces can have different formats, and because there is
2041+
* no clear language in the specification prohibiting different
2042+
* values for different controllers in the subsystem.
2043+
*/
2044+
atomic_bs = (1 + ns->ctrl->subsys->awupf) * bs;
20272045
}
2046+
20282047
lim->atomic_write_hw_max = atomic_bs;
20292048
lim->atomic_write_hw_boundary = boundary;
20302049
lim->atomic_write_hw_unit_min = bs;
20312050
lim->atomic_write_hw_unit_max = rounddown_pow_of_two(atomic_bs);
20322051
lim->features |= BLK_FEAT_ATOMIC_WRITES;
2052+
return atomic_bs;
20332053
}
20342054

20352055
static u32 nvme_max_drv_segments(struct nvme_ctrl *ctrl)
@@ -2067,34 +2087,8 @@ static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id,
20672087
valid = false;
20682088
}
20692089

2070-
atomic_bs = phys_bs = bs;
2071-
if (id->nabo == 0) {
2072-
/*
2073-
* Bit 1 indicates whether NAWUPF is defined for this namespace
2074-
* and whether it should be used instead of AWUPF. If NAWUPF ==
2075-
* 0 then AWUPF must be used instead.
2076-
*/
2077-
if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf)
2078-
atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs;
2079-
else
2080-
atomic_bs = (1 + ns->ctrl->awupf) * bs;
2081-
2082-
/*
2083-
* Set subsystem atomic bs.
2084-
*/
2085-
if (ns->ctrl->subsys->atomic_bs) {
2086-
if (atomic_bs != ns->ctrl->subsys->atomic_bs) {
2087-
dev_err_ratelimited(ns->ctrl->device,
2088-
"%s: Inconsistent Atomic Write Size, Namespace will not be added: Subsystem=%d bytes, Controller/Namespace=%d bytes\n",
2089-
ns->disk ? ns->disk->disk_name : "?",
2090-
ns->ctrl->subsys->atomic_bs,
2091-
atomic_bs);
2092-
}
2093-
} else
2094-
ns->ctrl->subsys->atomic_bs = atomic_bs;
2095-
2096-
nvme_update_atomic_write_disk_info(ns, id, lim, bs, atomic_bs);
2097-
}
2090+
phys_bs = bs;
2091+
atomic_bs = nvme_configure_atomic_write(ns, id, lim, bs);
20982092

20992093
if (id->nsfeat & NVME_NS_FEAT_IO_OPT) {
21002094
/* NPWG = Namespace Preferred Write Granularity */
@@ -2382,16 +2376,6 @@ static int nvme_update_ns_info_block(struct nvme_ns *ns,
23822376
if (!nvme_update_disk_info(ns, id, &lim))
23832377
capacity = 0;
23842378

2385-
/*
2386-
* Validate the max atomic write size fits within the subsystem's
2387-
* atomic write capabilities.
2388-
*/
2389-
if (lim.atomic_write_hw_max > ns->ctrl->subsys->atomic_bs) {
2390-
blk_mq_unfreeze_queue(ns->disk->queue, memflags);
2391-
ret = -ENXIO;
2392-
goto out;
2393-
}
2394-
23952379
nvme_config_discard(ns, &lim);
23962380
if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
23972381
ns->head->ids.csi == NVME_CSI_ZNS)
@@ -3215,6 +3199,7 @@ static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
32153199
memcpy(subsys->model, id->mn, sizeof(subsys->model));
32163200
subsys->vendor_id = le16_to_cpu(id->vid);
32173201
subsys->cmic = id->cmic;
3202+
subsys->awupf = le16_to_cpu(id->awupf);
32183203

32193204
/* Versions prior to 1.4 don't necessarily report a valid type */
32203205
if (id->cntrltype == NVME_CTRL_DISC ||
@@ -3552,6 +3537,15 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl)
35523537
if (ret)
35533538
goto out_free;
35543539
}
3540+
3541+
if (le16_to_cpu(id->awupf) != ctrl->subsys->awupf) {
3542+
dev_err_ratelimited(ctrl->device,
3543+
"inconsistent AWUPF, controller not added (%u/%u).\n",
3544+
le16_to_cpu(id->awupf), ctrl->subsys->awupf);
3545+
ret = -EINVAL;
3546+
goto out_free;
3547+
}
3548+
35553549
memcpy(ctrl->subsys->firmware_rev, id->fr,
35563550
sizeof(ctrl->subsys->firmware_rev));
35573551

@@ -3647,7 +3641,6 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl)
36473641
dev_pm_qos_expose_latency_tolerance(ctrl->device);
36483642
else if (!ctrl->apst_enabled && prev_apst_enabled)
36493643
dev_pm_qos_hide_latency_tolerance(ctrl->device);
3650-
ctrl->awupf = le16_to_cpu(id->awupf);
36513644
out_free:
36523645
kfree(id);
36533646
return ret;
@@ -4036,6 +4029,10 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
40364029
list_add_tail_rcu(&ns->siblings, &head->list);
40374030
ns->head = head;
40384031
mutex_unlock(&ctrl->subsys->lock);
4032+
4033+
#ifdef CONFIG_NVME_MULTIPATH
4034+
cancel_delayed_work(&head->remove_work);
4035+
#endif
40394036
return 0;
40404037

40414038
out_put_ns_head:

drivers/nvme/host/multipath.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1311,7 +1311,7 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head)
13111311
*/
13121312
if (!try_module_get(THIS_MODULE))
13131313
goto out;
1314-
queue_delayed_work(nvme_wq, &head->remove_work,
1314+
mod_delayed_work(nvme_wq, &head->remove_work,
13151315
head->delayed_removal_secs * HZ);
13161316
} else {
13171317
list_del_init(&head->entry);

drivers/nvme/host/nvme.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,6 @@ struct nvme_ctrl {
410410

411411
enum nvme_ctrl_type cntrltype;
412412
enum nvme_dctype dctype;
413-
u16 awupf; /* 0's based value. */
414413
};
415414

416415
static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl)
@@ -443,11 +442,11 @@ struct nvme_subsystem {
443442
u8 cmic;
444443
enum nvme_subsys_type subtype;
445444
u16 vendor_id;
445+
u16 awupf; /* 0's based value. */
446446
struct ida ns_ida;
447447
#ifdef CONFIG_NVME_MULTIPATH
448448
enum nvme_iopolicy iopolicy;
449449
#endif
450-
u32 atomic_bs;
451450
};
452451

453452
/*

0 commit comments

Comments
 (0)