}
static int check_min_rate(struct thread_data *td, struct timeval *now,
- unsigned long *bytes_done)
+ uint64_t *bytes_done)
{
int ret = 0;
* 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)
+static void do_verify(struct thread_data *td, uint64_t verify_bytes)
{
+ uint64_t bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 };
struct fio_file *f;
struct io_u *io_u;
int ret, min_events;
if (flow_threshold_exceeded(td))
continue;
- io_u = __get_io_u(td);
- if (!io_u)
- break;
+ if (!td->o.experimental_verify) {
+ io_u = __get_io_u(td);
+ if (!io_u)
+ break;
- if (get_next_verify(td, io_u)) {
- put_io_u(td, io_u);
- break;
- }
+ if (get_next_verify(td, io_u)) {
+ put_io_u(td, io_u);
+ break;
+ }
- if (td_io_prep(td, io_u)) {
- put_io_u(td, io_u);
- break;
+ if (td_io_prep(td, io_u)) {
+ put_io_u(td, io_u);
+ break;
+ }
+ } else {
+ if (ddir_rw_sum(bytes_done) + td->o.rw_min_bs > verify_bytes)
+ break;
+
+ while ((io_u = get_io_u(td)) != NULL) {
+ /*
+ * We are only interested in the places where
+ * we wrote or trimmed IOs. Turn those into
+ * reads for verification purposes.
+ */
+ if (io_u->ddir == DDIR_READ) {
+ /*
+ * Pretend we issued it for rwmix
+ * accounting
+ */
+ td->io_issues[DDIR_READ]++;
+ put_io_u(td, io_u);
+ continue;
+ } else if (io_u->ddir == DDIR_TRIM) {
+ io_u->ddir = DDIR_READ;
+ io_u->flags |= IO_U_F_TRIMMED;
+ break;
+ } else if (io_u->ddir == DDIR_WRITE) {
+ io_u->ddir = DDIR_READ;
+ break;
+ } else {
+ put_io_u(td, io_u);
+ continue;
+ }
+ }
+
+ if (!io_u)
+ break;
}
if (td->o.verify_async)
requeue_io_u(td, &io_u);
} else {
sync_done:
- ret = io_u_sync_complete(td, io_u, NULL);
+ ret = io_u_sync_complete(td, io_u, bytes_done);
if (ret < 0)
break;
}
* and do the verification on them through
* the callback handler
*/
- if (io_u_queued_complete(td, min_events, NULL) < 0) {
+ if (io_u_queued_complete(td, min_events, bytes_done) < 0) {
ret = -1;
break;
}
/*
* Main IO worker function. It retrieves io_u's to process and queues
* and reaps them, checking for rate and errors along the way.
+ *
+ * Returns number of bytes written and trimmed.
*/
-static void do_io(struct thread_data *td)
+static uint64_t do_io(struct thread_data *td)
{
+ uint64_t bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 };
unsigned int i;
int ret = 0;
(!flist_empty(&td->trim_list)) || !io_bytes_exceeded(td) ||
td->o.time_based) {
struct timeval comp_time;
- unsigned long bytes_done[DDIR_RWDIR_CNT] = { 0, 0, 0 };
int min_evts = 0;
struct io_u *io_u;
int ret2, full;
*/
if (!ddir_rw_sum(td->this_io_bytes))
td->done = 1;
+
+ return bytes_done[DDIR_WRITE] + bytes_done[DDIR_TRIM];
}
static void cleanup_io_u(struct thread_data *td)
INIT_FLIST_HEAD(&td->io_hist_list);
INIT_FLIST_HEAD(&td->verify_list);
INIT_FLIST_HEAD(&td->trim_list);
+ INIT_FLIST_HEAD(&td->next_rand_list);
pthread_mutex_init(&td->io_u_lock, NULL);
td->io_hist_tree = RB_ROOT;
}
}
- if (fio_pin_memory(td))
- goto err;
-
-#ifdef FIO_HAVE_LIBNUMA
+#ifdef CONFIG_LIBNUMA
/* numa node setup */
if (td->o.numa_cpumask_set || td->o.numa_memmask_set) {
int ret;
clear_state = 0;
while (keep_running(td)) {
+ uint64_t verify_bytes;
+
fio_gettime(&td->start, NULL);
memcpy(&td->bw_sample_time, &td->start, sizeof(td->start));
memcpy(&td->iops_sample_time, &td->start, sizeof(td->start));
prune_io_piece_log(td);
- do_io(td);
+ verify_bytes = do_io(td);
clear_state = 1;
fio_gettime(&td->start, NULL);
- do_verify(td);
+ do_verify(td, verify_bytes);
td->ts.runtime[DDIR_READ] += utime_since_now(&td->start);