X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=client.c;h=51d84e4249c0d072aa9548e42c359537f0dc9a9f;hp=5b409fea4b78c187ef03ae0ad287026b3e0cfb9d;hb=83742c72e3d69b2d5c8a890b3803042b5fd1aae0;hpb=44edeed343a217952f1c84bdee64547369450f5f diff --git a/client.c b/client.c index 5b409fea..51d84e42 100644 --- a/client.c +++ b/client.c @@ -1,13 +1,11 @@ #include #include #include -#include #include #include -#include +#include #include #include -#include #include #include #include @@ -23,17 +21,18 @@ #include "server.h" #include "flist.h" #include "hash.h" -#include "verify.h" +#include "verify-state.h" static void handle_du(struct fio_client *client, struct fio_net_cmd *cmd); static void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd); static void handle_gs(struct fio_client *client, struct fio_net_cmd *cmd); static void handle_probe(struct fio_client *client, struct fio_net_cmd *cmd); static void handle_text(struct fio_client *client, struct fio_net_cmd *cmd); -static void handle_stop(struct fio_client *client, struct fio_net_cmd *cmd); +static void handle_stop(struct fio_client *client); static void handle_start(struct fio_client *client, struct fio_net_cmd *cmd); static void convert_text(struct fio_net_cmd *cmd); +static void client_display_thread_status(struct jobs_eta *je); struct client_ops fio_client_ops = { .text = handle_text, @@ -42,7 +41,7 @@ struct client_ops fio_client_ops = { .group_stats = handle_gs, .stop = handle_stop, .start = handle_start, - .eta = display_thread_status, + .eta = client_display_thread_status, .probe = handle_probe, .eta_msec = FIO_CLIENT_DEF_ETA_MSEC, .client_type = FIO_CLIENT_TYPE_CLI, @@ -120,6 +119,58 @@ static int read_data(int fd, void *data, size_t size) return 0; } +static int read_ini_data(int fd, void *data, size_t size) +{ + char *p = data; + int ret = 0; + FILE *fp; + int dupfd; + + dupfd = dup(fd); + if (dupfd < 0) + return errno; + + fp = fdopen(dupfd, "r"); + if (!fp) { + ret = errno; + close(dupfd); + goto out; + } + + while (1) { + ssize_t len; + char buf[OPT_LEN_MAX+1], *sub; + + if (!fgets(buf, sizeof(buf), fp)) { + if (ferror(fp)) { + if (errno == EAGAIN || errno == EINTR) + continue; + ret = errno; + } + break; + } + + sub = fio_option_dup_subs(buf); + len = strlen(sub); + if (len + 1 > size) { + log_err("fio: no space left to read data\n"); + free(sub); + ret = ENOSPC; + break; + } + + memcpy(p, sub, len); + free(sub); + p += len; + *p = '\0'; + size -= len; + } + + fclose(fp); +out: + return ret; +} + static void fio_client_json_init(void) { char time_buf[32]; @@ -147,12 +198,17 @@ static void fio_client_json_init(void) static void fio_client_json_fini(void) { + struct buf_output out; + if (!(output_format & FIO_OUTPUT_JSON)) return; - log_info("\n"); - json_print_object(root, NULL); - log_info("\n"); + buf_output_init(&out); + __log_buf(&out, "\n"); + json_print_object(root, &out); + __log_buf(&out, "\n"); + log_info_buf(out.buf, out.buflen); + buf_output_free(&out); json_free_object(root); root = NULL; clients_array = NULL; @@ -765,13 +821,17 @@ static int __fio_client_send_local_ini(struct fio_client *client, return ret; } + /* + * Add extra space for variable expansion, but doesn't guarantee. + */ + sb.st_size += OPT_LEN_MAX; p_size = sb.st_size + sizeof(*pdu); pdu = malloc(p_size); buf = pdu->buf; len = sb.st_size; p = buf; - if (read_data(fd, p, len)) { + if (read_ini_data(fd, p, len)) { log_err("fio: failed reading job file %s\n", filename); close(fd); free(pdu); @@ -905,21 +965,21 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src) } for (i = 0; i < FIO_IO_U_MAP_NR; i++) { - dst->io_u_map[i] = le32_to_cpu(src->io_u_map[i]); - dst->io_u_submit[i] = le32_to_cpu(src->io_u_submit[i]); - dst->io_u_complete[i] = le32_to_cpu(src->io_u_complete[i]); + dst->io_u_map[i] = le64_to_cpu(src->io_u_map[i]); + dst->io_u_submit[i] = le64_to_cpu(src->io_u_submit[i]); + dst->io_u_complete[i] = le64_to_cpu(src->io_u_complete[i]); } for (i = 0; i < FIO_IO_U_LAT_N_NR; i++) - dst->io_u_lat_n[i] = le32_to_cpu(src->io_u_lat_n[i]); + dst->io_u_lat_n[i] = le64_to_cpu(src->io_u_lat_n[i]); for (i = 0; i < FIO_IO_U_LAT_U_NR; i++) - dst->io_u_lat_u[i] = le32_to_cpu(src->io_u_lat_u[i]); + dst->io_u_lat_u[i] = le64_to_cpu(src->io_u_lat_u[i]); for (i = 0; i < FIO_IO_U_LAT_M_NR; i++) - dst->io_u_lat_m[i] = le32_to_cpu(src->io_u_lat_m[i]); + dst->io_u_lat_m[i] = le64_to_cpu(src->io_u_lat_m[i]); for (i = 0; i < DDIR_RWDIR_CNT; i++) for (j = 0; j < FIO_IO_U_PLAT_NR; j++) - dst->io_u_plat[i][j] = le32_to_cpu(src->io_u_plat[i][j]); + dst->io_u_plat[i][j] = le64_to_cpu(src->io_u_plat[i][j]); for (i = 0; i < DDIR_RWDIR_CNT; i++) { dst->total_io_u[i] = le64_to_cpu(src->total_io_u[i]); @@ -942,6 +1002,8 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src) dst->kb_base = le32_to_cpu(src->kb_base); dst->unit_base = le32_to_cpu(src->unit_base); + dst->sig_figs = le32_to_cpu(src->sig_figs); + dst->latency_depth = le32_to_cpu(src->latency_depth); dst->latency_target = le64_to_cpu(src->latency_target); dst->latency_window = le64_to_cpu(src->latency_window); @@ -959,7 +1021,7 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src) dst->ss_deviation.u.f = fio_uint64_to_double(le64_to_cpu(src->ss_deviation.u.i)); dst->ss_criterion.u.f = fio_uint64_to_double(le64_to_cpu(src->ss_criterion.u.i)); - if (dst->ss_state & __FIO_SS_DATA) { + if (dst->ss_state & FIO_SS_DATA) { for (i = 0; i < dst->ss_dur; i++ ) { dst->ss_iops_data[i] = le64_to_cpu(src->ss_iops_data[i]); dst->ss_bw_data[i] = le64_to_cpu(src->ss_bw_data[i]); @@ -982,6 +1044,7 @@ static void convert_gs(struct group_run_stats *dst, struct group_run_stats *src) dst->kb_base = le32_to_cpu(src->kb_base); dst->unit_base = le32_to_cpu(src->unit_base); + dst->sig_figs = le32_to_cpu(src->sig_figs); dst->groupid = le32_to_cpu(src->groupid); dst->unified_rw_rep = le32_to_cpu(src->unified_rw_rep); } @@ -1021,6 +1084,7 @@ static void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd) client_ts.thread_number = p->ts.thread_number; client_ts.groupid = p->ts.groupid; client_ts.unified_rw_rep = p->ts.unified_rw_rep; + client_ts.sig_figs = p->ts.sig_figs; if (++sum_stat_nr == sum_stat_clients) { strcpy(client_ts.name, "All clients"); @@ -1079,13 +1143,17 @@ static void handle_text(struct fio_client *client, struct fio_net_cmd *cmd) const char *buf = (const char *) pdu->buf; const char *name; int fio_unused ret; + struct buf_output out; + + buf_output_init(&out); name = client->name ? client->name : client->hostname; - if (!client->skip_newline) - fprintf(f_out, "<%s> ", name); - ret = fwrite(buf, pdu->buf_len, 1, f_out); - fflush(f_out); + if (!client->skip_newline && !(output_format & FIO_OUTPUT_TERSE)) + __log_buf(&out, "<%s> ", name); + __log_buf(&out, "%s", buf); + log_info_buf(out.buf, out.buflen); + buf_output_free(&out); client->skip_newline = strchr(buf, '\n') == NULL; } @@ -1125,10 +1193,14 @@ static void convert_dus(struct disk_util_stat *dus) static void handle_du(struct fio_client *client, struct fio_net_cmd *cmd) { struct cmd_du_pdu *du = (struct cmd_du_pdu *) cmd->payload; + struct buf_output out; + + buf_output_init(&out); if (!client->disk_stats_shown) { client->disk_stats_shown = true; - log_info("\nDisk stats (read/write):\n"); + if (!(output_format & FIO_OUTPUT_JSON)) + __log_buf(&out, "\nDisk stats (read/write):\n"); } if (output_format & FIO_OUTPUT_JSON) { @@ -1138,9 +1210,10 @@ static void handle_du(struct fio_client *client, struct fio_net_cmd *cmd) json_object_add_client_info(duobj, client); } if (output_format & FIO_OUTPUT_TERSE) - print_disk_util(&du->dus, &du->agg, 1, NULL); + print_disk_util(&du->dus, &du->agg, 1, &out); if (output_format & FIO_OUTPUT_NORMAL) - print_disk_util(&du->dus, &du->agg, 0, NULL); + print_disk_util(&du->dus, &du->agg, 0, &out); + buf_output_free(&out); } static void convert_jobs_eta(struct jobs_eta *je) @@ -1167,6 +1240,7 @@ static void convert_jobs_eta(struct jobs_eta *je) je->nr_threads = le32_to_cpu(je->nr_threads); je->is_pow2 = le32_to_cpu(je->is_pow2); je->unit_base = le32_to_cpu(je->unit_base); + je->sig_figs = le32_to_cpu(je->sig_figs); } void fio_client_sum_jobs_eta(struct jobs_eta *dst, struct jobs_eta *je) @@ -1278,7 +1352,7 @@ static void client_flush_hist_samples(FILE *f, int hist_coarseness, void *sample int log_offset; uint64_t i, j, nr_samples; struct io_u_plat_entry *entry; - unsigned int *io_u_plat; + uint64_t *io_u_plat; int stride = 1 << hist_coarseness; @@ -1298,12 +1372,12 @@ static void client_flush_hist_samples(FILE *f, int hist_coarseness, void *sample entry = s->data.plat_entry; io_u_plat = entry->io_u_plat; - fprintf(f, "%lu, %u, %u, ", (unsigned long) s->time, - io_sample_ddir(s), s->bs); + fprintf(f, "%lu, %u, %llu, ", (unsigned long) s->time, + io_sample_ddir(s), (unsigned long long) s->bs); for (j = 0; j < FIO_IO_U_PLAT_NR - stride; j += stride) { - fprintf(f, "%lu, ", hist_sum(j, stride, io_u_plat, NULL)); + fprintf(f, "%llu, ", (unsigned long long)hist_sum(j, stride, io_u_plat, NULL)); } - fprintf(f, "%lu\n", (unsigned long) + fprintf(f, "%llu\n", (unsigned long long) hist_sum(FIO_IO_U_PLAT_NR - stride, stride, io_u_plat, NULL)); } @@ -1336,7 +1410,7 @@ static int fio_client_handle_iolog(struct fio_client *client, sprintf(log_pathname, "%s.%s", pdu->name, client->hostname); if (store_direct) { - ssize_t ret; + ssize_t wrote; size_t sz; int fd; @@ -1350,10 +1424,10 @@ static int fio_client_handle_iolog(struct fio_client *client, } sz = cmd->pdu_len - sizeof(*pdu); - ret = write(fd, pdu->samples, sz); + wrote = write(fd, pdu->samples, sz); close(fd); - if (ret != sz) { + if (wrote != sz) { log_err("fio: short write on compressed log\n"); ret = 1; goto out; @@ -1382,7 +1456,7 @@ static int fio_client_handle_iolog(struct fio_client *client, } out: - if (pdu && pdu != cmd->payload) + if (pdu && pdu != (void *) cmd->payload) free(pdu); if (log_pathname) @@ -1408,9 +1482,10 @@ static void handle_probe(struct fio_client *client, struct fio_net_cmd *cmd) sprintf(bit, "%d-bit", probe->bpp * 8); probe->flags = le64_to_cpu(probe->flags); - log_info("hostname=%s, be=%u, %s, os=%s, arch=%s, fio=%s, flags=%lx\n", - probe->hostname, probe->bigendian, bit, os, arch, - probe->fio_version, (unsigned long) probe->flags); + if (!(output_format & FIO_OUTPUT_JSON)) + log_info("hostname=%s, be=%u, %s, os=%s, arch=%s, fio=%s, flags=%lx\n", + probe->hostname, probe->bigendian, bit, os, arch, + probe->fio_version, (unsigned long) probe->flags); if (!client->name) client->name = strdup((char *) probe->hostname); @@ -1438,7 +1513,7 @@ static void handle_start(struct fio_client *client, struct fio_net_cmd *cmd) sum_stat_clients += client->nr_stat; } -static void handle_stop(struct fio_client *client, struct fio_net_cmd *cmd) +static void handle_stop(struct fio_client *client) { if (client->error) log_info("client <%s>: exited with error %d\n", client->hostname, client->error); @@ -1467,7 +1542,7 @@ static struct cmd_iolog_pdu *convert_iolog_gz(struct fio_net_cmd *cmd, #ifdef CONFIG_ZLIB struct cmd_iolog_pdu *ret; z_stream stream; - uint32_t nr_samples; + uint64_t nr_samples; size_t total; char *p; @@ -1588,7 +1663,7 @@ static struct cmd_iolog_pdu *convert_iolog(struct fio_net_cmd *cmd, s->time = le64_to_cpu(s->time); s->data.val = le64_to_cpu(s->data.val); s->__ddir = le32_to_cpu(s->__ddir); - s->bs = le32_to_cpu(s->bs); + s->bs = le64_to_cpu(s->bs); if (ret->log_offset) { struct io_sample_offset *so = (void *) s; @@ -1662,6 +1737,8 @@ int fio_handle_client(struct fio_client *client) dprint(FD_NET, "client: got cmd op %s from %s (pdu=%u)\n", fio_server_op(cmd->opcode), client->hostname, cmd->pdu_len); + client->last_cmd = cmd->opcode; + switch (cmd->opcode) { case FIO_NET_CMD_QUIT: if (ops->quit) @@ -1685,7 +1762,7 @@ int fio_handle_client(struct fio_client *client) struct cmd_ts_pdu *p = (struct cmd_ts_pdu *) cmd->payload; dprint(FD_NET, "client: ts->ss_state = %u\n", (unsigned int) le32_to_cpu(p->ts.ss_state)); - if (le32_to_cpu(p->ts.ss_state) & __FIO_SS_DATA) { + if (le32_to_cpu(p->ts.ss_state) & FIO_SS_DATA) { dprint(FD_NET, "client: received steadystate ring buffers\n"); size = le64_to_cpu(p->ts.ss_dur); @@ -1739,7 +1816,7 @@ int fio_handle_client(struct fio_client *client) client->state = Client_stopped; client->error = le32_to_cpu(pdu->error); client->signal = le32_to_cpu(pdu->signal); - ops->stop(client, cmd); + ops->stop(client); break; } case FIO_NET_CMD_ADD_JOB: { @@ -1828,6 +1905,9 @@ static void request_client_etas(struct client_ops *ops) struct client_eta *eta; int skipped = 0; + if (eta_print == FIO_ETA_NEVER) + return; + dprint(FD_NET, "client: request eta (%d)\n", nr_clients); eta = calloc(1, sizeof(*eta) + __THREAD_RUNSTR_SZ(REAL_MAX_JOBS)); @@ -1864,10 +1944,12 @@ static void request_client_etas(struct client_ops *ops) static int handle_cmd_timeout(struct fio_client *client, struct fio_net_cmd_reply *reply) { + uint16_t reply_opcode = reply->opcode; + flist_del(&reply->list); free(reply); - if (reply->opcode != FIO_NET_CMD_SEND_ETA) + if (reply_opcode != FIO_NET_CMD_SEND_ETA) return 1; log_info("client <%s>: timeout on SEND_ETA\n", client->hostname); @@ -1895,16 +1977,19 @@ static int client_check_cmd_timeout(struct fio_client *client, int ret = 0; flist_for_each_safe(entry, tmp, &client->cmd_list) { + unsigned int op; + reply = flist_entry(entry, struct fio_net_cmd_reply, list); if (mtime_since(&reply->ts, now) < FIO_NET_CLIENT_TIMEOUT) continue; + op = reply->opcode; if (!handle_cmd_timeout(client, reply)) continue; log_err("fio: client %s, timeout on cmd %s\n", client->hostname, - fio_server_op(reply->opcode)); + fio_server_op(op)); ret = 1; } @@ -1934,7 +2019,10 @@ static int fio_check_clients_timed_out(void) else log_err("fio: client %s timed out\n", client->hostname); - client->error = ETIMEDOUT; + if (client->last_cmd != FIO_NET_CMD_VTRIGGER) + client->error = ETIMEDOUT; + else + log_info("fio: ignoring timeout due to vtrigger\n"); remove_client(client); ret = 1; } @@ -1983,7 +2071,7 @@ int fio_handle_clients(struct client_ops *ops) int timeout; fio_gettime(&ts, NULL); - if (mtime_since(&eta_ts, &ts) >= 900) { + if (eta_time_within_slack(mtime_since(&eta_ts, &ts))) { request_client_etas(ops); memcpy(&eta_ts, &ts, sizeof(ts)); @@ -2030,3 +2118,9 @@ int fio_handle_clients(struct client_ops *ops) free(pfds); return retval || error_clients; } + +static void client_display_thread_status(struct jobs_eta *je) +{ + if (!(output_format & FIO_OUTPUT_JSON)) + display_thread_status(je); +}