Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 144 additions & 7 deletions nvme.c
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ struct set_reg_config {
__u32 pmrmscu;
};

#define NVME_OUT "nvme.out"
#define NVME_PREV_OUT "nvme-prev.out"

static const char nvme_version_string[] = NVME_VERSION;

static struct plugin builtin = {
Expand Down Expand Up @@ -191,6 +194,7 @@ const char *output_format = "Output format: normal|binary";
const char *timeout = "timeout value, in milliseconds";
const char *verbose = "Increase output verbosity";
const char *dry_run = "show command instead of sending";
const char *delay = "iterative delay as SECS [.TENTHS]";

static const char *app_tag = "app tag for end-to-end PI";
static const char *app_tag_mask = "app tag mask for end-to-end PI";
Expand Down Expand Up @@ -262,6 +266,7 @@ struct nvme_config nvme_cfg = {
.output_format = "normal",
.output_format_ver = 1,
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
.delay = 0,
};

static void *mmap_registers(struct nvme_transport_handle *hdl, bool writable);
Expand Down Expand Up @@ -362,6 +367,16 @@ static int get_transport_handle(struct nvme_global_ctx *ctx, int argc,
return ret;
}

static int set_stdout_file(void)
{
if (!freopen(NVME_OUT, "w", stdout)) {
perror("freopen");
return -errno;
}

return 0;
}

static int parse_args(int argc, char *argv[], const char *desc,
struct argconfig_commandline_options *opts)
{
Expand All @@ -374,7 +389,10 @@ static int parse_args(int argc, char *argv[], const char *desc,
log_level = map_log_level(nvme_cfg.verbose, false);
nvme_init_default_logging(stderr, log_level, false, false);

return 0;
if (nvme_cfg.delay)
ret = set_stdout_file();

return ret;
}

int parse_and_open(struct nvme_global_ctx **ctx,
Expand Down Expand Up @@ -9998,7 +10016,7 @@ static int tls_key(int argc, char **argv, struct command *acmd, struct plugin *p
OPT_FLAG("export", 'e', &cfg.export, export),
OPT_STR("revoke", 'r', &cfg.revoke, revoke));

err = argconfig_parse(argc, argv, desc, opts);
err = parse_args(argc, argv, desc, opts);
if (err)
return err;

Expand Down Expand Up @@ -10096,9 +10114,10 @@ static int show_topology_cmd(int argc, char **argv, struct command *acmd, struct
};

NVME_ARGS(opts,
OPT_FMT("ranking", 'r', &cfg.ranking, ranking));
OPT_FMT("ranking", 'r', &cfg.ranking, ranking),
OPT_DOUBLE("delay", 'd', &nvme_cfg.delay, delay));

err = argconfig_parse(argc, argv, desc, opts);
err = parse_args(argc, argv, desc, opts);
if (err)
return err;

Expand Down Expand Up @@ -11011,6 +11030,118 @@ void register_extension(struct plugin *plugin)
nvme.extensions->tail = plugin;
}

static char *read_file(const char *file, size_t *len)
{
struct stat st;
char *buf;
FILE *fp;

fp = fopen(file, "r");
if (!fp || stat(file, &st))
return NULL;

buf = malloc(st.st_size);
if (!buf)
return NULL;

*len = fread(buf, 1, st.st_size, fp);
if (*len)
return buf;

free(buf);
return NULL;
}

static bool delay_compare(void)
{
_cleanup_free_ char *prev_buf = NULL;
_cleanup_free_ char *buf = NULL;
size_t prev_len;
struct stat st;
size_t len;

if (stat(NVME_PREV_OUT, &st))
return true;

buf = read_file(NVME_OUT, &len);
if (!buf)
return true;

prev_buf = read_file(NVME_PREV_OUT, &prev_len);
if (!prev_buf || len != prev_len)
return true;

return !!memcmp(buf, prev_buf, len);
}

static bool delay_copy(void)
{
_cleanup_free_ char *cmd = NULL;
int err;

if (asprintf(&cmd, "cp %s %s", NVME_OUT, NVME_PREV_OUT) < 0)
return false;

err = system(cmd);
if (err < 0)
return false;

return true;
}

static bool delay_print(void)
{
size_t len;
_cleanup_free_ char *buf = read_file(NVME_OUT, &len);
int err;

err = system("clear");
if (err < 0)
return false;

printf("%s", buf);

return true;
}

static bool handle_delay(void)
{
struct timespec ts;
double delay_f;
double delay_i;
int err;

if (!freopen("/dev/tty", "w", stdout))
return false;

if (delay_compare()) {
if (!delay_print() || !delay_copy())
return false;
}

delay_f = modf(nvme_cfg.delay, &delay_i);
ts.tv_sec = delay_i;
ts.tv_nsec = delay_f * 1000000000;
err = pselect(0, NULL, NULL, NULL, &ts, NULL);
if (err < 0)
return false;

return true;
}

static int remove_file(void)
{
struct stat st;

if (!stat(NVME_OUT, &st) && remove(NVME_OUT))
return -errno;

if (!stat(NVME_PREV_OUT, &st) && remove(NVME_PREV_OUT))
return -errno;

return 0;
}

int main(int argc, char **argv)
{
int err;
Expand All @@ -11026,9 +11157,15 @@ int main(int argc, char **argv)
if (err)
return err;

err = handle_plugin(argc - 1, &argv[1], nvme.extensions);
if (err == -ENOTTY)
general_help(&builtin, NULL);
err = remove_file();
if (err)
return err;

do {
err = handle_plugin(argc - 1, &argv[1], nvme.extensions);
if (err == -ENOTTY)
general_help(&builtin, NULL);
} while (!err && nvme_cfg.delay && handle_delay());

return err ? 1 : 0;
}
2 changes: 2 additions & 0 deletions nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ struct nvme_config {
bool dry_run;
bool no_retries;
unsigned int output_format_ver;
double delay;
};

/*
Expand Down Expand Up @@ -109,6 +110,7 @@ extern const char *output_format;
extern const char *timeout;
extern const char *verbose;
extern const char *dry_run;
extern const char *delay;
extern struct nvme_config nvme_cfg;

int validate_output_format(const char *format, nvme_print_flags_t *flags);
Expand Down