Skip to content

Commit 8fda64d

Browse files
committed
get-lba-status: add Get LBA Status command
This command has been added in NVMe 1.4 spec. This command can retrieve some information about the unrecoverable LBAs from the device. Signed-off-by: Minwoo Im <[email protected]>
1 parent 583dffe commit 8fda64d

7 files changed

Lines changed: 145 additions & 0 deletions

File tree

linux/nvme.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,21 @@ struct nvme_fw_slot_info_log {
526526
__u8 rsvd64[448];
527527
};
528528

529+
struct nvme_lba_status_desc {
530+
__u64 dslba;
531+
__u32 nlb;
532+
__u8 rsvd_12;
533+
__u8 status;
534+
__u8 rsvd_15_14[2];
535+
};
536+
537+
struct nvme_lba_status {
538+
__u32 nlsd;
539+
__u8 cmpc;
540+
__u8 rsvd_7_5[3];
541+
struct nvme_lba_status_desc descs[0];
542+
};
543+
529544
/* NVMe Namespace Write Protect State */
530545
enum {
531546
NVME_NS_NO_WRITE_PROTECT = 0,
@@ -904,6 +919,7 @@ enum nvme_admin_opcode {
904919
nvme_admin_security_send = 0x81,
905920
nvme_admin_security_recv = 0x82,
906921
nvme_admin_sanitize_nvm = 0x84,
922+
nvme_admin_get_lba_status = 0x86,
907923
};
908924

909925
enum {

nvme-builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ COMMAND_LIST(
4343
ENTRY("io-passthru", "Submit an arbitrary IO command, return results", io_passthru)
4444
ENTRY("security-send", "Submit a Security Send command, return results", sec_send)
4545
ENTRY("security-recv", "Submit a Security Receive command, return results", sec_recv)
46+
ENTRY("get-lba-status", "Submit a Get LBA Status command, return results", get_lba_status)
4647
ENTRY("resv-acquire", "Submit a Reservation Acquire, return results", resv_acquire)
4748
ENTRY("resv-register", "Submit a Reservation Register, return results", resv_register)
4849
ENTRY("resv-release", "Submit a Reservation Release, return results", resv_release)

nvme-ioctl.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,21 @@ int nvme_sec_recv(int fd, __u32 nsid, __u8 nssf, __u16 spsp,
820820
return err;
821821
}
822822

823+
int nvme_get_lba_status(int fd, __u64 slba, __u32 mndw, __u8 atype, __u16 rl,
824+
void *data)
825+
{
826+
struct nvme_admin_cmd cmd = {
827+
.opcode = nvme_admin_get_lba_status,
828+
.addr = (__u64)(uintptr_t) data,
829+
.cdw10 = slba & 0xffffffff,
830+
.cdw11 = slba >> 32,
831+
.cdw12 = mndw,
832+
.cdw13 = (atype << 24) | rl,
833+
};
834+
835+
return nvme_submit_admin_passthru(fd, &cmd);
836+
}
837+
823838
int nvme_dir_send(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper,
824839
__u32 data_len, __u32 dw12, void *data, __u32 *result)
825840
{

nvme-ioctl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ int nvme_subsystem_reset(int fd);
131131
int nvme_reset_controller(int fd);
132132
int nvme_ns_rescan(int fd);
133133

134+
int nvme_get_lba_status(int fd, __u64 slba, __u32 mndw, __u8 atype, __u16 rl,
135+
void *data);
134136
int nvme_dir_send(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper,
135137
__u32 data_len, __u32 dw12, void *data, __u32 *result);
136138
int nvme_dir_recv(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper,

nvme-print.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2169,6 +2169,34 @@ void nvme_feature_show_fields(__u32 fid, unsigned int result, unsigned char *buf
21692169
}
21702170
}
21712171

2172+
void show_lba_status(struct nvme_lba_status *list)
2173+
{
2174+
int idx;
2175+
2176+
printf("Number of LBA Status Descriptors(NLSD): %lu\n",
2177+
le64_to_cpu(list->nlsd));
2178+
printf("Completion Condition(CMPC): %u\n", list->cmpc);
2179+
switch (list->cmpc) {
2180+
case 1:
2181+
printf("\tCompleted due to transferring the amount of data"\
2182+
" specified in the MNDW field\n");
2183+
break;
2184+
case 2:
2185+
printf("\tCompleted due to having performed the action\n"\
2186+
"\tspecified in the Action Type field over the\n"\
2187+
"\tnumber of logical blocks specified in the\n"\
2188+
"\tRange Length field\n");
2189+
break;
2190+
}
2191+
2192+
for (idx = 0; idx < list->nlsd; idx++) {
2193+
struct nvme_lba_status_desc *e = &list->descs[idx];
2194+
printf("{ DSLBA: 0x%016"PRIu64", NLB: 0x%08x, Status: 0x%02x }\n",
2195+
le64_to_cpu(e->dslba), le32_to_cpu(e->nlb),
2196+
e->status);
2197+
}
2198+
}
2199+
21722200
static void show_list_item(struct list_item list_item)
21732201
{
21742202
long long int lba = 1 << list_item.ns.lbaf[(list_item.ns.flbas & 0x0f)].ds;

nvme-print.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ void show_sanitize_log(struct nvme_sanitize_log_page *sanitize, unsigned int mod
3636
void show_ctrl_registers(void *bar, unsigned int mode, bool fabrics);
3737
void show_single_property(int offset, uint64_t prop, int human);
3838
void show_nvme_id_ns_descs(void *data);
39+
void show_lba_status(struct nvme_lba_status *list);
3940
void show_list_items(struct list_item *list_items, unsigned len);
4041
void show_nvme_subsystem_list(struct subsys_list_item *slist, int n);
4142
void show_nvme_id_nvmset(struct nvme_id_nvmset *nvmset);

nvme.c

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4852,6 +4852,88 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p
48524852
return nvme_status_to_errno(err, false);
48534853
}
48544854

4855+
static int get_lba_status(int argc, char **argv, struct command *cmd,
4856+
struct plugin *plugin)
4857+
{
4858+
const char *desc = "Information about potentially unrecoverable LBAs.";
4859+
const char *slba = "Starting LBA(SLBA) in 64-bit address of the first"\
4860+
" logical block addressed by this command";
4861+
const char *mndw = "Maximum Number of Dwords(MNDW) specifies maximum"\
4862+
" number of dwords to return";
4863+
const char *atype = "Action Type(ATYPE) specifies the mechanism the"\
4864+
" the controller uses in determining the LBA"\
4865+
" Status Descriptors to return.";
4866+
const char *rl = "Range Length(RL) specifies the length of the range"\
4867+
" of contiguous LBAs beginning at SLBA";
4868+
int err, fd, fmt;
4869+
void *buf;
4870+
unsigned long buf_len;
4871+
4872+
struct config {
4873+
__u64 slba;
4874+
__u32 mndw;
4875+
__u8 atype;
4876+
__u16 rl;
4877+
char *output_format;
4878+
};
4879+
4880+
struct config cfg = {
4881+
.slba = 0,
4882+
.mndw = 0,
4883+
.atype = 0,
4884+
.rl = 0,
4885+
.output_format = "normal",
4886+
};
4887+
4888+
const struct argconfig_commandline_options command_line_options[] = {
4889+
{"start-lba", 's', "NUM", CFG_LONG_SUFFIX, &cfg.slba, required_argument, slba},
4890+
{"max-dw", 'm', "NUM", CFG_POSITIVE, &cfg.mndw, required_argument, mndw},
4891+
{"action", 'a', "NUM", CFG_BYTE, &cfg.atype, required_argument, atype},
4892+
{"range-len", 'l', "NUM", CFG_SHORT, &cfg.rl, required_argument, rl},
4893+
{"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format},
4894+
{NULL}
4895+
};
4896+
4897+
err = fd = parse_and_open(argc, argv, desc, command_line_options, &cfg,
4898+
sizeof(cfg));
4899+
if (fd < 0)
4900+
goto ret;
4901+
4902+
err = fmt = validate_output_format(cfg.output_format);
4903+
if (fmt < 0)
4904+
goto close_fd;
4905+
4906+
if (!cfg.atype) {
4907+
fprintf(stderr, "action type (--action) has to be given\n");
4908+
err = -EINVAL;
4909+
goto close_fd;
4910+
}
4911+
4912+
buf_len = (cfg.mndw + 1) * 4;
4913+
buf = calloc(1, buf_len);
4914+
if (!buf) {
4915+
err = -ENOMEM;
4916+
goto close_fd;
4917+
}
4918+
4919+
err = nvme_get_lba_status(fd, cfg.slba, cfg.mndw, cfg.atype, cfg.rl,
4920+
buf);
4921+
if (err)
4922+
goto free;
4923+
4924+
if (fmt == BINARY)
4925+
d_raw((unsigned char *)buf, buf_len);
4926+
else
4927+
show_lba_status(buf);
4928+
4929+
free:
4930+
free(buf);
4931+
close_fd:
4932+
close(fd);
4933+
ret:
4934+
return nvme_status_to_errno(err, false);
4935+
}
4936+
48554937
static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin *plugin)
48564938
{
48574939
const char *desc = "Read directive parameters of the "\

0 commit comments

Comments
 (0)