[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