[PATCH 5/6] nvmet: Add support for configurable crdt (command retry delay) attributes
Sagi Grimberg
sagi at grimberg.me
Sun Aug 23 01:49:01 PDT 2026
Paired with host side error injection, allows us to exercise host retry delay
behavior.
Signed-off-by: Sagi Grimberg <sagi at grimberg.me>
---
drivers/nvme/target/admin-cmd.c | 4 +++
drivers/nvme/target/configfs.c | 62 +++++++++++++++++++++++++++++++++
drivers/nvme/target/nvmet.h | 1 +
3 files changed, 67 insertions(+)
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index 01b799e92ae6..c1a343e9a58a 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -786,6 +786,10 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
id->nwpc = 1 << 0; /* write protect and no write protect */
+ id->crdt1 = cpu_to_le16(subsys->crdt[0]);
+ id->crdt2 = cpu_to_le16(subsys->crdt[1]);
+ id->crdt3 = cpu_to_le16(subsys->crdt[2]);
+
status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id));
kfree(id);
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index 2b69ffcfc8df..7bd51f176da0 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -1470,6 +1470,65 @@ static ssize_t nvmet_subsys_attr_subsys_vendor_id_store(struct config_item *item
}
CONFIGFS_ATTR(nvmet_subsys_, attr_subsys_vendor_id);
+static ssize_t nvmet_subsys_attr_crdt_show(struct config_item *item,
+ char *page, unsigned int idx)
+{
+ return sysfs_emit(page, "%u\n", to_subsys(item)->crdt[idx]);
+}
+
+static ssize_t nvmet_subsys_attr_crdt_store(struct config_item *item,
+ const char *page, size_t count, unsigned int idx)
+{
+ u16 crdt;
+
+ if (kstrtou16(page, 0, &crdt))
+ return -EINVAL;
+
+ down_write(&nvmet_config_sem);
+ to_subsys(item)->crdt[idx] = crdt;
+ up_write(&nvmet_config_sem);
+ return count;
+}
+
+static ssize_t nvmet_subsys_attr_crdt1_show(struct config_item *item,
+ char *page)
+{
+ return nvmet_subsys_attr_crdt_show(item, page, 0);
+}
+
+static ssize_t nvmet_subsys_attr_crdt1_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ return nvmet_subsys_attr_crdt_store(item, page, count, 0);
+}
+CONFIGFS_ATTR(nvmet_subsys_, attr_crdt1);
+
+static ssize_t nvmet_subsys_attr_crdt2_show(struct config_item *item,
+ char *page)
+{
+ return nvmet_subsys_attr_crdt_show(item, page, 1);
+}
+
+static ssize_t nvmet_subsys_attr_crdt2_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ return nvmet_subsys_attr_crdt_store(item, page, count, 1);
+}
+CONFIGFS_ATTR(nvmet_subsys_, attr_crdt2);
+
+static ssize_t nvmet_subsys_attr_crdt3_show(struct config_item *item,
+ char *page)
+{
+ return nvmet_subsys_attr_crdt_show(item, page, 2);
+}
+
+static ssize_t nvmet_subsys_attr_crdt3_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ return nvmet_subsys_attr_crdt_store(item, page, count, 2);
+}
+CONFIGFS_ATTR(nvmet_subsys_, attr_crdt3);
+
static ssize_t nvmet_subsys_attr_model_show(struct config_item *item,
char *page)
{
@@ -1700,6 +1759,9 @@ static struct configfs_attribute *nvmet_subsys_attrs[] = {
&nvmet_subsys_attr_attr_cntlid_max,
&nvmet_subsys_attr_attr_vendor_id,
&nvmet_subsys_attr_attr_subsys_vendor_id,
+ &nvmet_subsys_attr_attr_crdt1,
+ &nvmet_subsys_attr_attr_crdt2,
+ &nvmet_subsys_attr_attr_crdt3,
&nvmet_subsys_attr_attr_model,
&nvmet_subsys_attr_attr_qid_max,
&nvmet_subsys_attr_attr_ieee_oui,
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index aaba745e3c21..2650c5e101f3 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -347,6 +347,7 @@ struct nvmet_subsys {
u16 vendor_id;
u16 subsys_vendor_id;
+ u16 crdt[3];
char *model_number;
u32 ieee_oui;
char *firmware_rev;
--
2.43.0
More information about the Linux-nvme
mailing list