X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=log.c;h=2b90f452e8c22bca740b235ebb26094a12892574;hb=8fd15a9a8d64deae4c2f13b02e1df7e23ea3cafb;hp=8d313ec65419ef926f560d762d88eb4996341379;hpb=8914a9d83c67a2ead861ac997a1d4b06d02639bc;p=fio.git diff --git a/log.c b/log.c index 8d313ec6..2b90f452 100644 --- a/log.c +++ b/log.c @@ -5,7 +5,7 @@ void write_iolog_put(struct thread_data *td, struct io_u *io_u) { - fprintf(td->iolog_f, "%d,%llu,%u\n", io_u->ddir, io_u->offset, io_u->buflen); + fprintf(td->iolog_f, "%u,%llu,%lu\n", io_u->ddir, io_u->offset, io_u->buflen); } int read_iolog_get(struct thread_data *td, struct io_u *io_u) @@ -18,6 +18,7 @@ int read_iolog_get(struct thread_data *td, struct io_u *io_u) io_u->offset = ipo->offset; io_u->buflen = ipo->len; io_u->ddir = ipo->ddir; + io_u->file = ipo->file; free(ipo); return 0; } @@ -28,49 +29,47 @@ int read_iolog_get(struct thread_data *td, struct io_u *io_u) void prune_io_piece_log(struct thread_data *td) { struct io_piece *ipo; + struct rb_node *n; - while (!list_empty(&td->io_hist_list)) { - ipo = list_entry(td->io_hist_list.next, struct io_piece, list); - - list_del(&ipo->list); + while ((n = rb_first(&td->io_hist_tree)) != NULL) { + ipo = rb_entry(n, struct io_piece, rb_node); + rb_erase(n, &td->io_hist_tree); free(ipo); } } /* - * log a succesful write, so we can unwind the log for verify + * log a successful write, so we can unwind the log for verify */ void log_io_piece(struct thread_data *td, struct io_u *io_u) { - struct io_piece *ipo = malloc(sizeof(struct io_piece)); - struct list_head *entry; + struct rb_node **p = &td->io_hist_tree.rb_node; + struct rb_node *parent = NULL; + struct io_piece *ipo, *__ipo; - INIT_LIST_HEAD(&ipo->list); + ipo = malloc(sizeof(struct io_piece)); + memset(&ipo->rb_node, 0, sizeof(ipo->rb_node)); + ipo->file = io_u->file; ipo->offset = io_u->offset; ipo->len = io_u->buflen; /* - * for random io where the writes extend the file, it will typically - * be laid out with the block scattered as written. it's faster to - * read them in in that order again, so don't sort - */ - if (td->sequential || !td->overwrite) { - list_add_tail(&ipo->list, &td->io_hist_list); - return; - } - - /* - * for random io, sort the list so verify will run faster + * Sort the entry into the verification list */ - entry = &td->io_hist_list; - while ((entry = entry->prev) != &td->io_hist_list) { - struct io_piece *__ipo = list_entry(entry, struct io_piece, list); - - if (__ipo->offset < ipo->offset) + while (*p) { + parent = *p; + + __ipo = rb_entry(parent, struct io_piece, rb_node); + if (ipo->offset < __ipo->offset) + p = &(*p)->rb_left; + else if (ipo->offset > __ipo->offset) + p = &(*p)->rb_right; + else break; } - list_add(&ipo->list, entry); + rb_link_node(&ipo->rb_node, parent, p); + rb_insert_color(&ipo->rb_node, &td->io_hist_tree); } void write_iolog_close(struct thread_data *td) @@ -80,49 +79,34 @@ void write_iolog_close(struct thread_data *td) free(td->iolog_buf); } -int init_iolog(struct thread_data *td) +/* + * Open a stored log and read in the entries. + */ +static int init_iolog_read(struct thread_data *td) { unsigned long long offset; unsigned int bytes; char *str, *p; FILE *f; - int rw, i, reads, writes; - - if (!td->read_iolog && !td->write_iolog) - return 0; - - if (td->read_iolog) - f = fopen(td->iolog_file, "r"); - else - f = fopen(td->iolog_file, "w"); + int rw, reads, writes; + f = fopen(td->o.read_iolog_file, "r"); if (!f) { - perror("fopen iolog"); - printf("file %s, %d/%d\n", td->iolog_file, td->read_iolog, td->write_iolog); + perror("fopen read iolog"); return 1; } - /* - * That's it for writing, setup a log buffer and we're done. - */ - if (td->write_iolog) { - td->iolog_f = f; - td->iolog_buf = malloc(8192); - setvbuf(f, td->iolog_buf, _IOFBF, 8192); - return 0; - } - /* * Read in the read iolog and store it, reuse the infrastructure * for doing verifications. */ str = malloc(4096); - reads = writes = i = 0; + reads = writes = 0; while ((p = fgets(str, 4096, f)) != NULL) { struct io_piece *ipo; if (sscanf(p, "%d,%llu,%u", &rw, &offset, &bytes) != 3) { - fprintf(stderr, "bad iolog: %s\n", p); + log_err("bad iolog: %s\n", p); continue; } if (rw == DDIR_READ) @@ -130,7 +114,7 @@ int init_iolog(struct thread_data *td) else if (rw == DDIR_WRITE) writes++; else { - fprintf(stderr, "bad ddir: %d\n", rw); + log_err("bad ddir: %d\n", rw); continue; } @@ -138,47 +122,64 @@ int init_iolog(struct thread_data *td) INIT_LIST_HEAD(&ipo->list); ipo->offset = offset; ipo->len = bytes; - if (bytes > td->max_bs) - td->max_bs = bytes; - ipo->ddir = rw; + ipo->ddir = (enum fio_ddir) rw; + if (bytes > td->o.max_bs[rw]) + td->o.max_bs[rw] = bytes; list_add_tail(&ipo->list, &td->io_log_list); - i++; } free(str); fclose(f); - if (!i) + if (!reads && !writes) return 1; - - if (reads && !writes) - td->ddir = DDIR_READ; + else if (reads && !writes) + td->o.td_ddir = TD_DDIR_READ; else if (!reads && writes) - td->ddir = DDIR_READ; + td->o.td_ddir = TD_DDIR_READ; else - td->iomix = 1; + td->o.td_ddir = TD_DDIR_RW; return 0; } -int setup_rate(struct thread_data *td) +/* + * Setup a log for storing io patterns. + */ +static int init_iolog_write(struct thread_data *td) { - int nr_reads_per_sec; - - if (!td->rate) - return 0; + FILE *f; - if (td->rate < td->ratemin) { - fprintf(stderr, "min rate larger than nominal rate\n"); - return -1; + f = fopen(td->o.write_iolog_file, "w+"); + if (!f) { + perror("fopen write iolog"); + return 1; } - nr_reads_per_sec = (td->rate * 1024) / td->min_bs; - td->rate_usec_cycle = 1000000 / nr_reads_per_sec; - td->rate_pending_usleep = 0; + /* + * That's it for writing, setup a log buffer and we're done. + */ + td->iolog_f = f; + td->iolog_buf = malloc(8192); + setvbuf(f, td->iolog_buf, _IOFBF, 8192); return 0; } +int init_iolog(struct thread_data *td) +{ + int ret = 0; + + if (td->io_ops->flags & FIO_DISKLESSIO) + return 0; + + if (td->o.read_iolog_file) + ret = init_iolog_read(td); + else if (td->o.write_iolog_file) + ret = init_iolog_write(td); + + return ret; +} + void setup_log(struct io_log **log) { struct io_log *l = malloc(sizeof(*l)); @@ -189,14 +190,12 @@ void setup_log(struct io_log **log) *log = l; } -void finish_log(struct thread_data *td, struct io_log *log, const char *name) +void __finish_log(struct io_log *log, const char *name) { - char file_name[256]; - FILE *f; unsigned int i; + FILE *f; - snprintf(file_name, 200, "client%d_%s.log", td->thread_number, name); - f = fopen(file_name, "w"); + f = fopen(name, "w"); if (!f) { perror("fopen log"); return; @@ -209,3 +208,11 @@ void finish_log(struct thread_data *td, struct io_log *log, const char *name) free(log->log); free(log); } + +void finish_log(struct thread_data *td, struct io_log *log, const char *name) +{ + char file_name[256]; + + snprintf(file_name, 200, "client%d_%s.log", td->thread_number, name); + __finish_log(log, file_name); +}