[PATCH] Support residual io counts from io engines
[fio.git] / fio.c
diff --git a/fio.c b/fio.c
index 225aaa4d4550c2ea385f8eaaee70b9b8d1bc321d..127314e3590bd1efd79908eeb5363c5580afef86 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -37,9 +37,9 @@
 #include "fio.h"
 #include "os.h"
 
-#define MASK   (4095)
-
-#define ALIGN(buf)     (char *) (((unsigned long) (buf) + MASK) & ~(MASK))
+static unsigned long page_mask;
+#define ALIGN(buf)     \
+       (char *) (((unsigned long) (buf) + page_mask) & ~page_mask)
 
 int groupid = 0;
 int thread_number = 0;
@@ -49,6 +49,8 @@ int temp_stall_ts;
 static volatile int startup_sem;
 static volatile int fio_abort;
 
+struct io_log *agg_io_log[2];
+
 #define TERMINATE_ALL          (-1)
 #define JOB_START_TIMEOUT      (5 * 1000)
 
@@ -404,11 +406,22 @@ static void do_io(struct thread_data *td)
 
                memcpy(&s, &io_u->start_time, sizeof(s));
 
+requeue:
                ret = td_io_queue(td, io_u);
                if (ret) {
-                       td_verror(td, io_u->error);
-                       put_io_u(td, io_u);
-                       break;
+                       if (ret > 0 && (io_u->xfer_buflen != io_u->resid) &&
+                           io_u->resid) {
+                               /*
+                                * short read/write. requeue.
+                                */
+                               io_u->xfer_buflen = io_u->resid;
+                               io_u->xfer_buf += ret;
+                               goto requeue;
+                       } else {
+                               td_verror(td, io_u->error);
+                               put_io_u(td, io_u);
+                               break;
+                       }
                }
 
                add_slat_sample(td, io_u->ddir, mtime_since(&io_u->start_time, &io_u->issue_time));
@@ -526,7 +539,7 @@ static int init_io_u(struct thread_data *td)
        if (td->mem_type == MEM_SHMHUGE || td->mem_type == MEM_MMAPHUGE)
                td->orig_buffer_size = (td->orig_buffer_size + td->hugepage_size - 1) & ~(td->hugepage_size - 1);
        else
-               td->orig_buffer_size += MASK;
+               td->orig_buffer_size += page_mask;
 
        if (allocate_io_mem(td))
                return 1;
@@ -645,9 +658,6 @@ static void *thread_main(void *data)
                goto err;
        }
 
-       if (td_io_init(td))
-               goto err;
-
        if (init_iolog(td))
                goto err;
 
@@ -678,6 +688,13 @@ static void *thread_main(void *data)
        if (open_files(td))
                goto err;
 
+       /*
+        * Do this late, as some IO engines would like to have the
+        * files setup prior to initializing structures.
+        */
+       if (td_io_init(td))
+               goto err;
+
        if (td->exec_prerun)
                system(td->exec_prerun);
 
@@ -835,7 +852,6 @@ static void run_threads(void)
 
        signal(SIGINT, sig_handler);
        signal(SIGALRM, sig_handler);
-       signal(SIGSEGV, sig_handler);
 
        todo = thread_number;
        nr_running = 0;
@@ -990,6 +1006,8 @@ static void run_threads(void)
 
 int main(int argc, char *argv[])
 {
+       long ps;
+
        if (parse_options(argc, argv))
                return 1;
 
@@ -998,12 +1016,30 @@ int main(int argc, char *argv[])
                return 1;
        }
 
+       ps = sysconf(_SC_PAGESIZE);
+       if (ps < 0) {
+               log_err("Failed to get page size\n");
+               return 1;
+       }
+
+       page_mask = ps - 1;
+
+       if (write_bw_log) {
+               setup_log(&agg_io_log[DDIR_READ]);
+               setup_log(&agg_io_log[DDIR_WRITE]);
+       }
+
        disk_util_timer_arm();
 
        run_threads();
 
-       if (!fio_abort)
+       if (!fio_abort) {
                show_run_stats();
+               if (write_bw_log) {
+                       __finish_log(agg_io_log[DDIR_READ],"agg-read_bw.log");
+                       __finish_log(agg_io_log[DDIR_WRITE],"agg-write_bw.log");
+               }
+       }
 
        return 0;
 }