X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=backend.c;h=23fa345b7e19496ae64af4a0bfa8983ddaefe794;hp=c1c8f96774850a755681dffa710d0ee1550fe16b;hb=6c784104cf90299aeec1d79f536a8e534c341c5f;hpb=49cba9b3e5fa6b30f0fdff52eaf83427ec1baa3f diff --git a/backend.c b/backend.c index c1c8f967..23fa345b 100644 --- a/backend.c +++ b/backend.c @@ -204,7 +204,11 @@ static int __check_min_rate(struct thread_data *td, struct timeval *now, td->o.name, rate_iops); return 1; } else { - rate = ((iops - td->rate_blocks[ddir]) * 1000) / spent; + if (spent) + rate = ((iops - td->rate_blocks[ddir]) * 1000) / spent; + else + rate = 0; + if (rate < rate_iops_min || iops < td->rate_blocks[ddir]) { log_err("%s: min iops rate %u not met," @@ -641,7 +645,7 @@ static unsigned int exceeds_number_ios(struct thread_data *td) static int io_bytes_exceeded(struct thread_data *td) { - unsigned long long bytes; + unsigned long long bytes, limit; if (td_rw(td)) bytes = td->this_io_bytes[DDIR_READ] + td->this_io_bytes[DDIR_WRITE]; @@ -652,7 +656,12 @@ static int io_bytes_exceeded(struct thread_data *td) else bytes = td->this_io_bytes[DDIR_TRIM]; - return bytes >= td->o.size || exceeds_number_ios(td); + if (td->o.io_limit) + limit = td->o.io_limit; + else + limit = td->o.size; + + return bytes >= limit || exceeds_number_ios(td); } /* @@ -771,16 +780,21 @@ static uint64_t do_io(struct thread_data *td) case FIO_Q_COMPLETED: if (io_u->error) { ret = -io_u->error; + unlog_io_piece(td, io_u); clear_io_u(td, io_u); } else if (io_u->resid) { int bytes = io_u->xfer_buflen - io_u->resid; struct fio_file *f = io_u->file; bytes_issued += bytes; + + trim_io_piece(td, io_u); + /* * zero read, fail */ if (!bytes) { + unlog_io_piece(td, io_u); td_verror(td, EIO, "full resid"); put_io_u(td, io_u); break; @@ -821,6 +835,7 @@ sync_done: bytes_issued += io_u->xfer_buflen; break; case FIO_Q_BUSY: + unlog_io_piece(td, io_u); requeue_io_u(td, &io_u); ret2 = td_io_commit(td); if (ret2 < 0) @@ -1114,13 +1129,14 @@ static int switch_ioscheduler(struct thread_data *td) /* * Read back and check that the selected scheduler is now the default. */ - memset(tmp, 0, sizeof(tmp)); - ret = fread(tmp, 1, sizeof(tmp) - 1, f); + ret = fread(tmp, sizeof(tmp), 1, f); if (ferror(f) || ret < 0) { td_verror(td, errno, "fread"); fclose(f); return 1; } + tmp[sizeof(tmp) - 1] = '\0'; + sprintf(tmp2, "[%s]", td->o.ioscheduler); if (!strstr(tmp, tmp2)) { @@ -1136,6 +1152,8 @@ static int switch_ioscheduler(struct thread_data *td) static int keep_running(struct thread_data *td) { + unsigned long long limit; + if (td->done) return 0; if (td->o.time_based) @@ -1147,14 +1165,19 @@ static int keep_running(struct thread_data *td) if (exceeds_number_ios(td)) return 0; - if (td->o.size != -1ULL && ddir_rw_sum(td->io_bytes) < td->o.size) { + if (td->o.io_limit) + limit = td->o.io_limit; + else + limit = td->o.size; + + if (limit != -1ULL && ddir_rw_sum(td->io_bytes) < limit) { uint64_t diff; /* * If the difference is less than the minimum IO size, we * are done. */ - diff = td->o.size - ddir_rw_sum(td->io_bytes); + diff = limit - ddir_rw_sum(td->io_bytes); if (diff < td_max_bs(td)) return 0; @@ -1247,11 +1270,6 @@ static void *thread_main(void *data) } else td->pid = gettid(); - /* - * fio_time_init() may not have been called yet if running as a server - */ - fio_time_init(); - fio_local_clock_init(o->use_thread); dprint(FD_PROCESS, "jobs pid=%d started\n", (int) td->pid); @@ -1322,6 +1340,7 @@ static void *thread_main(void *data) #ifdef CONFIG_LIBNUMA /* numa node setup */ if (o->numa_cpumask_set || o->numa_memmask_set) { + struct bitmask *mask; int ret; if (numa_available() < 0) { @@ -1330,7 +1349,9 @@ static void *thread_main(void *data) } if (o->numa_cpumask_set) { - ret = numa_run_on_node_mask(o->numa_cpunodesmask); + mask = numa_parse_nodestring(o->numa_cpunodes); + ret = numa_run_on_node_mask(mask); + numa_free_nodemask(mask); if (ret == -1) { td_verror(td, errno, \ "numa_run_on_node_mask failed\n"); @@ -1340,12 +1361,16 @@ static void *thread_main(void *data) if (o->numa_memmask_set) { + mask = NULL; + if (o->numa_memnodes) + mask = numa_parse_nodestring(o->numa_memnodes); + switch (o->numa_mem_mode) { case MPOL_INTERLEAVE: - numa_set_interleave_mask(o->numa_memnodesmask); + numa_set_interleave_mask(mask); break; case MPOL_BIND: - numa_set_membind(o->numa_memnodesmask); + numa_set_membind(mask); break; case MPOL_LOCAL: numa_set_localalloc(); @@ -1358,6 +1383,9 @@ static void *thread_main(void *data) break; } + if (mask) + numa_free_nodemask(mask); + } } #endif