}
}
+#ifdef WIN32
+static void sig_break(int sig)
+{
+ struct thread_data *td;
+ int i;
+
+ sig_int(sig);
+
+ /**
+ * Windows terminates all job processes on SIGBREAK after the handler
+ * returns, so give them time to wrap-up and give stats
+ */
+ for_each_td(td, i) {
+ while (td->runstate < TD_EXITED)
+ sleep(1);
+ }
+}
+#endif
+
void sig_show_status(int sig)
{
show_running_run_stats();
/* Windows uses SIGBREAK as a quit signal from other applications */
#ifdef WIN32
memset(&act, 0, sizeof(act));
- act.sa_handler = sig_int;
+ act.sa_handler = sig_break;
act.sa_flags = SA_RESTART;
sigaction(SIGBREAK, &act, NULL);
#endif
break;
}
} else {
- if (ddir_rw_sum(td->bytes_done) + td->o.rw_min_bs > verify_bytes)
+ if (td->bytes_verified + td->o.rw_min_bs > verify_bytes)
break;
while ((io_u = get_io_u(td)) != NULL) {
break;
} else if (io_u->ddir == DDIR_WRITE) {
io_u->ddir = DDIR_READ;
+ io_u->numberio = td->verify_read_issues;
+ td->verify_read_issues++;
populate_verify_io_u(td, io_u);
break;
} else {
total_bytes += td->o.size;
/* In trimwrite mode, each byte is trimmed and then written, so
- * allow total_bytes to be twice as big */
- if (td_trimwrite(td))
+ * allow total_bytes or number of ios to be twice as big */
+ if (td_trimwrite(td)) {
total_bytes += td->total_io_size;
+ td->o.number_ios *= 2;
+ }
while ((td->o.read_iolog_file && !flist_empty(&td->io_log_list)) ||
(!flist_empty(&td->trim_list)) || !io_issue_bytes_exceeded(td) ||
break;
}
- if (io_u->ddir == DDIR_WRITE && td->flags & TD_F_DO_VERIFY)
+ if (io_u->ddir == DDIR_WRITE && td->flags & TD_F_DO_VERIFY) {
+ io_u->numberio = td->io_issues[io_u->ddir];
populate_verify_io_u(td, io_u);
+ }
ddir = io_u->ddir;
}
}
- init_io_u_buffers(td);
+ if (init_io_u_buffers(td))
+ return 1;
if (init_file_completion_logging(td, max_units))
return 1;
* overflow later. this adjustment may be too much if we get
* lucky and the allocator gives us an aligned address.
*/
- if (td->o.odirect || td->o.mem_align || td->o.oatomic ||
+ if (td->o.odirect || td->o.mem_align ||
td_ioengine_flagged(td, FIO_RAWIO))
td->orig_buffer_size += page_mask + td->o.mem_align;
if (data_xfer && allocate_io_mem(td))
return 1;
- if (td->o.odirect || td->o.mem_align || td->o.oatomic ||
+ if (td->o.odirect || td->o.mem_align ||
td_ioengine_flagged(td, FIO_RAWIO))
p = PTR_ALIGN(td->orig_buffer, page_mask) + td->o.mem_align;
else
if (td_io_init(td))
goto err;
+ if (td_ioengine_flagged(td, FIO_SYNCIO) && td->o.iodepth > 1 && td->o.io_submit_mode != IO_MODE_OFFLOAD) {
+ log_info("note: both iodepth >= 1 and synchronous I/O engine "
+ "are selected, queue depth will be capped at 1\n");
+ }
+
if (init_io_u(td))
goto err;
}
} while (1);
- if (td_read(td) && td->io_bytes[DDIR_READ])
+ if (td->io_bytes[DDIR_READ] && (td_read(td) ||
+ ((td->flags & TD_F_VER_BACKLOG) && td_write(td))))
update_runtime(td, elapsed_us, DDIR_READ);
if (td_write(td) && td->io_bytes[DDIR_WRITE])
update_runtime(td, elapsed_us, DDIR_WRITE);
for_each_td(td, i) {
print_status_init(td->thread_number - 1);
- if (!td->o.create_serialize) {
- /*
- * When operating on a single rile in parallel,
- * perform single-threaded early setup so that
- * when setup_files() does not run into issues
- * later.
- */
- if (!i && td->o.nr_files==1) {
- if (setup_shared_file(td)) {
- exit_value++;
- if (td->error)
- log_err("fio: pid=%d, err=%d/%s\n",
- (int) td->pid, td->error, td->verror);
- td_set_runstate(td, TD_REAPED);
- todo--;
- }
- }
+ if (!td->o.create_serialize)
continue;
- }
if (fio_verify_load_state(td))
goto reap;
strerror(ret));
} else {
pid_t pid;
- struct fio_file **files;
void *eo;
dprint(FD_PROCESS, "will fork\n");
- files = td->files;
eo = td->eo;
read_barrier();
pid = fork();
_exit(ret);
} else if (i == fio_debug_jobno)
*fio_debug_jobp = pid;
- // freeing previously allocated memory for files
- // this memory freed MUST NOT be shared between processes, only the pointer itself may be shared within TD
- free(files);
free(eo);
free(fd);
fd = NULL;