[PATCH] fio: Add option for complete quit if one rate thread fails
authorJens Axboe <axboe@suse.de>
Wed, 19 Oct 2005 12:42:05 +0000 (14:42 +0200)
committerJens Axboe <axboe@suse.de>
Wed, 19 Oct 2005 12:42:05 +0000 (14:42 +0200)
README.fio
fio.c

index 66fa2d5767b86bc8115a95bf1590309ccc230ebb..942544404b5da0144a3f990795a776276fd72947 100644 (file)
@@ -15,6 +15,7 @@ $ fio
        -t <sec> Runtime in seconds
        -w Write statistics
        -r For random io, sequence must be repeatable
+       -R <on> If one thread fails to meet rate, quit all
        -o <on> Use direct IO is 1, buffered if 0
        -f <file> Read <file> for job descriptions
 
diff --git a/fio.c b/fio.c
index 905688250f3880ce5af733864887400671b0fa3b..6f462186cf978827112b3353d703c02e08dcf6b7 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -99,6 +99,7 @@ static int repeatable = DEF_RAND_REPEAT;
 static int timeout = DEF_TIMEOUT;
 static int odirect = DEF_ODIRECT;
 static int global_bs = DEF_BS;
+static int rate_quit = 1;
 
 static int thread_number;
 static char *ini_file;
@@ -112,6 +113,17 @@ enum {
        DDIR_WRITE,
 };
 
+/*
+ * thread life cycle
+ */
+enum {
+       TD_NOT_CREATED = 0,
+       TD_CREATED,
+       TD_STARTED,
+       TD_EXITED,
+       TD_REAPED,
+};
+
 struct thread_data {
        char file_name[256];
        int thread_number;
@@ -120,7 +132,7 @@ struct thread_data {
        int stat_fd;
        pid_t pid;
        volatile int terminate;
-       volatile int started;
+       volatile int runstate;
        unsigned int ddir;
        unsigned int ioprio;
        unsigned int sequential;
@@ -162,6 +174,8 @@ static struct thread_data *threads;
 
 static sem_t startup_sem;
 
+static volatile int do_quit;
+
 static void sig_handler(int sig)
 {
        int i;
@@ -173,6 +187,12 @@ static void sig_handler(int sig)
        }
 }
 
+static void terminate_threads(void)
+{
+       do_quit = 1;
+       sig_handler(0);
+}
+
 static int init_random_state(struct thread_data *td)
 {
        unsigned long seed = 123;
@@ -359,6 +379,8 @@ static int check_min_rate(struct thread_data *td, struct timeval *now)
                rate = ((td->io_blocks - td->rate_blocks) * td->bs) / spent;
                if (rate < td->ratemin) {
                        printf("Client%d: min rate %d not met, got %ldKiB/sec\n", td->thread_number, td->ratemin, rate);
+                       if (rate_quit)
+                               terminate_threads();
                        return 1;
                }
        }
@@ -522,6 +544,8 @@ err:
                close(td->fd);
        if (ret)
                sem_post(&startup_sem);
+
+       td->runstate = TD_EXITED;
        shmdt(data);
        return NULL;
 }
@@ -947,6 +971,10 @@ static int parse_options(int argc, char *argv[])
                                parm++;
                                repeatable = !!atoi(parm);
                                break;
+                       case 'R':
+                               parm++;
+                               rate_quit = !!atoi(parm);
+                               break;
                        case 'o':
                                parm++;
                                odirect = !!atoi(parm);
@@ -967,12 +995,29 @@ static int parse_options(int argc, char *argv[])
        return i;
 }
 
+static int reap_threads(void)
+{
+       int i, reaped = 0;
+
+       for (i = 0; i < thread_number; i++) {
+               struct thread_data *td = &threads[i];
+
+               if (td->runstate == TD_EXITED) {
+                       td->runstate = TD_REAPED;
+                       waitpid(td->pid, NULL, 0);
+                       reaped++;
+               }
+       }
+
+       return reaped;
+}
+
 static void run_threads(char *argv[])
 {
        struct timeval genesis, now;
        struct thread_data *td;
        unsigned long spent;
-       int i, todo;
+       int i, todo, nr_running;
 
        gettimeofday(&genesis, NULL);
 
@@ -985,12 +1030,13 @@ static void run_threads(char *argv[])
        }
 
        todo = thread_number;
+       nr_running = 0;
 
-       while (todo) {
+       while (todo && !do_quit) {
                for (i = 0; i < thread_number; i++) {
                        td = &threads[i];
 
-                       if (td->started)
+                       if (td->runstate != TD_NOT_CREATED)
                                continue;
 
                        if (td->start_delay) {
@@ -1001,7 +1047,7 @@ static void run_threads(char *argv[])
                                        continue;
                        }
 
-                       td->started = 1;
+                       td->runstate = TD_CREATED;
                        sem_init(&startup_sem, 1, 1);
                        todo--;
 
@@ -1016,15 +1062,24 @@ static void run_threads(char *argv[])
                for (i = 0; i < thread_number; i++) {
                        struct thread_data *td = &threads[i];
 
-                       if (td->started == 1) {
-                               td->started++;
+                       if (td->runstate == TD_CREATED) {
+                               td->runstate = TD_STARTED;
+                               nr_running++;
                                sem_post(&td->mutex);
+                               printf("%d threads now running\n", nr_running);
                        }
                }
 
+               nr_running -= reap_threads();
+
                if (todo)
                        usleep(100000);
        }
+
+       while (nr_running) {
+               nr_running -= reap_threads();
+               usleep(10000);
+       }
 }
 
 int main(int argc, char *argv[])
@@ -1070,12 +1125,6 @@ int main(int argc, char *argv[])
 
        run_threads(argv);
 
-       for (i = 0; i < thread_number; i++) {
-               struct thread_data *td = &threads[i];
-
-               waitpid(td->pid, NULL, 0);
-       }
-
        min_bw[0] = min_run[0] = ~0UL;
        min_bw[1] = min_run[1] = ~0UL;
        minl[0] = minl[1] = ~0UL;