can be given for both read and writes. If a single int is
given, it will apply to both. If a second int is specified
after a comma, it will apply to writes only. In other words,
- the format is either bs=read_and_write or bs=read,write.
- bs=4k,8k will thus use 4k blocks for reads, and 8k blocks
- for writes. If you only wish to set the write size, you
+ the format is either bs=read_and_write or bs=read,write,trim.
+ bs=4k,8k will thus use 4k blocks for reads, 8k blocks for
+ writes, and 8k for trims. You can terminate the list with
+ a trailing comma. bs=4k,8k, would use the default value for
+ trims.. If you only wish to set the write size, you
can do so by passing an empty read size - bs=,8k will set
8k for writes and leave the read default value.
is fully random. It can be set from anywhere from 0 to 100.
Setting it to 0 would make the workload fully sequential. Any
setting in between will result in a random mix of sequential
- and random IO, at the given percentages.
+ and random IO, at the given percentages. It is possible to
+ set different values for reads, writes, and trim. To do so,
+ simply use a comma separated list. See blocksize.
-percentage_sequential=int See percentage_random. It is guaranteed that
- they add up to 100. The later setting has priority, each
- will adjust the other.
-
norandommap Normally fio will cover every block of the file when doing
random IO. If this option is given, fio will just get a
new random offset without looking at past io history. This
o->ratemin[i] = le32_to_cpu(top->ratemin[i]);
o->rate_iops[i] = le32_to_cpu(top->rate_iops[i]);
o->rate_iops_min[i] = le32_to_cpu(top->rate_iops_min[i]);
+
+ o->perc_rand[i] = le32_to_cpu(top->perc_rand[i]);
}
o->ratecycle = le32_to_cpu(top->ratecycle);
o->zipf_theta.u.f = fio_uint64_to_double(le64_to_cpu(top->zipf_theta.u.i));
o->pareto_h.u.f = fio_uint64_to_double(le64_to_cpu(top->pareto_h.u.i));
o->random_generator = le32_to_cpu(top->random_generator);
- o->perc_rand = le32_to_cpu(top->perc_rand);
o->hugepage_size = le32_to_cpu(top->hugepage_size);
o->rw_min_bs = le32_to_cpu(top->rw_min_bs);
o->thinktime = le32_to_cpu(top->thinktime);
top->zipf_theta.u.i = __cpu_to_le64(fio_double_to_uint64(o->zipf_theta.u.f));
top->pareto_h.u.i = __cpu_to_le64(fio_double_to_uint64(o->pareto_h.u.f));
top->random_generator = cpu_to_le32(o->random_generator);
- top->perc_rand = cpu_to_le32(o->perc_rand);
top->hugepage_size = cpu_to_le32(o->hugepage_size);
top->rw_min_bs = cpu_to_le32(o->rw_min_bs);
top->thinktime = cpu_to_le32(o->thinktime);
top->ratemin[i] = cpu_to_le32(o->ratemin[i]);
top->rate_iops[i] = cpu_to_le32(o->rate_iops[i]);
top->rate_iops_min[i] = cpu_to_le32(o->rate_iops_min[i]);
+
+ top->perc_rand[i] = cpu_to_le32(o->perc_rand[i]);
}
memcpy(top->verify_pattern, o->verify_pattern, MAX_PATTERN_SIZE);
same size.
.TP
.BI blocksize \fR=\fPint[,int] "\fR,\fB bs" \fR=\fPint[,int]
-Block size for I/O units. Default: 4k. Values for reads and writes can be
-specified separately in the format \fIread\fR,\fIwrite\fR, either of
-which may be empty to leave that value at its default.
+Block size for I/O units. Default: 4k. Values for reads, writes, and trims
+can be specified separately in the format \fIread\fR,\fIwrite\fR,\fItrim\fR
+either of which may be empty to leave that value at its default. If a trailing
+comma isn't given, the remainder will inherit the last value set.
.TP
.BI blocksize_range \fR=\fPirange[,irange] "\fR,\fB bsrange" \fR=\fPirange[,irange]
Specify a range of I/O block sizes. The issued I/O unit will always be a
For a random workload, set how big a percentage should be random. This defaults
to 100%, in which case the workload is fully random. It can be set from
anywhere from 0 to 100. Setting it to 0 would make the workload fully
-sequential.
-.TP
-.BI percentage_sequential \fR=\fPint
-See \fBpercentage_random\fR.
+sequential. It is possible to set different values for reads, writes, and
+trim. To do so, simply use a comma separated list. See \fBblocksize\fR.
.TP
.B norandommap
Normally \fBfio\fR will cover every block of the file when doing random I/O. If
FIO_RAND_FILE_SIZE_OFF,
FIO_RAND_TRIM_OFF,
FIO_RAND_BUF_OFF,
- FIO_RAND_SEQ_RAND_OFF,
+ FIO_RAND_SEQ_RAND_READ_OFF,
+ FIO_RAND_SEQ_RAND_WRITE_OFF,
+ FIO_RAND_SEQ_RAND_TRIM_OFF,
FIO_RAND_NR_OFFS,
};
* rand/seq mixed workload state
*/
union {
- os_random_state_t seq_rand_state;
- struct frand_state __seq_rand_state;
+ os_random_state_t seq_rand_state[DDIR_RWDIR_CNT];
+ struct frand_state __seq_rand_state[DDIR_RWDIR_CNT];
};
/*
static int fixup_options(struct thread_data *td)
{
struct thread_options *o = &td->o;
- int ret = 0;
+ int i, ret = 0;
#ifndef FIO_HAVE_PSHARED_MUTEX
if (!o->use_thread) {
td->rand_seeds[FIO_RAND_BLOCK_OFF] = FIO_RANDSEED * td->thread_number;
os_random_seed(td->rand_seeds[FIO_RAND_BLOCK_OFF], &td->random_state);
- os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_OFF], &td->seq_rand_state);
+
+ os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF], &td->seq_rand_state[DDIR_READ]);
+ os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF], &td->seq_rand_state[DDIR_WRITE]);
+ os_random_seed(td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF], &td->seq_rand_state[DDIR_TRIM]);
}
static void td_fill_rand_seeds_internal(struct thread_data *td)
td->rand_seeds[FIO_RAND_BLOCK_OFF] = FIO_RANDSEED * td->thread_number;
init_rand_seed(&td->__random_state, td->rand_seeds[FIO_RAND_BLOCK_OFF]);
- init_rand_seed(&td->__seq_rand_state, td->rand_seeds[FIO_RAND_SEQ_RAND_OFF]);
+ init_rand_seed(&td->__seq_rand_state[DDIR_READ], td->rand_seeds[FIO_RAND_SEQ_RAND_READ_OFF]);
+ init_rand_seed(&td->__seq_rand_state[DDIR_WRITE], td->rand_seeds[FIO_RAND_SEQ_RAND_WRITE_OFF]);
+ init_rand_seed(&td->__seq_rand_state[DDIR_TRIM], td->rand_seeds[FIO_RAND_SEQ_RAND_TRIM_OFF]);
}
void td_fill_rand_seeds(struct thread_data *td)
return 1;
}
-static int should_do_random(struct thread_data *td)
+static int should_do_random(struct thread_data *td, enum fio_ddir ddir)
{
unsigned int v;
unsigned long r;
- if (td->o.perc_rand == 100)
+ if (td->o.perc_rand[ddir] == 100)
return 1;
if (td->o.use_os_rand) {
- r = os_random_long(&td->seq_rand_state);
+ r = os_random_long(&td->seq_rand_state[ddir]);
v = 1 + (int) (100.0 * (r / (OS_RAND_MAX + 1.0)));
} else {
- r = __rand(&td->__seq_rand_state);
+ r = __rand(&td->__seq_rand_state[ddir]);
v = 1 + (int) (100.0 * (r / (FRAND_MAX + 1.0)));
}
- return v <= td->o.perc_rand;
+ return v <= td->o.perc_rand[ddir];
}
static int get_next_rand_offset(struct thread_data *td, struct fio_file *f,
if (rw_seq) {
if (td_random(td)) {
- if (should_do_random(td))
+ if (should_do_random(td, ddir))
ret = get_next_rand_block(td, f, ddir, &b);
else {
io_u->flags |= IO_U_F_BUSY_OK;
return 0;
}
-static int str_perc_rand_cb(void *data, unsigned long long *val)
-{
- struct thread_data *td = data;
-
- td->o.perc_rand = *val;
- return 0;
-}
-
-static int str_perc_seq_cb(void *data, unsigned long long *val)
-{
- struct thread_data *td = data;
-
- td->o.perc_rand = 100 - *val;
- return 0;
-}
-
-
static int str_exitall_cb(void)
{
exitall_on_terminate = 1;
.name = "percentage_random",
.lname = "Percentage Random",
.type = FIO_OPT_INT,
- .cb = str_perc_rand_cb,
+ .off1 = td_var_offset(perc_rand[DDIR_READ]),
+ .off2 = td_var_offset(perc_rand[DDIR_WRITE]),
+ .off3 = td_var_offset(perc_rand[DDIR_TRIM]),
.maxval = 100,
.help = "Percentage of seq/random mix that should be random",
- .def = "100",
+ .def = "100,100,100",
.interval = 5,
.inverse = "percentage_sequential",
.category = FIO_OPT_C_IO,
{
.name = "percentage_sequential",
.lname = "Percentage Sequential",
- .type = FIO_OPT_INT,
- .cb = str_perc_seq_cb,
- .maxval = 100,
- .help = "Percentage of seq/random mix that should be sequential",
- .def = "0",
- .interval = 5,
- .inverse = "percentage_random",
+ .type = FIO_OPT_DEPRECATED,
.category = FIO_OPT_C_IO,
.group = FIO_OPT_G_RANDOM,
},
}
case FIO_OPT_DEPRECATED:
log_info("Option %s is deprecated\n", o->name);
+ ret = 1;
break;
default:
log_err("Bad option type %u\n", o->type);
};
enum {
- FIO_SERVER_VER = 23,
+ FIO_SERVER_VER = 24,
FIO_SERVER_MAX_FRAGMENT_PDU = 1024,
unsigned int random_generator;
- unsigned int perc_rand;
+ unsigned int perc_rand[DDIR_RWDIR_CNT];
unsigned int hugepage_size;
unsigned int rw_min_bs;
uint32_t random_generator;
- uint32_t perc_rand;
+ uint32_t perc_rand[DDIR_RWDIR_CNT];
uint32_t hugepage_size;
uint32_t rw_min_bs;