X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=io_u.c;h=77557dfdca12748f1db2249c05efc93a21b09f4b;hb=30cb4c650a0a4c7ca79d4336ddb1fe3f988a4b2a;hp=4264cd54115ca39e2e70d97857179f009d24b742;hpb=9a50c5c5650fdd9f3117e3745f16cc63c5b267b7;p=fio.git diff --git a/io_u.c b/io_u.c index 4264cd54..77557dfd 100644 --- a/io_u.c +++ b/io_u.c @@ -11,6 +11,7 @@ #include "trim.h" #include "lib/rand.h" #include "lib/axmap.h" +#include "err.h" struct io_completion_data { int nr; /* input */ @@ -985,6 +986,9 @@ static struct fio_file *get_next_file_rand(struct thread_data *td, if (!fio_file_open(f)) { int err; + if (td->nr_open_files >= td->o.open_files) + return ERR_PTR(-EBUSY); + err = td_io_open_file(td, f); if (err) continue; @@ -1027,6 +1031,9 @@ static struct fio_file *get_next_file_rr(struct thread_data *td, int goodf, if (!fio_file_open(f)) { int err; + if (td->nr_open_files >= td->o.open_files) + return ERR_PTR(-EBUSY); + err = td_io_open_file(td, f); if (err) { dprint(FD_FILE, "error %d on open of %s\n", @@ -1080,10 +1087,16 @@ static struct fio_file *__get_next_file(struct thread_data *td) else f = get_next_file_rand(td, FIO_FILE_open, FIO_FILE_closing); + if (IS_ERR(f)) + return f; + td->file_service_file = f; td->file_service_left = td->file_service_nr - 1; out: - dprint(FD_FILE, "get_next_file: %p [%s]\n", f, f->file_name); + if (f) + dprint(FD_FILE, "get_next_file: %p [%s]\n", f, f->file_name); + else + dprint(FD_FILE, "get_next_file: NULL\n"); return f; } @@ -1099,14 +1112,14 @@ static struct fio_file *get_next_file(struct thread_data *td) return __get_next_file(td); } -static int set_io_u_file(struct thread_data *td, struct io_u *io_u) +static long set_io_u_file(struct thread_data *td, struct io_u *io_u) { struct fio_file *f; do { f = get_next_file(td); - if (!f) - return 1; + if (IS_ERR_OR_NULL(f)) + return PTR_ERR(f); io_u->file = f; get_file(f); @@ -1152,6 +1165,10 @@ static int __lat_target_failed(struct thread_data *td) return 1; td->latency_qd_high = td->latency_qd; + + if (td->latency_qd == td->latency_qd_low) + td->latency_qd_low--; + td->latency_qd = (td->latency_qd + td->latency_qd_low) / 2; dprint(FD_RATE, "Ramped down: %d %d %d\n", td->latency_qd_low, td->latency_qd, td->latency_qd_high); @@ -1176,6 +1193,8 @@ static int lat_target_failed(struct thread_data *td) void lat_target_init(struct thread_data *td) { + td->latency_end_run = 0; + if (td->o.latency_target) { dprint(FD_RATE, "Latency target=%llu\n", td->o.latency_target); fio_gettime(&td->latency_ts, NULL); @@ -1187,9 +1206,16 @@ void lat_target_init(struct thread_data *td) td->latency_qd = td->o.iodepth; } +void lat_target_reset(struct thread_data *td) +{ + if (!td->latency_end_run) + lat_target_init(td); +} + static void lat_target_success(struct thread_data *td) { const unsigned int qd = td->latency_qd; + struct thread_options *o = &td->o; td->latency_qd_low = td->latency_qd; @@ -1198,20 +1224,32 @@ static void lat_target_success(struct thread_data *td) * of bisecting from highest possible queue depth. If we have set * a limit other than td->o.iodepth, bisect between that. */ - if (td->latency_qd_high != td->o.iodepth) + if (td->latency_qd_high != o->iodepth) td->latency_qd = (td->latency_qd + td->latency_qd_high) / 2; else td->latency_qd *= 2; - if (td->latency_qd > td->o.iodepth) - td->latency_qd = td->o.iodepth; + if (td->latency_qd > o->iodepth) + td->latency_qd = o->iodepth; dprint(FD_RATE, "Ramped up: %d %d %d\n", td->latency_qd_low, td->latency_qd, td->latency_qd_high); + /* - * Same as last one, we are done + * Same as last one, we are done. Let it run a latency cycle, so + * we get only the results from the targeted depth. */ - if (td->latency_qd == qd) - td->done = 1; + if (td->latency_qd == qd) { + if (td->latency_end_run) { + dprint(FD_RATE, "We are done\n"); + td->done = 1; + } else { + dprint(FD_RATE, "Quiesce and final run\n"); + io_u_quiesce(td); + td->latency_end_run = 1; + reset_all_stats(td); + reset_io_stats(td); + } + } lat_new_cycle(td); } @@ -1269,9 +1307,9 @@ again: else if (!queue_full(td)) { io_u = io_u_qpop(&td->io_u_freelist); + io_u->file = NULL; io_u->buflen = 0; io_u->resid = 0; - io_u->file = NULL; io_u->end_io = NULL; } @@ -1285,6 +1323,7 @@ again: io_u->acct_ddir = -1; td->cur_depth++; io_u->flags |= IO_U_F_IN_CUR_DEPTH; + io_u->ipo = NULL; } else if (td->o.verify_async) { /* * We ran out, wait for async verify threads to finish and @@ -1399,6 +1438,7 @@ struct io_u *get_io_u(struct thread_data *td) struct fio_file *f; struct io_u *io_u; int do_scramble = 0; + long ret = 0; io_u = __get_io_u(td); if (!io_u) { @@ -1424,11 +1464,17 @@ struct io_u *get_io_u(struct thread_data *td) if (read_iolog_get(td, io_u)) goto err_put; } else if (set_io_u_file(td, io_u)) { + ret = -EBUSY; dprint(FD_IO, "io_u %p, setting file failed\n", io_u); goto err_put; } f = io_u->file; + if (!f) { + dprint(FD_IO, "io_u %p, setting file failed\n", io_u); + goto err_put; + } + assert(fio_file_open(f)); if (ddir_rw(io_u->ddir)) { @@ -1477,7 +1523,7 @@ out: err_put: dprint(FD_IO, "get_io_u failed\n"); put_io_u(td, io_u); - return NULL; + return ERR_PTR(ret); } void io_u_log_error(struct thread_data *td, struct io_u *io_u) @@ -1503,13 +1549,19 @@ void io_u_log_error(struct thread_data *td, struct io_u *io_u) td_verror(td, io_u->error, "io_u error"); } +static inline int gtod_reduce(struct thread_data *td) +{ + return td->o.disable_clat && td->o.disable_lat && td->o.disable_slat + && td->o.disable_bw; +} + 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) { unsigned long lusec = 0; - if (!td->o.disable_clat || !td->o.disable_bw) + if (!gtod_reduce(td)) lusec = utime_since(&io_u->issue_time, &icd->time); if (!td->o.disable_lat) { @@ -1541,7 +1593,8 @@ static void account_io_completion(struct thread_data *td, struct io_u *io_u, if (!td->o.disable_bw) add_bw_sample(td, idx, bytes, &icd->time); - add_iops_sample(td, idx, bytes, &icd->time); + if (!gtod_reduce(td)) + add_iops_sample(td, idx, bytes, &icd->time); if (td->o.number_ios && !--td->o.number_ios) td->done = 1; @@ -1568,6 +1621,15 @@ static void io_completed(struct thread_data *td, struct io_u *io_u, td_io_u_lock(td); assert(io_u->flags & IO_U_F_FLIGHT); io_u->flags &= ~(IO_U_F_FLIGHT | IO_U_F_BUSY_OK); + + /* + * Mark IO ok to verify + */ + if (io_u->ipo) { + io_u->ipo->flags &= ~IP_F_IN_FLIGHT; + write_barrier(); + } + td_io_u_unlock(td); if (ddir_sync(io_u->ddir)) { @@ -1623,17 +1685,6 @@ static void io_completed(struct thread_data *td, struct io_u *io_u, utime_since_now(&td->start)); } - /* - * Verify_backlog enable: We need to log the write job after - * finishing it to prevent verifying before finish writing. - */ - if (td_write(td) && idx == DDIR_WRITE && - td->o.do_verify && - td->o.verify != VERIFY_NONE && - !td->o.experimental_verify && - (td->flags & TD_F_VER_BACKLOG)) - log_io_piece(td, io_u); - icd->bytes_done[idx] += bytes; if (io_u->end_io) { @@ -1664,7 +1715,8 @@ static void init_icd(struct thread_data *td, struct io_completion_data *icd, int nr) { int ddir; - if (!td->o.disable_clat || !td->o.disable_bw) + + if (!gtod_reduce(td)) fio_gettime(&icd->time, NULL); icd->nr = nr;