Skip to content

Commit

Permalink
16427 want libnvme support for supported command and log page logs
Browse files Browse the repository at this point in the history
16428 nvmeadm list-logs is not properly filtering unimpl logs
Reviewed by: Andy Fiddaman <illumos@fiddaman.net>
Reviewed by: C Fraire <cfraire@me.com>
Reviewed by: Dan McDonald <danmcd@mnx.io>
Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
Approved by: Gordon Ross <gordon.w.ross@gmail.com>
  • Loading branch information
rmustacc committed Apr 7, 2024
1 parent 627ade2 commit 046911e
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 5 deletions.
4 changes: 4 additions & 0 deletions usr/src/cmd/nvmeadm/nvmeadm.c
Expand Up @@ -1689,6 +1689,10 @@ usage_list_logs(const char *c_name)
static boolean_t
do_list_logs_match(const nvme_log_disc_t *disc, nvmeadm_list_logs_t *nll)
{
if (!nll->nll_unimpl && !nvme_log_disc_impl(disc)) {
return (B_FALSE);
}

if (nll->nll_nfilts <= 0) {
return (B_TRUE);
}
Expand Down
2 changes: 1 addition & 1 deletion usr/src/cmd/nvmeadm/nvmeadm_ofmt.c
Expand Up @@ -322,7 +322,7 @@ nvmeadm_list_logs_ofmt_cb(ofmt_arg_t *ofmt_arg, char *buf, uint_t buflen)
ret = snprintf(buf, buflen, "%" PRIu64, alloc);
break;
case NVME_LIST_LOGS_IMPL:
ret = strlcpy(buf, nvme_log_disc_impl(disc)? "yes" : "no",
ret = strlcpy(buf, nvme_log_disc_impl(disc) ? "yes" : "no",
buflen);
break;
case NVME_LIST_LOGS_SOURCES:
Expand Down
31 changes: 30 additions & 1 deletion usr/src/common/nvme/nvme_log.c
Expand Up @@ -228,12 +228,30 @@ nvme_lpd_changens_sup(const nvme_valid_ctrl_data_t *data,
data->vcd_id->id_oaes.oaes_nsan != 0);
}

static bool
nvme_lpd_cmdeff_sup(const nvme_valid_ctrl_data_t *data,
const nvme_log_page_info_t *lpi)
{
return (nvme_field_atleast(data, &nvme_vers_1v2) &&
data->vcd_id->id_lpa.lp_cmdeff != 0);
}

/*
* The short names here correspond to the well defined names in nvmeadm(8) and
* libnvme(3LIB) that users expect to be able to use. Please do not change them
* without accounting for aliases and backwards compatibility.
*/
const nvme_log_page_info_t nvme_std_log_pages[] = { {
.nlpi_short = "suplog",
.nlpi_human = "Supported Log Pages",
.nlpi_lid = NVME_LOGPAGE_SUP,
.nlpi_csi = NVME_CSI_NVM,
.nlpi_vers = &nvme_vers_2v0,
.nlpi_kind = NVME_LOG_ID_MANDATORY,
.nlpi_source = NVME_LOG_DISC_S_SPEC,
.nlpi_scope = NVME_LOG_SCOPE_CTRL,
.nlpi_len = sizeof (nvme_suplog_log_t)
}, {
.nlpi_short = "error",
.nlpi_human = "Error information",
.nlpi_lid = NVME_LOGPAGE_ERROR,
Expand Down Expand Up @@ -278,7 +296,18 @@ const nvme_log_page_info_t nvme_std_log_pages[] = { {
.nlpi_disc = NVME_LOG_DISC_F_NEED_RAE,
.nlpi_scope = NVME_LOG_SCOPE_CTRL,
.nlpi_len = sizeof (nvme_nschange_list_t)
} };
}, {
.nlpi_short = "cmdeff",
.nlpi_human = "commands supported and effects",
.nlpi_lid = NVME_LOGPAGE_CMDSUP,
.nlpi_csi = NVME_CSI_NVM,
.nlpi_vers = &nvme_vers_1v2,
.nlpi_sup_func = nvme_lpd_cmdeff_sup,
.nlpi_kind = NVME_LOG_ID_OPTIONAL,
.nlpi_source = NVME_LOG_DISC_S_ID_CTRL,
.nlpi_scope = NVME_LOG_SCOPE_CTRL,
.nlpi_len = sizeof (nvme_cmdeff_log_t)
} };

size_t nvme_std_log_npages = ARRAY_SIZE(nvme_std_log_pages);

Expand Down
8 changes: 8 additions & 0 deletions usr/src/man/man8/nvmeadm.8
Expand Up @@ -613,6 +613,10 @@ of the log will be written to
Most log pages are only available on a per-controller basis.
Known log pages are:
.Bl -tag -width "firmware"
.It suplog
Supported Log Pages.
Lists information about log pages that the device supports.
Available starting in NVMe 2.0 devices.
.It error
Error Information
.It health
Expand All @@ -622,6 +626,10 @@ A controller may support this log page on a per-namespace basis.
Firmware Slot Information
.It changens
Changed Namespaces.
.It cmdeff
Commands Supported and Effects.
An optional log page beginning in NVMe 1.2 that indicates what commands
the controller itself actually supports.
.El
.Pp
The following vendor-specific log pages are supported.
Expand Down
6 changes: 4 additions & 2 deletions usr/src/test/nvme-tests/tests/unit/controllers.c
Expand Up @@ -129,7 +129,8 @@ static const nvme_identify_ctrl_t nvme_ctrl_fancy = {
},
.id_lpa = {
.lp_extsup = 1,
.lp_smart = 1
.lp_smart = 1,
.lp_cmdeff = 1,
},
.id_oaes = {
.oaes_nsan = 1
Expand Down Expand Up @@ -213,7 +214,8 @@ static const nvme_identify_ctrl_t nvme_ctrl_nons = {
},
.id_lpa = {
.lp_extsup = 1,
.lp_smart = 1
.lp_smart = 1,
.lp_cmdeff = 1
},
.id_oaes = {
.oaes_nsan = 1
Expand Down
60 changes: 59 additions & 1 deletion usr/src/test/nvme-tests/tests/unit/logs.c
Expand Up @@ -599,10 +599,25 @@ static const log_scope_test_t log_scope_tests[] = { {
.lst_data = &nvme_ctrl_ns_2v0,
.lst_exp_scope = NVME_LOG_SCOPE_NVM
}, {
.lst_desc = "changed namespaces log (2.0)",
.lst_desc = "changed namespace log (2.0)",
.lst_short = "changens",
.lst_data = &nvme_ctrl_ns_2v0,
.lst_exp_scope = NVME_LOG_SCOPE_CTRL
}, {
.lst_desc = "supported logs log (2.0)",
.lst_short = "suplog",
.lst_data = &nvme_ctrl_ns_2v0,
.lst_exp_scope = NVME_LOG_SCOPE_CTRL
}, {
.lst_desc = "commands supported and effects log (1.2)",
.lst_short = "cmdeff",
.lst_data = &nvme_ctrl_ns_1v2,
.lst_exp_scope = NVME_LOG_SCOPE_CTRL
}, {
.lst_desc = "commands supported and effects log (2.0)",
.lst_short = "cmdeff",
.lst_data = &nvme_ctrl_ns_2v0,
.lst_exp_scope = NVME_LOG_SCOPE_CTRL
} };

typedef struct log_size_test {
Expand Down Expand Up @@ -661,6 +676,24 @@ static const log_size_test_t log_size_tests[] = { {
.lt_data = &nvme_ctrl_ns_1v4,
.lt_size = sizeof (nvme_nschange_list_t),
.lt_var = false
}, {
.lt_desc = "commands supported and effects log (1.2)",
.lt_short = "cmdeff",
.lt_data = &nvme_ctrl_ns_1v2,
.lt_size = sizeof (nvme_cmdeff_log_t),
.lt_var = false
}, {
.lt_desc = "commands supported and effects log (1.4)",
.lt_short = "cmdeff",
.lt_data = &nvme_ctrl_ns_1v4,
.lt_size = sizeof (nvme_cmdeff_log_t),
.lt_var = false
}, {
.lt_desc = "supported logs log (2.0)",
.lt_short = "suplog",
.lt_data = &nvme_ctrl_ns_2v0,
.lt_size = sizeof (nvme_suplog_log_t),
.lt_var = false
} };

typedef struct log_impl_test {
Expand All @@ -671,6 +704,16 @@ typedef struct log_impl_test {
} log_impl_test_t;

static const log_impl_test_t log_impl_tests[] = { {
.lit_desc = "supported logs (1.0)",
.lit_short = "suplog",
.lit_data = &nvme_ctrl_base_1v0,
.lit_impl = false
}, {
.lit_desc = "supported logs (2.0)",
.lit_short = "suplog",
.lit_data = &nvme_ctrl_base_2v0,
.lit_impl = true
}, {
.lit_desc = "error (1.0)",
.lit_short = "error",
.lit_data = &nvme_ctrl_base_1v0,
Expand Down Expand Up @@ -715,6 +758,21 @@ static const log_impl_test_t log_impl_tests[] = { {
.lit_short = "changens",
.lit_data = &nvme_ctrl_base_1v2,
.lit_impl = false
}, {
.lit_desc = "commands supported and effects (1.0)",
.lit_short = "cmdeff",
.lit_data = &nvme_ctrl_base_1v0,
.lit_impl = false
}, {
.lit_desc = "commands supported and effects (1.4 LPA)",
.lit_short = "cmdeff",
.lit_data = &nvme_ctrl_ns_1v4,
.lit_impl = true
}, {
.lit_desc = "commands supported and effects (2.0 No LPA)",
.lit_short = "cmdeff",
.lit_data = &nvme_ctrl_base_2v0,
.lit_impl = false
} };

static const nvme_log_page_info_t *
Expand Down
80 changes: 80 additions & 0 deletions usr/src/uts/common/sys/nvme.h
Expand Up @@ -22,6 +22,7 @@

#include <sys/types.h>
#include <sys/debug.h>
#include <sys/stddef.h>

#ifdef _KERNEL
#include <sys/types32.h>
Expand Down Expand Up @@ -1289,6 +1290,42 @@ typedef struct {
#define NVME_LOGPAGE_VEND_MIN 0xc0
#define NVME_LOGPAGE_VEND_MAX 0xff

/*
* Supported Log Pages (2.0). There is one entry of an nvme_logsup_t that then
* exists on a per-log basis.
*/

/*
* The NVMe Log Identifier specific parameter field. Currently there is only one
* defined field for the persistent event log (pel).
*/
typedef union {
uint16_t nsl_lidsp; /* Raw Value */
struct { /* Persistent Event Log */
uint16_t nsl_ec512:1;
uint16_t nsl_pel_rsvd0p1:15;
} nsl_pel;
} nvme_suplog_lidsp_t;

typedef struct {
uint16_t ns_lsupp:1;
uint16_t ns_ios:1;
uint16_t ns_rsvd0p2:14;
nvme_suplog_lidsp_t ns_lidsp;
} nvme_suplog_t;

CTASSERT(sizeof (nvme_suplog_lidsp_t) == 2);
CTASSERT(sizeof (nvme_suplog_t) == 4);

typedef struct {
nvme_suplog_t nl_logs[256];
} nvme_suplog_log_t;

CTASSERT(sizeof (nvme_suplog_log_t) == 1024);

/*
* SMART / Health information
*/
typedef struct {
uint64_t el_count; /* Error Count */
uint16_t el_sqid; /* Submission Queue ID */
Expand Down Expand Up @@ -1374,6 +1411,49 @@ typedef struct {
uint32_t nscl_ns[NVME_NSCHANGE_LIST_SIZE];
} nvme_nschange_list_t;

/*
* Commands Supported and Effects log page and information structure. This was
* an optional log page added in NVMe 1.2.
*/
typedef struct {
uint8_t cmd_csupp:1; /* Command supported */
uint8_t cmd_lbcc:1; /* Logical block content change */
uint8_t cmd_ncc:1; /* Namespace capability change */
uint8_t cmd_nic:1; /* Namespace inventory change */
uint8_t cmd_ccc:1; /* Controller capability change */
uint8_t cmd_rsvd0p5:3;
uint8_t cmd_rsvd1;
uint16_t cmd_cse:3; /* Command submission and execution */
uint16_t cmd_uuid:1; /* UUID select supported, 1.4 */
uint16_t cmd_csp:12; /* Command Scope, 2.0 */
} nvme_cmdeff_t;

CTASSERT(sizeof (nvme_cmdeff_t) == 4);

typedef enum {
NVME_CMDEFF_CSP_NS = 1 << 0,
NVME_CMDEFF_CSP_CTRL = 1 << 1,
NVME_CMDEFF_CSP_SET = 1 << 2,
NVME_CMDEFF_CSP_ENDURANCE = 1 << 3,
NVME_CMDEFF_CSP_DOMAIN = 1 << 4,
NVME_CMDEFF_CSP_NVM = 1 << 5
} nvme_cmdeff_csp_t;

typedef enum {
NVME_CMDEFF_CSE_NONE = 0,
NVME_CMDEFF_CSE_NS,
NVME_CMDEFF_CSE_CTRL
} nvme_cmdeff_cse_t;

typedef struct {
nvme_cmdeff_t cme_admin[256];
nvme_cmdeff_t cme_io[256];
uint8_t cme_rsvd2048[2048];
} nvme_cmdeff_log_t;

CTASSERT(sizeof (nvme_cmdeff_log_t) == 4096);
CTASSERT(offsetof(nvme_cmdeff_log_t, cme_rsvd2048) == 2048);

/*
* NVMe Format NVM
*/
Expand Down

0 comments on commit 046911e

Please sign in to comment.