Issue with AWUPF when using multiple controllers in a subsystem
alan.adamson at oracle.com
alan.adamson at oracle.com
Fri Apr 4 15:42:50 PDT 2025
While testing atomic write parameters with multiple controllers within a
subsystem, I found an issue:
QEMU-NVME Configuartion
=================
-device nvme-subsys,id=subsys0 \
-device
nvme,serial=deadbeef,id=nvme0,subsys=subsys0,atomic.dn=off,atomic.awun=31,atomic.awupf=15
\
-device
nvme,serial=deadbeef,id=nvme1,subsys=subsys0,atomic.dn=off,atomic.awun=127,atomic.awupf=63
\
-drive id=ns1,file=/dev/nullb3,if=none \
-drive id=ns2,file=/dev/nullb2,if=none \
-device nvme-ns,drive=ns1,bus=nvme0,nsid=1,shared=false \
-device nvme-ns,drive=ns2,bus=nvme1,nsid=2,shared=false \
[root at localhost ~]# nvme id-ctrl /dev/nvme1n2 | grep awupf
awupf : 63
[root at localhost ~]# cat /sys/block/nvme1n2/queue/atomic_write_max_bytes
32768
[root at localhost ~]# nvme id-ctrl /dev/nvme1n1 | grep awupf
awupf : 15
[root at localhost ~]# cat /sys/block/nvme1n1/queue/atomic_write_max_bytes
32768
[root at localhost ~]#
When dumping the awupf value with nvme-cli, the values match what was
setup in qemu, but when each devices atomic queue limits was displayed,
it didn't match its awupf. Currently the awupf is saved in the
nvme_subsystem, but the awupf is specific to the controller, not the
subsystem. Two controllers in a subsystem can have different atomic
parameters.
The commit 81adb8633491 ("nvme: set physical block size and optimal I/O
size") added subsys->awupf.
I think the awupf belongs in the nvme_ctrl structure.
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index a8259e3334ff..2483651817fb 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -2059,7 +2059,7 @@ static bool nvme_update_disk_info(struct nvme_ns
*ns, struct nvme_id_ns *id,
if (id->nsfeat & NVME_NS_FEAT_ATOMICS && id->nawupf)
atomic_bs = (1 + le16_to_cpu(id->nawupf)) * bs;
else
- atomic_bs = (1 + ns->ctrl->subsys->awupf) * bs;
+ atomic_bs = (1 + ns->ctrl->awupf) * bs;
nvme_update_atomic_write_disk_info(ns, id, lim, bs,
atomic_bs);
}
@@ -3032,7 +3032,6 @@ static int nvme_init_subsystem(struct nvme_ctrl
*ctrl, struct nvme_id_ctrl *id)
kfree(subsys);
return -EINVAL;
}
- subsys->awupf = le16_to_cpu(id->awupf);
nvme_mpath_default_iopolicy(subsys);
subsys->dev.class = &nvme_subsys_class;
@@ -3443,6 +3442,7 @@ static int nvme_init_identify(struct nvme_ctrl *ctrl)
else if (!ctrl->apst_enabled && prev_apst_enabled)
dev_pm_qos_hide_latency_tolerance(ctrl->device);
+ ctrl->awupf = le16_to_cpu(id->awupf);
out_free:
kfree(id);
return ret;
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 7be92d07430e..fddcd2de218c 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -410,6 +410,7 @@ struct nvme_ctrl {
enum nvme_ctrl_type cntrltype;
enum nvme_dctype dctype;
+ u16 awupf; /* 0's based awupf value. */
};
static inline enum nvme_ctrl_state nvme_ctrl_state(struct nvme_ctrl *ctrl)
@@ -442,7 +443,6 @@ struct nvme_subsystem {
u8 cmic;
enum nvme_subsys_type subtype;
u16 vendor_id;
- u16 awupf; /* 0's based awupf value. */
struct ida ns_ida;
#ifdef CONFIG_NVME_MULTIPATH
enum nvme_iopolicy iopolicy;
When I apply this fix, the problem is resolved.
[root at localhost ~]# nvme id-ctrl /dev/nvme1n2 | grep awupf
awupf : 63
[root at localhost ~]# cat /sys/block/nvme1n2/queue/atomic_write_max_bytes
32768
[root at localhost ~]# nvme id-ctrl /dev/nvme1n1 | grep awupf
awupf : 15
[root at localhost ~]# cat /sys/block/nvme1n1/queue/atomic_write_max_bytes
8192
[root at localhost ~]#
Does this fix make sense?
Alan Adamson
More information about the Linux-nvme
mailing list