Skip to content

Commit fe31f35

Browse files
ocp: add Persistent Event log support
This introduces a new OCP plugin command that mirrors the base nvme persistent-event-log command, but has additional parsing for the OCP 2.5 TCG Activity Event data. Signed-off-by: Brandon Paupore <[email protected]> Reviewed-by: Jeffrey Lien <[email protected]>
1 parent 4b75899 commit fe31f35

10 files changed

Lines changed: 660 additions & 0 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
nvme-ocp-persistent-event-log(1)
2+
================================
3+
4+
NAME
5+
----
6+
nvme-ocp-persistent-event-log - Send NVMe persistent event log page request,
7+
returns result and log additional OCP-specific data
8+
9+
SYNOPSIS
10+
--------
11+
[verse]
12+
'nvme ocp persistent-event-log' <device> [--action=<action> | -a <action>]
13+
[--log-len=<log-len> | -l <log-len>] [--raw-binary | -b]
14+
[--output-format=<fmt> | -o <fmt>] [--verbose | -v]
15+
16+
DESCRIPTION
17+
-----------
18+
Retrieves the NVMe persistent event log page from an NVMe device
19+
and provides the returned structure.
20+
21+
The <device> parameter is mandatory and may be either the NVMe character
22+
device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).
23+
24+
On success, the returned persistent event log structure may be returned
25+
in one of several ways depending on the option flags; the structure may
26+
parsed by the program and printed in a readable format or the raw buffer
27+
may be printed to stdout for another program to parse.
28+
29+
OPTIONS
30+
-------
31+
-a <action>::
32+
--action=<action>::
33+
While try to retrieve this log action the controller shall take
34+
during processing this persistent log page command. This mandatory
35+
field, based on the value issued it may Read Log Data, Establish
36+
Context and Read Log Data or Release Context can occur. For More
37+
details see NVM Express 1.4 Spec. Section 5.14.1.13 Persistent
38+
Event Log (Log Identifier 0Dh)
39+
40+
-l <log-len>::
41+
--log-len=<log-len>::
42+
Allocates a buffer of <log-len> bytes size and requests this
43+
many bytes be returned in the constructed NVMe command. This
44+
param is mandatory. If <log-len> given is 0 and action is 0,
45+
it will read the Total Log Length(TLL) of the page.
46+
47+
-b::
48+
--raw-binary::
49+
Print the raw persistent event log buffer to stdout.
50+
51+
-o <fmt>::
52+
--output-format=<fmt>::
53+
Set the reporting format to 'normal', 'json' or 'binary'. Only one
54+
output format can be used at a time.
55+
56+
-v::
57+
--verbose::
58+
Increase the information detail in the output.
59+
60+
EXAMPLES
61+
--------
62+
* Print the persistent event log page in a human readable format:
63+
+
64+
------------
65+
# nvme ocp persistent-event-log /dev/nvme0
66+
------------
67+
+
68+
69+
* Print the raw persistent event log to a file:
70+
+
71+
------------
72+
# nvme ocp persistent-event-log /dev/nvme0 --raw-binary > persistent_log.raw
73+
------------
74+
+
75+
It is probably a bad idea to not redirect stdout when using this mode.
76+
77+
NVME
78+
----
79+
Part of the nvme-user suite

plugins/ocp/ocp-nvme.c

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ static const char *type = "Error injection type";
195195
static const char *nrtdp = "Number of reads to trigger device panic";
196196
static const char *save = "Specifies that the controller shall save the attribute";
197197
static const char *enable_ieee1667_silo = "enable IEEE1667 silo";
198+
static const char *raw_use = "use binary output";
198199

