From 46198fba6dff5a01e9c0119b5b7cc85e24a06ec6 Mon Sep 17 00:00:00 2001 From: "Kenneth D. Merry" Date: Fri, 6 Nov 2026 20:05:53 -0500 Subject: [PATCH] nvmecontrol: Factor out namespace Identify printing Move print_namespace() from identify.c to identify_ext.c and rename it to nvme_print_namespace(), to match nvme_print_controller(). This allows other consumers (notably camcontrol(8)) to print NVMe namespace Identify data. No functional changes intended. sbin/nvmecontrol/identify.c: Remove print_namespace(), and call nvme_print_namespace() instead. sbin/nvmecontrol/identify_ext.c: Add nvme_print_namespace(), moved here from identify.c. sbin/nvmecontrol/nvmecontrol.h: Remove the print_namespace() prototype. sbin/nvmecontrol/nvmecontrol_ext.h: Add the nvme_print_namespace() prototype. sbin/nvmecontrol/ns.c: Include nvmecontrol_ext.h, and rename print_namespace() calls to nvme_print_namespace(). Co-authored-by: Claude Fable 5 Reviewed by: imp MFC after: 1 week Sponsored by: Spectra Logic Differential Revision: https://reviews.freebsd.org/D59530 --- sbin/nvmecontrol/identify.c | 129 +---------------------------- sbin/nvmecontrol/identify_ext.c | 127 ++++++++++++++++++++++++++++ sbin/nvmecontrol/ns.c | 3 +- sbin/nvmecontrol/nvmecontrol.h | 1 - sbin/nvmecontrol/nvmecontrol_ext.h | 1 + 5 files changed, 131 insertions(+), 130 deletions(-) diff --git a/sbin/nvmecontrol/identify.c b/sbin/nvmecontrol/identify.c index be5a343806ff..0617caf8eae9 100644 --- a/sbin/nvmecontrol/identify.c +++ b/sbin/nvmecontrol/identify.c @@ -57,133 +57,6 @@ static struct options { .nsid = NONE, }; -void -print_namespace(struct nvme_namespace_data *nsdata) -{ - char cbuf[UINT128_DIG + 1]; - uint32_t i; - uint32_t lbaf, lbads, ms, rp; - uint8_t thin_prov, ptype; - uint8_t flbas_fmt, t; - - thin_prov = NVMEV(NVME_NS_DATA_NSFEAT_THIN_PROV, nsdata->nsfeat); - - flbas_fmt = nvme_ns_data_format_index(nsdata); - - printf("Size: %lld blocks\n", - (long long)nsdata->nsze); - printf("Capacity: %lld blocks\n", - (long long)nsdata->ncap); - printf("Utilization: %lld blocks\n", - (long long)nsdata->nuse); - printf("Thin Provisioning: %s\n", - thin_prov ? "Supported" : "Not Supported"); - printf("Number of LBA Formats: %d\n", nsdata->nlbaf+1); - printf("Current LBA Format: LBA Format #%02d", flbas_fmt); - if (NVMEV(NVME_NS_DATA_LBAF_MS, nsdata->lbaf[flbas_fmt]) != 0) - printf(" %s metadata\n", - NVMEV(NVME_NS_DATA_FLBAS_EXTENDED, nsdata->flbas) != 0 ? - "Extended" : "Separate"); - else - printf("\n"); - printf("Metadata Capabilities\n"); - printf(" Extended: %s\n", - NVMEV(NVME_NS_DATA_MC_EXTENDED, nsdata->mc) != 0 ? "Supported" : - "Not Supported"); - printf(" Separate: %s\n", - NVMEV(NVME_NS_DATA_MC_POINTER, nsdata->mc) != 0 ? "Supported" : - "Not Supported"); - printf("Data Protection Caps: %s%s%s%s%s%s\n", - (nsdata->dpc == 0) ? "Not Supported" : "", - NVMEV(NVME_NS_DATA_DPC_MD_END, nsdata->dpc) != 0 ? "Last Bytes, " : - "", - NVMEV(NVME_NS_DATA_DPC_MD_START, nsdata->dpc) != 0 ? - "First Bytes, " : "", - NVMEV(NVME_NS_DATA_DPC_PIT3, nsdata->dpc) != 0 ? "Type 3, " : "", - NVMEV(NVME_NS_DATA_DPC_PIT2, nsdata->dpc) != 0 ? "Type 2, " : "", - NVMEV(NVME_NS_DATA_DPC_PIT1, nsdata->dpc) != 0 ? "Type 1" : ""); - printf("Data Protection Settings: "); - ptype = NVMEV(NVME_NS_DATA_DPS_PIT, nsdata->dps); - if (ptype != 0) { - printf("Type %d, %s Bytes\n", ptype, - NVMEV(NVME_NS_DATA_DPS_MD_START, nsdata->dps) != 0 ? - "First" : "Last"); - } else { - printf("Not Enabled\n"); - } - printf("Multi-Path I/O Capabilities: %s%s\n", - (nsdata->nmic == 0) ? "Not Supported" : "", - NVMEV(NVME_NS_DATA_NMIC_MAY_BE_SHARED, nsdata->nmic) != 0 ? - "May be shared" : ""); - printf("Reservation Capabilities: %s%s%s%s%s%s%s%s%s\n", - (nsdata->rescap == 0) ? "Not Supported" : "", - NVMEV(NVME_NS_DATA_RESCAP_IEKEY13, nsdata->rescap) != 0 ? - "IEKEY13, " : "", - NVMEV(NVME_NS_DATA_RESCAP_EX_AC_AR, nsdata->rescap) != 0 ? - "EX_AC_AR, " : "", - NVMEV(NVME_NS_DATA_RESCAP_WR_EX_AR, nsdata->rescap) != 0 ? - "WR_EX_AR, " : "", - NVMEV(NVME_NS_DATA_RESCAP_EX_AC_RO, nsdata->rescap) != 0 ? - "EX_AC_RO, " : "", - NVMEV(NVME_NS_DATA_RESCAP_WR_EX_RO, nsdata->rescap) != 0 ? - "WR_EX_RO, " : "", - NVMEV(NVME_NS_DATA_RESCAP_EX_AC, nsdata->rescap) != 0 ? - "EX_AC, " : "", - NVMEV(NVME_NS_DATA_RESCAP_WR_EX, nsdata->rescap) != 0 ? - "WR_EX, " : "", - NVMEV(NVME_NS_DATA_RESCAP_PTPL, nsdata->rescap) != 0 ? "PTPL" : ""); - printf("Format Progress Indicator: "); - if (NVMEV(NVME_NS_DATA_FPI_SUPP, nsdata->fpi) != 0) { - printf("%u%% remains\n", - NVMEV(NVME_NS_DATA_FPI_PERC, nsdata->fpi)); - } else - printf("Not Supported\n"); - t = NVMEV(NVME_NS_DATA_DLFEAT_READ, nsdata->dlfeat); - printf("Deallocate Logical Block: Read %s%s%s\n", - (t == NVME_NS_DATA_DLFEAT_READ_NR) ? "Not Reported" : - (t == NVME_NS_DATA_DLFEAT_READ_00) ? "00h" : - (t == NVME_NS_DATA_DLFEAT_READ_FF) ? "FFh" : "Unknown", - NVMEV(NVME_NS_DATA_DLFEAT_DWZ, nsdata->dlfeat) != 0 ? - ", Write Zero" : "", - NVMEV(NVME_NS_DATA_DLFEAT_GCRC, nsdata->dlfeat) != 0 ? - ", Guard CRC" : ""); - printf("Optimal I/O Boundary: %u blocks\n", nsdata->noiob); - printf("NVM Capacity: %s bytes\n", - uint128_to_str(to128(nsdata->nvmcap), cbuf, sizeof(cbuf))); - if (NVMEV(NVME_NS_DATA_NSFEAT_NPVALID, nsdata->nsfeat) != 0) { - printf("Preferred Write Granularity: %u blocks\n", - nsdata->npwg + 1); - printf("Preferred Write Alignment: %u blocks\n", - nsdata->npwa + 1); - printf("Preferred Deallocate Granul: %u blocks\n", - nsdata->npdg + 1); - printf("Preferred Deallocate Align: %u blocks\n", - nsdata->npda + 1); - printf("Optimal Write Size: %u blocks\n", - nsdata->nows + 1); - } - printf("Globally Unique Identifier: "); - for (i = 0; i < sizeof(nsdata->nguid); i++) - printf("%02x", nsdata->nguid[i]); - printf("\n"); - printf("IEEE EUI64: "); - for (i = 0; i < sizeof(nsdata->eui64); i++) - printf("%02x", nsdata->eui64[i]); - printf("\n"); - for (i = 0; i <= nsdata->nlbaf; i++) { - lbaf = nsdata->lbaf[i]; - lbads = NVMEV(NVME_NS_DATA_LBAF_LBADS, lbaf); - if (lbads == 0) - continue; - ms = NVMEV(NVME_NS_DATA_LBAF_MS, lbaf); - rp = NVMEV(NVME_NS_DATA_LBAF_RP, lbaf); - printf("LBA Format #%02d: Data Size: %5d Metadata Size: %5d" - " Performance: %s\n", - i, 1 << lbads, ms, (rp == 0) ? "Best" : - (rp == 1) ? "Better" : (rp == 2) ? "Good" : "Degraded"); - } -} - static void identify_ctrlr(int fd) { @@ -228,7 +101,7 @@ identify_ns(int fd, uint32_t nsid) exit(0); } - print_namespace(&nsdata); + nvme_print_namespace(&nsdata); exit(0); } diff --git a/sbin/nvmecontrol/identify_ext.c b/sbin/nvmecontrol/identify_ext.c index 521151989115..dc7f55155449 100644 --- a/sbin/nvmecontrol/identify_ext.c +++ b/sbin/nvmecontrol/identify_ext.c @@ -311,3 +311,130 @@ nvme_print_controller(struct nvme_controller_data *cdata) (cdata->ofcs & 1) == 1 ? "" : "Not "); } } + +void +nvme_print_namespace(struct nvme_namespace_data *nsdata) +{ + char cbuf[UINT128_DIG + 1]; + uint32_t i; + uint32_t lbaf, lbads, ms, rp; + uint8_t thin_prov, ptype; + uint8_t flbas_fmt, t; + + thin_prov = NVMEV(NVME_NS_DATA_NSFEAT_THIN_PROV, nsdata->nsfeat); + + flbas_fmt = nvme_ns_data_format_index(nsdata); + + printf("Size: %lld blocks\n", + (long long)nsdata->nsze); + printf("Capacity: %lld blocks\n", + (long long)nsdata->ncap); + printf("Utilization: %lld blocks\n", + (long long)nsdata->nuse); + printf("Thin Provisioning: %s\n", + thin_prov ? "Supported" : "Not Supported"); + printf("Number of LBA Formats: %d\n", nsdata->nlbaf+1); + printf("Current LBA Format: LBA Format #%02d", flbas_fmt); + if (NVMEV(NVME_NS_DATA_LBAF_MS, nsdata->lbaf[flbas_fmt]) != 0) + printf(" %s metadata\n", + NVMEV(NVME_NS_DATA_FLBAS_EXTENDED, nsdata->flbas) != 0 ? + "Extended" : "Separate"); + else + printf("\n"); + printf("Metadata Capabilities\n"); + printf(" Extended: %s\n", + NVMEV(NVME_NS_DATA_MC_EXTENDED, nsdata->mc) != 0 ? "Supported" : + "Not Supported"); + printf(" Separate: %s\n", + NVMEV(NVME_NS_DATA_MC_POINTER, nsdata->mc) != 0 ? "Supported" : + "Not Supported"); + printf("Data Protection Caps: %s%s%s%s%s%s\n", + (nsdata->dpc == 0) ? "Not Supported" : "", + NVMEV(NVME_NS_DATA_DPC_MD_END, nsdata->dpc) != 0 ? "Last Bytes, " : + "", + NVMEV(NVME_NS_DATA_DPC_MD_START, nsdata->dpc) != 0 ? + "First Bytes, " : "", + NVMEV(NVME_NS_DATA_DPC_PIT3, nsdata->dpc) != 0 ? "Type 3, " : "", + NVMEV(NVME_NS_DATA_DPC_PIT2, nsdata->dpc) != 0 ? "Type 2, " : "", + NVMEV(NVME_NS_DATA_DPC_PIT1, nsdata->dpc) != 0 ? "Type 1" : ""); + printf("Data Protection Settings: "); + ptype = NVMEV(NVME_NS_DATA_DPS_PIT, nsdata->dps); + if (ptype != 0) { + printf("Type %d, %s Bytes\n", ptype, + NVMEV(NVME_NS_DATA_DPS_MD_START, nsdata->dps) != 0 ? + "First" : "Last"); + } else { + printf("Not Enabled\n"); + } + printf("Multi-Path I/O Capabilities: %s%s\n", + (nsdata->nmic == 0) ? "Not Supported" : "", + NVMEV(NVME_NS_DATA_NMIC_MAY_BE_SHARED, nsdata->nmic) != 0 ? + "May be shared" : ""); + printf("Reservation Capabilities: %s%s%s%s%s%s%s%s%s\n", + (nsdata->rescap == 0) ? "Not Supported" : "", + NVMEV(NVME_NS_DATA_RESCAP_IEKEY13, nsdata->rescap) != 0 ? + "IEKEY13, " : "", + NVMEV(NVME_NS_DATA_RESCAP_EX_AC_AR, nsdata->rescap) != 0 ? + "EX_AC_AR, " : "", + NVMEV(NVME_NS_DATA_RESCAP_WR_EX_AR, nsdata->rescap) != 0 ? + "WR_EX_AR, " : "", + NVMEV(NVME_NS_DATA_RESCAP_EX_AC_RO, nsdata->rescap) != 0 ? + "EX_AC_RO, " : "", + NVMEV(NVME_NS_DATA_RESCAP_WR_EX_RO, nsdata->rescap) != 0 ? + "WR_EX_RO, " : "", + NVMEV(NVME_NS_DATA_RESCAP_EX_AC, nsdata->rescap) != 0 ? + "EX_AC, " : "", + NVMEV(NVME_NS_DATA_RESCAP_WR_EX, nsdata->rescap) != 0 ? + "WR_EX, " : "", + NVMEV(NVME_NS_DATA_RESCAP_PTPL, nsdata->rescap) != 0 ? "PTPL" : ""); + printf("Format Progress Indicator: "); + if (NVMEV(NVME_NS_DATA_FPI_SUPP, nsdata->fpi) != 0) { + printf("%u%% remains\n", + NVMEV(NVME_NS_DATA_FPI_PERC, nsdata->fpi)); + } else + printf("Not Supported\n"); + t = NVMEV(NVME_NS_DATA_DLFEAT_READ, nsdata->dlfeat); + printf("Deallocate Logical Block: Read %s%s%s\n", + (t == NVME_NS_DATA_DLFEAT_READ_NR) ? "Not Reported" : + (t == NVME_NS_DATA_DLFEAT_READ_00) ? "00h" : + (t == NVME_NS_DATA_DLFEAT_READ_FF) ? "FFh" : "Unknown", + NVMEV(NVME_NS_DATA_DLFEAT_DWZ, nsdata->dlfeat) != 0 ? + ", Write Zero" : "", + NVMEV(NVME_NS_DATA_DLFEAT_GCRC, nsdata->dlfeat) != 0 ? + ", Guard CRC" : ""); + printf("Optimal I/O Boundary: %u blocks\n", nsdata->noiob); + printf("NVM Capacity: %s bytes\n", + uint128_to_str(to128(nsdata->nvmcap), cbuf, sizeof(cbuf))); + if (NVMEV(NVME_NS_DATA_NSFEAT_NPVALID, nsdata->nsfeat) != 0) { + printf("Preferred Write Granularity: %u blocks\n", + nsdata->npwg + 1); + printf("Preferred Write Alignment: %u blocks\n", + nsdata->npwa + 1); + printf("Preferred Deallocate Granul: %u blocks\n", + nsdata->npdg + 1); + printf("Preferred Deallocate Align: %u blocks\n", + nsdata->npda + 1); + printf("Optimal Write Size: %u blocks\n", + nsdata->nows + 1); + } + printf("Globally Unique Identifier: "); + for (i = 0; i < sizeof(nsdata->nguid); i++) + printf("%02x", nsdata->nguid[i]); + printf("\n"); + printf("IEEE EUI64: "); + for (i = 0; i < sizeof(nsdata->eui64); i++) + printf("%02x", nsdata->eui64[i]); + printf("\n"); + for (i = 0; i <= nsdata->nlbaf; i++) { + lbaf = nsdata->lbaf[i]; + lbads = NVMEV(NVME_NS_DATA_LBAF_LBADS, lbaf); + if (lbads == 0) + continue; + ms = NVMEV(NVME_NS_DATA_LBAF_MS, lbaf); + rp = NVMEV(NVME_NS_DATA_LBAF_RP, lbaf); + printf("LBA Format #%02d: Data Size: %5d Metadata Size: %5d" + " Performance: %s\n", + i, 1 << lbads, ms, (rp == 0) ? "Best" : + (rp == 1) ? "Better" : (rp == 2) ? "Good" : "Degraded"); + } +} diff --git a/sbin/nvmecontrol/ns.c b/sbin/nvmecontrol/ns.c index c538338eb6c3..34d2fb03dfcf 100644 --- a/sbin/nvmecontrol/ns.c +++ b/sbin/nvmecontrol/ns.c @@ -40,6 +40,7 @@ #include #include "nvmecontrol.h" +#include "nvmecontrol_ext.h" /* Tables for command line parsing */ @@ -963,7 +964,7 @@ nsidentify(const struct cmd *f, int argc, char *argv[]) exit(0); } - print_namespace(&nsdata); + nvme_print_namespace(&nsdata); exit(0); } diff --git a/sbin/nvmecontrol/nvmecontrol.h b/sbin/nvmecontrol/nvmecontrol.h index 968e9c20160e..a55b4ef49762 100644 --- a/sbin/nvmecontrol/nvmecontrol.h +++ b/sbin/nvmecontrol/nvmecontrol.h @@ -83,7 +83,6 @@ int read_controller_data(int fd, struct nvme_controller_data *cdata); int read_namespace_data(int fd, uint32_t nsid, struct nvme_namespace_data *nsdata); int read_active_namespaces(int fd, uint32_t nsid, struct nvme_ns_list *nslist); void print_hex(void *data, uint32_t length); -void print_namespace(struct nvme_namespace_data *nsdata); void read_logpage(int fd, uint8_t log_page, uint32_t nsid, uint8_t lsp, uint16_t lsi, uint8_t rae, uint64_t lpo, uint8_t csi, uint8_t ot, uint16_t uuid_index, void *payload, uint32_t payload_size); diff --git a/sbin/nvmecontrol/nvmecontrol_ext.h b/sbin/nvmecontrol/nvmecontrol_ext.h index 97c3095e6d20..61432634bace 100644 --- a/sbin/nvmecontrol/nvmecontrol_ext.h +++ b/sbin/nvmecontrol/nvmecontrol_ext.h @@ -26,3 +26,4 @@ */ void nvme_print_controller(struct nvme_controller_data *cdata); +void nvme_print_namespace(struct nvme_namespace_data *nsdata);