X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=io_u.c;h=bee99c3798d8474afcfaaa71a0bc8d1a0c7de2d8;hp=eed7d9d91c8d12d829321ba8ec01b69e2576a381;hb=b3ce355dc217876b762d43dff663bbb45e5da653;hpb=6cc1a3d1ae6e574ac1773ec5dfa46caea4c3627d diff --git a/io_u.c b/io_u.c index eed7d9d9..bee99c37 100644 --- a/io_u.c +++ b/io_u.c @@ -10,6 +10,7 @@ #include "err.h" #include "lib/pow2.h" #include "minmax.h" +#include "zbd.h" struct io_completion_data { int nr; /* input */ @@ -41,9 +42,12 @@ static uint64_t mark_random_map(struct thread_data *td, struct io_u *io_u, block = (offset - f->file_offset) / (uint64_t) min_bs; nr_blocks = (buflen + min_bs - 1) / min_bs; + assert(nr_blocks > 0); - if (!(io_u->flags & IO_U_F_BUSY_OK)) + if (!(io_u->flags & IO_U_F_BUSY_OK)) { nr_blocks = axmap_set_nr(f->io_axmap, block, nr_blocks); + assert(nr_blocks > 0); + } if ((nr_blocks * min_bs) < buflen) buflen = nr_blocks * min_bs; @@ -566,8 +570,10 @@ static unsigned long long get_next_buflen(struct thread_data *td, struct io_u *i power_2 = is_power_of_2(minbs); if (!td->o.bs_unaligned && power_2) buflen &= ~(minbs - 1); - else if (!td->o.bs_unaligned && !power_2) - buflen -= buflen % minbs; + else if (!td->o.bs_unaligned && !power_2) + buflen -= buflen % minbs; + if (buflen > maxbs) + buflen = maxbs; } while (!io_u_fits(td, io_u, buflen)); return buflen; @@ -600,7 +606,7 @@ static inline enum fio_ddir get_rand_ddir(struct thread_data *td) int io_u_quiesce(struct thread_data *td) { - int completed = 0; + int ret = 0, completed = 0; /* * We are going to sleep, ensure that we flush anything pending as @@ -615,17 +621,20 @@ int io_u_quiesce(struct thread_data *td) td_io_commit(td); while (td->io_u_in_flight) { - int ret; - ret = io_u_queued_complete(td, 1); if (ret > 0) completed += ret; + else if (ret < 0) + break; } if (td->flags & TD_F_REGROW_LOGS) regrow_logs(td); - return completed; + if (completed) + return completed; + + return ret; } static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir) @@ -764,6 +773,8 @@ void put_file_log(struct thread_data *td, struct fio_file *f) void put_io_u(struct thread_data *td, struct io_u *io_u) { + const bool needs_lock = td_async_processing(td); + if (io_u->post_submit) { io_u->post_submit(io_u, io_u->error == 0); io_u->post_submit = NULL; @@ -772,7 +783,8 @@ void put_io_u(struct thread_data *td, struct io_u *io_u) if (td->parent) td = td->parent; - td_io_u_lock(td); + if (needs_lock) + __td_io_u_lock(td); if (io_u->file && !(io_u->flags & IO_U_F_NO_FILE_PUT)) put_file_log(td, io_u->file); @@ -786,7 +798,9 @@ void put_io_u(struct thread_data *td, struct io_u *io_u) } io_u_qpush(&td->io_u_freelist, io_u); td_io_u_free_notify(td); - td_io_u_unlock(td); + + if (needs_lock) + __td_io_u_unlock(td); } void clear_io_u(struct thread_data *td, struct io_u *io_u) @@ -797,6 +811,7 @@ void clear_io_u(struct thread_data *td, struct io_u *io_u) void requeue_io_u(struct thread_data *td, struct io_u **io_u) { + const bool needs_lock = td_async_processing(td); struct io_u *__io_u = *io_u; enum fio_ddir ddir = acct_ddir(__io_u); @@ -805,7 +820,8 @@ void requeue_io_u(struct thread_data *td, struct io_u **io_u) if (td->parent) td = td->parent; - td_io_u_lock(td); + if (needs_lock) + __td_io_u_lock(td); io_u_set(td, __io_u, IO_U_F_FREE); if ((__io_u->flags & IO_U_F_FLIGHT) && ddir_rw(ddir)) @@ -819,7 +835,10 @@ void requeue_io_u(struct thread_data *td, struct io_u **io_u) io_u_rpush(&td->io_u_requeues, __io_u); td_io_u_free_notify(td); - td_io_u_unlock(td); + + if (needs_lock) + __td_io_u_unlock(td); + *io_u = NULL; } @@ -869,6 +888,8 @@ static void setup_strided_zone_mode(struct thread_data *td, struct io_u *io_u) static int fill_io_u(struct thread_data *td, struct io_u *io_u) { bool is_random; + uint64_t offset; + enum io_u_action ret; if (td_ioengine_flagged(td, FIO_NOIO)) goto out; @@ -899,6 +920,13 @@ static int fill_io_u(struct thread_data *td, struct io_u *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) + return 1; + } + 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, @@ -911,8 +939,7 @@ 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)) - io_u->buflen = mark_random_map(td, io_u, io_u->offset, - io_u->buflen); + io_u->buflen = mark_random_map(td, io_u, offset, io_u->buflen); out: dprint_io_u(io_u, "fill"); @@ -1492,13 +1519,15 @@ bool queue_full(const struct thread_data *td) 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; - td_io_u_lock(td); + if (needs_lock) + __td_io_u_lock(td); again: if (!io_u_rempty(&td->io_u_requeues)) @@ -1532,10 +1561,13 @@ again: assert(!(td->flags & TD_F_CHILD)); ret = pthread_cond_wait(&td->free_cond, &td->io_u_lock); assert(ret == 0); - goto again; + if (!td->error) + goto again; } - td_io_u_unlock(td); + if (needs_lock) + __td_io_u_unlock(td); + return io_u; } @@ -1772,6 +1804,16 @@ static inline bool gtod_reduce(struct thread_data *td) || td->o.gtod_reduce; } +static void trim_block_info(struct thread_data *td, struct io_u *io_u) +{ + uint32_t *info = io_u_block_info(td, io_u); + + if (BLOCK_INFO_STATE(*info) >= BLOCK_STATE_TRIM_FAILURE) + return; + + *info = BLOCK_INFO(BLOCK_STATE_TRIMMED, BLOCK_INFO_TRIMS(*info) + 1); +} + static void account_io_completion(struct thread_data *td, struct io_u *io_u, struct io_completion_data *icd, const enum fio_ddir idx, unsigned int bytes) @@ -1823,18 +1865,8 @@ static void account_io_completion(struct thread_data *td, struct io_u *io_u, } else if (ddir_sync(idx) && !td->o.disable_clat) add_sync_clat_sample(&td->ts, llnsec); - if (td->ts.nr_block_infos && io_u->ddir == DDIR_TRIM) { - uint32_t *info = io_u_block_info(td, io_u); - if (BLOCK_INFO_STATE(*info) < BLOCK_STATE_TRIM_FAILURE) { - if (io_u->ddir == DDIR_TRIM) { - *info = BLOCK_INFO(BLOCK_STATE_TRIMMED, - BLOCK_INFO_TRIMS(*info) + 1); - } else if (io_u->ddir == DDIR_WRITE) { - *info = BLOCK_INFO_SET_STATE(BLOCK_STATE_WRITTEN, - *info); - } - } - } + if (td->ts.nr_block_infos && io_u->ddir == DDIR_TRIM) + trim_block_info(td, io_u); } static void file_log_write_comp(const struct thread_data *td, struct fio_file *f,