199200
static int get_c3_log_page(struct nvme_transport_handle *hdl, char *format)
200201
{
@@ -2974,3 +2975,124 @@ static int hwcomp_log(int argc, char **argv, struct command *acmd, struct plugin
29742975
{
29752976
return ocp_hwcomp_log(argc, argv, acmd, plugin);
29762977
}
2978+
2979+
static int ocp_get_persistent_event_log(int argc, char **argv,
2980+
struct command *command, struct plugin *plugin)
2981+
{
2982+
const char *desc = "Retrieve Persistent Event log info for "
2983+
"the given device in either decoded format(default), json or binary.";
2984+
const char *action = "action the controller shall take during "
2985+
"processing this persistent log page command.";
2986+
const char *log_len = "number of bytes to retrieve";
2987+
2988+
_cleanup_free_ struct nvme_persistent_event_log *pevent = NULL;
2989+
struct nvme_persistent_event_log *pevent_collected = NULL;
2990+
_cleanup_huge_ struct nvme_mem_huge mh = { 0, };
2991+
_cleanup_nvme_global_ctx_ struct nvme_global_ctx *ctx = NULL;
2992+
_cleanup_nvme_transport_handle_ struct nvme_transport_handle *hdl = NULL;
2993+
nvme_print_flags_t flags;
2994+
void *pevent_log_info;
2995+
int err;
2996+
2997+
struct config {
2998+
__u8 action;
2999+
__u32 log_len;
3000+
bool raw_binary;
3001+
};
3002+
3003+
struct config cfg = {
3004+
.action = 0xff,
3005+
.log_len = 0,
3006+
.raw_binary = false,
3007+
};
3008+
3009+
NVME_ARGS(opts,
3010+
OPT_BYTE("action", 'a', &cfg.action, action),
3011+
OPT_UINT("log_len", 'l', &cfg.log_len, log_len),
3012+
OPT_FLAG("raw-binary", 'b', &cfg.raw_binary, raw_use));
3013+
3014+
err = parse_and_open(&ctx, &hdl, argc, argv, desc, opts);
3015+
if (err)
3016+
return err;
3017+
3018+
err = validate_output_format(nvme_cfg.output_format, &flags);
3019+
if (err < 0) {
3020+
nvme_show_error("Invalid output format");
3021+
return err;
3022+
}
3023+
3024+
if (cfg.raw_binary)
3025+
flags = BINARY;
3026+
3027+
pevent = nvme_alloc(sizeof(*pevent));
3028+
if (!pevent)
3029+
return -ENOMEM;
3030+
3031+
err = nvme_get_log_persistent_event(hdl, cfg.action,
3032+
pevent, sizeof(*pevent));
3033+
if (err < 0) {
3034+
nvme_show_error("persistent event log: %s", nvme_strerror(err));
3035+
return err;
3036+
} else if (err) {
3037+
nvme_show_status(err);
3038+
return err;
3039+
}
3040+
3041+
if (cfg.action == NVME_PEVENT_LOG_RELEASE_CTX) {
3042+
printf("Releasing Persistent Event Log Context\n");
3043+
return 0;
3044+
}
3045+
3046+
if (!cfg.log_len && cfg.action != NVME_PEVENT_LOG_EST_CTX_AND_READ) {
3047+
cfg.log_len = le64_to_cpu(pevent->tll);
3048+
} else if (!cfg.log_len && cfg.action == NVME_PEVENT_LOG_EST_CTX_AND_READ) {
3049+
printf("Establishing Persistent Event Log Context\n");
3050+
return 0;
3051+
}
3052+
3053+
/*
3054+
* if header already read with context establish action 0x1,
3055+
* action shall not be 0x1 again in the subsequent request,
3056+
* until the current context is released by issuing action
3057+
* with 0x2, otherwise throws command sequence error, make
3058+
* it as zero to read the log page
3059+
*/
3060+
if (cfg.action == NVME_PEVENT_LOG_EST_CTX_AND_READ)
3061+
cfg.action = NVME_PEVENT_LOG_READ;
3062+
3063+
pevent_log_info = nvme_alloc_huge(cfg.log_len, &mh);
3064+
if (!pevent_log_info) {
3065+
nvme_show_error("failed to allocate huge memory");
3066+
return -ENOMEM;
3067+
}
3068+
3069+
err = nvme_get_log_persistent_event(hdl, cfg.action,
3070+
pevent_log_info, cfg.log_len);
3071+
if (!err) {
3072+
err = nvme_get_log_persistent_event(hdl, cfg.action,
3073+
pevent,
3074+
sizeof(*pevent));
3075+
if (err < 0) {
3076+
nvme_show_error("persistent event log: %s", nvme_strerror(err));
3077+
return err;
3078+
} else if (err) {
3079+
nvme_show_status(err);
3080+
return err;
3081+
}
3082+
pevent_collected = pevent_log_info;
3083+
if (pevent_collected->gen_number != pevent->gen_number) {
3084+
printf("Collected Persistent Event Log may be invalid,\n"
3085+
"Re-read the log is required\n");
3086+
return -EINVAL;
3087+
}
3088+
3089+
ocp_show_persistent_event_log(pevent_log_info, cfg.action,
3090+
cfg.log_len, nvme_transport_handle_get_name(hdl), flags);
3091+
} else if (err > 0) {
3092+
nvme_show_status(err);
3093+
} else {
3094+
nvme_show_error("persistent event log: %s", nvme_strerror(err));
3095+
}
3096+
3097+
return err;
3098+
}

plugins/ocp/ocp-nvme.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ PLUGIN(NAME("ocp", "OCP cloud SSD extensions", OCP_PLUGIN_VERSION),
4848
get_clear_pcie_correctable_error_counters)
4949
ENTRY("get-telemetry-profile", "Get Telemetry Profile Feature",
5050
ocp_get_telemetry_profile_feature)
51+
ENTRY("persistent-event-log", "Retrieve Persistent Event Log with OCP events, show it",
52+
ocp_get_persistent_event_log)
5153
)
5254
);
5355

