From 0279b88017b5d21f0fcbb1b57481339735c41797 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 15 Dec 2015 20:33:29 -0700 Subject: [PATCH] client/server: pass back job options to client Also fill in a few more missing pieces from the server based json output, like time stamp. Now the json output should match the local, on all accounts. Signed-off-by: Jens Axboe --- client.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- client.h | 2 ++ server.c | 28 +++++++++++++++++++++++ server.h | 13 +++++++++-- stat.c | 15 ++++++++----- stat.h | 2 +- 6 files changed, 118 insertions(+), 10 deletions(-) diff --git a/client.c b/client.c index c24f89b4..366db716 100644 --- a/client.c +++ b/client.c @@ -59,6 +59,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,11 +118,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(); @@ -132,6 +145,7 @@ 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"); @@ -176,6 +190,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--; @@ -936,9 +952,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); @@ -958,7 +978,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); @@ -974,6 +994,35 @@ static void handle_gs(struct fio_client *client, struct fio_net_cmd *cmd) 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; + + pdu->global = le16_to_cpu(pdu->global); + pdu->groupid = le16_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) { struct cmd_text_pdu *pdu = (struct cmd_text_pdu *) cmd->payload; @@ -1204,6 +1253,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; } @@ -1516,6 +1576,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; diff --git a/client.h b/client.h index 46e30edc..035e606f 100644 --- a/client.h +++ b/client.h @@ -41,6 +41,8 @@ struct fio_client { char *name; + struct flist_head *opt_lists; + int state; int skip_newline; diff --git a/server.c b/server.c index ca17f9a3..38a6bf85 100644 --- a/server.c +++ b/server.c @@ -1512,6 +1512,34 @@ void fio_server_send_gs(struct group_run_stats *rs) fio_net_queue_cmd(FIO_NET_CMD_GS, &gs, sizeof(gs), NULL, SK_F_COPY); } +void fio_server_send_job_options(struct flist_head *opt_list, + unsigned int groupid) +{ + struct cmd_job_option pdu; + struct flist_head *entry; + + if (flist_empty(opt_list)) + return; + + flist_for_each(entry, opt_list) { + struct print_option *p; + + p = flist_entry(entry, struct print_option, list); + memset(&pdu, 0, sizeof(pdu)); + if (groupid == -1U) { + pdu.global = __cpu_to_le16(1); + pdu.groupid = 0; + } else { + pdu.global = 0; + pdu.groupid = __cpu_to_le16(groupid); + } + memcpy(pdu.name, p->name, strlen(p->name)); + if (p->value) + memcpy(pdu.value, p->value, strlen(p->value)); + fio_net_queue_cmd(FIO_NET_CMD_JOB_OPT, &pdu, sizeof(pdu), NULL, SK_F_COPY); + } +} + static void convert_agg(struct disk_util_agg *dst, struct disk_util_agg *src) { int i; diff --git a/server.h b/server.h index d73ce1d6..fca9a874 100644 --- a/server.h +++ b/server.h @@ -38,7 +38,7 @@ struct fio_net_cmd_reply { }; enum { - FIO_SERVER_VER = 49, + FIO_SERVER_VER = 50, FIO_SERVER_MAX_FRAGMENT_PDU = 1024, FIO_SERVER_MAX_CMD_MB = 2048, @@ -64,7 +64,8 @@ enum { FIO_NET_CMD_LOAD_FILE = 19, FIO_NET_CMD_VTRIGGER = 20, FIO_NET_CMD_SENDFILE = 21, - FIO_NET_CMD_NR = 22, + FIO_NET_CMD_JOB_OPT = 22, + FIO_NET_CMD_NR = 23, FIO_NET_CMD_F_MORE = 1UL << 0, @@ -181,6 +182,13 @@ struct cmd_iolog_pdu { struct io_sample samples[0]; }; +struct cmd_job_option { + uint16_t global; + uint16_t groupid; + uint8_t name[64]; + uint8_t value[128]; +}; + extern int fio_start_server(char *); extern int fio_server_text_output(int, const char *, size_t); extern int fio_net_send_cmd(int, uint16_t, const void *, off_t, uint64_t *, struct flist_head *); @@ -196,6 +204,7 @@ struct group_run_stats; extern void fio_server_send_ts(struct thread_stat *, struct group_run_stats *); extern void fio_server_send_gs(struct group_run_stats *); extern void fio_server_send_du(void); +extern void fio_server_send_job_options(struct flist_head *, unsigned int); extern int fio_server_get_verify_state(const char *, int, void **, int *); extern struct fio_net_cmd *fio_net_recv_cmd(int sk); diff --git a/stat.c b/stat.c index 1c1dceb5..a3bfe632 100644 --- a/stat.c +++ b/stat.c @@ -1086,8 +1086,8 @@ static void show_thread_status_terse_v3_v4(struct thread_stat *ts, log_buf(out, "\n"); } -static void json_add_job_opts(struct json_object *root, const char *name, - struct flist_head *opt_list, bool num_jobs) +void json_add_job_opts(struct json_object *root, const char *name, + struct flist_head *opt_list, bool num_jobs) { struct json_object *dir_object; struct flist_head *entry; @@ -1268,6 +1268,7 @@ static void show_thread_status_terse(struct thread_stat *ts, struct json_object *show_thread_status(struct thread_stat *ts, struct group_run_stats *rs, + struct flist_head *opt_list, struct buf_output *out) { struct json_object *ret = NULL; @@ -1275,7 +1276,7 @@ struct json_object *show_thread_status(struct thread_stat *ts, if (output_format & FIO_OUTPUT_TERSE) show_thread_status_terse(ts, rs, out); if (output_format & FIO_OUTPUT_JSON) - ret = show_thread_status_json(ts, rs, NULL); + ret = show_thread_status_json(ts, rs, opt_list); if (output_format & FIO_OUTPUT_NORMAL) show_thread_status_normal(ts, rs, out); @@ -1649,13 +1650,17 @@ void __show_run_stats(void) json_object_add_value_array(root, "jobs", array); } + if (is_backend) + fio_server_send_job_options(&get_global_options()->opt_list, -1U); + for (i = 0; i < nr_ts; i++) { ts = &threadstats[i]; rs = &runstats[ts->groupid]; - if (is_backend) + if (is_backend) { + fio_server_send_job_options(opt_lists[i], i); fio_server_send_ts(ts, rs); - else { + } else { if (output_format & FIO_OUTPUT_TERSE) show_thread_status_terse(ts, rs, &output[__FIO_OUTPUT_TERSE]); if (output_format & FIO_OUTPUT_JSON) { diff --git a/stat.h b/stat.h index dda88fcd..9c3f1926 100644 --- a/stat.h +++ b/stat.h @@ -247,7 +247,7 @@ extern struct jobs_eta *get_jobs_eta(bool force, size_t *size); extern void stat_init(void); extern void stat_exit(void); -extern struct json_object * show_thread_status(struct thread_stat *ts, struct group_run_stats *rs, struct buf_output *); +extern struct json_object * show_thread_status(struct thread_stat *ts, struct group_run_stats *rs, struct flist_head *, struct buf_output *); extern void show_group_stats(struct group_run_stats *rs, struct buf_output *); extern int calc_thread_status(struct jobs_eta *je, int force); extern void display_thread_status(struct jobs_eta *je); -- 2.25.1