X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=client.c;h=605a3ce573aa4c842df83c4947c823c03882fa03;hp=e2525c812a94fd91c296e35ccff8c87255b31de5;hb=b3d5e3fd80e3834097578e92d1b788065b8346e1;hpb=bf0b7e75c1ccca4026c8880ed8a76fc7ef85f2f3 diff --git a/client.c b/client.c index e2525c81..605a3ce5 100644 --- a/client.c +++ b/client.c @@ -32,6 +32,7 @@ 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, @@ -40,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, @@ -58,6 +59,7 @@ struct group_run_stats client_gs; int sum_stat_clients; static int sum_stat_nr; +static struct buf_output allclients; static struct json_object *root = NULL; static struct json_object *job_opt_object = NULL; static struct json_array *clients_array = NULL; @@ -197,14 +199,23 @@ static void fio_client_json_init(void) static void fio_client_json_fini(void) { - if (!(output_format & FIO_OUTPUT_JSON)) + struct buf_output out; + + if (!root) 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; + job_opt_object = NULL; clients_array = NULL; du_array = NULL; } @@ -232,6 +243,9 @@ void fio_put_client(struct fio_client *client) if (--client->refs) return; + log_info_buf(client->buf.buf, client->buf.buflen); + buf_output_free(&client->buf); + free(client->hostname); if (client->argv) free(client->argv); @@ -270,9 +284,10 @@ static int fio_client_dec_jobs_eta(struct client_eta *eta, client_eta_op eta_fn) static void fio_drain_client_text(struct fio_client *client) { do { - struct fio_net_cmd *cmd; + struct fio_net_cmd *cmd = NULL; - cmd = fio_net_recv_cmd(client->fd, false); + if (fio_server_poll_fd(client->fd, POLLIN, 0)) + cmd = fio_net_recv_cmd(client->fd, false); if (!cmd) break; @@ -350,9 +365,7 @@ void fio_client_add_cmd_option(void *cookie, const char *opt) } } -struct fio_client *fio_client_add_explicit(struct client_ops *ops, - const char *hostname, int type, - int port) +static struct fio_client *get_new_client(void) { struct fio_client *client; @@ -365,7 +378,18 @@ struct fio_client *fio_client_add_explicit(struct client_ops *ops, INIT_FLIST_HEAD(&client->eta_list); INIT_FLIST_HEAD(&client->cmd_list); - client->hostname = strdup(hostname); + buf_output_init(&client->buf); + + return client; +} + +struct fio_client *fio_client_add_explicit(struct client_ops *ops, + const char *hostname, int type, + int port) +{ + struct fio_client *client; + + client = get_new_client(); if (type == Fio_client_socket) client->is_sock = true; @@ -385,6 +409,7 @@ struct fio_client *fio_client_add_explicit(struct client_ops *ops, client->ops = ops; client->refs = 1; client->type = ops->client_type; + client->hostname = strdup(hostname); __fio_client_add_cmd_option(client, "fio"); @@ -440,21 +465,16 @@ int fio_client_add(struct client_ops *ops, const char *hostname, void **cookie) } } - client = malloc(sizeof(*client)); - memset(client, 0, sizeof(*client)); - - INIT_FLIST_HEAD(&client->list); - INIT_FLIST_HEAD(&client->hash_list); - INIT_FLIST_HEAD(&client->arg_list); - INIT_FLIST_HEAD(&client->eta_list); - INIT_FLIST_HEAD(&client->cmd_list); + client = get_new_client(); if (fio_server_parse_string(hostname, &client->hostname, &client->is_sock, &client->port, &client->addr.sin_addr, &client->addr6.sin6_addr, - &client->ipv6)) + &client->ipv6)) { + fio_put_client(client); return -1; + } client->fd = -1; client->ops = ops; @@ -502,7 +522,7 @@ static void probe_client(struct fio_client *client) sname = server_name(client, buf, sizeof(buf)); memset(pdu.server, 0, sizeof(pdu.server)); - strncpy((char *) pdu.server, sname, sizeof(pdu.server) - 1); + snprintf((char *) pdu.server, sizeof(pdu.server), "%s", sname); fio_net_send_cmd(client->fd, FIO_NET_CMD_PROBE, &pdu, sizeof(pdu), &tag, &client->cmd_list); } @@ -556,7 +576,8 @@ static int fio_client_connect_sock(struct fio_client *client) memset(addr, 0, sizeof(*addr)); addr->sun_family = AF_UNIX; - strncpy(addr->sun_path, client->hostname, sizeof(addr->sun_path) - 1); + snprintf(addr->sun_path, sizeof(addr->sun_path), "%s", + client->hostname); fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { @@ -925,7 +946,7 @@ static void convert_io_stat(struct io_stat *dst, struct io_stat *src) static void convert_ts(struct thread_stat *dst, struct thread_stat *src) { - int i, j; + int i, j, k; dst->error = le32_to_cpu(src->error); dst->thread_number = le32_to_cpu(src->thread_number); @@ -933,6 +954,8 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src) dst->pid = le32_to_cpu(src->pid); dst->members = le32_to_cpu(src->members); dst->unified_rw_rep = le32_to_cpu(src->unified_rw_rep); + dst->ioprio = le32_to_cpu(src->ioprio); + dst->disable_prio_stat = le32_to_cpu(src->disable_prio_stat); for (i = 0; i < DDIR_RWDIR_CNT; i++) { convert_io_stat(&dst->clat_stat[i], &src->clat_stat[i]); @@ -941,6 +964,7 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src) convert_io_stat(&dst->bw_stat[i], &src->bw_stat[i]); convert_io_stat(&dst->iops_stat[i], &src->iops_stat[i]); } + convert_io_stat(&dst->sync_stat, &src->sync_stat); dst->usr_time = le64_to_cpu(src->usr_time); dst->sys_time = le64_to_cpu(src->sys_time); @@ -949,6 +973,7 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src) dst->majf = le64_to_cpu(src->majf); dst->clat_percentiles = le32_to_cpu(src->clat_percentiles); dst->lat_percentiles = le32_to_cpu(src->lat_percentiles); + dst->slat_percentiles = le32_to_cpu(src->slat_percentiles); dst->percentile_precision = le64_to_cpu(src->percentile_precision); for (i = 0; i < FIO_IO_U_LIST_MAX_LEN; i++) { @@ -971,18 +996,25 @@ static void convert_ts(struct thread_stat *dst, struct thread_stat *src) for (i = 0; i < FIO_IO_U_LAT_M_NR; 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] = le64_to_cpu(src->io_u_plat[i][j]); + for (i = 0; i < FIO_LAT_CNT; i++) + for (j = 0; j < DDIR_RWDIR_CNT; j++) + for (k = 0; k < FIO_IO_U_PLAT_NR; k++) + dst->io_u_plat[i][j][k] = le64_to_cpu(src->io_u_plat[i][j][k]); - for (i = 0; i < DDIR_RWDIR_CNT; i++) { + for (j = 0; j < FIO_IO_U_PLAT_NR; j++) + dst->io_u_sync_plat[j] = le64_to_cpu(src->io_u_sync_plat[j]); + + for (i = 0; i < DDIR_RWDIR_SYNC_CNT; i++) dst->total_io_u[i] = le64_to_cpu(src->total_io_u[i]); + + for (i = 0; i < DDIR_RWDIR_CNT; i++) { dst->short_io_u[i] = le64_to_cpu(src->short_io_u[i]); dst->drop_io_u[i] = le64_to_cpu(src->drop_io_u[i]); } dst->total_submit = le64_to_cpu(src->total_submit); dst->total_complete = le64_to_cpu(src->total_complete); + dst->nr_zone_resets = le64_to_cpu(src->nr_zone_resets); for (i = 0; i < DDIR_RWDIR_CNT; i++) { dst->io_bytes[i] = le64_to_cpu(src->io_bytes[i]); @@ -1015,12 +1047,28 @@ 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)); + for (i = 0; i < DDIR_RWDIR_CNT; i++) { + dst->nr_clat_prio[i] = le32_to_cpu(src->nr_clat_prio[i]); + for (j = 0; j < dst->nr_clat_prio[i]; j++) { + for (k = 0; k < FIO_IO_U_PLAT_NR; k++) + dst->clat_prio[i][j].io_u_plat[k] = + le64_to_cpu(src->clat_prio[i][j].io_u_plat[k]); + convert_io_stat(&dst->clat_prio[i][j].clat_stat, + &src->clat_prio[i][j].clat_stat); + dst->clat_prio[i][j].ioprio = + le32_to_cpu(dst->clat_prio[i][j].ioprio); + } + } + 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]); } } + + dst->cachehit = le64_to_cpu(src->cachehit); + dst->cachemiss = le64_to_cpu(src->cachemiss); } static void convert_gs(struct group_run_stats *dst, struct group_run_stats *src) @@ -1061,7 +1109,7 @@ static void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd) if (client->opt_lists && p->ts.thread_number <= client->jobs) opt_list = &client->opt_lists[p->ts.thread_number - 1]; - tsobj = show_thread_status(&p->ts, &p->rs, opt_list, NULL); + tsobj = show_thread_status(&p->ts, &p->rs, opt_list, &client->buf); client->did_stat = true; if (tsobj) { json_object_add_client_info(tsobj, client); @@ -1071,7 +1119,7 @@ static void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd) if (sum_stat_clients <= 1) return; - sum_thread_stats(&client_ts, &p->ts, sum_stat_nr == 1); + sum_thread_stats(&client_ts, &p->ts); sum_group_stats(&client_gs, &p->rs); client_ts.members++; @@ -1082,7 +1130,7 @@ static void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd) if (++sum_stat_nr == sum_stat_clients) { strcpy(client_ts.name, "All clients"); - tsobj = show_thread_status(&client_ts, &client_gs, NULL, NULL); + tsobj = show_thread_status(&client_ts, &client_gs, NULL, &allclients); if (tsobj) { json_object_add_client_info(tsobj, client); json_array_add_value_object(clients_array, tsobj); @@ -1095,38 +1143,32 @@ static void handle_gs(struct fio_client *client, struct fio_net_cmd *cmd) struct group_run_stats *gs = (struct group_run_stats *) cmd->payload; if (output_format & FIO_OUTPUT_NORMAL) - show_group_stats(gs, NULL); + show_group_stats(gs, &client->buf); } static void handle_job_opt(struct fio_client *client, struct fio_net_cmd *cmd) { struct cmd_job_option *pdu = (struct cmd_job_option *) cmd->payload; - struct print_option *p; - - if (!job_opt_object) - return; pdu->global = le16_to_cpu(pdu->global); pdu->truncated = le16_to_cpu(pdu->truncated); pdu->groupid = le32_to_cpu(pdu->groupid); - p = malloc(sizeof(*p)); - p->name = strdup((char *) pdu->name); - if (pdu->value[0] != '\0') - p->value = strdup((char *) pdu->value); - else - p->value = NULL; - if (pdu->global) { - const char *pos = ""; + if (!job_opt_object) + return; - if (p->value) - pos = p->value; - - json_object_add_value_string(job_opt_object, p->name, pos); + json_object_add_value_string(job_opt_object, + (const char *)pdu->name, + (const char *)pdu->value); } else if (client->opt_lists) { struct flist_head *opt_list = &client->opt_lists[pdu->groupid]; + struct print_option *p; + p = malloc(sizeof(*p)); + p->name = strdup((const char *)pdu->name); + p->value = pdu->value[0] ? strdup((const char *)pdu->value) : + NULL; flist_add_tail(&p->list, opt_list); } } @@ -1137,13 +1179,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; } @@ -1184,21 +1230,24 @@ static void handle_du(struct fio_client *client, struct fio_net_cmd *cmd) { struct cmd_du_pdu *du = (struct cmd_du_pdu *) cmd->payload; - if (!client->disk_stats_shown) { + if (!client->disk_stats_shown) client->disk_stats_shown = true; - log_info("\nDisk stats (read/write):\n"); - } if (output_format & FIO_OUTPUT_JSON) { struct json_object *duobj; + json_array_add_disk_util(&du->dus, &du->agg, du_array); duobj = json_array_last_value_object(du_array); json_object_add_client_info(duobj, client); } - if (output_format & FIO_OUTPUT_TERSE) - print_disk_util(&du->dus, &du->agg, 1, NULL); - if (output_format & FIO_OUTPUT_NORMAL) - print_disk_util(&du->dus, &du->agg, 0, NULL); + if (output_format & FIO_OUTPUT_NORMAL) { + __log_buf(&client->buf, "\nDisk stats (read/write):\n"); + print_disk_util(&du->dus, &du->agg, 0, &client->buf); + } + if (output_format & FIO_OUTPUT_TERSE && terse_version >= 3) { + print_disk_util(&du->dus, &du->agg, 1, &client->buf); + __log_buf(&client->buf, "\n"); + } } static void convert_jobs_eta(struct jobs_eta *je) @@ -1467,9 +1516,11 @@ 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_NORMAL) { + 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); @@ -1526,7 +1577,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; @@ -1571,6 +1622,11 @@ static struct cmd_iolog_pdu *convert_iolog_gz(struct fio_net_cmd *cmd, err = inflate(&stream, Z_NO_FLUSH); /* may be Z_OK, or Z_STREAM_END */ if (err < 0) { + /* + * Z_STREAM_ERROR and Z_BUF_ERROR can safely be + * ignored */ + if (err == Z_STREAM_ERROR || err == Z_BUF_ERROR) + break; log_err("fio: inflate error %d\n", err); free(ret); ret = NULL; @@ -1631,6 +1687,7 @@ static struct cmd_iolog_pdu *convert_iolog(struct fio_net_cmd *cmd, ret->log_type = le32_to_cpu(ret->log_type); ret->compressed = le32_to_cpu(ret->compressed); ret->log_offset = le32_to_cpu(ret->log_offset); + ret->log_prio = le32_to_cpu(ret->log_prio); ret->log_hist_coarseness = le32_to_cpu(ret->log_hist_coarseness); if (*store_direct) @@ -1646,8 +1703,9 @@ 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->__ddir = __le32_to_cpu(s->__ddir); s->bs = le64_to_cpu(s->bs); + s->priority = le16_to_cpu(s->priority); if (ret->log_offset) { struct io_sample_offset *so = (void *) s; @@ -1710,7 +1768,6 @@ int fio_handle_client(struct fio_client *client) { struct client_ops *ops = client->ops; struct fio_net_cmd *cmd; - int size; dprint(FD_NET, "client: handle %s\n", client->hostname); @@ -1744,14 +1801,26 @@ int fio_handle_client(struct fio_client *client) } case FIO_NET_CMD_TS: { struct cmd_ts_pdu *p = (struct cmd_ts_pdu *) cmd->payload; + uint64_t offset; + int i; + + for (i = 0; i < DDIR_RWDIR_CNT; i++) { + if (le32_to_cpu(p->ts.nr_clat_prio[i])) { + offset = le64_to_cpu(p->ts.clat_prio_offset[i]); + p->ts.clat_prio[i] = + (struct clat_prio_stat *)((char *)p + offset); + } + } 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) { dprint(FD_NET, "client: received steadystate ring buffers\n"); - size = le64_to_cpu(p->ts.ss_dur); - p->ts.ss_iops_data = (uint64_t *) ((struct cmd_ts_pdu *)cmd->payload + 1); - p->ts.ss_bw_data = p->ts.ss_iops_data + size; + offset = le64_to_cpu(p->ts.ss_iops_data_offset); + p->ts.ss_iops_data = (uint64_t *)((char *)p + offset); + + offset = le64_to_cpu(p->ts.ss_bw_data_offset); + p->ts.ss_bw_data = (uint64_t *)((char *)p + offset); } convert_ts(&p->ts, &p->ts); @@ -2097,8 +2166,18 @@ int fio_handle_clients(struct client_ops *ops) } } + log_info_buf(allclients.buf, allclients.buflen); + buf_output_free(&allclients); + fio_client_json_fini(); + free_clat_prio_stats(&client_ts); 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); +}