@@ -280,4 +282,28 @@ enum ocp_dssd_feature_id {
280282
OCP_FID_TEL_CFG, /* Telemetry Profile */
281283
OCP_FID_DAEC, /* DSSD Asynchronous Event Configuration */
282284
};
285+
286+
/*
287+
* struct tcg_activity_event_data - TCG Activity Event Data
288+
* @rsvd: Reserved
289+
* @tcg_command_count: TCG Command Count
290+
* @invoking_id: Invoking ID
291+
* @method_id: Method ID
292+
* @com_id: Com ID
293+
* @protocol_id: Protocol ID
294+
* @status: Status of the TCG command
295+
* @process_time: Time in milliseconds to process command
296+
* @tcg_activity_specific_context: Additional context for the TCG activity
297+
*/
298+
struct __packed tcg_activity_event_data {
299+
__u8 rsvd[2];
300+
__le32 tcg_command_count;
301+
__le64 invoking_id;
302+
__le64 method_id;
303+
__le16 com_id;
304+
__le16 protocol_id;
305+
__u8 status;
306+
__le16 process_time;
307+
__u8 tcg_activity_specific_context[10];
308+
};
283309
#endif /* OCP_NVME_H */

plugins/ocp/ocp-print-binary.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ static void binary_hwcomp_log(struct hwcomp_log *log, __u32 id, bool list)
1515
d_raw((unsigned char *)log, log_bytes);
1616
}
1717

18+
static void binary_persistent_event_log(void *pevent_log_info,
19+
__u8 action, __u32 size, const char *devname)
20+
{
21+
d_raw((unsigned char *)pevent_log_info, size);
22+
}
23+
1824
static void binary_c5_log(struct nvme_transport_handle *hdl, struct unsupported_requirement_log *log_data)
1925
{
2026
d_raw((unsigned char *)log_data, sizeof(*log_data));
@@ -43,6 +49,7 @@ static void binary_c7_log(struct nvme_transport_handle *hdl, struct tcg_configur
4349

4450
static struct ocp_print_ops binary_print_ops = {
4551
.hwcomp_log = binary_hwcomp_log,
52+
.persistent_event_log = binary_persistent_event_log,
4653
.c5_log = binary_c5_log,
4754
.c1_log = binary_c1_log,
4855
.c4_log = binary_c4_log,

0 commit comments

Comments
 (0)