From: Jens Axboe Date: Fri, 2 Jun 2006 04:14:21 +0000 (-0700) Subject: [PATCH] Add write_iolog support X-Git-Tag: fio-1.4~1^2 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=843a741389226f5f2d0ce8636cd57532be9b7e4d;hp=200bc855d16b5316933779fa554479e477084b01;ds=sidebyside [PATCH] Add write_iolog support --- diff --git a/README b/README index 8b84a08a..d6e266ad 100644 --- a/README +++ b/README @@ -92,6 +92,9 @@ The format is as follows: rw, offset, length where with rw=0/1 for read/write, and the offset and length entries being in bytes. + write_iolog=x Write an iolog to file 'x' in the same format as iolog. + The iolog options are exclusive, if both given the + read iolog will be performed. lockmem=x Lock down x amount of memory on the machine, to simulate a machine with less memory available. x can include k/m/g suffix. diff --git a/fio-ini.c b/fio-ini.c index f5297576..d5150351 100644 --- a/fio-ini.c +++ b/fio-ini.c @@ -402,8 +402,12 @@ typedef int (str_cb_fn)(struct thread_data *, char *); static int check_str(char *p, char *name, str_cb_fn *cb, struct thread_data *td) { - char *s = strstr(p, name); + char *s; + if (strncmp(p, name, strlen(name))) + return 1; + + s = strstr(p, name); if (!s) return 1; @@ -418,8 +422,12 @@ static int check_str(char *p, char *name, str_cb_fn *cb, struct thread_data *td) static int check_strstore(char *p, char *name, char *dest) { - char *s = strstr(p, name); + char *s; + if (strncmp(p, name, strlen(name))) + return 1; + + s = strstr(p, name); if (!s) return 1; @@ -454,6 +462,9 @@ static int check_range(char *p, char *name, unsigned long *s, unsigned long *e) char option[128]; char *str, *p1, *p2; + if (strncmp(p, name, strlen(name))) + return 1; + strcpy(option, p); p = option; @@ -634,7 +645,6 @@ static int str_ioengine_cb(struct thread_data *td, char *str) static int str_iolog_cb(struct thread_data *td, char *file) { strncpy(td->iolog_file, file, sizeof(td->iolog_file) - 1); - return 0; } @@ -858,7 +868,16 @@ int parse_jobs_ini(char *file) continue; } if (!check_str(p, "iolog", str_iolog_cb, td)) { - td->iolog = 1; + printf("got read iolog\n"); + td->read_iolog = 1; + td->write_iolog = 0; + fgetpos(f, &off); + continue; + } + if (!td->read_iolog && + !check_str(p, "write_iolog", str_iolog_cb, td)) { + printf("got write iolog\n"); + td->write_iolog = 1; fgetpos(f, &off); continue; } diff --git a/fio.c b/fio.c index 51cd1535..695d7549 100644 --- a/fio.c +++ b/fio.c @@ -628,17 +628,16 @@ void put_io_u(struct thread_data *td, struct io_u *io_u) td->cur_depth--; } -static int fill_io_u(struct thread_data *td, struct io_u *io_u) +static void write_iolog_put(struct thread_data *td, struct io_u *io_u) { - /* - * If using an iolog, grab next piece if any available. - */ - if (td->iolog) { - struct io_piece *ipo; + fprintf(td->iolog_f, "%d,%llu,%u\n", io_u->ddir, io_u->offset, io_u->buflen); +} - if (list_empty(&td->io_log_list)) - return 1; +static int read_iolog_get(struct thread_data *td, struct io_u *io_u) +{ + struct io_piece *ipo; + if (!list_empty(&td->io_log_list)) { ipo = list_entry(td->io_log_list.next, struct io_piece, list); list_del(&ipo->list); io_u->offset = ipo->offset; @@ -648,6 +647,17 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u) return 0; } + return 1; +} + +static int fill_io_u(struct thread_data *td, struct io_u *io_u) +{ + /* + * If using an iolog, grab next piece if any available. + */ + if (td->read_iolog) + return read_iolog_get(td, io_u); + /* * No log, let the seq/rand engine retrieve the next position. */ @@ -656,6 +666,13 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u) if (io_u->buflen) { io_u->ddir = get_rw_ddir(td); + + /* + * If using a write iolog, store this entry. + */ + if (td->write_iolog) + write_iolog_put(td, io_u); + return 0; } } @@ -707,7 +724,7 @@ static struct io_u *get_io_u(struct thread_data *td) return NULL; } - if (!td->iolog && !td->sequential) + if (!td->read_iolog && !td->sequential) mark_random_map(td, io_u); td->last_pos += io_u->buflen; @@ -795,6 +812,13 @@ static void log_io_piece(struct thread_data *td, struct io_u *io_u) list_add(&ipo->list, entry); } +static void write_iolog_close(struct thread_data *td) +{ + fflush(td->iolog_f); + fclose(td->iolog_f); + free(td->iolog_buf); +} + static int init_iolog(struct thread_data *td) { unsigned long long offset; @@ -803,15 +827,34 @@ static int init_iolog(struct thread_data *td) FILE *f; int rw, i, reads, writes; - if (!td->iolog) + if (!td->read_iolog && !td->write_iolog) return 0; - f = fopen(td->iolog_file, "r"); + if (td->read_iolog) + f = fopen(td->iolog_file, "r"); + else + f = fopen(td->iolog_file, "w"); + if (!f) { perror("fopen iolog"); + printf("file %s, %d/%d\n", td->iolog_file, td->read_iolog, td->write_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; while ((p = fgets(str, 4096, f)) != NULL) { @@ -1837,6 +1880,7 @@ static void *thread_main(void *data) td_set_runstate(td, TD_INITIALIZED); sem_post(&startup_sem); sem_wait(&td->mutex); + ret = 0; if (!td->create_serialize && setup_file(td)) goto err; @@ -1879,14 +1923,14 @@ static void *thread_main(void *data) break; } - ret = 0; - if (td->bw_log) finish_log(td, td->bw_log, "bw"); if (td->slat_log) finish_log(td, td->slat_log, "slat"); if (td->clat_log) finish_log(td, td->clat_log, "clat"); + if (td->write_iolog) + write_iolog_close(td); if (exitall_on_terminate) terminate_threads(td->groupid); diff --git a/fio.h b/fio.h index 4f87fb77..01c8b9ba 100644 --- a/fio.h +++ b/fio.h @@ -150,9 +150,12 @@ struct thread_data { unsigned int iodepth; os_cpu_mask_t cpumask; unsigned int jobnum; - unsigned int iolog; + unsigned int read_iolog; + unsigned int write_iolog; char iolog_file[256]; + void *iolog_buf; + FILE *iolog_f; struct drand48_data bsrange_state; struct drand48_data verify_state;