X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=fio.c;h=a146f035c19f5f18647aa2ce34a9fa1476fec3d8;hp=ea57d78308b149491f61a39e9e2caeb8dd2de552;hb=263e529f7d90892a610a5b26a519116fe3a675a6;hpb=ea2877a4ab0fb047a503ba0d7a0fd5393d0fb099 diff --git a/fio.c b/fio.c index ea57d783..a146f035 100644 --- a/fio.c +++ b/fio.c @@ -41,33 +41,12 @@ int groupid = 0; int thread_number = 0; -static char run_str[MAX_JOBS + 1]; int shm_id = 0; -static struct timeval genesis; -static int temp_stall_ts; +int temp_stall_ts; char *fio_inst_prefix = _INST_PREFIX; -static void print_thread_status(void); - extern unsigned long long mlock_size; -/* - * Thread life cycle. Once a thread has a runstate beyond TD_INITIALIZED, it - * will never back again. It may cycle between running/verififying/fsyncing. - * Once the thread reaches TD_EXITED, it is just waiting for the core to - * reap it. - */ -enum { - TD_NOT_CREATED = 0, - TD_CREATED, - TD_INITIALIZED, - TD_RUNNING, - TD_VERIFYING, - TD_FSYNCING, - TD_EXITED, - TD_REAPED, -}; - #define should_fsync(td) ((td_write(td) || td_rw(td)) && (!(td)->odirect || (td)->override_sync)) static volatile int startup_sem; @@ -109,26 +88,28 @@ static void sig_handler(int sig) * The ->file_map[] contains a map of blocks we have or have not done io * to yet. Used to make sure we cover the entire range in a fair fashion. */ -static int random_map_free(struct thread_data *td, unsigned long long block) +static int random_map_free(struct thread_data *td, struct fio_file *f, + unsigned long long block) { - unsigned int idx = RAND_MAP_IDX(td, block); - unsigned int bit = RAND_MAP_BIT(td, block); + unsigned int idx = RAND_MAP_IDX(td, f, block); + unsigned int bit = RAND_MAP_BIT(td, f, block); - return (td->file_map[idx] & (1UL << bit)) == 0; + return (f->file_map[idx] & (1UL << bit)) == 0; } /* * Return the next free block in the map. */ -static int get_next_free_block(struct thread_data *td, unsigned long long *b) +static int get_next_free_block(struct thread_data *td, struct fio_file *f, + unsigned long long *b) { int i; *b = 0; i = 0; - while ((*b) * td->min_bs < td->io_size) { - if (td->file_map[i] != -1UL) { - *b += ffz(td->file_map[i]); + while ((*b) * td->min_bs < f->file_size) { + if (f->file_map[i] != -1UL) { + *b += ffz(f->file_map[i]); return 0; } @@ -142,7 +123,8 @@ static int get_next_free_block(struct thread_data *td, unsigned long long *b) /* * Mark a given offset as used in the map. */ -static void mark_random_map(struct thread_data *td, struct io_u *io_u) +static void mark_random_map(struct thread_data *td, struct fio_file *f, + struct io_u *io_u) { unsigned long long block = io_u->offset / (unsigned long long) td->min_bs; unsigned int blocks = 0; @@ -150,15 +132,15 @@ static void mark_random_map(struct thread_data *td, struct io_u *io_u) while (blocks < (io_u->buflen / td->min_bs)) { unsigned int idx, bit; - if (!random_map_free(td, block)) + if (!random_map_free(td, f, block)) break; - idx = RAND_MAP_IDX(td, block); - bit = RAND_MAP_BIT(td, block); + idx = RAND_MAP_IDX(td, f, block); + bit = RAND_MAP_BIT(td, f, block); - assert(idx < td->num_maps); + assert(idx < f->num_maps); - td->file_map[idx] |= (1UL << bit); + f->file_map[idx] |= (1UL << bit); block++; blocks++; } @@ -172,7 +154,8 @@ static void mark_random_map(struct thread_data *td, struct io_u *io_u) * until we find a free one. For sequential io, just return the end of * the last io issued. */ -static int get_next_offset(struct thread_data *td, unsigned long long *offset) +static int get_next_offset(struct thread_data *td, struct fio_file *f, + unsigned long long *offset) { unsigned long long b, rb; long r; @@ -184,19 +167,19 @@ static int get_next_offset(struct thread_data *td, unsigned long long *offset) do { r = os_random_long(&td->random_state); b = ((max_blocks - 1) * r / (unsigned long long) (RAND_MAX+1.0)); - rb = b + (td->file_offset / td->min_bs); + rb = b + (f->file_offset / td->min_bs); loops--; - } while (!random_map_free(td, rb) && loops); + } while (!random_map_free(td, f, rb) && loops); if (!loops) { - if (get_next_free_block(td, &b)) + if (get_next_free_block(td, f, &b)) return 1; } } else - b = td->last_pos / td->min_bs; + b = f->last_pos / td->min_bs; - *offset = (b * td->min_bs) + td->file_offset; - if (*offset > td->real_file_size) + *offset = (b * td->min_bs) + f->file_offset; + if (*offset > f->file_size) return 1; return 0; @@ -215,8 +198,16 @@ static unsigned int get_next_buflen(struct thread_data *td) buflen = (buflen + td->min_bs - 1) & ~(td->min_bs - 1); } - if (buflen > td->io_size - td->this_io_bytes[td->ddir]) + if (buflen > td->io_size - td->this_io_bytes[td->ddir]) { + /* + * if using direct/raw io, we may not be able to + * shrink the size. so just fail it. + */ + if (td->io_ops->flags & FIO_RAWIO) + return 0; + buflen = td->io_size - td->this_io_bytes[td->ddir]; + } return buflen; } @@ -443,12 +434,14 @@ static int td_io_prep(struct thread_data *td, struct io_u *io_u) void put_io_u(struct thread_data *td, struct io_u *io_u) { + io_u->file = NULL; list_del(&io_u->list); list_add(&io_u->list, &td->io_u_freelist); td->cur_depth--; } -static int fill_io_u(struct thread_data *td, struct io_u *io_u) +static int fill_io_u(struct thread_data *td, struct fio_file *f, + struct io_u *io_u) { /* * If using an iolog, grab next piece if any available. @@ -459,7 +452,7 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u) /* * No log, let the seq/rand engine retrieve the next position. */ - if (!get_next_offset(td, &io_u->offset)) { + if (!get_next_offset(td, f, &io_u->offset)) { io_u->buflen = get_next_buflen(td); if (io_u->buflen) { @@ -471,6 +464,7 @@ static int fill_io_u(struct thread_data *td, struct io_u *io_u) if (td->write_iolog) write_iolog_put(td, io_u); + io_u->file = f; return 0; } } @@ -501,7 +495,7 @@ struct io_u *__get_io_u(struct thread_data *td) * Return an io_u to be processed. Gets a buflen and offset, sets direction, * etc. The returned io_u is fully ready to be prepped and submitted. */ -static struct io_u *get_io_u(struct thread_data *td) +static struct io_u *get_io_u(struct thread_data *td, struct fio_file *f) { struct io_u *io_u; @@ -511,16 +505,22 @@ static struct io_u *get_io_u(struct thread_data *td) if (td->zone_bytes >= td->zone_size) { td->zone_bytes = 0; - td->last_pos += td->zone_skip; + f->last_pos += td->zone_skip; } - if (fill_io_u(td, io_u)) { + if (fill_io_u(td, f, io_u)) { put_io_u(td, io_u); return NULL; } - if (io_u->buflen + io_u->offset > td->real_file_size) - io_u->buflen = td->real_file_size - io_u->offset; + if (io_u->buflen + io_u->offset > f->file_size) { + if (td->io_ops->flags & FIO_RAWIO) { + put_io_u(td, io_u); + return NULL; + } + + io_u->buflen = f->file_size - io_u->offset; + } if (!io_u->buflen) { put_io_u(td, io_u); @@ -528,9 +528,9 @@ static struct io_u *get_io_u(struct thread_data *td) } if (!td->read_iolog && !td->sequential) - mark_random_map(td, io_u); + mark_random_map(td, f, io_u); - td->last_pos += io_u->buflen; + f->last_pos += io_u->buflen; if (td->verify != VERIFY_NONE) populate_io_u(td, io_u); @@ -568,21 +568,42 @@ static int get_next_verify(struct thread_data *td, struct io_u *io_u) return 1; } -static int sync_td(struct thread_data *td) +static struct fio_file *get_next_file(struct thread_data *td) +{ + int old_next_file = td->next_file; + struct fio_file *f; + + do { + f = &td->files[td->next_file]; + + td->next_file++; + if (td->next_file >= td->nr_files) + td->next_file = 0; + + if (f->fd != -1) + break; + + f = NULL; + } while (td->next_file != old_next_file); + + return f; +} + +static int td_io_sync(struct thread_data *td, struct fio_file *f) { if (td->io_ops->sync) - return td->io_ops->sync(td); + return td->io_ops->sync(td, f); return 0; } -static int io_u_getevents(struct thread_data *td, int min, int max, +static int td_io_getevents(struct thread_data *td, int min, int max, struct timespec *t) { return td->io_ops->getevents(td, min, max, t); } -static int io_u_queue(struct thread_data *td, struct io_u *io_u) +static int td_io_queue(struct thread_data *td, struct io_u *io_u) { gettimeofday(&io_u->issue_time, NULL); @@ -652,7 +673,7 @@ static void cleanup_pending_aio(struct thread_data *td) /* * get immediately available events, if any */ - r = io_u_getevents(td, 0, td->cur_depth, &ts); + r = td_io_getevents(td, 0, td->cur_depth, &ts); if (r > 0) { icd.nr = r; ios_completed(td, &icd); @@ -672,7 +693,7 @@ static void cleanup_pending_aio(struct thread_data *td) } if (td->cur_depth) { - r = io_u_getevents(td, td->cur_depth, td->cur_depth, NULL); + r = td_io_getevents(td, td->cur_depth, td->cur_depth, NULL); if (r > 0) { icd.nr = r; ios_completed(td, &icd); @@ -703,6 +724,7 @@ static void do_verify(struct thread_data *td) struct timeval t; struct io_u *io_u, *v_io_u = NULL; struct io_completion_data icd; + struct fio_file *f; int ret; td_set_runstate(td, TD_VERIFYING); @@ -724,12 +746,18 @@ static void do_verify(struct thread_data *td) break; } + f = get_next_file(td); + if (!f) + break; + + io_u->file = f; + if (td_io_prep(td, io_u)) { put_io_u(td, io_u); break; } - ret = io_u_queue(td, io_u); + ret = td_io_queue(td, io_u); if (ret) { put_io_u(td, io_u); td_verror(td, ret); @@ -743,7 +771,7 @@ static void do_verify(struct thread_data *td) if (do_io_u_verify(td, &v_io_u)) break; - ret = io_u_getevents(td, 1, 1, NULL); + ret = td_io_getevents(td, 1, 1, NULL); if (ret != 1) { if (ret < 0) td_verror(td, ret); @@ -812,6 +840,8 @@ static void do_io(struct thread_data *td) struct io_completion_data icd; struct timeval s, e; unsigned long usec; + struct fio_file *f; + int i; td_set_runstate(td, TD_RUNNING); @@ -824,13 +854,17 @@ static void do_io(struct thread_data *td) if (td->terminate) break; - io_u = get_io_u(td); + f = get_next_file(td); + if (!f) + break; + + io_u = get_io_u(td, f); if (!io_u) break; memcpy(&s, &io_u->start_time, sizeof(s)); - ret = io_u_queue(td, io_u); + ret = td_io_queue(td, io_u); if (ret) { put_io_u(td, io_u); td_verror(td, ret); @@ -847,7 +881,7 @@ static void do_io(struct thread_data *td) min_evts = 1; } - ret = io_u_getevents(td, min_evts, td->cur_depth, timeout); + ret = td_io_getevents(td, min_evts, td->cur_depth, timeout); if (ret < 0) { td_verror(td, ret); break; @@ -884,7 +918,7 @@ static void do_io(struct thread_data *td) if (should_fsync(td) && td->fsync_blocks && (td->io_blocks[DDIR_WRITE] % td->fsync_blocks) == 0) - sync_td(td); + td_io_sync(td, f); } if (td->cur_depth) @@ -892,11 +926,12 @@ static void do_io(struct thread_data *td) if (should_fsync(td) && td->end_fsync) { td_set_runstate(td, TD_FSYNCING); - sync_td(td); + for_each_file(td, f, i) + td_io_sync(td, f); } } -static int init_io(struct thread_data *td) +static int td_io_init(struct thread_data *td) { if (td->io_ops->init) return td->io_ops->init(td); @@ -988,287 +1023,6 @@ static int init_io_u(struct thread_data *td) return 0; } -static int create_file(struct thread_data *td, unsigned long long size) -{ - unsigned long long left; - unsigned int bs; - char *b; - int r; - - /* - * unless specifically asked for overwrite, let normal io extend it - */ - if (!td->overwrite) { - td->real_file_size = size; - return 0; - } - - if (!size) { - log_err("Need size for create\n"); - td_verror(td, EINVAL); - return 1; - } - - temp_stall_ts = 1; - fprintf(f_out, "%s: Laying out IO file (%LuMiB)\n",td->name,size >> 20); - - td->fd = open(td->file_name, O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (td->fd < 0) { - td_verror(td, errno); - goto done_noclose; - } - - if (ftruncate(td->fd, td->file_size) == -1) { - td_verror(td, errno); - goto done; - } - - td->io_size = td->file_size; - b = malloc(td->max_bs); - memset(b, 0, td->max_bs); - - left = size; - while (left && !td->terminate) { - bs = td->max_bs; - if (bs > left) - bs = left; - - r = write(td->fd, b, bs); - - if (r == (int) bs) { - left -= bs; - continue; - } else { - if (r < 0) - td_verror(td, errno); - else - td_verror(td, EIO); - - break; - } - } - - if (td->terminate) - unlink(td->file_name); - else if (td->create_fsync) - fsync(td->fd); - - free(b); -done: - close(td->fd); - td->fd = -1; -done_noclose: - temp_stall_ts = 0; - return 0; -} - -static int file_size(struct thread_data *td) -{ - struct stat st; - - if (td->overwrite) { - if (fstat(td->fd, &st) == -1) { - td_verror(td, errno); - return 1; - } - - td->real_file_size = st.st_size; - - if (!td->file_size || td->file_size > td->real_file_size) - td->file_size = td->real_file_size; - } - - td->file_size -= td->file_offset; - return 0; -} - -static int bdev_size(struct thread_data *td) -{ - unsigned long long bytes; - int r; - - r = blockdev_size(td->fd, &bytes); - if (r) { - td_verror(td, r); - return 1; - } - - td->real_file_size = bytes; - - /* - * no extend possibilities, so limit size to device size if too large - */ - if (!td->file_size || td->file_size > td->real_file_size) - td->file_size = td->real_file_size; - - td->file_size -= td->file_offset; - return 0; -} - -static int get_file_size(struct thread_data *td) -{ - int ret = 0; - - if (td->filetype == FIO_TYPE_FILE) - ret = file_size(td); - else if (td->filetype == FIO_TYPE_BD) - ret = bdev_size(td); - else - td->real_file_size = -1; - - if (ret) - return ret; - - if (td->file_offset > td->real_file_size) { - log_err("%s: offset extends end (%Lu > %Lu)\n", td->name, td->file_offset, td->real_file_size); - return 1; - } - - td->io_size = td->file_size; - if (td->io_size == 0) { - log_err("%s: no io blocks\n", td->name); - td_verror(td, EINVAL); - return 1; - } - - if (!td->zone_size) - td->zone_size = td->io_size; - - td->total_io_size = td->io_size * td->loops; - return 0; -} - -static int setup_file_mmap(struct thread_data *td) -{ - int flags; - - if (td_rw(td)) - flags = PROT_READ | PROT_WRITE; - else if (td_write(td)) { - flags = PROT_WRITE; - - if (td->verify != VERIFY_NONE) - flags |= PROT_READ; - } else - flags = PROT_READ; - - td->mmap = mmap(NULL, td->file_size, flags, MAP_SHARED, td->fd, td->file_offset); - if (td->mmap == MAP_FAILED) { - td->mmap = NULL; - td_verror(td, errno); - return 1; - } - - if (td->invalidate_cache) { - if (madvise(td->mmap, td->file_size, MADV_DONTNEED) < 0) { - td_verror(td, errno); - return 1; - } - } - - if (td->sequential) { - if (madvise(td->mmap, td->file_size, MADV_SEQUENTIAL) < 0) { - td_verror(td, errno); - return 1; - } - } else { - if (madvise(td->mmap, td->file_size, MADV_RANDOM) < 0) { - td_verror(td, errno); - return 1; - } - } - - return 0; -} - -static int setup_file_plain(struct thread_data *td) -{ - if (td->invalidate_cache) { - if (fadvise(td->fd, td->file_offset, td->file_size, POSIX_FADV_DONTNEED) < 0) { - td_verror(td, errno); - return 1; - } - } - - if (td->sequential) { - if (fadvise(td->fd, td->file_offset, td->file_size, POSIX_FADV_SEQUENTIAL) < 0) { - td_verror(td, errno); - return 1; - } - } else { - if (fadvise(td->fd, td->file_offset, td->file_size, POSIX_FADV_RANDOM) < 0) { - td_verror(td, errno); - return 1; - } - } - - return 0; -} - -static int setup_file(struct thread_data *td) -{ - struct stat st; - int flags = 0; - - if (td->io_ops->setup) - return td->io_ops->setup(td); - - if (stat(td->file_name, &st) == -1) { - if (errno != ENOENT) { - td_verror(td, errno); - return 1; - } - if (!td->create_file) { - td_verror(td, ENOENT); - return 1; - } - if (create_file(td, td->file_size)) - return 1; - } else if (td->filetype == FIO_TYPE_FILE && - st.st_size < (off_t) td->file_size) { - if (create_file(td, td->file_size)) - return 1; - } - - if (td->odirect) - flags |= OS_O_DIRECT; - - if (td_write(td) || td_rw(td)) { - if (td->filetype == FIO_TYPE_FILE) { - if (!td->overwrite) - flags |= O_TRUNC; - - flags |= O_CREAT; - } - if (td->sync_io) - flags |= O_SYNC; - - flags |= O_RDWR; - - td->fd = open(td->file_name, flags, 0600); - } else { - if (td->filetype == FIO_TYPE_CHAR) - flags |= O_RDWR; - else - flags |= O_RDONLY; - - td->fd = open(td->file_name, flags); - } - - if (td->fd == -1) { - td_verror(td, errno); - return 1; - } - - if (get_file_size(td)) - return 1; - - if (td->io_ops->flags & FIO_MMAPIO) - return setup_file_mmap(td); - else - return setup_file_plain(td); -} - static int switch_ioscheduler(struct thread_data *td) { char tmp[256], tmp2[128]; @@ -1319,16 +1073,21 @@ static int switch_ioscheduler(struct thread_data *td) static void clear_io_state(struct thread_data *td) { - if (td->io_ops->flags & FIO_SYNCIO) - lseek(td->fd, SEEK_SET, 0); + struct fio_file *f; + int i; - td->last_pos = 0; td->stat_io_bytes[0] = td->stat_io_bytes[1] = 0; td->this_io_bytes[0] = td->this_io_bytes[1] = 0; td->zone_bytes = 0; - if (td->file_map) - memset(td->file_map, 0, td->num_maps * sizeof(long)); + for_each_file(td, f, i) { + f->last_pos = 0; + if (td->io_ops->flags & FIO_SYNCIO) + lseek(f->fd, SEEK_SET, 0); + + if (f->file_map) + memset(f->file_map, 0, f->num_maps * sizeof(long)); + } } /* @@ -1357,7 +1116,7 @@ static void *thread_main(void *data) goto err; } - if (init_io(td)) + if (td_io_init(td)) goto err; if (init_iolog(td)) @@ -1385,7 +1144,7 @@ static void *thread_main(void *data) fio_sem_up(&startup_sem); fio_sem_down(&td->mutex); - if (!td->create_serialize && setup_file(td)) + if (!td->create_serialize && setup_files(td)) goto err; gettimeofday(&td->epoch, NULL); @@ -1447,12 +1206,7 @@ static void *thread_main(void *data) terminate_threads(td->groupid); err: - if (td->fd != -1) { - close(td->fd); - td->fd = -1; - } - if (td->mmap) - munmap(td->mmap, td->file_size); + close_files(td); close_ioengine(td); cleanup_io_u(td); td_set_runstate(td, TD_EXITED); @@ -1481,231 +1235,6 @@ static void *fork_main(int shmid, int offset) return NULL; } -/* - * Sets the status of the 'td' in the printed status map. - */ -static void check_str_update(struct thread_data *td) -{ - char c = run_str[td->thread_number - 1]; - - switch (td->runstate) { - case TD_REAPED: - c = '_'; - break; - case TD_EXITED: - c = 'E'; - break; - case TD_RUNNING: - if (td_rw(td)) { - if (td->sequential) - c = 'M'; - else - c = 'm'; - } else if (td_read(td)) { - if (td->sequential) - c = 'R'; - else - c = 'r'; - } else { - if (td->sequential) - c = 'W'; - else - c = 'w'; - } - break; - case TD_VERIFYING: - c = 'V'; - break; - case TD_FSYNCING: - c = 'F'; - break; - case TD_CREATED: - c = 'C'; - break; - case TD_INITIALIZED: - c = 'I'; - break; - case TD_NOT_CREATED: - c = 'P'; - break; - default: - log_err("state %d\n", td->runstate); - } - - run_str[td->thread_number - 1] = c; -} - -/* - * Convert seconds to a printable string. - */ -static void eta_to_str(char *str, int eta_sec) -{ - unsigned int d, h, m, s; - static int always_d, always_h; - - d = h = m = s = 0; - - s = eta_sec % 60; - eta_sec /= 60; - m = eta_sec % 60; - eta_sec /= 60; - h = eta_sec % 24; - eta_sec /= 24; - d = eta_sec; - - if (d || always_d) { - always_d = 1; - str += sprintf(str, "%02dd:", d); - } - if (h || always_h) { - always_h = 1; - str += sprintf(str, "%02dh:", h); - } - - str += sprintf(str, "%02dm:", m); - str += sprintf(str, "%02ds", s); -} - -/* - * Best effort calculation of the estimated pending runtime of a job. - */ -static int thread_eta(struct thread_data *td, unsigned long elapsed) -{ - unsigned long long bytes_total, bytes_done; - unsigned int eta_sec = 0; - - bytes_total = td->total_io_size; - - /* - * if writing, bytes_total will be twice the size. If mixing, - * assume a 50/50 split and thus bytes_total will be 50% larger. - */ - if (td->verify) { - if (td_rw(td)) - bytes_total = bytes_total * 3 / 2; - else - bytes_total <<= 1; - } - if (td->zone_size && td->zone_skip) - bytes_total /= (td->zone_skip / td->zone_size); - - if (td->runstate == TD_RUNNING || td->runstate == TD_VERIFYING) { - double perc; - - bytes_done = td->io_bytes[DDIR_READ] + td->io_bytes[DDIR_WRITE]; - perc = (double) bytes_done / (double) bytes_total; - if (perc > 1.0) - perc = 1.0; - - eta_sec = (elapsed * (1.0 / perc)) - elapsed; - - if (td->timeout && eta_sec > (td->timeout - elapsed)) - eta_sec = td->timeout - elapsed; - } else if (td->runstate == TD_NOT_CREATED || td->runstate == TD_CREATED - || td->runstate == TD_INITIALIZED) { - int t_eta = 0, r_eta = 0; - - /* - * We can only guess - assume it'll run the full timeout - * if given, otherwise assume it'll run at the specified rate. - */ - if (td->timeout) - t_eta = td->timeout + td->start_delay - elapsed; - if (td->rate) { - r_eta = (bytes_total / 1024) / td->rate; - r_eta += td->start_delay - elapsed; - } - - if (r_eta && t_eta) - eta_sec = min(r_eta, t_eta); - else if (r_eta) - eta_sec = r_eta; - else if (t_eta) - eta_sec = t_eta; - else - eta_sec = 0; - } else { - /* - * thread is already done or waiting for fsync - */ - eta_sec = 0; - } - - return eta_sec; -} - -/* - * Print status of the jobs we know about. This includes rate estimates, - * ETA, thread state, etc. - */ -static void print_thread_status(void) -{ - unsigned long elapsed = time_since_now(&genesis); - int i, nr_running, nr_pending, t_rate, m_rate, *eta_secs, eta_sec; - char eta_str[32]; - double perc = 0.0; - - if (temp_stall_ts || terse_output) - return; - - eta_secs = malloc(thread_number * sizeof(int)); - memset(eta_secs, 0, thread_number * sizeof(int)); - - nr_pending = nr_running = t_rate = m_rate = 0; - for (i = 0; i < thread_number; i++) { - struct thread_data *td = &threads[i]; - - if (td->runstate == TD_RUNNING || td->runstate == TD_VERIFYING|| - td->runstate == TD_FSYNCING) { - nr_running++; - t_rate += td->rate; - m_rate += td->ratemin; - } else if (td->runstate < TD_RUNNING) - nr_pending++; - - if (elapsed >= 3) - eta_secs[i] = thread_eta(td, elapsed); - else - eta_secs[i] = INT_MAX; - - check_str_update(td); - } - - if (exitall_on_terminate) - eta_sec = INT_MAX; - else - eta_sec = 0; - - for (i = 0; i < thread_number; i++) { - if (exitall_on_terminate) { - if (eta_secs[i] < eta_sec) - eta_sec = eta_secs[i]; - } else { - if (eta_secs[i] > eta_sec) - eta_sec = eta_secs[i]; - } - } - - if (eta_sec != INT_MAX && elapsed) { - perc = (double) elapsed / (double) (elapsed + eta_sec); - eta_to_str(eta_str, eta_sec); - } - - if (!nr_running && !nr_pending) - return; - - printf("Threads running: %d", nr_running); - if (m_rate || t_rate) - printf(", commitrate %d/%dKiB/sec", t_rate, m_rate); - if (eta_sec != INT_MAX && nr_running) { - perc *= 100.0; - printf(": [%s] [%3.2f%% done] [eta %s]", run_str, perc,eta_str); - } - printf("\r"); - fflush(stdout); - free(eta_secs); -} - /* * Run over the job map and reap the threads that have exited, if any. */ @@ -1814,7 +1343,7 @@ static void run_threads(void) for (i = 0; i < thread_number; i++) { td = &threads[i]; - run_str[td->thread_number - 1] = 'P'; + print_status_init(td->thread_number - 1); init_disk_util(td); @@ -1826,13 +1355,13 @@ static void run_threads(void) * we don't want X number of threads getting their * client data interspersed on disk */ - if (setup_file(td)) { + if (setup_files(td)) { td_set_runstate(td, TD_REAPED); todo--; } } - gettimeofday(&genesis, NULL); + time_init(); while (todo) { struct thread_data *map[MAX_JOBS]; @@ -1858,7 +1387,7 @@ static void run_threads(void) } if (td->start_delay) { - spent = mtime_since_now(&genesis); + spent = mtime_since_genesis(); if (td->start_delay * 1000 > spent) continue;