dprint(FD_RANDOM, "off rand %llu\n", (unsigned long long) r);
- *b = (lastb - 1) * (r / ((uint64_t) rmax + 1.0));
+ *b = lastb * (r / ((uint64_t) rmax + 1.0));
} else {
uint64_t off = 0;
{
assert(ddir_rw(ddir));
- if (f->last_pos >= f->io_size + get_start_offset(td) && td->o.time_based)
+ if (f->last_pos >= f->io_size + get_start_offset(td, f) && td->o.time_based)
f->last_pos = f->last_pos - f->io_size;
if (f->last_pos < f->real_file_size) {
{
struct fio_file *f = io_u->file;
- return io_u->offset + buflen <= f->io_size + get_start_offset(td);
+ return io_u->offset + buflen <= f->io_size + get_start_offset(td, f);
}
static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u,
unsigned int minbs, maxbs;
unsigned long r, rand_max;
- assert(ddir_rw(io_u->ddir));
+ assert(ddir_rw(ddir));
if (td->o.bs_is_seq_rand)
ddir = is_random ? DDIR_WRITE: DDIR_READ;
- else
- ddir = io_u->ddir;
minbs = td->o.min_bs[ddir];
maxbs = td->o.max_bs[ddir];
td->file_service_file = f;
td->file_service_left = td->file_service_nr - 1;
out:
- dprint(FD_FILE, "get_next_file: %p [%s]\n", f, f->file_name);
+ if (f)
+ dprint(FD_FILE, "get_next_file: %p [%s]\n", f, f->file_name);
+ else
+ dprint(FD_FILE, "get_next_file: NULL\n");
return f;
}
return 1;
td->latency_qd_high = td->latency_qd;
+
+ if (td->latency_qd == td->latency_qd_low)
+ td->latency_qd_low--;
+
td->latency_qd = (td->latency_qd + td->latency_qd_low) / 2;
dprint(FD_RATE, "Ramped down: %d %d %d\n", td->latency_qd_low, td->latency_qd, td->latency_qd_high);
void lat_target_init(struct thread_data *td)
{
+ td->latency_end_run = 0;
+
if (td->o.latency_target) {
dprint(FD_RATE, "Latency target=%llu\n", td->o.latency_target);
fio_gettime(&td->latency_ts, NULL);
td->latency_qd = td->o.iodepth;
}
+void lat_target_reset(struct thread_data *td)
+{
+ if (!td->latency_end_run)
+ lat_target_init(td);
+}
+
static void lat_target_success(struct thread_data *td)
{
const unsigned int qd = td->latency_qd;
+ struct thread_options *o = &td->o;
td->latency_qd_low = td->latency_qd;
* of bisecting from highest possible queue depth. If we have set
* a limit other than td->o.iodepth, bisect between that.
*/
- if (td->latency_qd_high != td->o.iodepth)
+ if (td->latency_qd_high != o->iodepth)
td->latency_qd = (td->latency_qd + td->latency_qd_high) / 2;
else
td->latency_qd *= 2;
- if (td->latency_qd > td->o.iodepth)
- td->latency_qd = td->o.iodepth;
+ if (td->latency_qd > o->iodepth)
+ td->latency_qd = o->iodepth;
dprint(FD_RATE, "Ramped up: %d %d %d\n", td->latency_qd_low, td->latency_qd, td->latency_qd_high);
+
/*
- * Same as last one, we are done
+ * Same as last one, we are done. Let it run a latency cycle, so
+ * we get only the results from the targeted depth.
*/
- if (td->latency_qd == qd)
- td->done = 1;
+ if (td->latency_qd == qd) {
+ if (td->latency_end_run) {
+ dprint(FD_RATE, "We are done\n");
+ td->done = 1;
+ } else {
+ dprint(FD_RATE, "Quiesce and final run\n");
+ io_u_quiesce(td);
+ td->latency_end_run = 1;
+ reset_all_stats(td);
+ reset_io_stats(td);
+ }
+ }
lat_new_cycle(td);
}
struct io_u *__get_io_u(struct thread_data *td)
{
- struct io_u *io_u;
+ struct io_u *io_u = NULL;
td_io_u_lock(td);
else if (!queue_full(td)) {
io_u = io_u_qpop(&td->io_u_freelist);
+ io_u->file = NULL;
io_u->buflen = 0;
io_u->resid = 0;
- io_u->file = NULL;
io_u->end_io = NULL;
}
if (td->flags & TD_F_REFILL_BUFFERS) {
io_u_fill_buffer(td, io_u,
io_u->xfer_buflen, io_u->xfer_buflen);
- } else if (td->flags & TD_F_SCRAMBLE_BUFFERS)
+ } else if ((td->flags & TD_F_SCRAMBLE_BUFFERS) &&
+ !(td->flags & TD_F_COMPRESS))
do_scramble = 1;
if (td->flags & TD_F_VER_NONE) {
populate_verify_io_u(td, io_u);
if (!gtod_reduce(td))
add_iops_sample(td, idx, bytes, &icd->time);
-
- if (td->o.number_ios && !--td->o.number_ios)
- td->done = 1;
}
static long long usec_for_io(struct thread_data *td, enum fio_ddir ddir)