#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <sys/sysmacros.h>
#include "libnvme_impl.h"
bool
nvme_info_error(nvme_ctrl_info_t *ci, nvme_info_err_t err, int32_t sys,
const char *fmt, ...)
{
int ret;
va_list ap;
ci->nci_err = err;
ci->nci_syserr = sys;
va_start(ap, fmt);
ret = vsnprintf(ci->nci_errmsg, sizeof (ci->nci_errmsg), fmt, ap);
va_end(ap);
if (ret >= sizeof (ci->nci_errmsg)) {
ci->nci_errlen = sizeof (ci->nci_errmsg) - 1;
} else if (ret <= 0) {
ci->nci_errlen = 0;
ci->nci_errmsg[0] = '\0';
} else {
ci->nci_errlen = (size_t)ret;
}
return (false);
}
bool
nvme_info_success(nvme_ctrl_info_t *ci)
{
ci->nci_err = NVME_INFO_ERR_OK;
ci->nci_syserr = 0;
ci->nci_errmsg[0] = '\0';
ci->nci_errlen = 0;
return (true);
}
nvme_info_err_t
nvme_ctrl_info_err(nvme_ctrl_info_t *ci)
{
return (ci->nci_err);
}
int32_t
nvme_ctrl_info_syserr(nvme_ctrl_info_t *ci)
{
return (ci->nci_syserr);
}
const char *
nvme_ctrl_info_errmsg(nvme_ctrl_info_t *ci)
{
return (ci->nci_errmsg);
}
size_t
nvme_ctrl_info_errlen(nvme_ctrl_info_t *ci)
{
return (ci->nci_errlen);
}
const char *
nvme_ctrl_info_errtostr(nvme_ctrl_info_t *ci, nvme_info_err_t err)
{
switch (err) {
case NVME_INFO_ERR_OK:
return ("NVME_INFO_ERR_OK");
case NVME_INFO_ERR_TRANSPORT:
return ("NVME_INFO_ERR_TRANSPORT");
case NVME_INFO_ERR_VERSION:
return ("NVME_INFO_ERR_VERSION");
case NVME_INFO_ERR_MISSING_CAP:
return ("NVME_INFO_ERR_MISSING_CAP");
case NVME_INFO_ERR_BAD_LBA_FMT:
return ("NVME_INFO_ERR_BAD_LBA_FMT");
case NVME_INFO_ERR_PERSIST_NVL:
return ("NVME_INFO_ERR_PERSIST_NVL");
case NVME_INFO_ERR_BAD_FMT:
return ("NVME_INFO_ERR_BAD_FMT");
case NVME_INFO_ERR_BAD_FMT_DATA:
return ("NVME_INFO_ERR_BAD_FMT_DATA");
case NVME_INFO_ERR_NS_INACTIVE:
return ("NVME_INFO_ERR_NS_INACTIVE");
case NVME_INFO_ERR_NS_NO_BLKDEV:
return ("NVME_INFO_ERR_NS_NO_BLKDEV");
default:
return ("unknown error");
}
}
void
nvme_ctrl_info_free(nvme_ctrl_info_t *ci)
{
free(ci);
}
static void
nvme_ctrl_info_init_ident_str(const char *src, size_t max_src,
char *out)
{
while (max_src > 0 && src[max_src - 1] == ' ') {
max_src--;
}
if (max_src == 0) {
*out = '\0';
return;
}
(void) memcpy(out, src, max_src);
out[max_src] = '\0';
}
static void
nvme_ctrl_info_init_ident(nvme_ctrl_info_t *ci)
{
nvme_ctrl_info_init_ident_str(ci->nci_info.id_serial,
sizeof (ci->nci_info.id_serial), ci->nci_serial);
nvme_ctrl_info_init_ident_str(ci->nci_info.id_model,
sizeof (ci->nci_info.id_model), ci->nci_model);
nvme_ctrl_info_init_ident_str(ci->nci_info.id_fwrev,
sizeof (ci->nci_info.id_fwrev), ci->nci_fwrev);
}
bool
nvme_ctrl_info_restore(nvme_t *nvme, nvlist_t *nvl, nvme_ctrl_info_t **outp)
{
int ret;
uint32_t vers;
nvme_ctrl_info_t *ci;
char *path;
uchar_t *ctrl, *ns;
uint_t ctrl_len, ns_len;
if (nvl == NULL) {
return (nvme_error(nvme, NVME_ERR_BAD_PTR, 0, "encountered "
"invalid nvlist_t input pointer: %p", nvl));
}
if (outp == NULL) {
return (nvme_error(nvme, NVME_ERR_BAD_PTR, 0, "encountered "
"invalid nvme_ctrl_info_t output pointer: %p", outp));
}
*outp = NULL;
ci = calloc(1, sizeof (nvme_ctrl_info_t));
if (ci == NULL) {
int e = errno;
return (nvme_error(nvme, NVME_ERR_NO_MEM, e, "failed to "
"allocate memory for a new nvme_ctrl_info: %s",
strerror(e)));
}
if ((ret = nvlist_lookup_uint32(nvl, NVME_NVL_CI_VERS, &vers)) != 0) {
(void) nvme_error(nvme, NVME_ERR_BAD_RESTORE, ret, "failed "
"to get version key: %s", strerror(ret));
goto err;
}
if (vers != NVME_NVL_CI_VERS_0) {
(void) nvme_error(nvme, NVME_ERR_BAD_RESTORE, 0,
"found unsupported version key: 0x%x", vers);
goto err;
}
ret = nvlist_lookup_pairs(nvl, 0,
NVME_NVL_CI_MAJOR, DATA_TYPE_UINT16, &ci->nci_vers.v_major,
NVME_NVL_CI_MINOR, DATA_TYPE_UINT16, &ci->nci_vers.v_minor,
NVME_NVL_CI_INST, DATA_TYPE_INT32, &ci->nci_inst,
NVME_NVL_CI_DEV_PATH, DATA_TYPE_STRING, &path,
NVME_NVL_CI_ID_CTRL, DATA_TYPE_BYTE_ARRAY, &ctrl, &ctrl_len,
NVME_NVL_CI_ID_NS, DATA_TYPE_BYTE_ARRAY, &ns, &ns_len,
NVME_NVL_CI_TPORT, DATA_TYPE_UINT32, &ci->nci_tport, NULL);
if (ret != 0) {
(void) nvme_error(nvme, NVME_ERR_BAD_RESTORE, ret,
"failed to retrieve required keys: %s", strerror(ret));
goto err;
}
if (ci->nci_inst < 0) {
(void) nvme_error(nvme, NVME_ERR_BAD_RESTORE, 0,
"instance data is negative");
goto err;
}
if (ctrl_len != sizeof (ci->nci_info)) {
(void) nvme_error(nvme, NVME_ERR_BAD_RESTORE, 0, "identify "
"controller information is the wrong length, expected "
"0x%zx bytes, found 0x%x", sizeof (ci->nci_info), ctrl_len);
goto err;
}
if (ns_len != sizeof (ci->nci_ns)) {
(void) nvme_error(nvme, NVME_ERR_BAD_RESTORE, 0, "identify "
"namespace information is the wrong length, expected "
"0x%zx bytes, found 0x%x", sizeof (ci->nci_info), ctrl_len);
goto err;
}
(void) memcpy(&ci->nci_info, ctrl, ctrl_len);
(void) memcpy(&ci->nci_ns, ns, ns_len);
if (strlcpy(ci->nci_dev_path, path, sizeof (ci->nci_dev_path)) >=
sizeof (ci->nci_dev_path)) {
(void) nvme_error(nvme, NVME_ERR_BAD_RESTORE, 0, "device "
"path would have overflowed");
goto err;
}
if (ci->nci_tport != NVME_CTRL_TRANSPORT_PCI) {
(void) nvme_error(nvme, NVME_ERR_BAD_RESTORE, 0, "found "
"unknown transport type: 0x%x", ci->nci_tport);
goto err;
}
ret = nvlist_lookup_pairs(nvl, 0,
NVME_NVL_CI_PCI_VID, DATA_TYPE_UINT16, &ci->nci_vid,
NVME_NVL_CI_PCI_DID, DATA_TYPE_UINT16, &ci->nci_did,
NVME_NVL_CI_PCI_SUBVID, DATA_TYPE_UINT16, &ci->nci_subvid,
NVME_NVL_CI_PCI_SUBSYS, DATA_TYPE_UINT16, &ci->nci_subsys,
NVME_NVL_CI_PCI_REV, DATA_TYPE_UINT8, &ci->nci_rev,
NVME_NVL_CI_PCI_MPSMIN, DATA_TYPE_UINT32, &ci->nci_mps_min,
NVME_NVL_CI_PCI_MPSMAX, DATA_TYPE_UINT32, &ci->nci_mps_max,
NVME_NVL_CI_PCI_NINTRS, DATA_TYPE_UINT32, &ci->nci_nintrs, NULL);
if (ret != 0) {
(void) nvme_error(nvme, NVME_ERR_BAD_RESTORE, ret,
"failed to retrieve required PCI-specific keys: %s",
strerror(ret));
goto err;
}
nvme_ctrl_info_init_ident(ci);
*outp = ci;
return (true);
err:
nvme_ctrl_info_free(ci);
return (false);
}
bool
nvme_ctrl_info_persist(nvme_ctrl_info_t *ci, nvlist_t **nvlp)
{
int ret;
nvlist_t *nvl;
if ((ret = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0) {
return (nvme_info_error(ci, NVME_INFO_ERR_PERSIST_NVL,
ret, "failed to create initial nvlist_t *: %s",
strerror(ret)));
}
if ((ret = nvlist_add_uint32(nvl, NVME_NVL_CI_VERS,
NVME_NVL_CI_VERS_0)) != 0) {
return (nvme_info_error(ci, NVME_INFO_ERR_PERSIST_NVL, ret,
"failed to persist %s to nvlist: %s", NVME_NVL_CI_VERS,
strerror(ret)));
}
if ((ret = nvlist_add_int32(nvl, NVME_NVL_CI_INST, ci->nci_inst)) !=
0) {
return (nvme_info_error(ci, NVME_INFO_ERR_PERSIST_NVL, ret,
"failed to persist %s to nvlist: %s", NVME_NVL_CI_INST,
strerror(ret)));
}
if ((ret = nvlist_add_uint16(nvl, NVME_NVL_CI_MAJOR,
ci->nci_vers.v_major)) != 0 ||
(ret = nvlist_add_uint16(nvl, NVME_NVL_CI_MINOR,
ci->nci_vers.v_minor)) != 0) {
return (nvme_info_error(ci, NVME_INFO_ERR_PERSIST_NVL, ret,
"failed to persist version data to nvlist: %s",
strerror(ret)));
}
if ((ret = nvlist_add_string(nvl, NVME_NVL_CI_DEV_PATH,
ci->nci_dev_path)) != 0) {
return (nvme_info_error(ci, NVME_INFO_ERR_PERSIST_NVL, ret,
"failed to persist %s to nvlist: %s", NVME_NVL_CI_DEV_PATH,
strerror(ret)));
}
if ((ret = nvlist_add_byte_array(nvl, NVME_NVL_CI_ID_CTRL,
(void *)&ci->nci_info, sizeof (ci->nci_info))) != 0) {
return (nvme_info_error(ci, NVME_INFO_ERR_PERSIST_NVL, ret,
"failed to persist %s to nvlist: %s", NVME_NVL_CI_ID_CTRL,
strerror(ret)));
}
if ((ret = nvlist_add_byte_array(nvl, NVME_NVL_CI_ID_NS,
(void *)&ci->nci_ns, sizeof (ci->nci_ns))) != 0) {
return (nvme_info_error(ci, NVME_INFO_ERR_PERSIST_NVL, ret,
"failed to persist %s to nvlist: %s", NVME_NVL_CI_ID_NS,
strerror(ret)));
}
if ((ret = nvlist_add_uint32(nvl, NVME_NVL_CI_TPORT, ci->nci_tport)) !=
0) {
return (nvme_info_error(ci, NVME_INFO_ERR_PERSIST_NVL, ret,
"failed to persist %s to nvlist: %s", NVME_NVL_CI_TPORT,
strerror(ret)));
}
if ((ret = nvlist_add_uint16(nvl, NVME_NVL_CI_PCI_VID,
ci->nci_vid)) != 0 ||
(ret = nvlist_add_uint16(nvl, NVME_NVL_CI_PCI_DID,
ci->nci_did)) != 0 ||
(ret = nvlist_add_uint16(nvl, NVME_NVL_CI_PCI_SUBVID,
ci->nci_subvid)) != 0 ||
(ret = nvlist_add_uint16(nvl, NVME_NVL_CI_PCI_SUBSYS,
ci->nci_subsys)) != 0 ||
(ret = nvlist_add_uint8(nvl, NVME_NVL_CI_PCI_REV,
ci->nci_rev)) != 0 ||
(ret = nvlist_add_uint32(nvl, NVME_NVL_CI_PCI_MPSMIN,
ci->nci_mps_min)) != 0 ||
(ret = nvlist_add_uint32(nvl, NVME_NVL_CI_PCI_MPSMAX,
ci->nci_mps_max)) != 0 ||
(ret = nvlist_add_uint32(nvl, NVME_NVL_CI_PCI_NINTRS,
ci->nci_nintrs)) != 0) {
return (nvme_info_error(ci, NVME_INFO_ERR_PERSIST_NVL, ret,
"failed to persist PCI data to nvlist: %s", strerror(ret)));
}
*nvlp = nvl;
return (true);
}
static bool
nvme_ctrl_get_udi(nvme_ctrl_t *ctrl, di_node_t di, const char *prop,
uint32_t *outp, uint32_t max)
{
int *vals, nvals;
nvals = di_prop_lookup_ints(DDI_DEV_T_ANY, di, prop, &vals);
if (nvals < 0) {
int e = errno;
return (nvme_ctrl_error(ctrl, NVME_ERR_LIBDEVINFO, e, "failed "
"to get property %s while constructing controller "
"information: %s", prop, strerror(e)));
} else if (nvals != 1) {
return (nvme_ctrl_error(ctrl, NVME_ERR_BAD_DEVI_PROP, 0,
"found unexpected number of property values for %s while "
"constructing controller information, expected 1, found %d",
prop, nvals));
}
if (vals[0] < 0 || vals[0] > max) {
return (nvme_ctrl_error(ctrl, NVME_ERR_BAD_DEVI_PROP, 0,
"property %s has value 0x%x outside the allowed range "
"[0x0, 0x%x]", prop, vals[0], max));
}
*outp = (uint32_t)vals[0];
return (true);
}
bool
nvme_ctrl_info_snap(nvme_ctrl_t *ctrl, nvme_ctrl_info_t **outp)
{
nvme_ctrl_info_t *ci;
uint32_t val;
nvme_ioctl_ctrl_info_t info;
if (outp == NULL) {
return (nvme_ctrl_error(ctrl, NVME_ERR_BAD_PTR, 0,
"encountered invalid nvme_ctrl_info_t output pointer: %p",
outp));
}
*outp = NULL;
ci = calloc(1, sizeof (nvme_ctrl_info_t));
if (ci == NULL) {
int e = errno;
return (nvme_ctrl_error(ctrl, NVME_ERR_NO_MEM, e, "failed to "
"allocate memory for a new nvme_ctrl_info: %s",
strerror(e)));
}
if (!nvme_ctrl_get_udi(ctrl, ctrl->nc_devi, "vendor-id", &val,
UINT16_MAX)) {
goto err;
}
ci->nci_vid = (uint16_t)val;
if (!nvme_ctrl_get_udi(ctrl, ctrl->nc_devi, "device-id", &val,
UINT16_MAX)) {
goto err;
}
ci->nci_did = (uint16_t)val;
if (nvme_ctrl_get_udi(ctrl, ctrl->nc_devi, "subsystem-vendor-id", &val,
UINT16_MAX)) {
ci->nci_subvid = (uint16_t)val;
if (!nvme_ctrl_get_udi(ctrl, ctrl->nc_devi, "subsystem-id",
&val, UINT16_MAX)) {
goto err;
}
} else {
ci->nci_subvid = 0;
ci->nci_subsys = 0;
}
if (!nvme_ctrl_get_udi(ctrl, ctrl->nc_devi, "revision-id", &val,
UINT8_MAX)) {
goto err;
}
ci->nci_rev = (uint8_t)val;
ci->nci_tport = NVME_CTRL_TRANSPORT_PCI;
if (!nvme_ioc_ctrl_info(ctrl, &info)) {
goto err;
}
ci->nci_vers = info.nci_vers;
ci->nci_info = info.nci_ctrl_id;
ci->nci_ns = info.nci_common_ns;
ci->nci_mps_min = info.nci_caps.cap_mpsmin;
ci->nci_mps_max = info.nci_caps.cap_mpsmax;
ci->nci_nintrs = info.nci_nintrs;
nvme_ctrl_info_init_ident(ci);
*outp = ci;
return (nvme_ctrl_success(ctrl));
err:
nvme_ctrl_info_free(ci);
return (false);
}
uint16_t
nvme_ctrl_info_vendor(nvme_ctrl_info_t *ci)
{
return (ci->nci_info.id_vid);
}
const char *
nvme_ctrl_info_model(nvme_ctrl_info_t *ci)
{
return (ci->nci_model);
}
const char *
nvme_ctrl_info_serial(nvme_ctrl_info_t *ci)
{
return (ci->nci_serial);
}
uint32_t
nvme_ctrl_info_fwgran(nvme_ctrl_info_t *ci)
{
nvme_valid_ctrl_data_t data;
data.vcd_vers = &ci->nci_vers;
data.vcd_id = &ci->nci_info;
return (nvme_fw_load_granularity(&data));
}
const char *
nvme_ctrl_info_fwrev(nvme_ctrl_info_t *ci)
{
return (ci->nci_fwrev);
}
const nvme_identify_ctrl_t *
nvme_ctrl_info_identify(nvme_ctrl_info_t *ci)
{
return (&ci->nci_info);
}
const nvme_version_t *
nvme_ctrl_info_version(nvme_ctrl_info_t *ci)
{
return (&ci->nci_vers);
}
nvme_ctrl_transport_t
nvme_ctrl_info_transport(nvme_ctrl_info_t *ci)
{
return (ci->nci_tport);
}
nvme_ctrl_type_t
nvme_ctrl_info_type(nvme_ctrl_info_t *ci)
{
if (nvme_vers_ctrl_info_atleast(ci, &nvme_vers_1v4)) {
switch (ci->nci_info.id_cntrltype) {
case NVME_CNTRLTYPE_IO:
return (NVME_CTRL_TYPE_IO);
case NVME_CNTRLTYPE_DISC:
return (NVME_CTRL_TYPE_DISCOVERY);
case NVME_CNTRLTYPE_ADMIN:
return (NVME_CTRL_TYPE_ADMIN);
default:
return (NVME_CTRL_TYPE_UNKNOWN);
}
} else {
return (NVME_CTRL_TYPE_IO);
}
}
static bool
nvme_ctrl_info_pci_tport(nvme_ctrl_info_t *ci)
{
if (ci->nci_tport != NVME_CTRL_TRANSPORT_PCI) {
return (nvme_info_error(ci, NVME_INFO_ERR_TRANSPORT, 0,
"cannot get PCI data from device with type %s (0x%x)",
nvme_tporttostr(ci->nci_tport), ci->nci_tport));
}
return (true);
}
bool
nvme_ctrl_info_pci_vid(nvme_ctrl_info_t *ci, uint16_t *u16p)
{
if (!nvme_ctrl_info_pci_tport(ci))
return (false);
*u16p = ci->nci_vid;
return (nvme_info_success(ci));
}
bool
nvme_ctrl_info_pci_did(nvme_ctrl_info_t *ci, uint16_t *u16p)
{
if (!nvme_ctrl_info_pci_tport(ci))
return (false);
*u16p = ci->nci_did;
return (nvme_info_success(ci));
}
bool
nvme_ctrl_info_pci_subvid(nvme_ctrl_info_t *ci, uint16_t *u16p)
{
if (!nvme_ctrl_info_pci_tport(ci))
return (false);
*u16p = ci->nci_subvid;
return (nvme_info_success(ci));
}
bool
nvme_ctrl_info_pci_subsys(nvme_ctrl_info_t *ci, uint16_t *u16p)
{
if (!nvme_ctrl_info_pci_tport(ci))
return (false);
*u16p = ci->nci_subsys;
return (nvme_info_success(ci));
}
bool
nvme_ctrl_info_pci_rev(nvme_ctrl_info_t *ci, uint8_t *u8p)
{
if (!nvme_ctrl_info_pci_tport(ci))
return (false);
*u8p = ci->nci_rev;
return (nvme_info_success(ci));
}
bool
nvme_ctrl_info_pci_mps_min(nvme_ctrl_info_t *ci, uint32_t *u32p)
{
if (!nvme_ctrl_info_pci_tport(ci))
return (false);
*u32p = ci->nci_mps_min;
return (nvme_info_success(ci));
}
bool
nvme_ctrl_info_pci_mps_max(nvme_ctrl_info_t *ci, uint32_t *u32p)
{
if (!nvme_ctrl_info_pci_tport(ci))
return (false);
*u32p = ci->nci_mps_max;
return (nvme_info_success(ci));
}
bool
nvme_ctrl_info_pci_nintrs(nvme_ctrl_info_t *ci, uint32_t *u32p)
{
if (!nvme_ctrl_info_pci_tport(ci))
return (false);
*u32p = ci->nci_nintrs;
return (nvme_info_success(ci));
}
static bool
nvme_ctrl_info_nsmgmt(nvme_ctrl_info_t *ci)
{
if (!nvme_vers_ctrl_info_atleast(ci, &nvme_vers_1v2)) {
return (nvme_info_error(ci, NVME_INFO_ERR_VERSION, 0,
"cannot provide information, device must be at least "
"version 1.2, but is %u.%u", ci->nci_vers.v_major,
ci->nci_vers.v_minor));
}
if (ci->nci_info.id_oacs.oa_nsmgmt == 0) {
return (nvme_info_error(ci, NVME_INFO_ERR_MISSING_CAP, 0,
"cannot provide information, device does not support "
"namespace management"));
}
return (true);
}
bool
nvme_ctrl_info_cap(nvme_ctrl_info_t *ci, nvme_uint128_t *u128p)
{
if (!nvme_ctrl_info_nsmgmt(ci)) {
return (false);
}
(void) memcpy(u128p, &ci->nci_info.ap_tnvmcap, sizeof (nvme_uint128_t));
return (nvme_info_success(ci));
}
bool
nvme_ctrl_info_unalloc_cap(nvme_ctrl_info_t *ci, nvme_uint128_t *u128p)
{
if (!nvme_ctrl_info_nsmgmt(ci)) {
return (false);
}
(void) memcpy(u128p, &ci->nci_info.ap_unvmcap, sizeof (nvme_uint128_t));
return (nvme_info_success(ci));
}
bool
nvme_ctrl_info_common_ns(nvme_ctrl_info_t *ci, const nvme_identify_nsid_t **idp)
{
if (!nvme_ctrl_info_nsmgmt(ci)) {
return (false);
}
*idp = &ci->nci_ns;
return (nvme_info_success(ci));
}
uint32_t
nvme_ctrl_info_nformats(nvme_ctrl_info_t *ci)
{
return (MIN(ci->nci_ns.id_nlbaf + 1, NVME_MAX_LBAF));
}
uint32_t
nvme_ctrl_info_nns(nvme_ctrl_info_t *ci)
{
return (ci->nci_info.id_nn);
}
bool
nvme_ctrl_info_format(nvme_ctrl_info_t *ci, uint32_t idx,
const nvme_nvm_lba_fmt_t **outp)
{
const uint32_t max = nvme_ctrl_info_nformats(ci);
if (idx >= max) {
return (nvme_info_error(ci, NVME_INFO_ERR_BAD_FMT, 0,
"requested index %u is invalid: valid range is [0, %u]",
idx, max - 1));
}
if (!ci->nci_lbaf_valid[idx]) {
uint8_t lbads = ci->nci_ns.id_lbaf[idx].lbaf_lbads;
if (lbads == 0) {
return (nvme_info_error(ci, NVME_INFO_ERR_BAD_FMT, 0,
"format %u is not actually valid due to 0 LBA "
"data size even though it is considered a valid "
"LBA format by NLBAF", lbads));
}
if (lbads < 9) {
return (nvme_info_error(ci, NVME_INFO_ERR_BAD_FMT_DATA,
0, "NVMe devices are not allowed to have a LBA "
"data size of less than 512 bytes, found raw "
"shift value of %u for format %u", lbads, idx));
}
if (lbads >= 64) {
return (nvme_info_error(ci, NVME_INFO_ERR_BAD_FMT_DATA,
0, "LBA format %u has LBA data size greater "
"than 64 (%u), cannot be represented as a byte "
"size", idx, lbads));
}
ci->nci_lbaf[idx].nnlf_id = idx;
ci->nci_lbaf[idx].nnlf_ms = ci->nci_ns.id_lbaf[idx].lbaf_ms;
ci->nci_lbaf[idx].nnlf_lbasz = 1ULL << lbads;
ci->nci_lbaf[idx].nnlf_rel = ci->nci_ns.id_lbaf[idx].lbaf_rp;
ci->nci_lbaf_valid[idx] = true;
}
*outp = &ci->nci_lbaf[idx];
return (nvme_info_success(ci));
}
uint32_t
nvme_nvm_lba_fmt_id(const nvme_nvm_lba_fmt_t *lbaf)
{
return (lbaf->nnlf_id);
}
uint32_t
nvme_nvm_lba_fmt_meta_size(const nvme_nvm_lba_fmt_t *lbaf)
{
return (lbaf->nnlf_ms);
}
uint64_t
nvme_nvm_lba_fmt_data_size(const nvme_nvm_lba_fmt_t *lbaf)
{
return (lbaf->nnlf_lbasz);
}
uint32_t
nvme_nvm_lba_fmt_rel_perf(const nvme_nvm_lba_fmt_t *lbaf)
{
return (lbaf->nnlf_rel);
}