Skip to content

Commit 03bd440

Browse files
author
Keith Busch
authored
Merge pull request #546 from minwooim/for-1.9/add-get-lba-status
Add support for Get LBA Status command
2 parents 4813c15 + 8fda64d commit 03bd440

7 files changed

Lines changed: 164 additions & 2 deletions

File tree

linux/nvme.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,21 @@ struct nvme_fw_slot_info_log {
544544
__u8 rsvd64[448];
545545
};
546546

547+
struct nvme_lba_status_desc {
548+
__u64 dslba;
549+
__u32 nlb;
550+
__u8 rsvd_12;
551+
__u8 status;
552+
__u8 rsvd_15_14[2];
553+
};
554+
555+
struct nvme_lba_status {
556+
__u32 nlsd;
557+
__u8 cmpc;
558+
__u8 rsvd_7_5[3];
559+
struct nvme_lba_status_desc descs[0];
560+
};
561+
547562
/* NVMe Namespace Write Protect State */
548563
enum {
549564
NVME_NS_NO_WRITE_PROTECT = 0,
@@ -922,6 +937,7 @@ enum nvme_admin_opcode {
922937
nvme_admin_security_send = 0x81,
923938
nvme_admin_security_recv = 0x82,
924939
nvme_admin_sanitize_nvm = 0x84,
940+
nvme_admin_get_lba_status = 0x86,
925941
};
926942

927943
enum {

nvme-builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ COMMAND_LIST(
4444
ENTRY("io-passthru", "Submit an arbitrary IO command, return results", io_passthru)
4545
ENTRY("security-send", "Submit a Security Send command, return results", sec_send)
4646
ENTRY("security-recv", "Submit a Security Receive command, return results", sec_recv)
47+
ENTRY("get-lba-status", "Submit a Get LBA Status command, return results", get_lba_status)
4748
ENTRY("resv-acquire", "Submit a Reservation Acquire, return results", resv_acquire)
4849
ENTRY("resv-register", "Submit a Reservation Register, return results", resv_register)
4950
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
@@ -825,6 +825,21 @@ int nvme_sec_recv(int fd, __u32 nsid, __u8 nssf, __u16 spsp,
825825
return err;
826826
}
827827

828+
int nvme_get_lba_status(int fd, __u64 slba, __u32 mndw, __u8 atype, __u16 rl,
829+
void *data)
830+
{
831+
struct nvme_admin_cmd cmd = {
832+
.opcode = nvme_admin_get_lba_status,
833+
.addr = (__u64)(uintptr_t) data,
834+
.cdw10 = slba & 0xffffffff,
835+
.cdw11 = slba >> 32,
836+
.cdw12 = mndw,
837+
.cdw13 = (atype << 24) | rl,
838+
};
839+
840+
return nvme_submit_admin_passthru(fd, &cmd);
841+
}
842+
828843
int nvme_dir_send(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper,
829844
__u32 data_len, __u32 dw12, void *data, __u32 *result)
830845
{

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: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,27 @@ static void show_nvme_id_ctrl_cmic(__u8 cmic)
122122
static void show_nvme_id_ctrl_oaes(__le32 ctrl_oaes)
123123
{
124124
__u32 oaes = le32_to_cpu(ctrl_oaes);
125-
__u32 rsvd0 = (oaes & 0xFFFFFC00) >> 10;
125+
__u32 rsvd0 = (oaes & 0xFFFF8000) >> 15;
126126
__u32 nace = (oaes & 0x100) >> 8;
127127
__u32 fan = (oaes & 0x200) >> 9;
128+
__u32 anacn = (oaes & 800) >> 11;
129+
__u32 plealcn = (oaes & 0x1000) >> 12;
130+
__u32 lbasin = (oaes & 0x2000) >> 13;
131+
__u32 egealpcn = (oaes & 0x4000) >> 14;
128132
__u32 rsvd1 = oaes & 0xFF;
129133

130134
if (rsvd0)
131135
printf(" [31:10] : %#x\tReserved\n", rsvd0);
136+
printf("[14:14] : %#x\tEndurance Group Event Aggregate Log Page"\
137+
" Change Notice %sSupported\n",
138+
egealpcn, egealpcn ? "" : "Not ");
139+
printf("[13:13] : %#x\tLBA Status Information Notices %sSupported\n",
140+
lbasin, lbasin ? "" : "Not ");
141+
printf("[12:12] : %#x\tPredictable Latency Event Aggregate Log Change"\
142+
" Notices %sSupported\n",
143+
plealcn, plealcn ? "" : "Not ");
144+
printf("[11:11] : %#x\tAsymmetric Namespace Access Change Notices"\
145+
" %sSupported\n", anacn, anacn ? "" : "Not ");
132146
printf(" [9:9] : %#x\tFirmware Activation Notices %sSupported\n",
133147
fan, fan ? "" : "Not ");
134148
printf(" [8:8] : %#x\tNamespace Attribute Changed Event %sSupported\n",
@@ -172,7 +186,8 @@ static void show_nvme_id_ctrl_ctratt(__le32 ctrl_ctratt)
172186
static void show_nvme_id_ctrl_oacs(__le16 ctrl_oacs)
173187
{
174188
__u16 oacs = le16_to_cpu(ctrl_oacs);
175-
__u16 rsvd = (oacs & 0xFE00) >> 9;
189+
__u16 rsvd = (oacs & 0xFC00) >> 10;
190+
__u16 glbas = (oacs & 0x200) >> 9;
176191
__u16 dbc = (oacs & 0x100) >> 8;
177192
__u16 vir = (oacs & 0x80) >> 7;
178193
__u16 nmi = (oacs & 0x40) >> 6;
@@ -185,6 +200,8 @@ static void show_nvme_id_ctrl_oacs(__le16 ctrl_oacs)
185200

186201
if (rsvd)
187202
printf(" [15:9] : %#x\tReserved\n", rsvd);
203+
printf(" [9:9] : %#x\tGet LBA Status Capability %sSupported\n",
204+
glbas, glbas ? "" : "Not ");
188205
printf(" [8:8] : %#x\tDoorbell Buffer Config %sSupported\n",
189206
dbc, dbc ? "" : "Not ");
190207
printf(" [7:7] : %#x\tVirtualization Management %sSupported\n",
@@ -2232,6 +2249,34 @@ void nvme_feature_show_fields(__u32 fid, unsigned int result, unsigned char *buf
22322249
}
22332250
}
22342251

2252+
void show_lba_status(struct nvme_lba_status *list)
2253+
{
2254+
int idx;
2255+
2256+
printf("Number of LBA Status Descriptors(NLSD): %lu\n",
2257+
le64_to_cpu(list->nlsd));
2258+
printf("Completion Condition(CMPC): %u\n", list->cmpc);
2259+
switch (list->cmpc) {
2260+
case 1:
2261+
printf("\tCompleted due to transferring the amount of data"\
2262+
" specified in the MNDW field\n");
2263+
break;
2264+
case 2:
2265+
printf("\tCompleted due to having performed the action\n"\
2266+
"\tspecified in the Action Type field over the\n"\
2267+
"\tnumber of logical blocks specified in the\n"\
2268+
"\tRange Length field\n");
2269+
break;
2270+
}
2271+
2272+
for (idx = 0; idx < list->nlsd; idx++) {
2273+
struct nvme_lba_status_desc *e = &list->descs[idx];
2274+
printf("{ DSLBA: 0x%016"PRIu64", NLB: 0x%08x, Status: 0x%02x }\n",
2275+
le64_to_cpu(e->dslba), le32_to_cpu(e->nlb),
2276+
e->status);
2277+
}
2278+
}
2279+
22352280
static void show_list_item(struct list_item list_item)
22362281
{
22372282
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
@@ -5077,6 +5077,88 @@ static int sec_recv(int argc, char **argv, struct command *cmd, struct plugin *p
50775077
return nvme_status_to_errno(err, false);
50785078
}
50795079

5080+
static int get_lba_status(int argc, char **argv, struct command *cmd,
5081+
struct plugin *plugin)
5082+
{
5083+
const char *desc = "Information about potentially unrecoverable LBAs.";
5084+
const char *slba = "Starting LBA(SLBA) in 64-bit address of the first"\
5085+
" logical block addressed by this command";
5086+
const char *mndw = "Maximum Number of Dwords(MNDW) specifies maximum"\
5087+
" number of dwords to return";
5088+
const char *atype = "Action Type(ATYPE) specifies the mechanism the"\
5089+
" the controller uses in determining the LBA"\
5090+
" Status Descriptors to return.";
5091+
const char *rl = "Range Length(RL) specifies the length of the range"\
5092+
" of contiguous LBAs beginning at SLBA";
5093+
int err, fd, fmt;
5094+
void *buf;
5095+
unsigned long buf_len;
5096+
5097+
struct config {
5098+
__u64 slba;
5099+
__u32 mndw;
5100+
__u8 atype;
5101+
__u16 rl;
5102+
char *output_format;
5103+
};
5104+
5105+
struct config cfg = {
5106+
.slba = 0,
5107+
.mndw = 0,
5108+
.atype = 0,
5109+
.rl = 0,
5110+
.output_format = "normal",
5111+
};
5112+
5113+
const struct argconfig_commandline_options command_line_options[] = {
5114+
{"start-lba", 's', "NUM", CFG_LONG_SUFFIX, &cfg.slba, required_argument, slba},
5115+
{"max-dw", 'm', "NUM", CFG_POSITIVE, &cfg.mndw, required_argument, mndw},
5116+
{"action", 'a', "NUM", CFG_BYTE, &cfg.atype, required_argument, atype},
5117+
{"range-len", 'l', "NUM", CFG_SHORT, &cfg.rl, required_argument, rl},
5118+
{"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, required_argument, output_format},
5119+
{NULL}
5120+
};
5121+
5122+
err = fd = parse_and_open(argc, argv, desc, command_line_options, &cfg,
5123+
sizeof(cfg));
5124+
if (fd < 0)
5125+
goto ret;
5126+
5127+
err = fmt = validate_output_format(cfg.output_format);
5128+
if (fmt < 0)
5129+
goto close_fd;
5130+
5131+
if (!cfg.atype) {
5132+
fprintf(stderr, "action type (--action) has to be given\n");
5133+
err = -EINVAL;
5134+
goto close_fd;
5135+
}
5136+
5137+
buf_len = (cfg.mndw + 1) * 4;
5138+
buf = calloc(1, buf_len);
5139+
if (!buf) {
5140+
err = -ENOMEM;
5141+
goto close_fd;
5142+
}
5143+
5144+
err = nvme_get_lba_status(fd, cfg.slba, cfg.mndw, cfg.atype, cfg.rl,
5145+
buf);
5146+
if (err)
5147+
goto free;
5148+
5149+
if (fmt == BINARY)
5150+
d_raw((unsigned char *)buf, buf_len);
5151+
else
5152+
show_lba_status(buf);
5153+
5154+
free:
5155+
free(buf);
5156+
close_fd:
5157+
close(fd);
5158+
ret:
5159+
return nvme_status_to_errno(err, false);
5160+
}
5161+
50805162
static int dir_receive(int argc, char **argv, struct command *cmd, struct plugin *plugin)
50815163
{
50825164
const char *desc = "Read directive parameters of the "\

0 commit comments

Comments
 (0)