X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=fio.c;h=b53a58ebe1883bbc9ad17f83fd598ce0c81c0c3c;hp=ccf0ad8a4dc24c28262014aabdfb42a174b680b8;hb=88c6ed8085efd1403fd34072311991cb666a5b9e;hpb=bbfd6b00dea4daee05133c8cb991b78d091df9ae diff --git a/fio.c b/fio.c index ccf0ad8a..b53a58eb 100644 --- a/fio.c +++ b/fio.c @@ -43,13 +43,17 @@ int thread_number = 0; static char run_str[MAX_JOBS + 1]; int shm_id = 0; static struct timeval genesis; +static int temp_stall_ts; static void print_thread_status(void); extern unsigned long long mlock_size; /* - * thread life cycle + * 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, @@ -57,6 +61,7 @@ enum { TD_INITIALIZED, TD_RUNNING, TD_VERIFYING, + TD_FSYNCING, TD_EXITED, TD_REAPED, }; @@ -221,7 +226,7 @@ static int check_min_rate(struct thread_data *td, struct timeval *now) rate = (td->this_io_bytes[ddir] - td->rate_bytes) / spent; if (rate < td->ratemin) { - printf("%s: min rate %d not met, got %ldKiB/sec\n", td->name, td->ratemin, rate); + fprintf(f_out, "%s: min rate %d not met, got %ldKiB/sec\n", td->name, td->ratemin, rate); if (rate_quit) terminate_threads(td->groupid); return 1; @@ -273,8 +278,8 @@ static void hexdump(void *buffer, int len) int i; for (i = 0; i < len; i++) - printf("%02x", p[i]); - printf("\n"); + fprintf(f_out, "%02x", p[i]); + fprintf(f_out, "\n"); } static int verify_io_u_crc32(struct verify_header *hdr, struct io_u *io_u) @@ -286,8 +291,8 @@ static int verify_io_u_crc32(struct verify_header *hdr, struct io_u *io_u) c = crc32(p, hdr->len - sizeof(*hdr)); if (c != hdr->crc32) { - fprintf(stderr, "crc32: verify failed at %llu/%u\n", io_u->offset, io_u->buflen); - fprintf(stderr, "crc32: wanted %lx, got %lx\n", hdr->crc32, c); + log_err("crc32: verify failed at %llu/%u\n", io_u->offset, io_u->buflen); + log_err("crc32: wanted %lx, got %lx\n", hdr->crc32, c); return 1; } @@ -304,7 +309,7 @@ static int verify_io_u_md5(struct verify_header *hdr, struct io_u *io_u) md5_update(&md5_ctx, p, hdr->len - sizeof(*hdr)); if (memcmp(hdr->md5_digest, md5_ctx.hash, sizeof(md5_ctx.hash))) { - fprintf(stderr, "md5: verify failed at %llu/%u\n", io_u->offset, io_u->buflen); + log_err("md5: verify failed at %llu/%u\n", io_u->offset, io_u->buflen); hexdump(hdr->md5_digest, sizeof(hdr->md5_digest)); hexdump(md5_ctx.hash, sizeof(md5_ctx.hash)); return 1; @@ -326,7 +331,7 @@ static int verify_io_u(struct io_u *io_u) else if (hdr->verify_type == VERIFY_CRC32) ret = verify_io_u_crc32(hdr, io_u); else { - fprintf(stderr, "Bad verify type %d\n", hdr->verify_type); + log_err("Bad verify type %d\n", hdr->verify_type); ret = 1; } @@ -360,11 +365,11 @@ static int get_rw_ddir(struct thread_data *td) * Check if it's time to seed a new data direction. */ if (elapsed >= td->rwmixcycle) { - unsigned long v; + int v; long r; - r = os_random_long(&td->random_state); - v = 100UL * r / (unsigned long) (RAND_MAX + 1.0); + r = os_random_long(&td->rwmix_state); + v = 1 + (int) (100.0 * (r / (RAND_MAX + 1.0))); if (v < td->rwmixread) td->rwmix_ddir = DDIR_READ; else @@ -512,7 +517,6 @@ static struct io_u *get_io_u(struct thread_data *td) static inline void td_set_runstate(struct thread_data *td, int runstate) { - td->old_runstate = td->runstate; td->runstate = runstate; } @@ -747,6 +751,8 @@ static void do_io(struct thread_data *td) struct timeval s, e; unsigned long usec; + td_set_runstate(td, TD_RUNNING); + while (td->this_io_bytes[td->ddir] < td->io_size) { struct timespec ts = { .tv_sec = 0, .tv_nsec = 0}; struct timespec *timeout; @@ -822,8 +828,10 @@ static void do_io(struct thread_data *td) if (td->cur_depth) cleanup_pending_aio(td); - if (should_fsync(td) && td->end_fsync) + if (should_fsync(td) && td->end_fsync) { + td_set_runstate(td, TD_FSYNCING); sync_td(td); + } } static void cleanup_io(struct thread_data *td) @@ -847,7 +855,7 @@ static int init_io(struct thread_data *td) else if (td->io_engine == FIO_SPLICEIO) return fio_spliceio_init(td); else { - fprintf(stderr, "bad io_engine %d\n", td->io_engine); + log_err("bad io_engine %d\n", td->io_engine); return 1; } } @@ -874,7 +882,7 @@ static void cleanup_io_u(struct thread_data *td) } else if (td->mem_type == MEM_MMAP) munmap(td->orig_buffer, td->orig_buffer_size); else - fprintf(stderr, "Bad memory type %d\n", td->mem_type); + log_err("Bad memory type %d\n", td->mem_type); td->orig_buffer = NULL; } @@ -933,22 +941,6 @@ static int init_io_u(struct thread_data *td) return 0; } -static void cleanup_allocs(struct thread_data *td) -{ - if (td->directory) - free(td->directory); - if (td->iolog_file) - free(td->iolog_file); - if (td->exec_prerun) - free(td->exec_prerun); - if (td->exec_postrun) - free(td->exec_postrun); - if (td->ioscheduler) - free(td->ioscheduler); - if (td->sysfs_root) - free(td->sysfs_root); -} - static int create_file(struct thread_data *td, unsigned long long size, int extend) { @@ -964,27 +956,31 @@ static int create_file(struct thread_data *td, unsigned long long size, return 0; if (!size) { - fprintf(stderr, "Need size for create\n"); + log_err("Need size for create\n"); td_verror(td, EINVAL); return 1; } + temp_stall_ts = 1; + if (!extend) { oflags = O_CREAT | O_TRUNC; - printf("%s: Laying out IO file (%LuMiB)\n", td->name, size >> 20); + fprintf(f_out, "%s: Laying out IO file (%LuMiB)\n", td->name, size >> 20); } else { oflags = O_APPEND; - printf("%s: Extending IO file (%Lu -> %LuMiB)\n", td->name, (td->file_size - size) >> 20, td->file_size >> 20); + fprintf(f_out, "%s: Extending IO file (%Lu -> %LuMiB)\n", td->name, (td->file_size - size) >> 20, td->file_size >> 20); } td->fd = open(td->file_name, O_WRONLY | oflags, 0644); if (td->fd < 0) { td_verror(td, errno); + temp_stall_ts = 0; return 1; } if (!extend && ftruncate(td->fd, td->file_size) == -1) { td_verror(td, errno); + temp_stall_ts = 0; return 1; } @@ -1018,6 +1014,7 @@ static int create_file(struct thread_data *td, unsigned long long size, else if (td->create_fsync) fsync(td->fd); + temp_stall_ts = 0; close(td->fd); td->fd = -1; free(b); @@ -1080,13 +1077,13 @@ static int get_file_size(struct thread_data *td) return ret; if (td->file_offset > td->real_file_size) { - fprintf(stderr, "%s: offset extends end (%Lu > %Lu)\n", td->name, 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) { - fprintf(stderr, "%s: no io blocks\n", td->name); + log_err("%s: no io blocks\n", td->name); td_verror(td, EINVAL); return 1; } @@ -1189,7 +1186,7 @@ static int setup_file(struct thread_data *td) } if (td->odirect) - flags |= O_DIRECT; + flags |= OS_O_DIRECT; if (td_write(td) || td_rw(td)) { if (td->filetype == FIO_TYPE_FILE) { @@ -1265,7 +1262,7 @@ static int switch_ioscheduler(struct thread_data *td) sprintf(tmp2, "[%s]", td->ioscheduler); if (!strstr(tmp, tmp2)) { - fprintf(stderr, "fio: io scheduler %s not found\n", td->ioscheduler); + log_err("fio: io scheduler %s not found\n", td->ioscheduler); td_verror(td, EINVAL); fclose(f); return 1; @@ -1404,7 +1401,6 @@ err: } if (td->mmap) munmap(td->mmap, td->file_size); - cleanup_allocs(td); cleanup_io(td); cleanup_io_u(td); td_set_runstate(td, TD_EXITED); @@ -1433,9 +1429,6 @@ static void check_str_update(struct thread_data *td) { char c = run_str[td->thread_number - 1]; - if (td->runstate == td->old_runstate) - return; - switch (td->runstate) { case TD_REAPED: c = '_'; @@ -1464,6 +1457,9 @@ static void check_str_update(struct thread_data *td) case TD_VERIFYING: c = 'V'; break; + case TD_FSYNCING: + c = 'F'; + break; case TD_CREATED: c = 'C'; break; @@ -1474,11 +1470,10 @@ static void check_str_update(struct thread_data *td) c = 'P'; break; default: - printf("state %d\n", td->runstate); + log_err("state %d\n", td->runstate); } run_str[td->thread_number - 1] = c; - td->old_runstate = td->runstate; } static void eta_to_str(char *str, int eta_sec) @@ -1563,10 +1558,10 @@ static int thread_eta(struct thread_data *td, unsigned long elapsed) else if (t_eta) eta_sec = t_eta; else - eta_sec = INT_MAX; + eta_sec = 0; } else { /* - * thread is already done + * thread is already done or waiting for fsync */ eta_sec = 0; } @@ -1577,22 +1572,27 @@ static int thread_eta(struct thread_data *td, unsigned long elapsed) static void print_thread_status(void) { unsigned long elapsed = time_since_now(&genesis); - int i, nr_running, t_rate, m_rate, *eta_secs, eta_sec; + 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) + return; + eta_secs = malloc(thread_number * sizeof(int)); memset(eta_secs, 0, thread_number * sizeof(int)); - nr_running = t_rate = m_rate = 0; + 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){ + 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); @@ -1622,7 +1622,10 @@ static void print_thread_status(void) eta_to_str(eta_str, eta_sec); } - printf("Threads now running (%d)", nr_running); + 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) { @@ -1687,8 +1690,7 @@ static void *fio_pin_memory(void) if (phys_mem) { if ((mlock_size + 128 * 1024 * 1024) > phys_mem) { mlock_size = phys_mem - 128 * 1024 * 1024; - printf("fio: limiting mlocked memory to %lluMiB\n", - mlock_size >> 20); + fprintf(f_out, "fio: limiting mlocked memory to %lluMiB\n", mlock_size >> 20); } } @@ -1810,7 +1812,6 @@ static void run_threads(void) * Wait for the started threads to transition to * TD_INITIALIZED. */ - printf("fio: Waiting for threads to initialize...\n"); gettimeofday(&this_start, NULL); left = this_jobs; while (left) { @@ -1836,7 +1837,7 @@ static void run_threads(void) } if (left) { - fprintf(stderr, "fio: %d jobs failed to start\n", left); + log_err("fio: %d jobs failed to start\n", left); for (i = 0; i < this_jobs; i++) { td = map[i]; if (!td) @@ -1849,7 +1850,6 @@ static void run_threads(void) /* * start created threads (TD_INITIALIZED -> TD_RUNNING). */ - printf("fio: Go for launch\n"); for (i = 0; i < thread_number; i++) { td = &threads[i]; @@ -1886,7 +1886,7 @@ int main(int argc, char *argv[]) return 1; if (!thread_number) { - printf("Nothing to do\n"); + log_err("Nothing to do\n"); return 1; }