[PATCH] fio: improve io engine to include embedded error and resid count
authorJens Axboe <axboe@suse.de>
Tue, 6 Dec 2005 19:09:35 +0000 (20:09 +0100)
committerJens Axboe <axboe@suse.de>
Tue, 6 Dec 2005 19:09:35 +0000 (20:09 +0100)
Also fixes a bug in the posix aio completion, it would not notice
an error before. Also allow any bs and bsrange option, we cannot
always now the restrictions.

fio-ini.c
fio-io.c
fio.c
fio.h

index 3fa9d09ba1716c29dfa60ad050179faa02da194a..d27b2389f7a66697121a1acea0568d26d1fc1722 100644 (file)
--- a/fio-ini.c
+++ b/fio-ini.c
@@ -692,22 +692,18 @@ int parse_jobs_ini(char *file)
                                continue;
                        }
                        if (!check_range(p, "bsrange", &ul1, &ul2)) {
-                               if (ul1 & 511)
-                                       printf("bad min block size, must be a multiple of 512\n");
-                               else
-                                       td->min_bs = ul1;
-                               if (ul2 & 511)
-                                       printf("bad max block size, must be a multiple of 512\n");
-                               else
+                               if (ul1 > ul2) {
+                                       td->max_bs = ul1;
+                                       td->min_bs = ul2;
+                               } else {
                                        td->max_bs = ul2;
+                                       td->min_bs = ul1;
+                               }
                                fgetpos(f, &off);
                                continue;
                        }
                        if (!check_strcnv(p, "bs", &ull)) {
-                               if (ull & 511)
-                                       printf("bad block size, must be a multiple of 512\n");
-                               else
-                                       td->bs = ull;
+                               td->bs = ull;
                                fgetpos(f, &off);
                                continue;
                        }
index f663dbae2bdfa2174f6ea58255754aa3d332ce57..16d894a92f87f4861a9fe0fbdfe0f900325a4e5e 100644 (file)
--- a/fio-io.c
+++ b/fio-io.c
@@ -178,13 +178,22 @@ static int fio_posixaio_getevents(struct thread_data *td, int min, int max,
 restart:
        list_for_each(entry, &td->io_u_busylist) {
                struct io_u *io_u = list_entry(entry, struct io_u, list);
+               int err;
 
                if (io_u->seen)
                        continue;
 
-               if (aio_error(&io_u->aiocb) != EINPROGRESS) {
-                       pd->aio_events[r++] = io_u;
-                       io_u->seen = 1;
+               err = aio_error(&io_u->aiocb);
+               switch (err) {
+                       default:
+                               io_u->error = err;
+                       case ECANCELED:
+                       case 0:
+                               pd->aio_events[r++] = io_u;
+                               io_u->seen = 1;
+                               break;
+                       case EINPROGRESS:
+                               break;
                }
 
                if (r >= max)
@@ -220,9 +229,9 @@ static int fio_posixaio_queue(struct thread_data *td, struct io_u *io_u)
                ret = aio_write(aiocb);
 
        if (ret)
-               return errno;
-
-       return 0;
+               io_u->error = errno;
+               
+       return io_u->error;
 }
 
 static void fio_posixaio_cleanup(struct thread_data *td)
@@ -314,11 +323,18 @@ static int fio_syncio_queue(struct thread_data *td, struct io_u *io_u)
        else
                ret = write(td->fd, io_u->buf, io_u->buflen);
 
-       if (ret < 0)
-               return errno;
+       if (ret != io_u->buflen) {
+               if (ret > 0) {
+                       io_u->resid = io_u->buflen - ret;
+                       io_u->error = ENODATA;
+               } else
+                       io_u->error = errno;
+       }
 
-       sd->last_io_u = io_u;
-       return 0;
+       if (!io_u->error)
+               sd->last_io_u = io_u;
+
+       return io_u->error;
 }
 
 static void fio_syncio_cleanup(struct thread_data *td)
@@ -360,12 +376,16 @@ static int fio_mmapio_queue(struct thread_data *td, struct io_u *io_u)
         * not really direct, but should drop the pages from the cache
         */
        if (td->odirect) {
-               msync(td->mmap + real_off, io_u->buflen, MS_SYNC);
-               madvise(td->mmap + real_off, io_u->buflen,  MADV_DONTNEED);
+               if (msync(td->mmap + real_off, io_u->buflen, MS_SYNC) < 0)
+                       io_u->error = errno;
+               if (madvise(td->mmap + real_off, io_u->buflen,  MADV_DONTNEED) < 0)
+                       io_u->error = errno;
        }
 
-       sd->last_io_u = io_u;
-       return 0;
+       if (!io_u->error)
+               sd->last_io_u = io_u;
+
+       return io_u->error;
 }
 
 static int fio_mmapio_sync(struct thread_data *td)
