Skip to content

Commit 3301d20

Browse files
committed
nvme: add show-topology delay option for nvme top
This is to monitor the system changes. Signed-off-by: Tokunori Ikegami <ikegami.t@gmail.com>
1 parent a2e1b83 commit 3301d20

File tree

2 files changed

+146
-7
lines changed

2 files changed

+146
-7
lines changed

nvme.c

Lines changed: 144 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ struct set_reg_config {
162162
__u32 pmrmscu;
163163
};
164164

165+
#define NVME_OUT "nvme.out"
166+
#define NVME_PREV_OUT "nvme-prev.out"
167+
165168
static const char nvme_version_string[] = NVME_VERSION;
166169

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

195199
static const char *app_tag = "app tag for end-to-end PI";
196200
static const char *app_tag_mask = "app tag mask for end-to-end PI";
@@ -262,6 +266,7 @@ struct nvme_config nvme_cfg = {
262266
.output_format = "normal",
263267
.output_format_ver = 1,
264268
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
269+
.delay = 0,
265270
};
266271

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

370+
static int set_stdout_file(void)
371+
{
372+
if (!freopen(NVME_OUT, "w", stdout)) {
373+
perror("freopen");
374+
return -errno;
375+
}
376+
377+
return 0;
378+
}
379+
365380
static int parse_args(int argc, char *argv[], const char *desc,
366381
struct argconfig_commandline_options *opts)
367382
{
@@ -374,7 +389,10 @@ static int parse_args(int argc, char *argv[], const char *desc,
374389
log_level = map_log_level(nvme_cfg.verbose, false);
375390
nvme_init_default_logging(stderr, log_level, false, false);
376391

377-
return 0;
392+
if (nvme_cfg.delay)
393+
ret = set_stdout_file();
394+
395+
return ret;
378396
}
379397

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

10001-
err = argconfig_parse(argc, argv, desc, opts);
10019+
err = parse_args(argc, argv, desc, opts);
1000210020
if (err)
1000310021
return err;
1000410022

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

1009810116
NVME_ARGS(opts,
10099-
OPT_FMT("ranking", 'r', &cfg.ranking, ranking));
10117+
OPT_FMT("ranking", 'r', &cfg.ranking, ranking),
10118+
OPT_DOUBLE("delay", 'd', &nvme_cfg.delay, delay));
1010010119

10101-
err = argconfig_parse(argc, argv, desc, opts);
10120+
err = parse_args(argc, argv, desc, opts);
1010210121
if (err)
1010310122
return err;
1010410123

@@ -11011,6 +11030,118 @@ void register_extension(struct plugin *plugin)
1101111030
nvme.extensions->tail = plugin;
1101211031
}
1101311032

11033+
static char *read_file(const char *file, size_t *len)
11034+
{
11035+
struct stat st;
11036+
char *buf;
11037+
FILE *fp;
11038+
11039+
fp = fopen(file, "r");
11040+
if (!fp || stat(file, &st))
11041+
return NULL;
11042+
11043+
buf = malloc(st.st_size);
11044+
if (!buf)
11045+
return NULL;
11046+
11047+
*len = fread(buf, 1, st.st_size, fp);
11048+
if (*len)
11049+
return buf;
11050+
11051+
free(buf);
11052+
return NULL;
11053+
}
11054+
11055+
static bool delay_compare(void)
11056+
{
11057+
_cleanup_free_ char *prev_buf = NULL;
11058+
_cleanup_free_ char *buf = NULL;
11059+
size_t prev_len;
11060+
struct stat st;
11061+
size_t len;
11062+
11063+
if (stat(NVME_PREV_OUT, &st))
11064+
return true;
11065+
11066+
buf = read_file(NVME_OUT, &len);
11067+
if (!buf)
11068+
return true;
11069+
11070+
prev_buf = read_file(NVME_PREV_OUT, &prev_len);
11071+
if (!prev_buf || len != prev_len)
11072+
return true;
11073+
11074+
return !!memcmp(buf, prev_buf, len);
11075+
}
11076+
11077+
static bool delay_copy(void)
11078+
{
11079+
_cleanup_free_ char *cmd = NULL;
11080+
int err;
11081+
11082+
if (asprintf(&cmd, "cp %s %s", NVME_OUT, NVME_PREV_OUT) < 0)
11083+
return false;
11084+
11085+
err = system(cmd);
11086+
if (err < 0)
11087+
return false;
11088+
11089+
return true;
11090+
}
11091+
11092+
static bool delay_print(void)
11093+
{
11094+
size_t len;
11095+
_cleanup_free_ char *buf = read_file(NVME_OUT, &len);
11096+
int err;
11097+
11098+
err = system("clear");
11099+
if (err < 0)
11100+
return false;
11101+
11102+
printf("%s", buf);
11103+
11104+
return true;
11105+
}
11106+
11107+
static bool handle_delay(void)
11108+
{
11109+
struct timespec ts;
11110+
double delay_f;
11111+
double delay_i;
11112+
int err;
11113+
11114+
if (!freopen("/dev/tty", "w", stdout))
11115+
return false;
11116+
11117+
if (delay_compare()) {
11118+
if (!delay_print() || !delay_copy())
11119+
return false;
11120+
}
11121+
11122+
delay_f = modf(nvme_cfg.delay, &delay_i);
11123+
ts.tv_sec = delay_i;
11124+
ts.tv_nsec = delay_f * 1000000000;
11125+
err = pselect(0, NULL, NULL, NULL, &ts, NULL);
11126+
if (err < 0)
11127+
return false;
11128+
11129+
return true;
11130+
}
11131+
11132+
static int remove_file(void)
11133+
{
11134+
struct stat st;
11135+
11136+
if (!stat(NVME_OUT, &st) && remove(NVME_OUT))
11137+
return -errno;
11138+
11139+
if (!stat(NVME_PREV_OUT, &st) && remove(NVME_PREV_OUT))
11140+
return -errno;
11141+
11142+
return 0;
11143+
}
11144+
1101411145
int main(int argc, char **argv)
1101511146
{
1101611147
int err;
@@ -11026,9 +11157,15 @@ int main(int argc, char **argv)
1102611157
if (err)
1102711158
return err;
1102811159

11029-
err = handle_plugin(argc - 1, &argv[1], nvme.extensions);
11030-
if (err == -ENOTTY)
11031-
general_help(&builtin, NULL);
11160+
err = remove_file();
11161+
if (err)
11162+
return err;
11163+
11164+
do {
11165+
err = handle_plugin(argc - 1, &argv[1], nvme.extensions);
11166+
if (err == -ENOTTY)
11167+
general_help(&builtin, NULL);
11168+
} while (!err && nvme_cfg.delay && handle_delay());
1103211169

1103311170
return err ? 1 : 0;
1103411171
}

nvme.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ struct nvme_config {
5959
bool dry_run;
6060
bool no_retries;
6161
unsigned int output_format_ver;
62+
double delay;
6263
};
6364

6465
/*
@@ -109,6 +110,7 @@ extern const char *output_format;
109110
extern const char *timeout;
110111
extern const char *verbose;
111112
extern const char *dry_run;
113+
extern const char *delay;
112114
extern struct nvme_config nvme_cfg;
113115

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

0 commit comments

Comments
 (0)