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);
}
}
}
default:
printf("\nfio: terminating on signal %d\n", sig);
fflush(stdout);
- terminate_threads(TERMINATE_ALL, 0);
+ terminate_threads(TERMINATE_ALL);
break;
}
}
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
*/
}
/*
- * 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)
io_u = NULL;
while (!td->terminate) {
+ int ret2;
+
io_u = __get_io_u(td);
if (!io_u)
break;
}
io_u->end_io = verify_io_u;
-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;
- 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);
- 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);
long bytes_done = 0;
int min_evts = 0;
struct io_u *io_u;
+ int ret2;
if (td->terminate)
break;
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);
- if (bytes_done < 0)
- ret = bytes_done;
break;
case FIO_Q_QUEUED:
/*
*/
if (td->io_ops->commit == NULL)
io_u_queued(td, io_u);
- else if (td->io_u_queued >= td->iodepth_batch)
- ret = td_io_commit(td);
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);
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;
}
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;
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);
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) {
}
if (exitall_on_terminate)
- terminate_threads(td->groupid, 0);
+ terminate_threads(td->groupid);
err:
if (td->error)
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;
}
}
if (*nr_running == cputhreads && !pending)
- terminate_threads(TERMINATE_ALL, 0);
+ terminate_threads(TERMINATE_ALL);
}
/*