X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=io_u.c;h=7709df5fe55bf7fb6237d6b93476b2f09a2d3d3d;hp=6d539a01fbdaec105144c2b93252683a4630af46;hb=78c1eda5486f586ca73e9cbe7e40b93fccdbd218;hpb=1ef2b6be973eded12827990ae1a9eb28b7b20be7 diff --git a/io_u.c b/io_u.c index 6d539a01..7709df5f 100644 --- a/io_u.c +++ b/io_u.c @@ -30,7 +30,7 @@ static int random_map_free(struct fio_file *f, const unsigned long long block) dprint(FD_RANDOM, "free: b=%llu, idx=%u, bit=%u\n", block, idx, bit); - return (f->file_map[idx] & (1 << bit)) == 0; + return (f->file_map[idx] & (1UL << bit)) == 0; } /* @@ -50,8 +50,8 @@ static void mark_random_map(struct thread_data *td, struct io_u *io_u) busy_check = !(io_u->flags & IO_U_F_BUSY_OK); while (nr_blocks) { - unsigned int this_blocks, mask; unsigned int idx, bit; + unsigned long mask, this_blocks; /* * If we have a mixed random workload, we may @@ -75,9 +75,9 @@ static void mark_random_map(struct thread_data *td, struct io_u *io_u) do { if (this_blocks == BLOCKS_PER_MAP) - mask = -1U; + mask = -1UL; else - mask = ((1U << this_blocks) - 1) << bit; + mask = ((1UL << this_blocks) - 1) << bit; if (!(f->file_map[idx] & mask)) break; @@ -126,22 +126,27 @@ static unsigned long long last_block(struct thread_data *td, struct fio_file *f, static int get_next_free_block(struct thread_data *td, struct fio_file *f, enum fio_ddir ddir, unsigned long long *b) { - unsigned long long min_bs = td->o.rw_min_bs; + unsigned long long block, min_bs = td->o.rw_min_bs, lastb; int i; + lastb = last_block(td, f, ddir); + if (!lastb) + return 1; + i = f->last_free_lookup; - *b = (i * BLOCKS_PER_MAP); - while ((*b) * min_bs < f->real_file_size && - (*b) * min_bs < f->io_size) { - if (f->file_map[i] != (unsigned int) -1) { - *b += ffz(f->file_map[i]); - if (*b > last_block(td, f, ddir)) + block = i * BLOCKS_PER_MAP; + while (block * min_bs < f->real_file_size && + block * min_bs < f->io_size) { + if (f->file_map[i] != -1UL) { + block += ffz(f->file_map[i]); + if (block > lastb) break; f->last_free_lookup = i; + *b = block; return 0; } - *b += BLOCKS_PER_MAP; + block += BLOCKS_PER_MAP; i++; } @@ -152,31 +157,47 @@ 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; + unsigned long long r, lastb; int loops = 5; + lastb = last_block(td, f, ddir); + if (!lastb) + return 1; + + if (f->failed_rands >= 200) + goto ffz; + do { - r = os_random_long(&td->random_state); + 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 { + r = __rand(&td->__random_state); + *b = (lastb - 1) * (r / ((unsigned long long) FRAND_MAX + 1.0)); + } + dprint(FD_RANDOM, "off rand %llu\n", r); - *b = (last_block(td, f, ddir) - 1) - * (r / ((unsigned long long) OS_RAND_MAX + 1.0)); + /* * if we are not maintaining a random map, we are done. */ if (!file_randommap(td, f)) - return 0; + goto ret_good; /* * calculate map offset and check if it's free */ if (random_map_free(f, *b)) - return 0; + goto ret_good; dprint(FD_RANDOM, "get_next_rand_offset: offset %llu busy\n", *b); } while (--loops); + if (!f->failed_rands++) + f->last_free_lookup = 0; + /* * we get here, if we didn't suceed in looking up a block. generate * a random start offset into the filemap, and find the first free @@ -187,16 +208,27 @@ static int get_next_rand_offset(struct thread_data *td, struct fio_file *f, f->last_free_lookup = (f->num_maps - 1) * (r / (OS_RAND_MAX + 1.0)); if (!get_next_free_block(td, f, ddir, b)) - return 0; + goto ret; - r = os_random_long(&td->random_state); + if (td->o.use_os_rand) + r = os_random_long(&td->random_state); + else + r = __rand(&td->__random_state); } while (--loops); /* * that didn't work either, try exhaustive search from the start */ f->last_free_lookup = 0; +ffz: + if (!get_next_free_block(td, f, ddir, b)) + return 0; + f->last_free_lookup = 0; return get_next_free_block(td, f, ddir, b); +ret_good: + f->failed_rands = 0; +ret: + return 0; } static int get_next_rand_block(struct thread_data *td, struct fio_file *f, @@ -217,7 +249,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) { - *b = (f->last_pos - f->file_offset) / td->o.min_bs[ddir]; + unsigned long long pos = f->last_pos - f->file_offset; + + if (pos) + pos += td->o.ddir_seq_add; + + *b = pos / td->o.min_bs[ddir]; return 0; } @@ -309,12 +346,20 @@ static int get_next_offset(struct thread_data *td, struct io_u *io_u) return __get_next_offset(td, io_u); } +static inline int io_u_fits(struct thread_data *td, struct io_u *io_u, + unsigned int buflen) +{ + struct fio_file *f = io_u->file; + + return io_u->offset + buflen <= f->io_size + td->o.start_offset; +} + static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u) { const int ddir = io_u->ddir; unsigned int uninitialized_var(buflen); unsigned int minbs, maxbs; - long r; + unsigned long r, rand_max; assert(ddir_rw(ddir)); @@ -322,12 +367,22 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u) maxbs = td->o.max_bs[ddir]; if (minbs == maxbs) - buflen = minbs; - else { - r = os_random_long(&td->bsrange_state); + return minbs; + + if (td->o.use_os_rand) + rand_max = OS_RAND_MAX; + else + rand_max = FRAND_MAX; + + do { + if (td->o.use_os_rand) + r = os_random_long(&td->bsrange_state); + else + r = __rand(&td->__bsrange_state); + if (!td->o.bssplit_nr[ddir]) { buflen = 1 + (unsigned int) ((double) maxbs * - (r / (OS_RAND_MAX + 1.0))); + (r / (rand_max + 1.0))); if (buflen < minbs) buflen = minbs; } else { @@ -339,19 +394,16 @@ static unsigned int __get_next_buflen(struct thread_data *td, struct io_u *io_u) buflen = bsp->bs; perc += bsp->perc; - if (r <= ((OS_RAND_MAX / 100L) * perc)) + if ((r <= ((rand_max / 100L) * perc)) && + io_u_fits(td, io_u, buflen)) break; } } + if (!td->o.bs_unaligned && is_power_of_2(minbs)) buflen = (buflen + minbs - 1) & ~(minbs - 1); - } - if (io_u->offset + buflen > io_u->file->real_file_size) { - dprint(FD_IO, "lower buflen %u -> %u (ddir=%d)\n", buflen, - minbs, ddir); - buflen = minbs; - } + } while (!io_u_fits(td, io_u, buflen)); return buflen; } @@ -382,10 +434,16 @@ static void set_rwmix_bytes(struct thread_data *td) static inline enum fio_ddir get_rand_ddir(struct thread_data *td) { unsigned int v; - long r; + unsigned long r; + + if (td->o.use_os_rand) { + r = os_random_long(&td->rwmix_state); + v = 1 + (int) (100.0 * (r / (OS_RAND_MAX + 1.0))); + } else { + r = __rand(&td->__rwmix_state); + v = 1 + (int) (100.0 * (r / (FRAND_MAX + 1.0))); + } - r = os_random_long(&td->rwmix_state); - v = 1 + (int) (100.0 * (r / (OS_RAND_MAX + 1.0))); if (v <= td->o.rwmix[DDIR_READ]) return DDIR_READ; @@ -428,6 +486,16 @@ static enum fio_ddir rate_ddir(struct thread_data *td, enum fio_ddir ddir) } else usec = td->rate_pending_usleep[ddir]; + /* + * We are going to sleep, ensure that we flush anything pending as + * not to skew our latency numbers + */ + if (td->cur_depth) { + int fio_unused ret; + + ret = io_u_queued_complete(td, td->cur_depth, NULL); + } + fio_gettime(&t, NULL); usec_sleep(td, usec); usec = utime_since_now(&t); @@ -628,31 +696,31 @@ out: static void __io_u_mark_map(unsigned int *map, unsigned int nr) { - int index = 0; + int idx = 0; switch (nr) { default: - index = 6; + idx = 6; break; case 33 ... 64: - index = 5; + idx = 5; break; case 17 ... 32: - index = 4; + idx = 4; break; case 9 ... 16: - index = 3; + idx = 3; break; case 5 ... 8: - index = 2; + idx = 2; break; case 1 ... 4: - index = 1; + idx = 1; case 0: break; } - map[index]++; + map[idx]++; } void io_u_mark_submit(struct thread_data *td, unsigned int nr) @@ -669,117 +737,117 @@ void io_u_mark_complete(struct thread_data *td, unsigned int nr) void io_u_mark_depth(struct thread_data *td, unsigned int nr) { - int index = 0; + int idx = 0; switch (td->cur_depth) { default: - index = 6; + idx = 6; break; case 32 ... 63: - index = 5; + idx = 5; break; case 16 ... 31: - index = 4; + idx = 4; break; case 8 ... 15: - index = 3; + idx = 3; break; case 4 ... 7: - index = 2; + idx = 2; break; case 2 ... 3: - index = 1; + idx = 1; case 1: break; } - td->ts.io_u_map[index] += nr; + td->ts.io_u_map[idx] += nr; } static void io_u_mark_lat_usec(struct thread_data *td, unsigned long usec) { - int index = 0; + int idx = 0; assert(usec < 1000); switch (usec) { case 750 ... 999: - index = 9; + idx = 9; break; case 500 ... 749: - index = 8; + idx = 8; break; case 250 ... 499: - index = 7; + idx = 7; break; case 100 ... 249: - index = 6; + idx = 6; break; case 50 ... 99: - index = 5; + idx = 5; break; case 20 ... 49: - index = 4; + idx = 4; break; case 10 ... 19: - index = 3; + idx = 3; break; case 4 ... 9: - index = 2; + idx = 2; break; case 2 ... 3: - index = 1; + idx = 1; case 0 ... 1: break; } - assert(index < FIO_IO_U_LAT_U_NR); - td->ts.io_u_lat_u[index]++; + assert(idx < FIO_IO_U_LAT_U_NR); + td->ts.io_u_lat_u[idx]++; } static void io_u_mark_lat_msec(struct thread_data *td, unsigned long msec) { - int index = 0; + int idx = 0; switch (msec) { default: - index = 11; + idx = 11; break; case 1000 ... 1999: - index = 10; + idx = 10; break; case 750 ... 999: - index = 9; + idx = 9; break; case 500 ... 749: - index = 8; + idx = 8; break; case 250 ... 499: - index = 7; + idx = 7; break; case 100 ... 249: - index = 6; + idx = 6; break; case 50 ... 99: - index = 5; + idx = 5; break; case 20 ... 49: - index = 4; + idx = 4; break; case 10 ... 19: - index = 3; + idx = 3; break; case 4 ... 9: - index = 2; + idx = 2; break; case 2 ... 3: - index = 1; + idx = 1; case 0 ... 1: break; } - assert(index < FIO_IO_U_LAT_M_NR); - td->ts.io_u_lat_m[index]++; + assert(idx < FIO_IO_U_LAT_M_NR); + td->ts.io_u_lat_m[idx]++; } static void io_u_mark_latency(struct thread_data *td, unsigned long usec) @@ -801,11 +869,19 @@ static struct fio_file *get_next_file_rand(struct thread_data *td, int fno; do { - long r = os_random_long(&td->next_file_state); int opened = 0; + unsigned long r; + + if (td->o.use_os_rand) { + r = os_random_long(&td->next_file_state); + fno = (unsigned int) ((double) td->o.nr_files + * (r / (OS_RAND_MAX + 1.0))); + } else { + r = __rand(&td->__next_file_state); + fno = (unsigned int) ((double) td->o.nr_files + * (r / (FRAND_MAX + 1.0))); + } - fno = (unsigned int) ((double) td->o.nr_files - * (r / (OS_RAND_MAX + 1.0))); f = td->files[fno]; if (fio_file_done(f)) continue; @@ -1367,6 +1443,8 @@ void io_u_queued(struct thread_data *td, struct io_u *io_u) void io_u_fill_buffer(struct thread_data *td, struct io_u *io_u, unsigned int max_bs) { + io_u->buf_filled_len = 0; + if (!td->o.zero_buffers) fill_random_buf(io_u->buf, max_bs); else