X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=io_u.c;h=d1f66a949293310f166690089438e2a883f9feec;hp=7709df5fe55bf7fb6237d6b93476b2f09a2d3d3d;hb=7e356b2dee2e86f3684424fc6e903f1ef9f00ef4;hpb=78c1eda5486f586ca73e9cbe7e40b93fccdbd218 diff --git a/io_u.c b/io_u.c index 7709df5f..d1f66a94 100644 --- a/io_u.c +++ b/io_u.c @@ -13,6 +13,7 @@ struct io_completion_data { int nr; /* input */ + int account; /* input */ int error; /* output */ unsigned long bytes_done[2]; /* output */ @@ -157,7 +158,7 @@ static int get_next_free_block(struct thread_data *td, struct fio_file *f, static int get_next_rand_offset(struct thread_data *td, struct fio_file *f, enum fio_ddir ddir, unsigned long long *b) { - unsigned long long r, lastb; + unsigned long long rmax, r, lastb; int loops = 5; lastb = last_block(td, f, ddir); @@ -167,14 +168,14 @@ static int get_next_rand_offset(struct thread_data *td, struct fio_file *f, if (f->failed_rands >= 200) goto ffz; + rmax = td->o.use_os_rand ? OS_RAND_MAX : FRAND_MAX; do { - if (td->o.use_os_rand) { + if (td->o.use_os_rand) r = os_random_long(&td->random_state); - *b = (lastb - 1) * (r / ((unsigned long long) OS_RAND_MAX + 1.0)); - } else { + else r = __rand(&td->__random_state); - *b = (lastb - 1) * (r / ((unsigned long long) FRAND_MAX + 1.0)); - } + + *b = (lastb - 1) * (r / ((unsigned long long) rmax + 1.0)); dprint(FD_RANDOM, "off rand %llu\n", r); @@ -206,7 +207,7 @@ static int get_next_rand_offset(struct thread_data *td, struct fio_file *f, loops = 10; do { f->last_free_lookup = (f->num_maps - 1) * - (r / (OS_RAND_MAX + 1.0)); + (r / ((unsigned long long) rmax + 1.0)); if (!get_next_free_block(td, f, ddir, b)) goto ret; @@ -249,8 +250,12 @@ static int get_next_seq_block(struct thread_data *td, struct fio_file *f, assert(ddir_rw(ddir)); if (f->last_pos < f->real_file_size) { - unsigned long long pos = f->last_pos - f->file_offset; + unsigned long long pos; + + if (f->last_pos == f->file_offset && td->o.ddir_seq_add < 0) + f->last_pos = f->real_file_size; + pos = f->last_pos - f->file_offset; if (pos) pos += td->o.ddir_seq_add; @@ -1116,6 +1121,44 @@ static int check_get_verify(struct thread_data *td, struct io_u *io_u) return 0; } +/* + * Fill offset and start time into the buffer content, to prevent too + * easy compressible data for simple de-dupe attempts. Do this for every + * 512b block in the range, since that should be the smallest block size + * we can expect from a device. + */ +static void small_content_scramble(struct io_u *io_u) +{ + unsigned int i, nr_blocks = io_u->buflen / 512; + unsigned long long boffset; + unsigned int offset; + void *p, *end; + + if (!nr_blocks) + return; + + p = io_u->xfer_buf; + boffset = io_u->offset; + + for (i = 0; i < nr_blocks; i++) { + /* + * Fill the byte offset into a "random" start offset of + * the buffer, given by the product of the usec time + * and the actual offset. + */ + offset = (io_u->start_time.tv_usec ^ boffset) & 511; + offset &= ~(sizeof(unsigned long long) - 1); + if (offset >= 512 - sizeof(unsigned long long)) + offset -= sizeof(unsigned long long); + memcpy(p + offset, &boffset, sizeof(boffset)); + + end = p + 512 - sizeof(io_u->start_time); + memcpy(end, &io_u->start_time, sizeof(io_u->start_time)); + p += 512; + boffset += 512; + } +} + /* * Return an io_u to be processed. Gets a buflen and offset, sets direction, * etc. The returned io_u is fully ready to be prepped and submitted. @@ -1124,6 +1167,7 @@ struct io_u *get_io_u(struct thread_data *td) { struct fio_file *f; struct io_u *io_u; + int do_scramble = 0; io_u = __get_io_u(td); if (!io_u) { @@ -1165,11 +1209,14 @@ struct io_u *get_io_u(struct thread_data *td) f->last_start = io_u->offset; f->last_pos = io_u->offset + io_u->buflen; - if (td->o.verify != VERIFY_NONE && io_u->ddir == DDIR_WRITE) - populate_verify_io_u(td, io_u); - else if (td->o.refill_buffers && io_u->ddir == DDIR_WRITE) - io_u_fill_buffer(td, io_u, io_u->xfer_buflen); - else if (io_u->ddir == DDIR_READ) { + if (io_u->ddir == DDIR_WRITE) { + if (td->o.verify != VERIFY_NONE) + populate_verify_io_u(td, io_u); + else if (td->o.refill_buffers) + io_u_fill_buffer(td, io_u, io_u->xfer_buflen); + else if (td->o.scramble_buffers) + do_scramble = 1; + } else if (io_u->ddir == DDIR_READ) { /* * Reset the buf_filled parameters so next time if the * buffer is used for writes it is refilled. @@ -1189,6 +1236,8 @@ out: if (!td_io_prep(td, io_u)) { if (!td->o.disable_slat) fio_gettime(&io_u->start_time, NULL); + if (do_scramble) + small_content_scramble(io_u); return io_u; } err_put: @@ -1218,6 +1267,36 @@ void io_u_log_error(struct thread_data *td, struct io_u *io_u) td_verror(td, io_u->error, "io_u error"); } +static void account_io_completion(struct thread_data *td, struct io_u *io_u, + struct io_completion_data *icd, + const enum fio_ddir idx, unsigned int bytes) +{ + unsigned long uninitialized_var(lusec); + + if (!icd->account) + return; + + if (!td->o.disable_clat || !td->o.disable_bw) + lusec = utime_since(&io_u->issue_time, &icd->time); + + if (!td->o.disable_lat) { + unsigned long tusec; + + tusec = utime_since(&io_u->start_time, &icd->time); + add_lat_sample(td, idx, tusec, bytes); + } + + if (!td->o.disable_clat) { + add_clat_sample(td, idx, lusec, bytes); + io_u_mark_latency(td, lusec); + } + + if (!td->o.disable_bw) + add_bw_sample(td, idx, bytes, &icd->time); + + add_iops_sample(td, idx, &icd->time); +} + static void io_completed(struct thread_data *td, struct io_u *io_u, struct io_completion_data *icd) { @@ -1255,6 +1334,7 @@ static void io_completed(struct thread_data *td, struct io_u *io_u, int ret; td->io_blocks[idx]++; + td->this_io_blocks[idx]++; td->io_bytes[idx] += bytes; td->this_io_bytes[idx] += bytes; @@ -1270,25 +1350,9 @@ static void io_completed(struct thread_data *td, struct io_u *io_u, } } - if (ramp_time_over(td)) { - unsigned long uninitialized_var(lusec); + if (ramp_time_over(td) && td->runstate == TD_RUNNING) { + account_io_completion(td, io_u, icd, idx, bytes); - if (!td->o.disable_clat || !td->o.disable_bw) - lusec = utime_since(&io_u->issue_time, - &icd->time); - if (!td->o.disable_lat) { - unsigned long tusec; - - tusec = utime_since(&io_u->start_time, - &icd->time); - add_lat_sample(td, idx, tusec, bytes); - } - if (!td->o.disable_clat) { - add_clat_sample(td, idx, lusec, bytes); - io_u_mark_latency(td, lusec); - } - if (!td->o.disable_bw) - add_bw_sample(td, idx, bytes, &icd->time); if (__should_check_rate(td, idx)) { td->rate_pending_usleep[idx] = ((td->this_io_bytes[idx] * @@ -1338,6 +1402,7 @@ static void init_icd(struct thread_data *td, struct io_completion_data *icd, fio_gettime(&icd->time, NULL); icd->nr = nr; + icd->account = 1; icd->error = 0; icd->bytes_done[0] = icd->bytes_done[1] = 0; @@ -1356,6 +1421,8 @@ static void ios_completed(struct thread_data *td, if (!(io_u->flags & IO_U_F_FREE_DEF)) put_io_u(td, io_u); + + icd->account = 0; } } @@ -1446,7 +1513,7 @@ void io_u_fill_buffer(struct thread_data *td, struct io_u *io_u, io_u->buf_filled_len = 0; if (!td->o.zero_buffers) - fill_random_buf(io_u->buf, max_bs); + fill_random_buf(&td->buf_state, io_u->buf, max_bs); else memset(io_u->buf, 0, max_bs); }