static int get_next_rand_offset(struct thread_data *td, struct fio_file *f,
int ddir, unsigned long long *b)
{
- unsigned long long max_blocks = f->file_size / td->o.min_bs[ddir];
+ unsigned long long max_blocks = f->io_size / td->o.min_bs[ddir];
unsigned long long r, rb;
int loops = 5;
if (get_next_rand_offset(td, f, ddir, &b))
return 1;
- } else
+ } else {
+ if (f->last_pos >= f->real_file_size)
+ return 1;
+
b = f->last_pos / td->o.min_bs[ddir];
+ }
io_u->offset = (b * td->o.min_bs[ddir]) + f->file_offset;
if (io_u->offset >= f->real_file_size)
static unsigned int get_next_buflen(struct thread_data *td, struct io_u *io_u)
{
- struct fio_file *f = io_u->file;
const int ddir = io_u->ddir;
unsigned int buflen;
long r;
buflen = (buflen + td->o.min_bs[ddir] - 1) & ~(td->o.min_bs[ddir] - 1);
}
- while (buflen + io_u->offset > f->real_file_size) {
- if (buflen == td->o.min_bs[ddir]) {
- if (!td->o.odirect) {
- assert(io_u->offset <= f->real_file_size);
- buflen = f->real_file_size - io_u->offset;
- return buflen;
- }
- return 0;
- }
-
- buflen = td->o.min_bs[ddir];
- }
-
return buflen;
}
*/
ddir = get_rand_ddir(td);
max_bytes = td->this_io_bytes[ddir];
- if (max_bytes >= (td->io_size * td->o.rwmix[ddir] / 100)) {
+ if (max_bytes >= (td->o.size * td->o.rwmix[ddir] / 100)) {
if (!td->rw_end_set[ddir]) {
td->rw_end_set[ddir] = 1;
memcpy(&td->rw_end[ddir], &now, sizeof(now));
!(td->io_issues[DDIR_WRITE] % td->o.fsync_blocks) &&
td->io_issues[DDIR_WRITE] && should_fsync(td)) {
io_u->ddir = DDIR_SYNC;
- return 0;
+ goto out;
}
io_u->ddir = get_rw_ddir(td);
/*
* mark entry before potentially trimming io_u
*/
- if (!td->o.read_iolog && td_random(td) && !td->o.norandommap)
+ if (td_random(td) && !td->o.norandommap)
mark_random_map(td, io_u);
/*
* If using a write iolog, store this entry.
*/
+out:
if (td->o.write_iolog_file)
write_iolog_put(td, io_u);
fno = (unsigned int) ((double) td->o.nr_files * (r / (RAND_MAX + 1.0)));
f = &td->files[fno];
+ if (f->flags & FIO_FILE_DONE)
+ continue;
if ((!goodf || (f->flags & goodf)) && !(f->flags & badf))
return f;
if (td->next_file >= td->o.nr_files)
td->next_file = 0;
+ if (f->flags & FIO_FILE_DONE) {
+ f = NULL;
+ continue;
+ }
+
if ((!goodf || (f->flags & goodf)) && !(f->flags & badf))
break;
*/
io_u->file = NULL;
td_io_close_file(td, f);
+ f->flags |= FIO_FILE_DONE;
/*
* probably not the right place to do this, but see
f->last_pos += td->o.zone_skip;
}
- if (io_u->buflen + io_u->offset > f->real_file_size) {
- if (td->io_ops->flags & FIO_RAWIO) {
- put_io_u(td, io_u);
- return NULL;
- }
-
- io_u->buflen = f->real_file_size - io_u->offset;
- }
-
if (io_u->ddir != DDIR_SYNC) {
if (!io_u->buflen) {
put_io_u(td, io_u);
add_bw_sample(td, idx, &icd->time);
io_u_mark_latency(td, msec);
- if ((td_rw(td) || td_write(td)) && idx == DDIR_WRITE)
+ if ((td_rw(td) || td_write(td)) && idx == DDIR_WRITE &&
+ td->o.verify != VERIFY_NONE)
log_io_piece(td, io_u);
icd->bytes_done[idx] += bytes;