* and invalidate the cache, if we need to.
*/
if (f->last_pos[ddir] >= f->io_size + get_start_offset(td, f) &&
- o->time_based) {
+ o->time_based && o->nr_files == 1) {
f->last_pos[ddir] = f->file_offset;
loop_cache_invalidate(td, f);
}
b = offset = -1ULL;
- if (rw_seq) {
+ if (td_randtrimwrite(td) && ddir == DDIR_WRITE) {
+ /* don't mark randommap for these writes */
+ io_u_set(td, io_u, IO_U_F_BUSY_OK);
+ offset = f->last_start[DDIR_TRIM];
+ *is_random = true;
+ ret = 0;
+ } else if (rw_seq) {
if (td_random(td)) {
if (should_do_random(td, ddir)) {
ret = get_next_rand_block(td, f, ddir, &b);
return 1;
}
+ /*
+ * For randtrimwrite, we decide whether to issue a trim or a write
+ * based on whether the offsets for the most recent trim and write
+ * operations match. If they don't match that means we just issued a
+ * new trim and the next operation should be a write. If they *do*
+ * match that means we just completed a trim+write pair and the next
+ * command should be a trim.
+ *
+ * This works fine for sequential workloads but for random workloads
+ * it's possible to complete a trim+write pair and then have the next
+ * randomly generated offset match the previous offset. If that happens
+ * we need to alter the offset for the last write operation in order
+ * to ensure that we issue a write operation the next time through.
+ */
+ if (td_randtrimwrite(td) && ddir == DDIR_TRIM &&
+ f->last_start[DDIR_TRIM] == io_u->offset)
+ f->last_start[DDIR_WRITE]--;
+
io_u->verify_offset = io_u->offset;
return 0;
}
assert(ddir_rw(ddir));
+ if (td_randtrimwrite(td) && ddir == DDIR_WRITE) {
+ struct fio_file *f = io_u->file;
+
+ return f->last_pos[DDIR_TRIM] - f->last_start[DDIR_TRIM];
+ }
+
if (td->o.bs_is_seq_rand)
ddir = is_random ? DDIR_WRITE : DDIR_READ;
if (td_trimwrite(td)) {
struct fio_file *f = io_u->file;
- if (f->last_pos[DDIR_WRITE] == f->last_pos[DDIR_TRIM])
+ if (f->last_start[DDIR_WRITE] == f->last_start[DDIR_TRIM])
ddir = DDIR_TRIM;
else
ddir = DDIR_WRITE;
break;
case 1 ... 4:
idx = 1;
- fallthrough;
+ fio_fallthrough;
case 0:
break;
}
break;
case 2 ... 3:
idx = 1;
- fallthrough;
+ fio_fallthrough;
case 1:
break;
}
break;
case 2 ... 3:
idx = 1;
- fallthrough;
+ fio_fallthrough;
case 0 ... 1:
break;
}
break;
case 2 ... 3:
idx = 1;
- fallthrough;
+ fio_fallthrough;
case 0 ... 1:
break;
}
break;
case 2 ... 3:
idx = 1;
- fallthrough;
+ fio_fallthrough;
case 0 ... 1:
break;
}
int ret;
if (io_u->ddir == DDIR_SYNC) {
+#ifdef CONFIG_FCNTL_SYNC
+ ret = fcntl(io_u->file->fd, F_FULLFSYNC);
+#else
ret = fsync(io_u->file->fd);
+#endif
} else if (io_u->ddir == DDIR_DATASYNC) {
#ifdef CONFIG_FDATASYNC
ret = fdatasync(io_u->file->fd);