nvme: refactor the atomic write unit detection

Move all the code out of nvme_update_disk_info into the helper, and
rename the helper to have a somewhat less clumsy name.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
Reviewed-by: John Garry <john.g.garry@oracle.com>
This commit is contained in:
Christoph Hellwig 2025-06-11 07:09:21 +02:00
parent dd2c185489
commit b2e607feca

View file

@ -2015,21 +2015,51 @@ static void nvme_configure_metadata(struct nvme_ctrl *ctrl,
}
static void nvme_update_atomic_write_disk_info(struct nvme_ns *ns,
struct nvme_id_ns *id, struct queue_limits *lim,
u32 bs, u32 atomic_bs)
static u32 nvme_configure_atomic_write(struct nvme_ns *ns,
struct nvme_id_ns *id, struct queue_limits *lim, u32 bs)
{
unsigned int boundary = 0;
u32 atomic_bs, boundary = 0;
if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf) {
if (le16_to_cpu(id->nabspf))
/*
* We do not support an offset for the atomic boundaries.
*/
if (id->nabo)
return bs;
if ((id->nsfeat & NVME_NS_FEAT_ATOMICS) && id->nawupf) {
/*
* Use the per-namespace atomic write unit when available.
*/
atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs;
if (id->nabspf)
boundary = (le16_to_cpu(id->nabspf) + 1) * bs;
} else {
/*
* Use the controller wide atomic write unit. This sucks
* because the limit is defined in terms of logical blocks while
* namespaces can have different formats, and because there is
* no clear language in the specification prohibiting different
* values for different controllers in the subsystem.
*/
atomic_bs = (1 + ns->ctrl->awupf) * bs;
}
if (!ns->ctrl->subsys->atomic_bs) {
ns->ctrl->subsys->atomic_bs = atomic_bs;
} else if (ns->ctrl->subsys->atomic_bs != atomic_bs) {
dev_err_ratelimited(ns->ctrl->device,
"%s: Inconsistent Atomic Write Size, Namespace will not be added: Subsystem=%d bytes, Controller/Namespace=%d bytes\n",
ns->disk ? ns->disk->disk_name : "?",
ns->ctrl->subsys->atomic_bs,
atomic_bs);
}
lim->atomic_write_hw_max = atomic_bs;
lim->atomic_write_hw_boundary = boundary;
lim->atomic_write_hw_unit_min = bs;
lim->atomic_write_hw_unit_max = rounddown_pow_of_two(atomic_bs);
lim->features |= BLK_FEAT_ATOMIC_WRITES;
return atomic_bs;
}
static u32 nvme_max_drv_segments(struct nvme_ctrl *ctrl)
@ -2067,34 +2097,8 @@ static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id,
valid = false;
}
atomic_bs = phys_bs = bs;
if (id->nabo == 0) {
/*
* Bit 1 indicates whether NAWUPF is defined for this namespace
* and whether it should be used instead of AWUPF. If NAWUPF ==
* 0 then AWUPF must be used instead.
*/
if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf)
atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs;
else
atomic_bs = (1 + ns->ctrl->awupf) * bs;
/*
* Set subsystem atomic bs.
*/
if (ns->ctrl->subsys->atomic_bs) {
if (atomic_bs != ns->ctrl->subsys->atomic_bs) {
dev_err_ratelimited(ns->ctrl->device,
"%s: Inconsistent Atomic Write Size, Namespace will not be added: Subsystem=%d bytes, Controller/Namespace=%d bytes\n",
ns->disk ? ns->disk->disk_name : "?",
ns->ctrl->subsys->atomic_bs,
atomic_bs);
}
} else
ns->ctrl->subsys->atomic_bs = atomic_bs;
nvme_update_atomic_write_disk_info(ns, id, lim, bs, atomic_bs);
}
phys_bs = bs;
atomic_bs = nvme_configure_atomic_write(ns, id, lim, bs);
if (id->nsfeat & NVME_NS_FEAT_IO_OPT) {
/* NPWG = Namespace Preferred Write Granularity */