From 5d64e8a26388e2abbf6a6585d17392d6e944ae7b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 1 Jul 2023 00:38:51 +0200 Subject: Merging upstream version 2.5. Signed-off-by: Daniel Baumann --- plugins/solidigm/solidigm-telemetry/data-area.c | 208 +++++++++++++++--------- 1 file changed, 128 insertions(+), 80 deletions(-) (limited to 'plugins/solidigm/solidigm-telemetry/data-area.c') diff --git a/plugins/solidigm/solidigm-telemetry/data-area.c b/plugins/solidigm/solidigm-telemetry/data-area.c index 2f18ea2..0cfa56c 100644 --- a/plugins/solidigm/solidigm-telemetry/data-area.c +++ b/plugins/solidigm/solidigm-telemetry/data-area.c @@ -6,25 +6,29 @@ */ #include "common.h" +#include "header.h" +#include "cod.h" #include "data-area.h" #include "config.h" +#include "nlog.h" #include #define SIGNED_INT_PREFIX "int" #define BITS_IN_BYTE 8 #define MAX_WARNING_SIZE 1024 +#define MAX_ARRAY_RANK 16 static bool telemetry_log_get_value(const struct telemetry_log *tl, - uint32_t offset_bit, uint32_t size_bit, + uint64_t offset_bit, uint32_t size_bit, bool is_signed, struct json_object **val_obj) { uint32_t offset_bit_from_byte; uint32_t additional_size_byte; uint32_t offset_byte; - uint32_t val; + uint64_t val; - if (size_bit == 0) { + if (!size_bit) { char err_msg[MAX_WARNING_SIZE]; snprintf(err_msg, MAX_WARNING_SIZE, @@ -34,7 +38,7 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl, return false; } additional_size_byte = (size_bit - 1) ? (size_bit - 1) / BITS_IN_BYTE : 0; - offset_byte = offset_bit / BITS_IN_BYTE; + offset_byte = (uint32_t)offset_bit / BITS_IN_BYTE; if (offset_byte > (tl->log_size - additional_size_byte)) { char err_msg[MAX_WARNING_SIZE]; @@ -47,15 +51,14 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl, return false; } - offset_bit_from_byte = offset_bit - (offset_byte * BITS_IN_BYTE); + offset_bit_from_byte = (uint32_t) (offset_bit - ((uint64_t)offset_byte * BITS_IN_BYTE)); if ((size_bit + offset_bit_from_byte) > (sizeof(uint64_t) * BITS_IN_BYTE)) { char err_msg[MAX_WARNING_SIZE]; snprintf(err_msg, MAX_WARNING_SIZE, - "Value crossing 64 bit, byte aligned bounday, " - "not supported. size_bit=%u, offset_bit_from_byte=%u.", - size_bit, offset_bit_from_byte); + "Value crossing 64 bit, byte aligned bounday, not supported. size_bit=%u, offset_bit_from_byte=%u.", + size_bit, offset_bit_from_byte); *val_obj = json_object_new_string(err_msg); return false; @@ -67,7 +70,7 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl, val &= (1ULL << size_bit) - 1; if (is_signed) { if (val >> (size_bit - 1)) - val |= -1ULL << size_bit; + val |= (0ULL - 1) << size_bit; *val_obj = json_object_new_int64(val); } else { *val_obj = json_object_new_uint64(val); @@ -78,23 +81,24 @@ static bool telemetry_log_get_value(const struct telemetry_log *tl, static int telemetry_log_structure_parse(const struct telemetry_log *tl, struct json_object *struct_def, - size_t parent_offset_bit, + uint64_t parent_offset_bit, struct json_object *output, struct json_object *metadata) { struct json_object *obj_arraySizeArray = NULL; struct json_object *obj = NULL; struct json_object *obj_memberList; - struct json_object *major_dimension; + struct json_object *major_dimension = NULL; struct json_object *sub_output; bool is_enumeration = false; bool has_member_list; const char *type = ""; const char *name; size_t array_rank; - size_t offset_bit; - size_t size_bit; - uint32_t linear_array_pos_bit; + uint64_t offset_bit; + uint32_t size_bit; + uint64_t linear_array_pos_bit; + uint32_t array_size_dimension[MAX_ARRAY_RANK]; if (!json_object_object_get_ex(struct_def, "name", &obj)) { SOLIDIGM_LOG_WARNING("Warning: Structure definition missing property 'name': %s", @@ -113,22 +117,22 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl, type = json_object_get_string(obj); if (!json_object_object_get_ex(struct_def, "offsetBit", &obj)) { - SOLIDIGM_LOG_WARNING("Warning: Structure definition missing " - "property 'offsetBit': %s", - json_object_to_json_string(struct_def)); + SOLIDIGM_LOG_WARNING( + "Warning: Structure definition missing property 'offsetBit': %s", + json_object_to_json_string(struct_def)); return -1; } offset_bit = json_object_get_uint64(obj); if (!json_object_object_get_ex(struct_def, "sizeBit", &obj)) { - SOLIDIGM_LOG_WARNING("Warning: Structure definition missing " - "property 'sizeBit': %s", - json_object_to_json_string(struct_def)); + SOLIDIGM_LOG_WARNING( + "Warning: Structure definition missing property 'sizeBit': %s", + json_object_to_json_string(struct_def)); return -1; } - size_bit = json_object_get_uint64(obj); + size_bit = (uint32_t)json_object_get_uint64(obj); if (json_object_object_get_ex(struct_def, "enum", &obj)) is_enumeration = json_object_get_boolean(obj); @@ -139,25 +143,30 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl, if (!json_object_object_get_ex(struct_def, "arraySize", &obj_arraySizeArray)) { - SOLIDIGM_LOG_WARNING("Warning: Structure definition missing " - "property 'arraySize': %s", - json_object_to_json_string(struct_def)); + SOLIDIGM_LOG_WARNING( + "Warning: Structure definition missing property 'arraySize': %s", + json_object_to_json_string(struct_def)); return -1; } array_rank = json_object_array_length(obj_arraySizeArray); - if (array_rank == 0) { - SOLIDIGM_LOG_WARNING("Warning: Structure property 'arraySize' " - "don't support flexible array: %s", - json_object_to_json_string(struct_def)); + if (!array_rank) { + SOLIDIGM_LOG_WARNING( + "Warning: Structure property 'arraySize' don't support flexible array: %s", + json_object_to_json_string(struct_def)); + return -1; + } + if (array_rank > MAX_ARRAY_RANK) { + SOLIDIGM_LOG_WARNING( + "Warning: Structure property 'arraySize' don't support more than %d dimensions: %s", + MAX_ARRAY_RANK, json_object_to_json_string(struct_def)); return -1; } - uint32_t array_size_dimension[array_rank]; for (size_t i = 0; i < array_rank; i++) { struct json_object *dimension = json_object_array_get_idx(obj_arraySizeArray, i); - array_size_dimension[i] = json_object_get_uint64(dimension); + array_size_dimension[i] = json_object_get_int(dimension); major_dimension = dimension; } if (array_rank > 1) { @@ -165,7 +174,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl, uint32_t prev_index_offset_bit = 0; struct json_object *dimension_output; - for (int i = 1; i < (array_rank - 1); i++) + for (unsigned int i = 1; i < (array_rank - 1); i++) linear_pos_per_index *= array_size_dimension[i]; dimension_output = json_create_array(); @@ -181,9 +190,9 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl, json_object_get(major_dimension); json_object_array_del_idx(obj_arraySizeArray, array_rank - 1, 1); - for (int i = 0 ; i < array_size_dimension[0]; i++) { + for (unsigned int i = 0 ; i < array_size_dimension[0]; i++) { struct json_object *sub_array = json_create_array(); - size_t offset; + uint64_t offset; offset = parent_offset_bit + prev_index_offset_bit; @@ -214,7 +223,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl, if (is_enumeration || !has_member_list) { bool is_signed = !strncmp(type, SIGNED_INT_PREFIX, sizeof(SIGNED_INT_PREFIX)-1); struct json_object *val_obj; - size_t offset; + uint64_t offset; offset = parent_offset_bit + offset_bit + linear_array_pos_bit; if (telemetry_log_get_value(tl, offset, size_bit, is_signed, &val_obj)) { @@ -223,10 +232,10 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl, else json_object_object_add(sub_output, name, val_obj); } else { - SOLIDIGM_LOG_WARNING("Warning: %s From property '%s', " - "array index %u, structure definition: %s", - json_object_get_string(val_obj), - name, j, json_object_to_json_string(struct_def)); + SOLIDIGM_LOG_WARNING( + "Warning: %s From property '%s', array index %u, structure definition: %s", + json_object_get_string(val_obj), name, j, + json_object_to_json_string(struct_def)); json_free_object(val_obj); } } else { @@ -241,7 +250,7 @@ static int telemetry_log_structure_parse(const struct telemetry_log *tl, num_members = json_object_array_length(obj_memberList); for (int k = 0; k < num_members; k++) { struct json_object *member = json_object_array_get_idx(obj_memberList, k); - size_t offset; + uint64_t offset; offset = parent_offset_bit + offset_bit + linear_array_pos_bit; telemetry_log_structure_parse(tl, member, offset, @@ -293,6 +302,27 @@ static int telemetry_log_data_area_get_offset(const struct telemetry_log *tl, return 0; } +static int telemetry_log_nlog_parse(const struct telemetry_log *tl, struct json_object *formats, + uint64_t nlog_file_offset, uint64_t nlog_size, + struct json_object *output, struct json_object *metadata) +{ + /* boundary check */ + if (tl->log_size < (nlog_file_offset + nlog_size)) { + const char *name = ""; + int media_bank = -1; + struct json_object *jobj; + + if (json_object_object_get_ex(metadata, "objName", &jobj)) + name = json_object_get_string(jobj); + if (json_object_object_get_ex(metadata, "mediaBankId", &jobj)) + media_bank = json_object_get_int(jobj); + SOLIDIGM_LOG_WARNING("%s:%d do not fit this log dump.", name, media_bank); + return -1; + } + return solidigm_nlog_parse(((char *) tl->log) + nlog_file_offset, + nlog_size, formats, metadata, output); +} + struct toc_item { uint32_t OffsetBytes; uint32_t ContentSizeBytes; @@ -319,7 +349,6 @@ struct telemetry_object_header { uint8_t Reserved[3]; }; - static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl, enum nvme_telemetry_da da, struct json_object *toc_array, @@ -331,30 +360,35 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl, char *payload; uint32_t da_offset; uint32_t da_size; + struct json_object *nlog_formats; if (telemetry_log_data_area_get_offset(tl, da, &da_offset, &da_size)) return; toc = (struct table_of_contents *)(((char *)tl->log) + da_offset); payload = (char *) tl->log; + nlog_formats = solidigm_config_get_nlog_formats(tl->configuration); for (int i = 0; i < toc->header.TableOfContentsCount; i++) { struct json_object *structure_definition = NULL; struct json_object *toc_item; uint32_t obj_offset; bool has_struct; - - if ((char *)&toc->items[i] > (((char *)toc) + da_size - sizeof(const struct toc_item))) { - SOLIDIGM_LOG_WARNING("Warning: Data Area %d, " - "Table of Contents item %d " - "crossed Data Area size.", da, i); + const char *nlog_name = NULL; + uint32_t header_offset = sizeof(const struct telemetry_object_header); + + if ((char *)&toc->items[i] > + (((char *)toc) + da_size - sizeof(const struct toc_item))) { + SOLIDIGM_LOG_WARNING( + "Warning: Data Area %d, Table of Contents item %d crossed Data Area size.", + da, i); return; } obj_offset = toc->items[i].OffsetBytes; if ((obj_offset + sizeof(const struct telemetry_object_header)) > da_size) { - SOLIDIGM_LOG_WARNING("Warning: Data Area %d, item %d " - "data, crossed Data Area size.", da, i); + SOLIDIGM_LOG_WARNING( + "Warning: Data Area %d, item %d data, crossed Data Area size.", da, i); continue; } @@ -372,53 +406,67 @@ static void telemetry_log_data_area_toc_parse(const struct telemetry_log *tl, json_object_add_value_uint(toc_item, "objectId", header->Token); json_object_add_value_uint(toc_item, "mediaBankId", header->CoreId); - has_struct = solidigm_config_get_by_token_version(tl->configuration, - header->Token, - header->versionMajor, - header->versionMinor, - &structure_definition); - - if (has_struct) { - struct json_object *tele_obj_item = json_create_object(); + has_struct = solidigm_config_get_struct_by_token_version(tl->configuration, + header->Token, + header->versionMajor, + header->versionMinor, + &structure_definition); + if (!has_struct) { + if (!nlog_formats) + continue; + nlog_name = solidigm_config_get_nlog_obj_name(tl->configuration, + header->Token); + if (!nlog_name) + continue; + } + struct json_object *tele_obj_item = json_create_object(); - json_object_array_add(tele_obj_array, tele_obj_item); - json_object_get(toc_item); - json_object_add_value_object(tele_obj_item, "metadata", toc_item); - struct json_object *parsed_struct = json_create_object(); + json_object_array_add(tele_obj_array, tele_obj_item); + json_object_get(toc_item); + json_object_add_value_object(tele_obj_item, "metadata", toc_item); + struct json_object *parsed_struct = json_create_object(); - json_object_add_value_object(tele_obj_item, "objectData", parsed_struct); - struct json_object *obj_hasTelemObjHdr = NULL; - uint32_t header_offset = sizeof(const struct telemetry_object_header); - uint32_t file_offset; + json_object_add_value_object(tele_obj_item, "objectData", parsed_struct); + struct json_object *obj_hasTelemObjHdr = NULL; + uint64_t object_file_offset; - if (json_object_object_get_ex(structure_definition, - "hasTelemObjHdr", - &obj_hasTelemObjHdr)) { - bool hasHeader = json_object_get_boolean(obj_hasTelemObjHdr); + if (json_object_object_get_ex(structure_definition, + "hasTelemObjHdr", + &obj_hasTelemObjHdr)) { + bool hasHeader = json_object_get_boolean(obj_hasTelemObjHdr); - if (hasHeader) - header_offset = 0; - } - - file_offset = da_offset + obj_offset + header_offset; + if (hasHeader) + header_offset = 0; + } + object_file_offset = ((uint64_t)da_offset) + obj_offset + header_offset; + if (has_struct) { telemetry_log_structure_parse(tl, structure_definition, - BITS_IN_BYTE * file_offset, - parsed_struct, toc_item); + BITS_IN_BYTE * object_file_offset, + parsed_struct, toc_item); + } else if (nlog_formats) { + json_object_object_add(toc_item, "objName", + json_object_new_string(nlog_name)); + telemetry_log_nlog_parse(tl, nlog_formats, object_file_offset, + toc->items[i].ContentSizeBytes - header_offset, + parsed_struct, toc_item); } } } -int solidigm_telemetry_log_data_areas_parse(const struct telemetry_log *tl, +int solidigm_telemetry_log_data_areas_parse(struct telemetry_log *tl, enum nvme_telemetry_da last_da) { struct json_object *tele_obj_array = json_create_array(); struct json_object *toc_array = json_create_array(); - json_object_add_value_array(tl->root, "tableOfContents", toc_array); - json_object_add_value_array(tl->root, "telemetryObjects", tele_obj_array); - - for (enum nvme_telemetry_da da = NVME_TELEMETRY_DA_1; da <= last_da; da++) - telemetry_log_data_area_toc_parse(tl, da, toc_array, tele_obj_array); + solidigm_telemetry_log_header_parse(tl); + solidigm_telemetry_log_cod_parse(tl); + if (tl->configuration) { + json_object_add_value_array(tl->root, "tableOfContents", toc_array); + json_object_add_value_array(tl->root, "telemetryObjects", tele_obj_array); + for (enum nvme_telemetry_da da = NVME_TELEMETRY_DA_1; da <= last_da; da++) + telemetry_log_data_area_toc_parse(tl, da, toc_array, tele_obj_array); + } return 0; } -- cgit v1.2.3