Add support for other ways of triggering intermediate result outputs
authorJens Axboe <axboe@kernel.dk>
Thu, 25 Apr 2013 02:38:54 +0000 (20:38 -0600)
committerJens Axboe <axboe@kernel.dk>
Thu, 25 Apr 2013 02:38:54 +0000 (20:38 -0600)
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>
HOWTO
README
backend.c
fio.h
init.c
parse.c
parse.h
stat.c
stat.h

diff --git a/HOWTO b/HOWTO
index c7d0c9e..6445348 100644 (file)
--- a/HOWTO
+++ b/HOWTO
@@ -1600,6 +1600,9 @@ util=             The disk utilization. A value of 100% means we kept the disk
 
 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 @@ trim       trim the given file from the given 'offset' for 'length' bytes
 
 
 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 (file)
--- a/README
+++ b/README
@@ -155,6 +155,7 @@ $ fio
        --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)
index f48b43d..4d4e8ef 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -1558,6 +1558,12 @@ reaped:
                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 @@ static void run_threads(void)
                        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 @@ static void run_threads(void)
                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 (file)
--- a/fio.h
+++ b/fio.h
@@ -362,6 +362,7 @@ extern int terse_version;
 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 (file)
--- a/init.c
+++ b/init.c
@@ -58,6 +58,7 @@ int log_syslog = 0;
 
 int write_bw_log = 0;
 int read_only = 0;
+int status_interval = 0;
 
 static int write_lat_log;
 
@@ -123,9 +124,9 @@ static struct option l_opts[FIO_NR_OPTIONS] = {
                .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",
@@ -211,6 +212,11 @@ static struct option l_opts[FIO_NR_OPTIONS] = {
                .has_arg        = required_argument,
                .val            = 'I',
        },
+       {
+               .name           = (char *) "status-interval",
+               .has_arg        = required_argument,
+               .val            = 'L',
+       },
        {
                .name           = NULL,
        },
@@ -1361,6 +1367,8 @@ static void usage(const char *name)
        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 @@ int parse_cmd_line(int argc, char *argv[], int client_type)
                        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 (file)
--- a/parse.c
+++ b/parse.c
@@ -285,7 +285,7 @@ int check_str_bytes(const char *p, long long *val, void *data)
        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 (file)
--- a/parse.h
+++ b/parse.h
@@ -89,6 +89,7 @@ extern void strip_blank_front(char **);
 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 (file)
--- a/stat.c
+++ b/stat.c
@@ -1420,6 +1420,40 @@ void show_running_run_stats(void)
        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 (file)
--- a/stat.h
+++ b/stat.h
@@ -205,6 +205,7 @@ extern int calc_thread_status(struct jobs_eta *je, int force);
 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);