summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Axboe <axboe@suse.de>2005-12-06 20:09:35 +0100
committerJens Axboe <axboe@suse.de>2005-12-06 20:09:35 +0100
commit6fb1339a43dcf007e15cc11ab6cd2c877fae2e27 (patch)
tree522f68ce6b6d43a881e29869f005e86a01b29614
parent23c611af33983eafcba3e7ad223046ad9d5e028f (diff)
[PATCH] fio: improve io engine to include embedded error and resid count
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.
-rw-r--r--fio-ini.c18
-rw-r--r--fio-io.c48
-rw-r--r--fio.c49
-rw-r--r--fio.h3
4 files changed, 78 insertions, 40 deletions
diff --git a/fio-ini.c b/fio-ini.c
index 3fa9d09..d27b238 100644
--- 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;
}
diff --git a/fio-io.c b/fio-io.c
index f663dba..16d894a 100644
--- 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 546ac98..52ad7a6 100644
--- 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 de065cd..ff8e78e 100644
--- 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;