X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=client.c;h=752b508c73802013f215b0c1fff5627021b6c288;hp=db472c4cb0b4cb1d87368358b8bb34d65f78d94c;hb=bead01d7dcd76467f0aba0d32b173442bbdaa020;hpb=f672ef67527a27eb2bbc59aa6041a42d88a00838 diff --git a/client.c b/client.c index db472c4c..752b508c 100644 --- a/client.c +++ b/client.c @@ -32,6 +32,7 @@ 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_start(struct fio_client *client, struct fio_net_cmd *cmd); +static void handle_iolog(struct fio_client *client, struct cmd_iolog_pdu *pdu); struct client_ops fio_client_ops = { .text = handle_text, @@ -42,6 +43,7 @@ struct client_ops fio_client_ops = { .start = handle_start, .eta = display_thread_status, .probe = handle_probe, + .iolog = handle_iolog, .eta_msec = FIO_CLIENT_DEF_ETA_MSEC, .client_type = FIO_CLIENT_TYPE_CLI, }; @@ -59,6 +61,7 @@ int sum_stat_clients; static int sum_stat_nr; static struct json_object *root = NULL; +static struct json_object *job_opt_object = NULL; static struct json_array *clients_array = NULL; static struct json_array *du_array = NULL; @@ -117,10 +120,23 @@ static int read_data(int fd, void *data, size_t size) static void fio_client_json_init(void) { + char time_buf[32]; + time_t time_p; + if (!(output_format & FIO_OUTPUT_JSON)) return; + + time(&time_p); + os_ctime_r((const time_t *) &time_p, time_buf, sizeof(time_buf)); + time_buf[strlen(time_buf) - 1] = '\0'; + root = json_create_object(); json_object_add_value_string(root, "fio version", fio_version_string); + json_object_add_value_int(root, "timestamp", time_p); + json_object_add_value_string(root, "time", time_buf); + + job_opt_object = json_create_object(); + json_object_add_value_object(root, "global options", job_opt_object); clients_array = json_create_array(); json_object_add_value_array(root, "client_stats", clients_array); du_array = json_create_array(); @@ -131,6 +147,8 @@ static void fio_client_json_fini(void) { if (!(output_format & FIO_OUTPUT_JSON)) return; + + log_info("\n"); json_print_object(root, NULL); log_info("\n"); json_free_object(root); @@ -174,6 +192,8 @@ void fio_put_client(struct fio_client *client) } if (client->files) free(client->files); + if (client->opt_lists) + free(client->opt_lists); if (!client->did_stat) sum_stat_clients--; @@ -934,9 +954,13 @@ static void json_object_add_client_info(struct json_object *obj, static void handle_ts(struct fio_client *client, struct fio_net_cmd *cmd) { struct cmd_ts_pdu *p = (struct cmd_ts_pdu *) cmd->payload; + struct flist_head *opt_list = NULL; struct json_object *tsobj; - tsobj = show_thread_status(&p->ts, &p->rs, NULL); + 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); client->did_stat = 1; if (tsobj) { json_object_add_client_info(tsobj, client); @@ -946,7 +970,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); + sum_thread_stats(&client_ts, &p->ts, sum_stat_nr == 1); sum_group_stats(&client_gs, &p->rs); client_ts.members++; @@ -956,7 +980,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); + tsobj = show_thread_status(&client_ts, &client_gs, NULL, NULL); if (tsobj) { json_object_add_client_info(tsobj, client); json_array_add_value_object(clients_array, tsobj); @@ -968,7 +992,41 @@ static void handle_gs(struct fio_client *client, struct fio_net_cmd *cmd) { struct group_run_stats *gs = (struct group_run_stats *) cmd->payload; - show_group_stats(gs, NULL); + if (output_format & FIO_OUTPUT_NORMAL) + show_group_stats(gs, NULL); +} + +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 (p->value) + pos = p->value; + + json_object_add_value_string(job_opt_object, p->name, pos); + } else if (client->opt_lists) { + struct flist_head *opt_list = &client->opt_lists[pdu->groupid]; + + flist_add_tail(&p->list, opt_list); + } } static void handle_text(struct fio_client *client, struct fio_net_cmd *cmd) @@ -1159,6 +1217,7 @@ static void handle_eta(struct fio_client *client, struct fio_net_cmd *cmd) client->eta_in_flight = NULL; flist_del_init(&client->eta_list); + client->eta_timeouts = 0; if (client->ops->jobs_eta) client->ops->jobs_eta(client, je); @@ -1167,6 +1226,23 @@ static void handle_eta(struct fio_client *client, struct fio_net_cmd *cmd) fio_client_dec_jobs_eta(eta, client->ops->eta); } +static void handle_iolog(struct fio_client *client, struct cmd_iolog_pdu *pdu) +{ + FILE *f; + + printf("got log compressed; %d\n", pdu->compressed); + + f = fopen((const char *) pdu->name, "w"); + if (!f) { + perror("fopen log"); + return; + } + + flush_samples(f, pdu->samples, + pdu->nr_samples * sizeof(struct io_sample)); + fclose(f); +} + static void handle_probe(struct fio_client *client, struct fio_net_cmd *cmd) { struct cmd_probe_reply_pdu *probe = (struct cmd_probe_reply_pdu *) cmd->payload; @@ -1200,6 +1276,17 @@ static void handle_start(struct fio_client *client, struct fio_net_cmd *cmd) client->jobs = le32_to_cpu(pdu->jobs); client->nr_stat = le32_to_cpu(pdu->stat_outputs); + if (client->jobs) { + int i; + + if (client->opt_lists) + free(client->opt_lists); + + client->opt_lists = malloc(client->jobs * sizeof(struct flist_head)); + for (i = 0; i < client->jobs; i++) + INIT_FLIST_HEAD(&client->opt_lists[i]); + } + sum_stat_clients += client->nr_stat; } @@ -1512,6 +1599,10 @@ int fio_handle_client(struct fio_client *client) send_file(client, pdu, cmd->tag); break; } + case FIO_NET_CMD_JOB_OPT: { + handle_job_opt(client, cmd); + break; + } default: log_err("fio: unknown client op: %s\n", fio_server_op(cmd->opcode)); break; @@ -1588,6 +1679,35 @@ static void request_client_etas(struct client_ops *ops) dprint(FD_NET, "client: requested eta tag %p\n", eta); } +/* + * A single SEND_ETA timeout isn't fatal. Attempt to recover. + */ +static int handle_cmd_timeout(struct fio_client *client, + struct fio_net_cmd_reply *reply) +{ + flist_del(&reply->list); + free(reply); + + if (reply->opcode != FIO_NET_CMD_SEND_ETA) + return 1; + + log_info("client <%s>: timeout on SEND_ETA\n", client->hostname); + + flist_del_init(&client->eta_list); + if (client->eta_in_flight) { + fio_client_dec_jobs_eta(client->eta_in_flight, client->ops->eta); + client->eta_in_flight = NULL; + } + + /* + * If we fail 5 in a row, give up... + */ + if (client->eta_timeouts++ > 5) + return 1; + + return 0; +} + static int client_check_cmd_timeout(struct fio_client *client, struct timeval *now) { @@ -1601,10 +1721,11 @@ static int client_check_cmd_timeout(struct fio_client *client, if (mtime_since(&reply->tv, now) < FIO_NET_CLIENT_TIMEOUT) continue; + if (!handle_cmd_timeout(client, reply)) + continue; + log_err("fio: client %s, timeout on cmd %s\n", client->hostname, fio_server_op(reply->opcode)); - flist_del(&reply->list); - free(reply); ret = 1; }