From: Jens Axboe Date: Tue, 6 Dec 2005 19:09:35 +0000 (+0100) Subject: [PATCH] fio: improve io engine to include embedded error and resid count X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=6fb1339a43dcf007e15cc11ab6cd2c877fae2e27;p=disktools.git [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. --- 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;