diff --git a/fio.c b/fio.c
index 546ac98b304cbdfa179c960de640bb322c0b4089..52ad7a6406fa2ae4b58f208105110c366286df06 100644 (file)
--- a/fio.c
+++ b/fio.c
@@ -570,6 +570,8 @@ static struct io_u *__get_io_u(struct thread_data *td)
                return NULL;
 
        io_u = list_entry(td->io_u_freelist.next, struct io_u, list);
+       io_u->error = 0;
+       io_u->resid = 0;
        list_del(&io_u->list);
        list_add(&io_u->list, &td->io_u_busylist);
        td->cur_depth++;
@@ -725,31 +727,38 @@ static int io_u_queue(struct thread_data *td, struct io_u *io_u)
 
 #define iocb_time(iocb)        ((unsigned long) (iocb)->data)
 
-static int ios_completed(struct thread_data *td, int nr)
+static int ios_completed(struct thread_data *td, int nr, int *err)
 {
        unsigned long msec;
        struct io_u *io_u;
        struct timeval e;
        int i, bytes_done;
 
+       if (err)
+               *err = 0;
+
        gettimeofday(&e, NULL);
 
        for (i = 0, bytes_done = 0; i < nr; i++) {
                io_u = td->io_event(td, i);
 
-               td->io_blocks++;
-               td->io_bytes += io_u->buflen;
-               td->this_io_bytes += io_u->buflen;
+               if (!io_u->error) {
+                       td->io_blocks++;
+                       td->io_bytes += (io_u->buflen - io_u->resid);
+                       td->this_io_bytes += (io_u->buflen - io_u->resid);
+
+                       msec = mtime_since(&io_u->issue_time, &e);
 
-               msec = mtime_since(&io_u->issue_time, &e);
+                       add_clat_sample(td, msec);
+                       add_bw_sample(td);
 
-               add_clat_sample(td, msec);
-               add_bw_sample(td);
+                       if (td_write(td))
+                               log_io_piece(td, io_u);
 
-               if (td_write(td))
-                       log_io_piece(td, io_u);
+                       bytes_done += (io_u->buflen - io_u->resid);
+               } else if (err)
+                       *err = io_u->error;
 
-               bytes_done += io_u->buflen;
                put_io_u(td, io_u);
        }
 
@@ -768,7 +777,7 @@ static void cleanup_pending_aio(struct thread_data *td)
         */
        r = io_u_getevents(td, 0, td->cur_depth, &ts);
        if (r > 0)
-               ios_completed(td, r);
+               ios_completed(td, r, NULL);
 
        /*
         * now cancel remaining active events
@@ -786,7 +795,7 @@ static void cleanup_pending_aio(struct thread_data *td)
        if (td->cur_depth) {
                r = io_u_getevents(td, td->cur_depth, td->cur_depth, NULL);
                if (r > 0)
-                       ios_completed(td, r);
+                       ios_completed(td, r, NULL);
        }
 }
 
@@ -856,6 +865,12 @@ static void do_verify(struct thread_data *td)
                }
 
                v_io_u = td->io_event(td, 0);
+               if (v_io_u->error) {
+                       td_verror(td, v_io_u->error);
+                       put_io_u(td, v_io_u);
+                       v_io_u = NULL;
+                       break;
+               }
 
                td->cur_off = v_io_u->offset + v_io_u->buflen;
 
@@ -883,7 +898,7 @@ static void do_io(struct thread_data *td)
        while (td->this_io_bytes < td->io_size) {
                struct timespec ts = { .tv_sec = 0, .tv_nsec = 0};
                struct timespec *timeout;
-               int ret, min_evts = 0;
+               int ret, min_evts = 0, err;
                struct io_u *io_u;
                unsigned int bytes_done;
 
@@ -920,7 +935,11 @@ static void do_io(struct thread_data *td)
                } else if (!ret)
                        continue;
 
-               bytes_done = ios_completed(td, ret);
+               bytes_done = ios_completed(td, ret, &err);
+               if (err) {
+                       td_verror(td, err);
+                       break;
+               }
 
                /*
                 * the rate is batched for now, it should work for batches
@@ -1554,7 +1573,7 @@ static void disk_util_timer_arm(void)
 
 static void clear_io_state(struct thread_data *td)
 {
-       if (td->io_engine & FIO_SYNCIO)
+       if (td->io_engine == FIO_SYNCIO)
                lseek(td->fd, SEEK_SET, 0);
 
        td->cur_off = 0;
diff --git a/fio.h b/fio.h
index de065cd4be7d2b320ab2f7944b9cbee9cce2913a..ff8e78ee14c452b1d95ebd4443c193f6fef8b966 100644 (file)
--- a/fio.h
+++ b/fio.h
@@ -58,6 +58,9 @@ struct io_u {
        unsigned int buflen;
        unsigned long long offset;
 
+       unsigned int resid;
+       unsigned int error;
+
        unsigned char seen;
        unsigned char ddir;