X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=io_u.c;h=eec378ddc0258169e3edbeb84046f7f27cef6282;hp=0b2754f1e9441f8d0ba5a8ea060ad7760fa76c90;hb=HEAD;hpb=ad21b61d27fd94b4c94a5e26842106d76ea54ba0 diff --git a/io_u.c b/io_u.c index 0b2754f1..a090e121 100644 --- a/io_u.c +++ b/io_u.c @@ -360,6 +360,17 @@ static int get_next_seq_offset(struct thread_data *td, struct fio_file *f, loop_cache_invalidate(td, f); } + /* + * If we reach the end for a rw-io-size based run, reset us back to 0 + * and invalidate the cache, if we need to. + */ + if (td_rw(td) && o->io_size > o->size) { + if (f->last_pos[ddir] >= f->io_size + get_start_offset(td, f)) { + f->last_pos[ddir] = f->file_offset; + loop_cache_invalidate(td, f); + } + } + if (f->last_pos[ddir] < f->real_file_size) { uint64_t pos; @@ -717,7 +728,7 @@ static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir) * check if the usec is capable of taking negative values */ if (now > td->o.timeout) { - ddir = DDIR_INVAL; + ddir = DDIR_TIMEOUT; return ddir; } usec = td->o.timeout - now; @@ -726,7 +737,7 @@ static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir) now = utime_since_now(&td->epoch); if ((td->o.timeout && (now > td->o.timeout)) || td->terminate) - ddir = DDIR_INVAL; + ddir = DDIR_TIMEOUT; return ddir; } @@ -940,6 +951,65 @@ static void setup_strided_zone_mode(struct thread_data *td, struct io_u *io_u) fio_file_reset(td, f); } +static int fill_multi_range_io_u(struct thread_data *td, struct io_u *io_u) +{ + bool is_random; + uint64_t buflen, i = 0; + struct trim_range *range; + struct fio_file *f = io_u->file; + uint8_t *buf; + + buf = io_u->buf; + buflen = 0; + + while (i < td->o.num_range) { + range = (struct trim_range *)buf; + if (get_next_offset(td, io_u, &is_random)) { + dprint(FD_IO, "io_u %p, failed getting offset\n", + io_u); + break; + } + + io_u->buflen = get_next_buflen(td, io_u, is_random); + if (!io_u->buflen) { + dprint(FD_IO, "io_u %p, failed getting buflen\n", io_u); + break; + } + + if (io_u->offset + io_u->buflen > io_u->file->real_file_size) { + dprint(FD_IO, "io_u %p, off=0x%llx + len=0x%llx exceeds file size=0x%llx\n", + io_u, + (unsigned long long) io_u->offset, io_u->buflen, + (unsigned long long) io_u->file->real_file_size); + break; + } + + range->start = io_u->offset; + range->len = io_u->buflen; + buflen += io_u->buflen; + f->last_start[io_u->ddir] = io_u->offset; + f->last_pos[io_u->ddir] = io_u->offset + range->len; + + buf += sizeof(struct trim_range); + i++; + + if (td_random(td) && file_randommap(td, io_u->file)) + mark_random_map(td, io_u, io_u->offset, io_u->buflen); + dprint_io_u(io_u, "fill"); + } + if (buflen) { + /* + * Set buffer length as overall trim length for this IO, and + * tell the ioengine about the number of ranges to be trimmed. + */ + io_u->buflen = buflen; + io_u->number_trim = i; + return 0; + } + + return 1; +} + static int fill_io_u(struct thread_data *td, struct io_u *io_u) { bool is_random; @@ -951,7 +1021,7 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u) set_rw_ddir(td, io_u); - if (io_u->ddir == DDIR_INVAL) { + if (io_u->ddir == DDIR_INVAL || io_u->ddir == DDIR_TIMEOUT) { dprint(FD_IO, "invalid direction received ddir = %d", io_u->ddir); return 1; } @@ -966,28 +1036,38 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u) else if (td->o.zone_mode == ZONE_MODE_ZBD) setup_zbd_zone_mode(td, io_u); - /* - * No log, let the seq/rand engine retrieve the next buflen and - * position. - */ - if (get_next_offset(td, io_u, &is_random)) { - dprint(FD_IO, "io_u %p, failed getting offset\n", io_u); - return 1; - } + if (multi_range_trim(td, io_u)) { + if (fill_multi_range_io_u(td, io_u)) + return 1; + } else { + /* + * No log, let the seq/rand engine retrieve the next buflen and + * position. + */ + if (get_next_offset(td, io_u, &is_random)) { + dprint(FD_IO, "io_u %p, failed getting offset\n", io_u); + return 1; + } - io_u->buflen = get_next_buflen(td, io_u, is_random); - if (!io_u->buflen) { - dprint(FD_IO, "io_u %p, failed getting buflen\n", io_u); - return 1; + io_u->buflen = get_next_buflen(td, io_u, is_random); + if (!io_u->buflen) { + dprint(FD_IO, "io_u %p, failed getting buflen\n", io_u); + return 1; + } } - offset = io_u->offset; + if (td->o.zone_mode == ZONE_MODE_ZBD) { ret = zbd_adjust_block(td, io_u); - if (ret == io_u_eof) + if (ret == io_u_eof) { + dprint(FD_IO, "zbd_adjust_block() returned io_u_eof\n"); return 1; + } } + if (td->o.dp_type != FIO_DP_NONE) + dp_fill_dspec_data(td, io_u); + if (io_u->offset + io_u->buflen > io_u->file->real_file_size) { dprint(FD_IO, "io_u %p, off=0x%llx + len=0x%llx exceeds file size=0x%llx\n", io_u, @@ -999,11 +1079,12 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u) /* * mark entry before potentially trimming io_u */ - if (td_random(td) && file_randommap(td, io_u->file)) + if (!multi_range_trim(td, io_u) && td_random(td) && file_randommap(td, io_u->file)) io_u->buflen = mark_random_map(td, io_u, offset, io_u->buflen); out: - dprint_io_u(io_u, "fill"); + if (!multi_range_trim(td, io_u)) + dprint_io_u(io_u, "fill"); io_u->verify_offset = io_u->offset; td->zone_bytes += io_u->buflen; return 0; @@ -1365,8 +1446,8 @@ static struct fio_file *__get_next_file(struct thread_data *td) if (td->o.file_service_type == FIO_FSERVICE_SEQ) goto out; if (td->file_service_left) { - td->file_service_left--; - goto out; + td->file_service_left--; + goto out; } } @@ -1414,6 +1495,10 @@ static long set_io_u_file(struct thread_data *td, struct io_u *io_u) put_file_log(td, f); td_io_close_file(td, f); io_u->file = NULL; + + if (io_u->ddir == DDIR_TIMEOUT) + return 1; + if (td->o.file_service_type & __FIO_FSERVICE_NONUNIFORM) fio_file_reset(td, f); else { @@ -1608,7 +1693,6 @@ struct io_u *__get_io_u(struct thread_data *td) { const bool needs_lock = td_async_processing(td); struct io_u *io_u = NULL; - int ret; if (td->stop_io) return NULL; @@ -1642,14 +1726,16 @@ again: io_u_set(td, io_u, IO_U_F_IN_CUR_DEPTH); io_u->ipo = NULL; } else if (td_async_processing(td)) { + int ret; /* * We ran out, wait for async verify threads to finish and * return one */ assert(!(td->flags & TD_F_CHILD)); ret = pthread_cond_wait(&td->free_cond, &td->io_u_lock); - assert(ret == 0); - if (!td->error) + if (fio_unlikely(ret != 0)) { + td->error = errno; + } else if (!td->error) goto again; } @@ -1804,7 +1890,7 @@ struct io_u *get_io_u(struct thread_data *td) assert(fio_file_open(f)); - if (ddir_rw(io_u->ddir)) { + if (ddir_rw(io_u->ddir) && !multi_range_trim(td, io_u)) { if (!io_u->buflen && !td_ioengine_flagged(td, FIO_NOIO)) { dprint(FD_IO, "get_io_u: zero buflen on %p\n", io_u); goto err_put; @@ -1820,8 +1906,9 @@ struct io_u *get_io_u(struct thread_data *td) io_u->buflen); } else if ((td->flags & TD_F_SCRAMBLE_BUFFERS) && !(td->flags & TD_F_COMPRESS) && - !(td->flags & TD_F_DO_VERIFY)) + !(td->flags & TD_F_DO_VERIFY)) { do_scramble = 1; + } } else if (io_u->ddir == DDIR_READ) { /* * Reset the buf_filled parameters so next time if the @@ -1873,6 +1960,8 @@ static void __io_u_log_error(struct thread_data *td, struct io_u *io_u) io_ddir_name(io_u->ddir), io_u->offset, io_u->xfer_buflen); + zbd_log_err(td, io_u); + if (td->io_ops->errdetails) { char *err = td->io_ops->errdetails(io_u); @@ -2022,7 +2111,8 @@ static void io_completed(struct thread_data *td, struct io_u **io_u_ptr, } if (ddir_sync(ddir)) { - td->last_was_sync = true; + if (io_u->error) + goto error; if (f) { f->first_write = -1ULL; f->last_write = -1ULL; @@ -2032,7 +2122,6 @@ static void io_completed(struct thread_data *td, struct io_u **io_u_ptr, return; } - td->last_was_sync = false; td->last_ddir = ddir; if (!io_u->error && ddir_rw(ddir)) { @@ -2077,6 +2166,7 @@ static void io_completed(struct thread_data *td, struct io_u **io_u_ptr, icd->error = ret; } } else if (io_u->error) { +error: icd->error = io_u->error; io_u_log_error(td, io_u); } @@ -2136,7 +2226,8 @@ static void io_u_update_bytes_done(struct thread_data *td, if (td->runstate == TD_VERIFYING) { td->bytes_verified += icd->bytes_done[DDIR_READ]; - return; + if (td_write(td)) + return; } for (ddir = 0; ddir < DDIR_RWDIR_CNT; ddir++) @@ -2371,7 +2462,7 @@ int do_io_u_sync(const struct thread_data *td, struct io_u *io_u) return ret; } -int do_io_u_trim(const struct thread_data *td, struct io_u *io_u) +int do_io_u_trim(struct thread_data *td, struct io_u *io_u) { #ifndef FIO_HAVE_TRIM io_u->error = EINVAL;