Skip to content

Commit e3fed74

Browse files
brandon-paupore-sndkigaw
authored andcommitted
nvme-print: support PEL VS Events and Info
This adds support for reporting and parsing Vendor Specific events within a Persistent Event Log, and accounts for any Vendor Specific Information for parsing Event Data. Without this change, the presence of any VS Information associated with an event would result in the incorrect data offset being used. Signed-off-by: Brandon Paupore <[email protected]> Reviewed-by: Jeffrey Lien <[email protected]>
1 parent 1800170 commit e3fed74

3 files changed

Lines changed: 182 additions & 9 deletions

File tree

libnvme/src/nvme/types.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4554,6 +4554,36 @@ enum nvme_pel_ehai_pit {
45544554
NVME_PEL_EHAI_PIT_NOT_ASSOCIATED = 3,
45554555
};
45564556

4557+
/**
4558+
* enum nvme_pel_vsedt_code - Persistent Event Log - Vendor Specific Event Data Type Code
4559+
* @NVME_PEL_VSEDT_RSVD: Reserved
4560+
* @NVME_PEL_VSEDT_EVENT_NAME: Event Name
4561+
* @NVME_PEL_VSEDT_ASCII_STRING: ASCII String
4562+
* @NVME_PEL_VSEDT_BINARY: Binary
4563+
* @NVME_PEL_VSEDT_SIGNED_INT: Signed Integer
4564+
*/
4565+
enum nvme_pel_vsedt_code {
4566+
NVME_PEL_VSEDT_RSVD = 0,
4567+
NVME_PEL_VSEDT_EVENT_NAME = 1,
4568+
NVME_PEL_VSEDT_ASCII_STRING = 2,
4569+
NVME_PEL_VSEDT_BINARY = 3,
4570+
NVME_PEL_VSEDT_SIGNED_INT = 4,
4571+
};
4572+
4573+
/**
4574+
* struct nvme_vs_event_desc - Vendor Specific Event Descriptor
4575+
* @vsec: Vendor Specific Event Code
4576+
* @vsedt: Vendor Specific Event Data Type
4577+
* @uidx: UUID Index
4578+
* @vsedl: Vendor Specific Event Data Length
4579+
*/
4580+
struct nvme_vs_event_desc {
4581+
__le16 vsec;
4582+
__u8 vsedt;
4583+
__u8 uidx;
4584+
__le16 vsedl;
4585+
};
4586+
45574587
/**
45584588
* struct nvme_fw_commit_event - Firmware Commit Event Data
45594589
* @old_fw_rev: Old Firmware Revision

nvme-print-json.c

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1811,10 +1811,81 @@ static void json_pel_thermal_excursion(void *pevent_log_info, __u32 offset,
18111811
obj_add_uint(valid_attrs, "threshold", thermal_exc_event->threshold);
18121812
}
18131813

1814+
static void json_pel_vs_event_data(struct json_object *valid_attrs, void *vsed,
1815+
__u8 vsedt, __u16 vsedl)
1816+
{
1817+
struct json_object *vs_data = json_create_object();
1818+
char *str;
1819+
1820+
switch (vsedt) {
1821+
case NVME_PEL_VSEDT_EVENT_NAME:
1822+
str = malloc(vsedl + 1);
1823+
if (str) {
1824+
memcpy(str, vsed, vsedl);
1825+
str[vsedl] = '\0';
1826+
obj_add_str(vs_data, "event_name", str);
1827+
free(str);
1828+
}
1829+
break;
1830+
case NVME_PEL_VSEDT_ASCII_STRING:
1831+
str = malloc(vsedl + 1);
1832+
if (str) {
1833+
memcpy(str, vsed, vsedl);
1834+
str[vsedl] = '\0';
1835+
obj_add_str(vs_data, "ascii_string_data", str);
1836+
free(str);
1837+
}
1838+
break;
1839+
case NVME_PEL_VSEDT_BINARY:
1840+
obj_d(vs_data, "binary_data", (unsigned char *)vsed, vsedl, 16, 1);
1841+
break;
1842+
case NVME_PEL_VSEDT_SIGNED_INT:
1843+
obj_add_int(vs_data, "signed_integer_data", *(int64_t *)vsed);
1844+
break;
1845+
default:
1846+
obj_d(vs_data, "reserved_data_type_bin", (unsigned char *)vsed, vsedl, 16, 1);
1847+
break;
1848+
}
1849+
1850+
obj_add_obj(valid_attrs, "vs_event_data", vs_data);
1851+
}
1852+
1853+
static void json_pel_vendor_specific_event(void *pevent_log_info, __u32 offset,
1854+
__u32 event_data_len, struct json_object *valid_attrs)
1855+
{
1856+
__u32 progress = 0;
1857+
__u16 vsedl;
1858+
uint i;
1859+
struct nvme_vs_event_desc *vs_desc;
1860+
struct json_object *vs_events = json_create_array();
1861+
1862+
for (i = 0; progress < event_data_len; i++) {
1863+
struct json_object *vs_event = json_create_object();
1864+
1865+
vs_desc = pevent_log_info + offset + progress;
1866+
vsedl = le16_to_cpu(vs_desc->vsedl);
1867+
1868+
obj_add_uint(vs_event, "vs_event_descriptor_number", i);
1869+
obj_add_uint(vs_event, "vs_event_code", le16_to_cpu(vs_desc->vsec));
1870+
obj_add_uint(vs_event, "vs_event_data_type", vs_desc->vsedt);
1871+
obj_add_uint(vs_event, "vs_event_uuid_index", vs_desc->uidx);
1872+
obj_add_uint(vs_event, "vs_event_data_len", vsedl);
1873+
1874+
if (vsedl)
1875+
json_pel_vs_event_data(vs_event, vs_desc + 1, vs_desc->vsedt, vsedl);
1876+
1877+
array_add_obj(vs_events, vs_event);
1878+
progress += sizeof(*vs_desc) + vsedl;
1879+
}
1880+
1881+
obj_add_array(valid_attrs, "vs_event_entry", vs_events);
1882+
}
1883+
18141884
static void json_pevent_entry(void *pevent_log_info, __u8 action, __u32 size, const char *devname,
18151885
__u32 offset, struct json_object *valid)
18161886
{
18171887
int i;
1888+
__u16 vsil, el;
18181889
struct nvme_persistent_event_log *pevent_log_head = pevent_log_info;
18191890
struct nvme_persistent_event_entry *pevent_entry_head;
18201891
struct json_object *valid_attrs;
@@ -1824,8 +1895,10 @@ static void json_pevent_entry(void *pevent_log_info, __u8 action, __u32 size, co
18241895
break;
18251896

18261897
pevent_entry_head = pevent_log_info + offset;
1898+
vsil = le16_to_cpu(pevent_entry_head->vsil);
1899+
el = le16_to_cpu(pevent_entry_head->el);
18271900

1828-
if (offset + pevent_entry_head->ehl + 3 + le16_to_cpu(pevent_entry_head->el) >=
1901+
if (offset + pevent_entry_head->ehl + 3 + el >=
18291902
size)
18301903
break;
18311904

@@ -1841,10 +1914,14 @@ static void json_pevent_entry(void *pevent_log_info, __u8 action, __u32 size, co
18411914
obj_add_uint64(valid_attrs, "event_time_stamp",
18421915
le64_to_cpu(pevent_entry_head->ets));
18431916
obj_add_uint(valid_attrs, "port_id", le16_to_cpu(pevent_entry_head->pelpid));
1844-
obj_add_uint(valid_attrs, "vu_info_len", le16_to_cpu(pevent_entry_head->vsil));
1845-
obj_add_uint(valid_attrs, "event_len", le16_to_cpu(pevent_entry_head->el));
1917+
obj_add_uint(valid_attrs, "vu_info_len", vsil);
1918+
obj_add_uint(valid_attrs, "event_len", el);
1919+
1920+
if (vsil)
1921+
obj_d(valid_attrs, "vs_info_bin",
1922+
(void *)pevent_entry_head + 1, vsil, 16, 1);
18461923

1847-
offset += pevent_entry_head->ehl + 3;
1924+
offset += pevent_entry_head->ehl + vsil + 3;
18481925

18491926
switch (pevent_entry_head->etype) {
18501927
case NVME_PEL_SMART_HEALTH_EVENT:
@@ -1887,6 +1964,10 @@ static void json_pevent_entry(void *pevent_log_info, __u8 action, __u32 size, co
18871964
case NVME_PEL_THERMAL_EXCURSION_EVENT:
18881965
json_pel_thermal_excursion(pevent_log_info, offset, valid_attrs);
18891966
break;
1967+
case NVME_PEL_VENDOR_SPECIFIC_EVENT:
1968+
json_pel_vendor_specific_event(pevent_log_info, offset, el - vsil,
1969+
valid_attrs);
1970+
break;
18901971
default:
18911972
break;
18921973
}

nvme-print-stdout.c

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,8 @@ void nvme_show_pel_header(struct nvme_persistent_event_log *pevent_log_head, int
312312
static void pel_event_header(int i, struct nvme_persistent_event_entry *pevent_entry_head,
313313
int human)
314314
{
315+
__u16 vsil = le16_to_cpu(pevent_entry_head->vsil);
316+
315317
printf("Event Number: %u\n", i);
316318
printf("Event Type: %s\n", nvme_pel_event_to_string(pevent_entry_head->etype));
317319
printf("Event Type Revision: %u\n", pevent_entry_head->etype_rev);
@@ -324,8 +326,13 @@ static void pel_event_header(int i, struct nvme_persistent_event_entry *pevent_e
324326
printf("Controller Identifier: %u\n", le16_to_cpu(pevent_entry_head->cntlid));
325327
printf("Event Timestamp: %"PRIu64"\n", le64_to_cpu(pevent_entry_head->ets));
326328
printf("Port Identifier: %u\n", le16_to_cpu(pevent_entry_head->pelpid));
327-
printf("Vendor Specific Information Length: %u\n", le16_to_cpu(pevent_entry_head->vsil));
329+
printf("Vendor Specific Information Length: %u\n", vsil);
328330
printf("Event Length: %u\n", le16_to_cpu(pevent_entry_head->el));
331+
332+
if (vsil) {
333+
printf("Vendor Specific Information:\n");
334+
d((void *)pevent_entry_head + 1, vsil, 16, 1);
335+
}
329336
}
330337

331338
static void pel_smart_health_event(void *pevent_log_info, __u32 offset, const char *devname)
@@ -493,11 +500,62 @@ static void pel_thermal_excursion_event(void *pevent_log_info, __u32 offset)
493500
printf("Threshold: %u\n", thermal_exc_event->threshold);
494501
}
495502

503+
static void pel_vs_event_data(void *vsed, __u8 vsedt, __u16 vsedl)
504+
{
505+
printf("Vendor Specific Event Data:\n");
506+
switch (vsedt) {
507+
case NVME_PEL_VSEDT_EVENT_NAME:
508+
printf("Event Name for Vendor Specific Event Code:\n");
509+
printf("%.*s\n", vsedl, (char *)vsed);
510+
break;
511+
case NVME_PEL_VSEDT_ASCII_STRING:
512+
printf("ASCII String Data:\n");
513+
printf("%.*s\n", vsedl, (char *)vsed);
514+
break;
515+
case NVME_PEL_VSEDT_BINARY:
516+
printf("Binary Data:\n");
517+
d(vsed, vsedl, 16, 1);
518+
break;
519+
case NVME_PEL_VSEDT_SIGNED_INT:
520+
printf("Signed Integer Data: %" PRId64 "\n", (int64_t)vsedt);
521+
break;
522+
default:
523+
printf("Reserved data type. As Binary:\n");
524+
d(vsed, vsedl, 16, 1);
525+
}
526+
}
527+
528+
static void pel_vendor_specific_event(void *pevent_log_info, __u32 offset,
529+
__u32 event_data_len)
530+
{
531+
__u32 progress = 0;
532+
__u16 vsedl;
533+
int i;
534+
struct nvme_vs_event_desc *vs_desc;
535+
536+
printf("Vendor Specific Event Entry:\n");
537+
for (i = 0; progress < event_data_len; i++) {
538+
vs_desc = pevent_log_info + offset + progress;
539+
vsedl = le16_to_cpu(vs_desc->vsedl);
540+
541+
printf("Vendor Specific Event Descriptor %u:\n", i);
542+
printf("Vendor Specific Event Code: %u\n", le16_to_cpu(vs_desc->vsec));
543+
printf("Vendor Specific Event Data Type: %u\n", vs_desc->vsedt);
544+
printf("Vendor Specific Event UIndex: %u\n", vs_desc->uidx);
545+
printf("Vendor Specific Event Data Length: %u\n", vsedl);
546+
if (vsedl)
547+
pel_vs_event_data(vs_desc + 1, vs_desc->vsedt,
548+
vsedl);
549+
progress += sizeof(*vs_desc) + vsedl;
550+
}
551+
}
552+
496553
static void stdout_persistent_event_log(void *pevent_log_info, __u8 action, __u32 size,
497554
const char *devname)
498555
{
499556
struct nvme_persistent_event_log *pevent_log_head;
500557
__u32 offset = sizeof(*pevent_log_head);
558+
__u16 vsil, el;
501559
struct nvme_persistent_event_entry *pevent_entry_head;
502560
int human = stdout_print_ops.flags & VERBOSE;
503561

@@ -522,14 +580,15 @@ static void stdout_persistent_event_log(void *pevent_log_info, __u8 action, __u3
522580
break;
523581

524582
pevent_entry_head = pevent_log_info + offset;
583+
vsil = le16_to_cpu(pevent_entry_head->vsil);
584+
el = le16_to_cpu(pevent_entry_head->el);
525585

526-
if ((offset + pevent_entry_head->ehl + 3 +
527-
le16_to_cpu(pevent_entry_head->el)) >= size)
586+
if ((offset + pevent_entry_head->ehl + 3 + el) >= size)
528587
break;
529588

530589
pel_event_header(i, pevent_entry_head, human);
531590

532-
offset += pevent_entry_head->ehl + 3;
591+
offset += pevent_entry_head->ehl + vsil + 3;
533592

534593
switch (pevent_entry_head->etype) {
535594
case NVME_PEL_SMART_HEALTH_EVENT:
@@ -574,11 +633,14 @@ static void stdout_persistent_event_log(void *pevent_log_info, __u8 action, __u3
574633
case NVME_PEL_SANITIZE_MEDIA_VERIF_EVENT:
575634
printf("Sanitize Media Verification Event\n");
576635
break;
636+
case NVME_PEL_VENDOR_SPECIFIC_EVENT:
637+
pel_vendor_specific_event(pevent_log_info, offset, el - vsil);
638+
break;
577639
default:
578640
printf("Reserved Event\n\n");
579641
break;
580642
}
581-
offset += le16_to_cpu(pevent_entry_head->el);
643+
offset += el;
582644
printf("\n");
583645
}
584646
}

0 commit comments

Comments
 (0)