X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=fio.c;h=ab84b60a59ca77ace2e9984b4353b530a569ed8c;hb=b2560f3ca4677e2908fc4111f4d04fae5df3b229;hp=dbea661d961ca5b911b0a35161510c238d6f0b2a;hpb=0904200b6f113233a28c4c1ddf68f216bd922b78;p=fio.git diff --git a/fio.c b/fio.c index dbea661d..ab84b60a 100644 --- a/fio.c +++ b/fio.c @@ -60,17 +60,20 @@ static inline void td_set_runstate(struct thread_data *td, int runstate) td->runstate = runstate; } -static void terminate_threads(int group_id, int forced_kill) +static void terminate_threads(int group_id) { struct thread_data *td; int i; for_each_td(td, i) { if (group_id == TERMINATE_ALL || groupid == td->groupid) { + /* + * if the thread is running, just let it exit + */ + if (td->runstate < TD_RUNNING) + kill(td->pid, SIGQUIT); td->terminate = 1; td->start_delay = 0; - if (forced_kill) - td_set_runstate(td, TD_EXITED); } } } @@ -86,7 +89,7 @@ static void sig_handler(int sig) default: printf("\nfio: terminating on signal %d\n", sig); fflush(stdout); - terminate_threads(TERMINATE_ALL, 0); + terminate_threads(TERMINATE_ALL); break; } } @@ -100,6 +103,12 @@ static int check_min_rate(struct thread_data *td, struct timeval *now) unsigned long spent; unsigned long rate; + /* + * No minimum rate set, always ok + */ + if (!td->ratemin) + return 0; + /* * allow a 2 second settle period in the beginning */ @@ -159,7 +168,7 @@ static void cleanup_pending_aio(struct thread_data *td) /* * get immediately available events, if any */ - r = io_u_queued_complete(td, 0, NULL); + r = io_u_queued_complete(td, 0); if (r < 0) return; @@ -187,7 +196,7 @@ static void cleanup_pending_aio(struct thread_data *td) } if (td->cur_depth) - r = io_u_queued_complete(td, td->cur_depth, NULL); + r = io_u_queued_complete(td, td->cur_depth); } /* @@ -217,7 +226,7 @@ requeue: put_io_u(td, io_u); return 1; } else if (ret == FIO_Q_QUEUED) { - if (io_u_queued_complete(td, 1, NULL) < 0) + if (io_u_queued_complete(td, 1) < 0) return 1; } else if (ret == FIO_Q_COMPLETED) { if (io_u->error) { @@ -225,7 +234,7 @@ requeue: return 1; } - if (io_u_sync_complete(td, io_u, NULL) < 0) + if (io_u_sync_complete(td, io_u) < 0) return 1; } else if (ret == FIO_Q_BUSY) { if (td_io_commit(td)) @@ -237,7 +246,7 @@ requeue: } /* - * The main verify engine. Runs over the writes we previusly submitted, + * The main verify engine. Runs over the writes we previously submitted, * reads the blocks back in, and checks the crc/md5 of the data. */ static void do_verify(struct thread_data *td) @@ -264,6 +273,8 @@ static void do_verify(struct thread_data *td) io_u = NULL; while (!td->terminate) { + int ret2; + io_u = __get_io_u(td); if (!io_u) break; @@ -282,29 +293,33 @@ static void do_verify(struct thread_data *td) put_io_u(td, io_u); break; } -requeue: - ret = td_io_queue(td, io_u); + io_u->end_io = verify_io_u; + + ret = td_io_queue(td, io_u); switch (ret) { case FIO_Q_COMPLETED: if (io_u->error) ret = -io_u->error; - if (io_u->xfer_buflen != io_u->resid && io_u->resid) { + else if (io_u->xfer_buflen != io_u->resid && io_u->resid) { int bytes = io_u->xfer_buflen - io_u->resid; io_u->xfer_buflen = io_u->resid; io_u->xfer_buf += bytes; - goto requeue; + requeue_io_u(td, &io_u); + } else { + ret = io_u_sync_complete(td, io_u); + if (ret < 0) + break; } - ret = io_u_sync_complete(td, io_u, verify_io_u); - if (ret < 0) - break; continue; case FIO_Q_QUEUED: break; case FIO_Q_BUSY: requeue_io_u(td, &io_u); - ret = td_io_commit(td); + ret2 = td_io_commit(td); + if (ret2 < 0) + ret = ret2; break; default: assert(ret < 0); @@ -331,11 +346,16 @@ requeue: * Reap required number of io units, if any, and do the * verification on them through the callback handler */ - if (io_u_queued_complete(td, min_events, verify_io_u) < 0) + if (io_u_queued_complete(td, min_events) < 0) break; } - if (td->cur_depth) + if (!td->error) { + min_events = td->cur_depth; + + if (min_events) + ret = io_u_queued_complete(td, min_events); + } else cleanup_pending_aio(td); td_set_runstate(td, TD_RUNNING); @@ -383,6 +403,7 @@ static void do_io(struct thread_data *td) long bytes_done = 0; int min_evts = 0; struct io_u *io_u; + int ret2; if (td->terminate) break; @@ -397,26 +418,24 @@ static void do_io(struct thread_data *td) put_io_u(td, io_u); break; } -requeue: - ret = td_io_queue(td, io_u); + ret = td_io_queue(td, io_u); switch (ret) { case FIO_Q_COMPLETED: - if (io_u->error) { - ret = io_u->error; - break; - } - if (io_u->xfer_buflen != io_u->resid && io_u->resid) { + if (io_u->error) + ret = -io_u->error; + else if (io_u->xfer_buflen != io_u->resid && io_u->resid) { int bytes = io_u->xfer_buflen - io_u->resid; io_u->xfer_buflen = io_u->resid; io_u->xfer_buf += bytes; - goto requeue; + requeue_io_u(td, &io_u); + } else { + fio_gettime(&comp_time, NULL); + bytes_done = io_u_sync_complete(td, io_u); + if (bytes_done < 0) + ret = bytes_done; } - fio_gettime(&comp_time, NULL); - bytes_done = io_u_sync_complete(td, io_u, NULL); - if (bytes_done < 0) - ret = bytes_done; break; case FIO_Q_QUEUED: /* @@ -429,7 +448,9 @@ requeue: break; case FIO_Q_BUSY: requeue_io_u(td, &io_u); - ret = td_io_commit(td); + ret2 = td_io_commit(td); + if (ret2 < 0) + ret = ret2; break; default: assert(ret < 0); @@ -453,7 +474,7 @@ requeue: } fio_gettime(&comp_time, NULL); - bytes_done = io_u_queued_complete(td, min_evts, NULL); + bytes_done = io_u_queued_complete(td, min_evts); if (bytes_done < 0) break; } @@ -472,7 +493,7 @@ requeue: if (check_min_rate(td, &comp_time)) { if (exitall_on_terminate) - terminate_threads(td->groupid, 0); + terminate_threads(td->groupid); td_verror(td, ENODATA, "check_min_rate"); break; } @@ -497,15 +518,17 @@ requeue: if (!td->error) { struct fio_file *f; - if (td->cur_depth) - cleanup_pending_aio(td); + i = td->cur_depth; + if (i) + ret = io_u_queued_complete(td, i); if (should_fsync(td) && td->end_fsync) { td_set_runstate(td, TD_FSYNCING); for_each_file(td, f, i) fio_io_sync(td, f); } - } + } else + cleanup_pending_aio(td); } static void cleanup_io_u(struct thread_data *td) @@ -638,7 +661,7 @@ static void clear_io_state(struct thread_data *td) struct fio_file *f; int i; - td->ts.stat_io_bytes[0] = td->ts.stat_io_bytes[1] = 0; + td->ts->stat_io_bytes[0] = td->ts->stat_io_bytes[1] = 0; td->this_io_bytes[0] = td->this_io_bytes[1] = 0; td->zone_bytes = 0; @@ -728,15 +751,15 @@ static void *thread_main(void *data) fio_gettime(&td->epoch, NULL); memcpy(&td->timeout_end, &td->epoch, sizeof(td->epoch)); - getrusage(RUSAGE_SELF, &td->ts.ru_start); + getrusage(RUSAGE_SELF, &td->ts->ru_start); runtime[0] = runtime[1] = 0; while (td->loops--) { fio_gettime(&td->start, NULL); - memcpy(&td->ts.stat_sample_time, &td->start, sizeof(td->start)); + memcpy(&td->ts->stat_sample_time, &td->start, sizeof(td->start)); if (td->ratemin) - memcpy(&td->lastrate, &td->ts.stat_sample_time, sizeof(td->lastrate)); + memcpy(&td->lastrate, &td->ts->stat_sample_time, sizeof(td->lastrate)); clear_io_state(td); prune_io_piece_log(td); @@ -773,12 +796,12 @@ static void *thread_main(void *data) td->runtime[0] = runtime[0] / 1000; td->runtime[1] = runtime[1] / 1000; - if (td->ts.bw_log) - finish_log(td, td->ts.bw_log, "bw"); - if (td->ts.slat_log) - finish_log(td, td->ts.slat_log, "slat"); - if (td->ts.clat_log) - finish_log(td, td->ts.clat_log, "clat"); + if (td->ts->bw_log) + finish_log(td, td->ts->bw_log, "bw"); + if (td->ts->slat_log) + finish_log(td, td->ts->slat_log, "slat"); + if (td->ts->clat_log) + finish_log(td, td->ts->clat_log, "clat"); if (td->write_iolog_file) write_iolog_close(td); if (td->exec_postrun) { @@ -787,7 +810,7 @@ static void *thread_main(void *data) } if (exitall_on_terminate) - terminate_threads(td->groupid, 0); + terminate_threads(td->groupid); err: if (td->error) @@ -873,7 +896,8 @@ static void reap_threads(int *nr_running, int *t_rate, int *m_rate) if (WIFSIGNALED(status)) { int sig = WTERMSIG(status); - log_err("fio: pid=%d, got signal=%d\n", td->pid, sig); + if (sig != SIGQUIT) + log_err("fio: pid=%d, got signal=%d\n", td->pid, sig); td_set_runstate(td, TD_REAPED); goto reaped; } @@ -907,7 +931,7 @@ reaped: } if (*nr_running == cputhreads && !pending) - terminate_threads(TERMINATE_ALL, 0); + terminate_threads(TERMINATE_ALL); } /*