Add support for other ways of triggering intermediate result outputs
Fio has support for using the USR1 signal to dump the current
results while continuing to run. Add a --status-interval parameter
to allow this to be configured to automatically happen every X
seconds.
There's also support for signaling fio through the file system. To
do that, simply touch /tmp/fio-dump-status. When fio sees this file,
it will unlink and dump the current results.
A small tweak is needed for the file approach to work in Windows.
Signed-off-by: Jens Axboe <axboe@kernel.dk>
diff --git a/HOWTO b/HOWTO
index c7d0c9e..6445348 100644
--- a/HOWTO
+++ b/HOWTO
@@ -1600,6 +1600,9 @@
It is also possible to get fio to dump the current output while it is
running, without terminating the job. To do that, send fio the USR1 signal.
+You can also get regularly timed dumps by using the --status-interval
+parameter, or by creating a file in /tmp named fio-dump-status. If fio
+sees this file, it will unlink it and dump the current output status.
7.0 Terse output
@@ -1721,7 +1724,7 @@
9.0 CPU idleness profiling
-
+--------------------------
In some cases, we want to understand CPU overhead in a test. For example,
we test patches for the specific goodness of whether they reduce CPU usage.
fio implements a balloon approach to create a thread per CPU that runs at
diff --git a/README b/README
index 3782570..15a0731 100644
--- a/README
+++ b/README
@@ -155,6 +155,7 @@
--eta=when When ETA estimate should be printed
May be "always", "never" or "auto"
--eta-newline=time Force a new line for every 'time' period passed
+ --status-interval=t Force full status dump every 't' period passed
--section=name Only run specified section in job file.
Multiple sections can be specified.
--alloc-size=kb Set smalloc pool to this size in kb (def 1024)
diff --git a/backend.c b/backend.c
index f48b43d..4d4e8ef 100644
--- a/backend.c
+++ b/backend.c
@@ -1558,6 +1558,12 @@
fio_terminate_threads(TERMINATE_ALL);
}
+static void do_usleep(unsigned int usecs)
+{
+ check_for_running_stats();
+ usleep(usecs);
+}
+
/*
* Main function for kicking off and reaping jobs, as needed.
*/
@@ -1736,7 +1742,7 @@
if (mtime_since_now(&this_start) > JOB_START_TIMEOUT)
break;
- usleep(100000);
+ do_usleep(100000);
for (i = 0; i < this_jobs; i++) {
td = map[i];
@@ -1788,12 +1794,12 @@
reap_threads(&nr_running, &t_rate, &m_rate);
if (todo)
- usleep(100000);
+ do_usleep(100000);
}
while (nr_running) {
reap_threads(&nr_running, &t_rate, &m_rate);
- usleep(10000);
+ do_usleep(10000);
}
fio_idle_prof_stop();
diff --git a/fio.h b/fio.h
index 50a868a..ebf6309 100644
--- a/fio.h
+++ b/fio.h
@@ -362,6 +362,7 @@
extern int is_backend;
extern int nr_clients;
extern int log_syslog;
+extern int status_interval;
extern const char fio_version_string[];
extern struct thread_data *threads;
diff --git a/init.c b/init.c
index 634dda2..ff9b6d4 100644
--- a/init.c
+++ b/init.c
@@ -58,6 +58,7 @@
int write_bw_log = 0;
int read_only = 0;
+int status_interval = 0;
static int write_lat_log;
@@ -123,9 +124,9 @@
.val = 'c' | FIO_CLIENT_FLAG,
},
{
- .name = (char *) "enghelp",
+ .name = (char *) "enghelp",
.has_arg = optional_argument,
- .val = 'i' | FIO_CLIENT_FLAG,
+ .val = 'i' | FIO_CLIENT_FLAG,
},
{
.name = (char *) "showcmd",
@@ -212,6 +213,11 @@
.val = 'I',
},
{
+ .name = (char *) "status-interval",
+ .has_arg = required_argument,
+ .val = 'L',
+ },
+ {
.name = NULL,
},
};
@@ -1361,6 +1367,8 @@
printf(" \t\tMay be \"always\", \"never\" or \"auto\"\n");
printf(" --eta-newline=time\tForce a new line for every 'time'");
printf(" period passed\n");
+ printf(" --status-interval=t\tForce full status dump every");
+ printf(" 't' period passed\n");
printf(" --readonly\t\tTurn on safety read-only checks, preventing"
" writes\n");
printf(" --section=name\tOnly run specified section in job file\n");
@@ -1789,6 +1797,18 @@
do_exit++;
exit_val = fio_monotonic_clocktest();
break;
+ case 'L': {
+ long long val;
+
+ if (check_str_time(optarg, &val)) {
+ log_err("fio: failed parsing time %s\n", optarg);
+ do_exit++;
+ exit_val = 1;
+ break;
+ }
+ status_interval = val * 1000;
+ break;
+ }
case '?':
log_err("%s: unrecognized option '%s'\n", argv[0],
argv[optind - 1]);
diff --git a/parse.c b/parse.c
index e8b628c..63c94e3 100644
--- a/parse.c
+++ b/parse.c
@@ -285,7 +285,7 @@
return str_to_decimal(p, val, 1, data);
}
-static int check_str_time(const char *p, long long *val)
+int check_str_time(const char *p, long long *val)
{
return str_to_decimal(p, val, 0, NULL);
}
diff --git a/parse.h b/parse.h
index b9da7b9..cf15ce0 100644
--- a/parse.h
+++ b/parse.h
@@ -89,6 +89,7 @@
extern void strip_blank_end(char *);
extern int str_to_decimal(const char *, long long *, int, void *);
extern int check_str_bytes(const char *p, long long *val, void *data);
+extern int check_str_time(const char *p, long long *val);
extern int str_to_float(const char *str, double *val);
/*
diff --git a/stat.c b/stat.c
index 3db0612..7ff7ad4 100644
--- a/stat.c
+++ b/stat.c
@@ -1420,6 +1420,40 @@
pthread_detach(thread);
}
+static int status_interval_init;
+static struct timeval status_time;
+
+#define FIO_STATUS_FILE "/tmp/fio-dump-status"
+
+static int check_status_file(void)
+{
+ struct stat sb;
+
+ if (stat(FIO_STATUS_FILE, &sb))
+ return 0;
+
+ unlink(FIO_STATUS_FILE);
+ return 1;
+}
+
+void check_for_running_stats(void)
+{
+ if (status_interval) {
+ if (!status_interval_init) {
+ fio_gettime(&status_time, NULL);
+ status_interval_init = 1;
+ } else if (mtime_since_now(&status_time) >= status_interval) {
+ show_running_run_stats();
+ fio_gettime(&status_time, NULL);
+ return;
+ }
+ }
+ if (check_status_file()) {
+ show_running_run_stats();
+ return;
+ }
+}
+
static inline void add_stat_sample(struct io_stat *is, unsigned long data)
{
double val = data;
diff --git a/stat.h b/stat.h
index 0125f57..b1bf5dc 100644
--- a/stat.h
+++ b/stat.h
@@ -205,6 +205,7 @@
extern void display_thread_status(struct jobs_eta *je);
extern void show_run_stats(void);
extern void show_running_run_stats(void);
+extern void check_for_running_stats(void);
extern void sum_thread_stats(struct thread_stat *dst, struct thread_stat *src, int nr);
extern void sum_group_stats(struct group_run_stats *dst, struct group_run_stats *src);
extern void init_thread_stat(struct thread_stat *ts);