X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=iolog.c;h=1aeb7a76b2b6ca21ab8bd3d5c18e5ec200669fcb;hb=1db268db68823f0fa4c4a4701d3deee88b4c1d84;hp=b0122bed78b10de59d76d07cbaccb0fe1f0a9513;hpb=a94aedbc11829470cce77eb52969601d618054d6;p=fio.git diff --git a/iolog.c b/iolog.c index b0122bed..1aeb7a76 100644 --- a/iolog.c +++ b/iolog.c @@ -19,6 +19,7 @@ #include "smalloc.h" #include "blktrace.h" #include "pshared.h" +#include "lib/roundup.h" #include #include @@ -150,7 +151,8 @@ int read_iolog_get(struct thread_data *td, struct io_u *io_u) while (!flist_empty(&td->io_log_list)) { int ret; - if (td->o.read_iolog_chunked) { + + if (!td->io_log_blktrace && td->o.read_iolog_chunked) { if (td->io_log_checkmark == td->io_log_current) { if (!read_iolog2(td)) return 1; @@ -173,6 +175,7 @@ int read_iolog_get(struct thread_data *td, struct io_u *io_u) io_u->ddir = ipo->ddir; if (ipo->ddir != DDIR_WAIT) { io_u->offset = ipo->offset; + io_u->verify_offset = ipo->offset; io_u->buflen = ipo->len; io_u->file = td->files[ipo->fileno]; get_file(io_u->file); @@ -342,6 +345,9 @@ void trim_io_piece(const struct io_u *io_u) void write_iolog_close(struct thread_data *td) { + if (!td->iolog_f) + return; + fflush(td->iolog_f); fclose(td->iolog_f); free(td->iolog_buf); @@ -349,6 +355,34 @@ void write_iolog_close(struct thread_data *td) td->iolog_buf = NULL; } +static int64_t iolog_items_to_fetch(struct thread_data *td) +{ + struct timespec now; + uint64_t elapsed; + uint64_t for_1s; + int64_t items_to_fetch; + + if (!td->io_log_highmark) + return 10; + + + fio_gettime(&now, NULL); + elapsed = ntime_since(&td->io_log_highmark_time, &now); + if (elapsed) { + for_1s = (td->io_log_highmark - td->io_log_current) * 1000000000 / elapsed; + items_to_fetch = for_1s - td->io_log_current; + if (items_to_fetch < 0) + items_to_fetch = 0; + } else + items_to_fetch = 0; + + td->io_log_highmark = td->io_log_current + items_to_fetch; + td->io_log_checkmark = (td->io_log_highmark + 1) / 2; + fio_gettime(&td->io_log_highmark_time, NULL); + + return items_to_fetch; +} + /* * Read version 2 iolog data. It is enhanced to include per-file logging, * syncs, etc. @@ -361,28 +395,15 @@ static bool read_iolog2(struct thread_data *td) char *rfname, *fname, *act; char *str, *p; enum fio_ddir rw; + bool realloc = false; int64_t items_to_fetch = 0; if (td->o.read_iolog_chunked) { - if (td->io_log_highmark == 0) { - items_to_fetch = 10; - } else { - struct timespec now; - uint64_t elapsed; - uint64_t for_1s; - fio_gettime(&now, NULL); - elapsed = ntime_since(&td->io_log_highmark_time, &now); - for_1s = (td->io_log_highmark - td->io_log_current) * 1000000000 / elapsed; - items_to_fetch = for_1s - td->io_log_current; - if (items_to_fetch < 0) - items_to_fetch = 0; - td->io_log_highmark = td->io_log_current + items_to_fetch; - td->io_log_checkmark = (td->io_log_highmark + 1) / 2; - fio_gettime(&td->io_log_highmark_time, NULL); - if (items_to_fetch == 0) - return true; - } + items_to_fetch = iolog_items_to_fetch(td); + if (!items_to_fetch) + return true; } + /* * Read in the read iolog and store it, reuse the infrastructure * for doing verifications. @@ -432,7 +453,7 @@ static bool read_iolog2(struct thread_data *td) dprint(FD_FILE, "iolog: ignoring" " re-add of file %s\n", fname); } else { - fileno = add_file(td, fname, 0, 1); + fileno = add_file(td, fname, td->subjob_number, 1); file_action = FIO_LOG_ADD_FILE; } continue; @@ -487,8 +508,10 @@ static bool read_iolog2(struct thread_data *td) ipo_bytes_align(td->o.replay_align, ipo); ipo->len = bytes; - if (rw != DDIR_INVAL && bytes > td->o.max_bs[rw]) + if (rw != DDIR_INVAL && bytes > td->o.max_bs[rw]) { + realloc = true; td->o.max_bs[rw] = bytes; + } ipo->fileno = fileno; ipo->file_action = file_action; td->o.size += bytes; @@ -525,6 +548,12 @@ static bool read_iolog2(struct thread_data *td) return false; } td->o.td_ddir = TD_DDIR_RW; + if (realloc && td->orig_buffer) + { + io_u_quiesce(td); + free_io_mem(td); + init_io_u_buffers(td); + } return true; } @@ -543,7 +572,9 @@ static bool read_iolog2(struct thread_data *td) static bool is_socket(const char *path) { struct stat buf; - int r = stat(path, &buf); + int r; + + r = stat(path, &buf); if (r == -1) return false; @@ -552,34 +583,51 @@ static bool is_socket(const char *path) static int open_socket(const char *path) { - int fd = socket(AF_UNIX, SOCK_STREAM, 0); struct sockaddr_un addr; + int ret, fd; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) return fd; + addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, path, sizeof(addr.sun_path)); - if (connect(fd, (const struct sockaddr *)&addr, strlen(path) + sizeof(addr.sun_family)) == 0) + if (snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path) >= + sizeof(addr.sun_path)) { + log_err("%s: path name %s is too long for a Unix socket\n", + __func__, path); + } + + ret = connect(fd, (const struct sockaddr *)&addr, strlen(path) + sizeof(addr.sun_family)); + if (!ret) return fd; - else - close(fd); + + close(fd); return -1; } /* * open iolog, check version, and call appropriate parser */ -static bool init_iolog_read(struct thread_data *td) +static bool init_iolog_read(struct thread_data *td, char *fname) { char buffer[256], *p; FILE *f = NULL; - bool ret; - if (is_socket(td->o.read_iolog_file)) { - int fd = open_socket(td->o.read_iolog_file); - if (fd >= 0) { + + dprint(FD_IO, "iolog: name=%s\n", fname); + + if (is_socket(fname)) { + int fd; + + fd = open_socket(fname); + if (fd >= 0) f = fdopen(fd, "r"); - } + } else if (!strcmp(fname, "-")) { + f = stdin; } else - f = fopen(td->o.read_iolog_file, "r"); + f = fopen(fname, "r"); + + free(fname); + if (!f) { perror("fopen read iolog"); return false; @@ -592,21 +640,20 @@ static bool init_iolog_read(struct thread_data *td) fclose(f); return false; } - td->io_log_rfile = f; + /* * version 2 of the iolog stores a specific string as the * first line, check for that */ if (!strncmp(iolog_ver2, buffer, strlen(iolog_ver2))) { free_release_files(td); - ret = read_iolog2(td); - } - else { - log_err("fio: iolog version 1 is no longer supported\n"); - ret = false; + td->io_log_rfile = f; + return read_iolog2(td); } - return ret; + log_err("fio: iolog version 1 is no longer supported\n"); + fclose(f); + return false; } /* @@ -654,15 +701,19 @@ bool init_iolog(struct thread_data *td) if (td->o.read_iolog_file) { int need_swap; + char * fname = get_name_by_idx(td->o.read_iolog_file, td->subjob_number); /* * Check if it's a blktrace file and load that if possible. * Otherwise assume it's a normal log file and load that. */ - if (is_blktrace(td->o.read_iolog_file, &need_swap)) - ret = load_blktrace(td, td->o.read_iolog_file, need_swap); - else - ret = init_iolog_read(td); + if (is_blktrace(fname, &need_swap)) { + td->io_log_blktrace = 1; + ret = load_blktrace(td, fname, need_swap); + } else { + td->io_log_blktrace = 0; + ret = init_iolog_read(td, fname); + } } else if (td->o.write_iolog_file) ret = init_iolog_write(td); else @@ -686,6 +737,7 @@ void setup_log(struct io_log **log, struct log_params *p, INIT_FLIST_HEAD(&l->io_logs); l->log_type = p->log_type; l->log_offset = p->log_offset; + l->log_prio = p->log_prio; l->log_gz = p->log_gz; l->log_gz_store = p->log_gz_store; l->avg_msec = p->avg_msec; @@ -705,16 +757,21 @@ void setup_log(struct io_log **log, struct log_params *p, } if (l->td && l->td->o.io_submit_mode != IO_MODE_OFFLOAD) { + unsigned int def_samples = DEF_LOG_ENTRIES; struct io_logs *__p; __p = calloc(1, sizeof(*l->pending)); - __p->max_samples = DEF_LOG_ENTRIES; + if (l->td->o.iodepth > DEF_LOG_ENTRIES) + def_samples = roundup_pow2(l->td->o.iodepth); + __p->max_samples = def_samples; __p->log = calloc(__p->max_samples, log_entry_sz(l)); l->pending = __p; } if (l->log_offset) l->log_ddir_mask = LOG_OFFSET_SAMPLE_BIT; + if (l->log_prio) + l->log_ddir_mask |= LOG_PRIO_SAMPLE_BIT; INIT_FLIST_HEAD(&l->chunk_list); @@ -841,33 +898,55 @@ static void flush_hist_samples(FILE *f, int hist_coarseness, void *samples, void flush_samples(FILE *f, void *samples, uint64_t sample_size) { struct io_sample *s; - int log_offset; + int log_offset, log_prio; uint64_t i, nr_samples; + unsigned int prio_val; + const char *fmt; if (!sample_size) return; s = __get_sample(samples, 0, 0); log_offset = (s->__ddir & LOG_OFFSET_SAMPLE_BIT) != 0; + log_prio = (s->__ddir & LOG_PRIO_SAMPLE_BIT) != 0; + + if (log_offset) { + if (log_prio) + fmt = "%lu, %" PRId64 ", %u, %llu, %llu, 0x%04x\n"; + else + fmt = "%lu, %" PRId64 ", %u, %llu, %llu, %u\n"; + } else { + if (log_prio) + fmt = "%lu, %" PRId64 ", %u, %llu, 0x%04x\n"; + else + fmt = "%lu, %" PRId64 ", %u, %llu, %u\n"; + } nr_samples = sample_size / __log_entry_sz(log_offset); for (i = 0; i < nr_samples; i++) { s = __get_sample(samples, log_offset, i); + if (log_prio) + prio_val = s->priority; + else + prio_val = ioprio_value_is_class_rt(s->priority); + if (!log_offset) { - fprintf(f, "%lu, %" PRId64 ", %u, %llu\n", - (unsigned long) s->time, - s->data.val, - io_sample_ddir(s), (unsigned long long) s->bs); + fprintf(f, fmt, + (unsigned long) s->time, + s->data.val, + io_sample_ddir(s), (unsigned long long) s->bs, + prio_val); } else { struct io_sample_offset *so = (void *) s; - fprintf(f, "%lu, %" PRId64 ", %u, %llu, %llu\n", - (unsigned long) s->time, - s->data.val, - io_sample_ddir(s), (unsigned long long) s->bs, - (unsigned long long) so->offset); + fprintf(f, fmt, + (unsigned long) s->time, + s->data.val, + io_sample_ddir(s), (unsigned long long) s->bs, + (unsigned long long) so->offset, + prio_val); } } }