Skip to content

Commit

Permalink
plugins/solidigm: Compressing vs-internal-log log files into zip file.
Browse files Browse the repository at this point in the history
Creates zip file containing files useful to debug.

Signed-off-by: Leonardo da Cunha <leonardo.da.cunha@solidigm.com>
  • Loading branch information
lgdacunh authored and igaw committed Feb 2, 2024
1 parent 3196089 commit 79abafe
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 33 deletions.
116 changes: 84 additions & 32 deletions plugins/solidigm/solidigm-internal-logs.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <unistd.h>
#include <inttypes.h>
#include <linux/limits.h>
#include <time.h>

#include "common.h"
#include "nvme.h"
Expand Down Expand Up @@ -122,7 +123,7 @@ struct nlog_dump_header4_1 {

struct config {
__u32 namespace_id;
char *file_prefix;
char *dir_prefix;
char *type;
bool verbose;
};
Expand Down Expand Up @@ -222,6 +223,7 @@ static int dump_assert_logs(struct nvme_dev *dev, struct config cfg)
__u8 buf[INTERNAL_LOG_MAX_BYTE_TRANSFER];
__u8 head_buf[INTERNAL_LOG_MAX_BYTE_TRANSFER];
char file_path[PATH_MAX];
char file_name[] = "AssertLog.bin";
struct assert_dump_header *ad = (struct assert_dump_header *) head_buf;
struct nvme_passthru_cmd cmd = {
.opcode = 0xd2,
Expand All @@ -236,7 +238,8 @@ static int dump_assert_logs(struct nvme_dev *dev, struct config cfg)
if (err)
return err;

sprintf(file_path, "%s_AssertLog.bin", cfg.file_prefix);
snprintf(file_path, sizeof(file_path), "%.*s/%s",
(int) (sizeof(file_path) - sizeof(file_name) - 1), cfg.dir_prefix, file_name);
output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (output < 0)
return -errno;
Expand Down Expand Up @@ -291,7 +294,7 @@ static int dump_event_logs(struct nvme_dev *dev, struct config cfg)
err = read_header(&cmd, dev_fd(dev));
if (err)
return err;
sprintf(file_path, "%s_EventLog.bin", cfg.file_prefix);
snprintf(file_path, sizeof(file_path), "%s/EventLog.bin", cfg.dir_prefix);
output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (output < 0)
return -errno;
Expand Down Expand Up @@ -387,7 +390,8 @@ static int dump_nlogs(struct nvme_dev *dev, struct config cfg, int core)
count = nlog_header->totalnlogs;
core_num = core < 0 ? nlog_header->corecount : 0;
if (!header_size) {
sprintf(file_path, "%s_NLog.bin", cfg.file_prefix);
snprintf(file_path, sizeof(file_path), "%s/NLog.bin",
cfg.dir_prefix);
output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (output < 0)
return -errno;
Expand Down Expand Up @@ -423,25 +427,32 @@ enum telemetry_type {

static int dump_telemetry(struct nvme_dev *dev, struct config cfg, enum telemetry_type ttype)
{
struct nvme_telemetry_log *log = NULL;
_cleanup_free_ struct nvme_telemetry_log *log = NULL;
size_t log_size = 0;
int err = 0, output;
int err = 0;
__u8 *buffer = NULL;
size_t bytes_remaining = 0;
enum nvme_telemetry_da da;
size_t max_data_tx;
char file_path[PATH_MAX];
char *log_name;
char *file_name;
char *log_descr;
struct stat sb;

_cleanup_file_ int output = -1;

switch (ttype) {
case HOSTGENNEW:
log_name = "TelemetryHostGenNew";
file_name = "lid_0x07_lsp_0x01_lsi_0x0000.bin";
log_descr = "Generated Host Initiated";
break;
case HOSTGENOLD:
log_name = "TelemetryHostGenOld";
file_name = "lid_0x07_lsp_0x00_lsi_0x0000.bin";
log_descr = "Existing Host Initiated";
break;
case CONTROLLER:
log_name = "TelemetryController";
file_name = "lid_0x08_lsp_0x00_lsi_0x0000.bin";
log_descr = "Controller Initiated";
break;
default:
return -EINVAL;
Expand All @@ -453,11 +464,6 @@ static int dump_telemetry(struct nvme_dev *dev, struct config cfg, enum telemetr
if (max_data_tx > DRIVER_MAX_TX_256K)
max_data_tx = DRIVER_MAX_TX_256K;

sprintf(file_path, "%s_%s.bin", cfg.file_prefix, log_name);
output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (output < 0)
return -errno;

switch (ttype) {
case HOSTGENNEW:
err = nvme_get_telemetry_log(dev_fd(dev), true, false, false, max_data_tx, da,
Expand All @@ -474,7 +480,20 @@ static int dump_telemetry(struct nvme_dev *dev, struct config cfg, enum telemetr
}

if (err)
goto tele_close_output;
return err;

snprintf(file_path, sizeof(file_path), "%s/log_pages", cfg.dir_prefix);
if (!(stat(file_path, &sb) == 0 && S_ISDIR(sb.st_mode))) {
if (mkdir(file_path, 777) != 0) {
perror(file_path);
return -errno;
}
}

snprintf(file_path, sizeof(file_path), "%s/log_pages/%s", cfg.dir_prefix, file_name);
output = open(file_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (output < 0)
return -errno;

bytes_remaining = log_size;
buffer = (__u8 *)log;
Expand All @@ -486,45 +505,49 @@ static int dump_telemetry(struct nvme_dev *dev, struct config cfg, enum telemetr
err = -errno;
goto tele_close_output;
}

bytes_remaining -= bytes_written;
buffer += bytes_written;
}
printf("Successfully wrote log to %s\n", file_path);
printf("Successfully wrote %s Telemetry log to %s\n", log_descr, file_path);

tele_close_output:
free(log);
close(output);

return err;
}

int solidigm_get_internal_log(int argc, char **argv, struct command *command,
struct plugin *plugin)
{
char folder[PATH_MAX];
char zip_name[PATH_MAX];
char *output_path;
char sn_prefix[sizeof(((struct nvme_id_ctrl *)0)->sn)+1];
int log_count = 0;
int err;
struct nvme_dev *dev;
_cleanup_nvme_dev_ struct nvme_dev *dev = NULL;
bool all = false;
time_t t;
struct tm tm;

const char *desc = "Get Debug Firmware Logs and save them.";
const char *type =
"Log type: ALL, CONTROLLERINITTELEMETRY, HOSTINITTELEMETRY, HOSTINITTELEMETRYNOGEN, NLOG, ASSERT, EVENT. Defaults to ALL.";
const char *prefix = "Output file prefix; defaults to device serial number.";
const char *prefix = "Output dir prefix; defaults to device serial number.";
const char *verbose = "To print out verbose info.";
const char *namespace_id = "Namespace to get logs from.";


struct config cfg = {
.namespace_id = NVME_NSID_ALL,
.file_prefix = NULL,
.dir_prefix = NULL,
.type = NULL,
};

OPT_ARGS(opts) = {
OPT_STR("type", 't', &cfg.type, type),
OPT_UINT("namespace-id", 'n', &cfg.namespace_id, namespace_id),
OPT_FILE("file-prefix", 'p', &cfg.file_prefix, prefix),
OPT_FILE("dir-prefix", 'p', &cfg.dir_prefix, prefix),
OPT_FLAG("verbose", 'v', &cfg.verbose, verbose),
OPT_END()
};
Expand All @@ -533,12 +556,22 @@ int solidigm_get_internal_log(int argc, char **argv, struct command *command,
if (err)
return err;

if (!cfg.file_prefix) {
if (!cfg.dir_prefix) {
err = get_serial_number(sn_prefix, dev_fd(dev));
if (err)
goto out_dev;
cfg.file_prefix = sn_prefix;
return err;
cfg.dir_prefix = sn_prefix;
}
t = time(NULL);
tm = *localtime(&t);
snprintf(folder, sizeof(folder), "%s-%d%02d%02d%02d%02d%02d", cfg.dir_prefix,
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
if (mkdir(folder, 0777) != 0) {
perror("mkdir");
return -errno;
}
cfg.dir_prefix = folder;
output_path = folder;

if (!cfg.type)
cfg.type = "ALL";
Expand All @@ -547,8 +580,9 @@ int solidigm_get_internal_log(int argc, char **argv, struct command *command,
*p = toupper(*p);
}

if (!strcmp(cfg.type, "ALL"))
if (!strcmp(cfg.type, "ALL")) {
all = true;
}
if (all || !strcmp(cfg.type, "ASSERT")) {
err = dump_assert_logs(dev, cfg);
if (err == 0)
Expand Down Expand Up @@ -592,14 +626,32 @@ int solidigm_get_internal_log(int argc, char **argv, struct command *command,
perror("Error retrieving Telemetry Host Initiated");
}

if (log_count > 0) {
int ret_cmd;
char cmd[ARG_MAX];
char *where_err = cfg.verbose ? "" : ">/dev/null 2>&1";

snprintf(zip_name, sizeof(zip_name), "%s.zip", cfg.dir_prefix);
snprintf(cmd, sizeof(cmd), "cd \"%s\" && zip -r \"../%s\" ./* %s", cfg.dir_prefix,
zip_name, where_err);
printf("Compressing logs to %s\n", zip_name);
ret_cmd = system(cmd);
if (ret_cmd == -1)
perror(cmd);
else {
output_path = zip_name;
snprintf(cmd, sizeof(cmd), "rm -rf %s", cfg.dir_prefix);
printf("Removing %s\n", cfg.dir_prefix);
if (system(cmd) != 0)
perror("Failed removing logs folder");
}
}

if (log_count == 0) {
if (err > 0)
nvme_show_status(err);
} else if ((log_count > 1) || cfg.verbose)
printf("Total: %d log files with prefix: %s\n", log_count, cfg.file_prefix);
out_dev:
/* Redundant close() to make static code analysis happy */
close(dev->direct.fd);
dev_close(dev);
printf("Total: %d log files in %s\n", log_count, output_path);

return err;
}
2 changes: 1 addition & 1 deletion plugins/solidigm/solidigm-nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

#include "cmd.h"

#define SOLIDIGM_PLUGIN_VERSION "1.0"
#define SOLIDIGM_PLUGIN_VERSION "1.1"

PLUGIN(NAME("solidigm", "Solidigm vendor specific extensions", SOLIDIGM_PLUGIN_VERSION),
COMMAND_LIST(
Expand Down

0 comments on commit 79abafe

Please sign in to comment.