unsigned long page_mask;
unsigned long page_size;
-#define ALIGN(buf) \
+
+#define PAGE_ALIGN(buf) \
(char *) (((unsigned long) (buf) + page_mask) & ~page_mask)
int groupid = 0;
unsigned int rate_iops = 0;
unsigned int rate_iops_min = 0;
+ if (!td->o.ratemin[ddir] && !td->o.rate_iops_min[ddir])
+ return 0;
+
/*
* allow a 2 second settle period in the beginning
*/
fio_gettime(&td->tv_cache, NULL);
}
+static int break_on_this_error(struct thread_data *td, int *retptr)
+{
+ int ret = *retptr;
+
+ if (ret < 0 || td->error) {
+ int err;
+
+ if (!td->o.continue_on_error)
+ return 1;
+
+ if (ret < 0)
+ err = -ret;
+ else
+ err = td->error;
+
+ if (td_non_fatal_error(err)) {
+ /*
+ * Continue with the I/Os in case of
+ * a non fatal error.
+ */
+ update_error_count(td, err);
+ td_clear_error(td);
+ *retptr = 0;
+ return 0;
+ } else if (td->o.fill_device && err == ENOSPC) {
+ /*
+ * We expect to hit this error if
+ * fill_device option is set.
+ */
+ td_clear_error(td);
+ td->terminate = 1;
+ return 1;
+ } else {
+ /*
+ * Stop the I/O in case of a fatal
+ * error.
+ */
+ update_error_count(td, err);
+ return 1;
+ }
+ }
+
+ return 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.
while (!td->terminate) {
int ret2, full;
- io_u = __get_io_u(td);
- if (!io_u)
- break;
-
update_tv_cache(td);
if (runtime_exceeded(td, &td->tv_cache)) {
- put_io_u(td, io_u);
td->terminate = 1;
break;
}
+ io_u = __get_io_u(td);
+ if (!io_u)
+ break;
+
if (get_next_verify(td, io_u)) {
put_io_u(td, io_u);
break;
ret = td_io_queue(td, io_u);
switch (ret) {
case FIO_Q_COMPLETED:
- if (io_u->error)
+ if (io_u->error) {
ret = -io_u->error;
- else if (io_u->resid) {
+ clear_io_u(td, io_u);
+ } else if (io_u->resid) {
int bytes = io_u->xfer_buflen - io_u->resid;
struct fio_file *f = io_u->file;
break;
}
- if (ret < 0 || td->error)
+ if (break_on_this_error(td, &ret))
break;
/*
if (td->terminate)
break;
- io_u = get_io_u(td);
- if (!io_u)
- break;
-
update_tv_cache(td);
if (runtime_exceeded(td, &td->tv_cache)) {
- put_io_u(td, io_u);
td->terminate = 1;
break;
}
+ io_u = get_io_u(td);
+ if (!io_u)
+ break;
+
/*
* Add verification end_io handler, if asked to verify
* a previously written file.
ret = td_io_queue(td, io_u);
switch (ret) {
case FIO_Q_COMPLETED:
- if (io_u->error)
+ if (io_u->error) {
ret = -io_u->error;
- else if (io_u->resid) {
+ clear_io_u(td, io_u);
+ } else if (io_u->resid) {
int bytes = io_u->xfer_buflen - io_u->resid;
struct fio_file *f = io_u->file;
break;
}
- if (ret < 0 || td->error)
+ if (break_on_this_error(td, &ret))
break;
/*
if (allocate_io_mem(td))
return 1;
- if (td->o.odirect)
- p = ALIGN(td->orig_buffer);
+ if (td->o.odirect || td->o.mem_align)
+ p = PAGE_ALIGN(td->orig_buffer) + td->o.mem_align;
else
p = td->orig_buffer;
io_u = ptr;
memset(io_u, 0, sizeof(*io_u));
INIT_FLIST_HEAD(&io_u->list);
+ dprint(FD_MEM, "io_u alloc %p, index %u\n", io_u, i);
if (!(td->io_ops->flags & FIO_NOIO)) {
io_u->buf = p + max_bs * i;
+ dprint(FD_MEM, "io_u %p, mem %p\n", io_u, io_u->buf);
if (td_write(td) && !td->o.refill_buffers)
io_u_fill_buffer(td, io_u, max_bs);
* its own files. so close them, if we opened them
* for creation
*/
- for_each_file(td, f, i)
- td_io_close_file(td, f);
+ for_each_file(td, f, i) {
+ if (fio_file_open(f))
+ td_io_close_file(td, f);
+ }
}
init_disk_util(td);
*fio_debug_jobp = pid;
}
dprint(FD_MUTEX, "wait on startup_mutex\n");
- fio_mutex_down(startup_mutex);
+ if (fio_mutex_down_timeout(startup_mutex, 10)) {
+ log_err("fio: job startup hung? exiting.\n");
+ terminate_threads(TERMINATE_ALL);
+ fio_abort = 1;
+ nr_started--;
+ break;
+ }
dprint(FD_MUTEX, "done waiting on startup_mutex\n");
}