X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=io_u.c;h=40fd1968eb08b4a9e8d1bcd6108ab7b6f780d1fe;hp=08969427dd41b3753058b831987492e845ac27f5;hb=d1bd7213c61dabc5e7ae967614e38923123a1f1a;hpb=62977e09a378a713b31d64c63e15adcf9f6f9d9d diff --git a/io_u.c b/io_u.c index 08969427..40fd1968 100644 --- a/io_u.c +++ b/io_u.c @@ -7,6 +7,7 @@ #include "fio.h" #include "hash.h" +#include "verify.h" struct io_completion_data { int nr; /* input */ @@ -95,7 +96,7 @@ static unsigned long long last_block(struct thread_data *td, struct fio_file *f, if (max_size > f->real_file_size) max_size = f->real_file_size; - max_blocks = max_size / (unsigned long long) td->o.min_bs[ddir]; + max_blocks = max_size / (unsigned long long) td->o.ba[ddir]; if (!max_blocks) return 0; @@ -113,7 +114,8 @@ static int get_next_free_block(struct thread_data *td, struct fio_file *f, i = f->last_free_lookup; *b = (i * BLOCKS_PER_MAP); - while ((*b) * min_bs < f->real_file_size) { + 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)) @@ -194,18 +196,25 @@ static int get_next_offset(struct thread_data *td, struct io_u *io_u) if (td_random(td) && (td->o.ddir_nr && !--td->ddir_nr)) { td->ddir_nr = td->o.ddir_nr; - if (get_next_rand_offset(td, f, ddir, &b)) + if (get_next_rand_offset(td, f, ddir, &b)) { + dprint(FD_IO, "%s: getting rand offset failed\n", + f->file_name); return 1; + } } else { if (f->last_pos >= f->real_file_size) { if (!td_random(td) || - get_next_rand_offset(td, f, ddir, &b)) + get_next_rand_offset(td, f, ddir, &b)) { + dprint(FD_IO, "%s: pos %llu > size %llu\n", + f->file_name, f->last_pos, + f->real_file_size); return 1; + } } else b = (f->last_pos - f->file_offset) / td->o.min_bs[ddir]; } - io_u->offset = b * td->o.min_bs[ddir]; + io_u->offset = b * td->o.ba[ddir]; if (io_u->offset >= f->io_size) { dprint(FD_IO, "get_next_offset: offset %llu >= io_size %llu\n", io_u->offset, f->io_size); @@ -241,7 +250,7 @@ static unsigned int get_next_buflen(struct thread_data *td, struct io_u *io_u) buflen = minbs; else { r = os_random_long(&td->bsrange_state); - if (!td->o.bssplit_nr) { + if (!td->o.bssplit_nr[ddir]) { buflen = 1 + (unsigned int) ((double) maxbs * (r / (OS_RAND_MAX + 1.0))); if (buflen < minbs) @@ -250,8 +259,8 @@ static unsigned int get_next_buflen(struct thread_data *td, struct io_u *io_u) long perc = 0; unsigned int i; - for (i = 0; i < td->o.bssplit_nr; i++) { - struct bssplit *bsp = &td->o.bssplit[i]; + for (i = 0; i < td->o.bssplit_nr[ddir]; i++) { + struct bssplit *bsp = &td->o.bssplit[ddir][i]; buflen = bsp->bs; perc += bsp->perc; @@ -310,7 +319,6 @@ static enum fio_ddir get_rw_ddir(struct thread_data *td) * Check if it's time to seed a new data direction. */ if (td->io_issues[td->rwmix_ddir] >= td->rwmix_issues) { - unsigned long long max_bytes; enum fio_ddir ddir; /* @@ -319,16 +327,6 @@ static enum fio_ddir get_rw_ddir(struct thread_data *td) * ranges too much */ ddir = get_rand_ddir(td); - max_bytes = td->this_io_bytes[ddir]; - if (max_bytes >= - (td->o.size * td->o.rwmix[ddir] / 100)) { - if (!td->rw_end_set[ddir]) { - td->rw_end_set[ddir] = 1; - fio_gettime(&td->rw_end[ddir], NULL); - } - - ddir ^= 1; - } if (ddir != td->rwmix_ddir) set_rwmix_bytes(td); @@ -613,25 +611,37 @@ static void io_u_mark_latency(struct thread_data *td, unsigned long usec) /* * Get next file to service by choosing one at random */ -static struct fio_file *get_next_file_rand(struct thread_data *td, int goodf, - int badf) +static struct fio_file *get_next_file_rand(struct thread_data *td, enum fio_file_flags goodf, + enum fio_file_flags badf) { struct fio_file *f; int fno; do { long r = os_random_long(&td->next_file_state); + int opened = 0; fno = (unsigned int) ((double) td->o.nr_files * (r / (OS_RAND_MAX + 1.0))); f = td->files[fno]; - if (f->flags & FIO_FILE_DONE) + if (fio_file_done(f)) continue; + if (!fio_file_open(f)) { + int err; + + err = td_io_open_file(td, f); + if (err) + continue; + opened = 1; + } + if ((!goodf || (f->flags & goodf)) && !(f->flags & badf)) { dprint(FD_FILE, "get_next_file_rand: %p\n", f); return f; } + if (opened) + td_io_close_file(td, f); } while (1); } @@ -645,20 +655,40 @@ static struct fio_file *get_next_file_rr(struct thread_data *td, int goodf, struct fio_file *f; do { + int opened = 0; + f = td->files[td->next_file]; td->next_file++; if (td->next_file >= td->o.nr_files) td->next_file = 0; - if (f->flags & FIO_FILE_DONE) { + dprint(FD_FILE, "trying file %s %x\n", f->file_name, f->flags); + if (fio_file_done(f)) { f = NULL; continue; } + if (!fio_file_open(f)) { + int err; + + err = td_io_open_file(td, f); + if (err) { + dprint(FD_FILE, "error %d on open of %s\n", + err, f->file_name); + f = NULL; + continue; + } + opened = 1; + } + + dprint(FD_FILE, "goodf=%x, badf=%x, ff=%x\n", goodf, badf, f->flags); if ((!goodf || (f->flags & goodf)) && !(f->flags & badf)) break; + if (opened) + td_io_close_file(td, f); + f = NULL; } while (td->next_file != old_next_file); @@ -672,7 +702,7 @@ static struct fio_file *get_next_file(struct thread_data *td) assert(td->o.nr_files <= td->files_index); - if (!td->nr_open_files || td->nr_done_files >= td->o.nr_files) { + if (td->nr_done_files >= td->o.nr_files) { dprint(FD_FILE, "get_next_file: nr_open=%d, nr_done=%d," " nr_files=%d\n", td->nr_open_files, td->nr_done_files, @@ -681,33 +711,23 @@ static struct fio_file *get_next_file(struct thread_data *td) } f = td->file_service_file; - if (f && (f->flags & FIO_FILE_OPEN) && td->file_service_left--) - goto out; + if (f && fio_file_open(f) && !fio_file_closing(f)) { + if (td->o.file_service_type == FIO_FSERVICE_SEQ) + goto out; + if (td->file_service_left--) + goto out; + } - if (td->o.file_service_type == FIO_FSERVICE_RR) - f = get_next_file_rr(td, FIO_FILE_OPEN, FIO_FILE_CLOSING); + if (td->o.file_service_type == FIO_FSERVICE_RR || + td->o.file_service_type == FIO_FSERVICE_SEQ) + f = get_next_file_rr(td, FIO_FILE_open, FIO_FILE_closing); else - f = get_next_file_rand(td, FIO_FILE_OPEN, FIO_FILE_CLOSING); + f = get_next_file_rand(td, FIO_FILE_open, FIO_FILE_closing); td->file_service_file = f; td->file_service_left = td->file_service_nr - 1; out: - dprint(FD_FILE, "get_next_file: %p\n", f); - return f; -} - -static struct fio_file *find_next_new_file(struct thread_data *td) -{ - struct fio_file *f; - - if (!td->nr_open_files || td->nr_done_files >= td->o.nr_files) - return NULL; - - if (td->o.file_service_type == FIO_FSERVICE_RR) - f = get_next_file_rr(td, 0, FIO_FILE_OPEN); - else - f = get_next_file_rand(td, 0, FIO_FILE_OPEN); - + dprint(FD_FILE, "get_next_file: %p [%s]\n", f, f->file_name); return f; } @@ -720,45 +740,18 @@ static int set_io_u_file(struct thread_data *td, struct io_u *io_u) if (!f) return 1; -set_file: io_u->file = f; get_file(f); if (!fill_io_u(td, io_u)) break; - /* - * optimization to prevent close/open of the same file. This - * way we preserve queueing etc. - */ - if (td->o.nr_files == 1 && td->o.time_based) { - put_file_log(td, f); - fio_file_reset(f); - goto set_file; - } - - /* - * td_io_close() does a put_file() as well, so no need to - * do that here. - */ - io_u->file = NULL; + put_file_log(td, f); td_io_close_file(td, f); - f->flags |= FIO_FILE_DONE; + io_u->file = NULL; + fio_file_set_done(f); td->nr_done_files++; - - /* - * probably not the right place to do this, but see - * if we need to open a new file - */ - if (td->nr_open_files < td->o.open_files && - td->o.open_files != td->o.nr_files) { - f = find_next_new_file(td); - - if (!f || td_io_open_file(td, f)) - return 1; - - goto set_file; - } + dprint(FD_FILE, "%s: is done (%d of %d)\n", f->file_name, td->nr_done_files, td->o.nr_files); } while (1); return 0; @@ -826,7 +819,7 @@ struct io_u *get_io_u(struct thread_data *td) } f = io_u->file; - assert(f->flags & FIO_FILE_OPEN); + assert(fio_file_open(f)); if (io_u->ddir != DDIR_SYNC) { if (!io_u->buflen && !(td->io_ops->flags & FIO_NOIO)) { @@ -836,7 +829,7 @@ struct io_u *get_io_u(struct thread_data *td) f->last_pos = io_u->offset + io_u->buflen; - if (td->o.verify != VERIFY_NONE) + 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); @@ -845,13 +838,13 @@ struct io_u *get_io_u(struct thread_data *td) /* * Set io data pointers. */ - io_u->endpos = io_u->offset + io_u->buflen; io_u->xfer_buf = io_u->buf; io_u->xfer_buflen = io_u->buflen; out: if (!td_io_prep(td, io_u)) { - fio_gettime(&io_u->start_time, NULL); + if (!td->o.disable_slat) + fio_gettime(&io_u->start_time, NULL); return io_u; } err_put: @@ -881,7 +874,11 @@ void io_u_log_error(struct thread_data *td, struct io_u *io_u) static void io_completed(struct thread_data *td, struct io_u *io_u, struct io_completion_data *icd) { - unsigned long usec; + /* + * Older gcc's are too dumb to realize that usec is always used + * initialized, silence that warning. + */ + unsigned long uninitialized_var(usec); dprint_io_u(io_u, "io complete"); @@ -905,11 +902,16 @@ static void io_completed(struct thread_data *td, struct io_u *io_u, td->this_io_bytes[idx] += bytes; if (ramp_time_over(td)) { - usec = utime_since(&io_u->issue_time, &icd->time); + if (!td->o.disable_clat || !td->o.disable_bw) + usec = utime_since(&io_u->issue_time, + &icd->time); - add_clat_sample(td, idx, usec); - add_bw_sample(td, idx, &icd->time); - io_u_mark_latency(td, usec); + if (!td->o.disable_clat) { + add_clat_sample(td, idx, usec, bytes); + io_u_mark_latency(td, usec); + } + if (!td->o.disable_bw) + add_bw_sample(td, idx, bytes, &icd->time); } if (td_write(td) && idx == DDIR_WRITE && @@ -930,9 +932,11 @@ static void io_completed(struct thread_data *td, struct io_u *io_u, } } -static void init_icd(struct io_completion_data *icd, int nr) +static void init_icd(struct thread_data *td, struct io_completion_data *icd, + int nr) { - fio_gettime(&icd->time, NULL); + if (!td->o.disable_clat || !td->o.disable_bw) + fio_gettime(&icd->time, NULL); icd->nr = nr; @@ -961,7 +965,7 @@ long io_u_sync_complete(struct thread_data *td, struct io_u *io_u) { struct io_completion_data icd; - init_icd(&icd, 1); + init_icd(td, &icd, 1); io_completed(td, io_u, &icd); put_io_u(td, io_u); @@ -994,7 +998,7 @@ long io_u_queued_complete(struct thread_data *td, int min_evts) } else if (!ret) return ret; - init_icd(&icd, ret); + init_icd(td, &icd, ret); ios_completed(td, &icd); if (!icd.error) return icd.bytes_done[0] + icd.bytes_done[1]; @@ -1008,10 +1012,12 @@ long io_u_queued_complete(struct thread_data *td, int min_evts) */ void io_u_queued(struct thread_data *td, struct io_u *io_u) { - unsigned long slat_time; + if (!td->o.disable_slat) { + unsigned long slat_time; - slat_time = utime_since(&io_u->start_time, &io_u->issue_time); - add_slat_sample(td, io_u->ddir, slat_time); + slat_time = utime_since(&io_u->start_time, &io_u->issue_time); + add_slat_sample(td, io_u->ddir, io_u->xfer_buflen, slat_time); + } } /*