#include <locale.h>
#include <assert.h>
#include <time.h>
+#include <inttypes.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/ipc.h>
unsigned long done_secs = 0;
#define PAGE_ALIGN(buf) \
- (char *) (((unsigned long) (buf) + page_mask) & ~page_mask)
+ (char *) (((uintptr_t) (buf) + page_mask) & ~page_mask)
#define JOB_START_TIMEOUT (5 * 1000)
}
}
+ if (flow_threshold_exceeded(td))
+ continue;
+
io_u = __get_io_u(td);
if (!io_u)
break;
dprint(FD_VERIFY, "exiting loop\n");
}
+static int io_bytes_exceeded(struct thread_data *td)
+{
+ unsigned long long bytes;
+
+ if (td_rw(td))
+ bytes = td->this_io_bytes[0] + td->this_io_bytes[1];
+ else if (td_write(td))
+ bytes = td->this_io_bytes[1];
+ else
+ bytes = td->this_io_bytes[0];
+
+ return bytes >= td->o.size;
+}
+
/*
* Main IO worker function. It retrieves io_u's to process and queues
* and reaps them, checking for rate and errors along the way.
else
td_set_runstate(td, TD_RUNNING);
- while ( (td->o.read_iolog_file && !flist_empty(&td->io_log_list)) ||
- (!flist_empty(&td->trim_list)) ||
- ((td->this_io_bytes[0] + td->this_io_bytes[1]) < td->o.size) ) {
+ while ((td->o.read_iolog_file && !flist_empty(&td->io_log_list)) ||
+ (!flist_empty(&td->trim_list)) || !io_bytes_exceeded(td)) {
struct timeval comp_time;
unsigned long bytes_done[2] = { 0, 0 };
int min_evts = 0;
}
}
+ if (flow_threshold_exceeded(td))
+ continue;
+
io_u = get_io_u(td);
if (!io_u)
break;
ddir = io_u->ddir;
/*
- * Add verification end_io handler, if asked to verify
- * a previously written file.
+ * Add verification end_io handler if:
+ * - Asked to verify (!td_rw(td))
+ * - Or the io_u is from our verify list (mixed write/ver)
*/
if (td->o.verify != VERIFY_NONE && io_u->ddir == DDIR_READ &&
- !td_rw(td)) {
+ ((io_u->flags & IO_U_F_VER_LIST) || !td_rw(td))) {
if (td->o.verify_async)
io_u->end_io = verify_io_u_async;
else
static int init_io_u(struct thread_data *td)
{
struct io_u *io_u;
- unsigned int max_bs;
+ unsigned int max_bs, min_write;
int cl_align, i, max_units;
char *p;
max_units = td->o.iodepth;
max_bs = max(td->o.max_bs[DDIR_READ], td->o.max_bs[DDIR_WRITE]);
+ min_write = td->o.min_bs[DDIR_WRITE];
td->orig_buffer_size = (unsigned long long) max_bs
* (unsigned long long) max_units;
dprint(FD_MEM, "io_u %p, mem %p\n", io_u, io_u->buf);
if (td_write(td))
- io_u_fill_buffer(td, io_u, max_bs);
+ io_u_fill_buffer(td, io_u, min_write, max_bs);
if (td_write(td) && td->o.verify_pattern_bytes) {
/*
* Fill the buffer with the pattern if we are
if (td->o.cgroup_weight && cgroup_setup(td, cgroup_list, &cgroup_mnt))
goto err;
- if (nice(td->o.nice) == -1) {
+ errno = 0;
+ if (nice(td->o.nice) == -1 && errno != 0) {
td_verror(td, errno, "nice");
goto err;
}
write_iolog_close(td);
td_set_runstate(td, TD_EXITED);
- return (void *) (unsigned long) td->error;
+ return (void *) (uintptr_t) td->error;
}
td = data + offset * sizeof(struct thread_data);
ret = thread_main(td);
shmdt(data);
- return (int) (unsigned long) ret;
+ return (int) (uintptr_t) ret;
}
/*
}
if (left) {
- log_err("fio: %d jobs failed to start\n", left);
+ log_err("fio: %d job%s failed to start\n", left,
+ left > 1 ? "s" : "");
for (i = 0; i < this_jobs; i++) {
td = map[i];
if (!td)