* [PATCH v1 0/1] nvmet: implement discovery Get Log indexing and LID 0x00
@ 2026-06-18 3:03 Xixin Liu
2026-06-18 3:03 ` [PATCH v1 1/1] " Xixin Liu
0 siblings, 1 reply; 2+ messages in thread
From: Xixin Liu @ 2026-06-18 3:03 UTC (permalink / raw)
To: linux-nvme
Cc: hch, sagi, kch, kbusch, axboe, linux-nvme, linux-kernel, liuxixin
Hi,
NVM Express Base Specification 2.3 defines Get Log CDW14 Offset Type (OT):
when OT is set, LPO is a structure index into the log page rather than a
byte offset. For the Discovery log (LID 0x70), the controller advertises
Index Offset Supported (IOS) in Supported Log Pages (LID 0x00) and must
reject OT=1 when IOS is clear for the requested LID.
nvmet already handles OT=0 byte offsets on the Discovery controller
(including partial reads and zero-fill within the log page). It does not
implement LID 0x00 there, does not set IOS for LID 0x70, and treats LPO
as bytes even when OT=1.
This patch:
- Answers Get Log LID 0x00 on the Discovery controller.
- Sets LSUPP|IOS for the Supported and Discovery log page IDs.
- Adds NVME_LIDS_IOS and NVME_LOG_CDW14_OT (bit 23, matching libnvme).
- Translates OT=1 LPO from index to byte offset (index 0 = header).
- Rejects OT=1 when IOS is not set for the requested LID.
- Guards u64 overflow when converting large indices so a wrapped offset
cannot bypass the existing offset > alloc_len check.
OT=0 behaviour and nvme discover (libnvme default) are unchanged.
Tested on linux-next (7.1.0-rc7-next-20260611) with nvmet-tcp and
null_blk:
- nvme get-log LID 0x00 / 0x70 with OT=0 and OT=1 (index and byte paths)
- blktests nvme/003 (tcp), nvme/002/016/017/030 (loop): passed
- make -C drivers/nvme/target
Thanks,
Xixin Liu
---
Xixin Liu (1):
nvmet: implement discovery Get Log indexing and LID 0x00
drivers/nvme/target/discovery.c | 101 +++++++++++++++++++++++++++++++++++++++--
include/linux/nvme.h | 18 +++++++-
2 files changed, 113 insertions(+), 6 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 2+ messages in thread
* [PATCH v1 1/1] nvmet: implement discovery Get Log indexing and LID 0x00
2026-06-18 3:03 [PATCH v1 0/1] nvmet: implement discovery Get Log indexing and LID 0x00 Xixin Liu
@ 2026-06-18 3:03 ` Xixin Liu
0 siblings, 0 replies; 2+ messages in thread
From: Xixin Liu @ 2026-06-18 3:03 UTC (permalink / raw)
To: linux-nvme
Cc: hch, sagi, kch, kbusch, axboe, linux-nvme, linux-kernel, liuxixin
Per NVM Express Base Specification 2.3, Discovery controllers must
expose Supported Log Pages (LID 0x00) and, for the Discovery log (LID
0x70), advertise Index Offset Supported so hosts may use Get Log CDW14
Offset Type to supply a structure index in LPO instead of a byte offset.
Implement LID 0x00 for the Discovery controller with LSUPP set for the
Supported log itself and LSUPP|IOS for the Discovery log. When OT is
set, translate LPO from index to byte offset (index 0 maps to the
header at byte 0; index N>=1 maps to entry N-1). Reject OT=1 with
Invalid Field when IOS is clear for the requested LID.
Keep the existing OT=0 path: dword-aligned byte offsets, partial copy,
and zero-fill within the log page. Reject indices whose byte offset
would overflow u64 before the existing offset > alloc_len validation;
otherwise a wrapped offset could fall inside the log and return wrong
data.
Signed-off-by: Xixin Liu <liuxixin@kylinos.cn>
---
drivers/nvme/target/discovery.c | 101 +++++++++++++++++++++++++++++++++++++--
include/linux/nvme.h | 18 ++++++-
2 files changed, 113 insertions(+), 6 deletions(-)
diff --git a/drivers/nvme/target/discovery.c b/drivers/nvme/target/discovery.c
index 114869d16a1f..430a197243da 100644
--- a/drivers/nvme/target/discovery.c
+++ b/drivers/nvme/target/discovery.c
@@ -158,12 +158,96 @@ static size_t discovery_log_entries(struct nvmet_req *req)
return entries;
}
+/*
+ * LID Supported and Effects for log pages served by this controller.
+ * Must match Supported Log Pages (LID 0x00) lids[] contents.
+ */
+static u32 nvmet_disc_lid_support_effects(u8 lid)
+{
+ switch (lid) {
+ case NVME_LOG_SUPPORTED:
+ return NVME_LIDS_LSUPP;
+ case NVME_LOG_DISC:
+ return NVME_LIDS_LSUPP | NVME_LIDS_IOS;
+ default:
+ return 0;
+ }
+}
+
+static bool nvmet_disc_lid_ios(u8 lid)
+{
+ return nvmet_disc_lid_support_effects(lid) & NVME_LIDS_IOS;
+}
+
+static u16 nvmet_execute_disc_get_supported_log_pages(struct nvmet_req *req)
+{
+ struct nvme_supported_log *logs;
+ u16 status;
+
+ logs = kzalloc_obj(*logs);
+ if (!logs)
+ return NVME_SC_INTERNAL;
+
+ logs->lids[NVME_LOG_SUPPORTED] =
+ cpu_to_le32(nvmet_disc_lid_support_effects(NVME_LOG_SUPPORTED));
+ logs->lids[NVME_LOG_DISC] =
+ cpu_to_le32(nvmet_disc_lid_support_effects(NVME_LOG_DISC));
+
+ status = nvmet_copy_to_sgl(req, 0, logs, sizeof(*logs));
+ kfree(logs);
+ return status;
+}
+
+static bool nvmet_disc_get_log_ot(struct nvme_command *cmd)
+{
+ return le32_to_cpu(cmd->common.cdw14) & NVME_LOG_CDW14_OT;
+}
+
+static u64 nvmet_disc_get_log_offset(struct nvme_command *cmd, u8 lid,
+ u32 entry_size, u16 *error_loc)
+{
+ u64 lpo = nvmet_get_log_page_offset(cmd);
+
+ if (nvmet_disc_get_log_ot(cmd)) {
+ u64 byte_off;
+
+ if (!nvmet_disc_lid_ios(lid)) {
+ *error_loc = offsetof(struct nvme_common_command, cdw14);
+ return U64_MAX;
+ }
+
+ if (lpo == 0)
+ return 0;
+ /*
+ * byte_off = sizeof(hdr) + (index - 1) * entry_size.
+ * Reject if that would overflow u64: a wrapped offset could
+ * otherwise pass offset > alloc_len below.
+ */
+ if (lpo - 1 > (U64_MAX - sizeof(struct nvmf_disc_rsp_page_hdr)) /
+ entry_size) {
+ *error_loc = offsetof(struct nvme_get_log_page_command,
+ lpo);
+ return U64_MAX;
+ }
+ byte_off = sizeof(struct nvmf_disc_rsp_page_hdr) +
+ (lpo - 1) * entry_size;
+ return byte_off;
+ }
+
+ if (lpo & 0x3) {
+ *error_loc = offsetof(struct nvme_get_log_page_command, lpo);
+ return U64_MAX;
+ }
+
+ return lpo;
+}
+
static void nvmet_execute_disc_get_log_page(struct nvmet_req *req)
{
const int entry_size = sizeof(struct nvmf_disc_rsp_page_entry);
struct nvmet_ctrl *ctrl = req->sq->ctrl;
struct nvmf_disc_rsp_page_hdr *hdr;
- u64 offset = nvmet_get_log_page_offset(req->cmd);
+ u64 offset;
size_t data_len = nvmet_get_log_page_len(req->cmd);
size_t alloc_len;
size_t copy_len;
@@ -177,6 +261,14 @@ static void nvmet_execute_disc_get_log_page(struct nvmet_req *req)
if (!nvmet_check_transfer_len(req, data_len))
return;
+ if (req->cmd->get_log_page.lid == NVME_LOG_SUPPORTED) {
+ u16 status;
+
+ status = nvmet_execute_disc_get_supported_log_pages(req);
+ nvmet_req_complete(req, status);
+ return;
+ }
+
if (req->cmd->get_log_page.lid != NVME_LOG_DISC) {
req->error_loc =
offsetof(struct nvme_get_log_page_command, lid);
@@ -184,10 +276,9 @@ static void nvmet_execute_disc_get_log_page(struct nvmet_req *req)
goto out;
}
- /* Spec requires dword aligned offsets */
- if (offset & 0x3) {
- req->error_loc =
- offsetof(struct nvme_get_log_page_command, lpo);
+ offset = nvmet_disc_get_log_offset(req->cmd, NVME_LOG_DISC, entry_size,
+ &req->error_loc);
+ if (offset == U64_MAX) {
status = NVME_SC_INVALID_FIELD | NVME_STATUS_DNR;
goto out;
}
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 041f30931a90..269136cda485 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -1427,8 +1427,15 @@ struct nvme_supported_log {
__le32 lids[256];
};
+/*
+ * LID Supported and Effects (Supported Log Pages log, LID 0x00):
+ *
+ * @NVME_LIDS_LSUPP: LID Supported
+ * @NVME_LIDS_IOS: Index Offset Supported
+ */
enum {
- NVME_LIDS_LSUPP = 1 << 0,
+ NVME_LIDS_LSUPP = (1 << 0),
+ NVME_LIDS_IOS = (1 << 1),
};
struct nvme_supported_features_log {
@@ -1583,6 +1590,15 @@ struct nvme_get_log_page_command {
__u32 rsvd15;
};
+/*
+ * Get Log Page Command Dword 14:
+ *
+ * @NVME_LOG_CDW14_OT: Offset Type (0 = byte offset, 1 = structure index)
+ */
+enum {
+ NVME_LOG_CDW14_OT = (1 << 23),
+};
+
struct nvme_directive_cmd {
__u8 opcode;
__u8 flags;
--
2.43.0
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-06-18 3:12 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-18 3:03 [PATCH v1 0/1] nvmet: implement discovery Get Log indexing and LID 0x00 Xixin Liu
2026-06-18 3:03 ` [PATCH v1 1/1] " Xixin Liu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome