The following changes since commit 03a22d9188def5a2643c577a70d410f65a3e8f79: client: fix free of wrong pointer (2013-10-16 08:35:12 -0600) are available in the git repository at: git://git.kernel.dk/fio.git master Castor Fu (2): Add json output for client/server mode configure: add option to disable libnuma usage Jens Axboe (1): Fix bad asm constrants for x86-64 cpuid() arch/arch-x86_64.h | 2 +- client.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++--- configure | 5 +++- diskutil.c | 49 ++++++++++++++++++++++++----------------- diskutil.h | 5 +++- json.h | 3 ++ stat.c | 22 +++++++++++++++--- stat.h | 2 +- 8 files changed, 117 insertions(+), 32 deletions(-) --- Diff of recent changes: diff --git a/arch/arch-x86_64.h b/arch/arch-x86_64.h index d7ea12e..61ac75e 100644 --- a/arch/arch-x86_64.h +++ b/arch/arch-x86_64.h @@ -5,7 +5,7 @@ static inline void do_cpuid(unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx) { asm volatile("cpuid" - : "=a" (*eax), "=b" (*ebx), "=r" (*ecx), "=d" (*edx) + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "0" (*eax), "2" (*ecx) : "memory"); } diff --git a/client.c b/client.c index 1fefda8..1557240 100644 --- a/client.c +++ b/client.c @@ -57,6 +57,9 @@ struct group_run_stats client_gs; int sum_stat_clients; static int sum_stat_nr; +static struct json_object *root = NULL; +static struct json_array *clients_array = NULL; +static struct json_array *du_array = NULL; static int do_output_all_clients; #define FIO_CLIENT_HASH_BITS 7 @@ -86,6 +89,30 @@ static void fio_init fio_client_hash_init(void) INIT_FLIST_HEAD(&client_hash[i]); } +static void fio_client_json_init(void) +{ + if (output_format != FIO_OUTPUT_JSON) + return; + root = json_create_object(); + json_object_add_value_string(root, "fio version", fio_version_string); + clients_array = json_create_array(); + json_object_add_value_array(root, "client_stats", clients_array); + du_array = json_create_array(); + json_object_add_value_array(root, "disk_util", du_array); +} + +static void fio_client_json_fini(void) +{ + if (output_format != FIO_OUTPUT_JSON) + return; + json_print_object(root); + log_info("\n"); + json_free_object(root); + root = NULL; + clients_array = NULL; + du_array = NULL; +} + static struct fio_client *find_client_by_fd(int fd) { int bucket = hash_long(fd, FIO_CLIENT_HASH_BITS) & FIO_CLIENT_HASH_MASK; @@ -557,6 +584,8 @@ int fio_start_all_clients(void) dprint(FD_NET, "client: start all\n"); + fio_client_json_init(); + flist_for_each_safe(entry, tmp, &client_list) { client = flist_entry(entry, struct fio_client, list); @@ -684,7 +713,7 @@ int fio_client_update_options(struct fio_client *client, pdu.thread_number = cpu_to_le32(client->thread_number); pdu.groupid = cpu_to_le32(client->groupid); convert_thread_options_to_net(&pdu.top, o); - + return fio_net_send_cmd(client->fd, FIO_NET_CMD_UPDATE_JOB, &pdu, sizeof(pdu), tag, &client->cmd_list); } @@ -788,12 +817,24 @@ static void convert_gs(struct group_run_stats *dst, struct group_run_stats *src) dst->unified_rw_rep = le32_to_cpu(src->unified_rw_rep); } +static void json_object_add_client_info(struct json_object *obj, +struct fio_client *client) +{ + json_object_add_value_string(obj, "hostname", client->hostname); + json_object_add_value_int(obj, "port", client->port); +} + 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 json_object *tsobj; - show_thread_status(&p->ts, &p->rs); + tsobj = show_thread_status(&p->ts, &p->rs); client->did_stat = 1; + if (tsobj) { + json_object_add_client_info(tsobj, client); + json_array_add_value_object(clients_array, tsobj); + } if (!do_output_all_clients) return; @@ -808,7 +849,11 @@ 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"); - show_thread_status(&client_ts, &client_gs); + tsobj = show_thread_status(&client_ts, &client_gs); + if (tsobj) { + json_object_add_client_info(tsobj, client); + json_array_add_value_object(clients_array, tsobj); + } } } @@ -877,7 +922,13 @@ static void handle_du(struct fio_client *client, struct fio_net_cmd *cmd) log_info("\nDisk stats (read/write):\n"); } - print_disk_util(&du->dus, &du->agg, output_format == FIO_OUTPUT_TERSE); + 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); + } else + print_disk_util(&du->dus, &du->agg, output_format == FIO_OUTPUT_TERSE); } static void convert_jobs_eta(struct jobs_eta *je) @@ -1476,6 +1527,8 @@ int fio_handle_clients(struct client_ops *ops) } } + fio_client_json_fini(); + free(pfds); return retval; } diff --git a/configure b/configure index c00a3a4..b6bfe19 100755 --- a/configure +++ b/configure @@ -153,6 +153,8 @@ for opt do --enable-gfio) gfio="yes" ;; + --disable-numa) disable_numa="yes" + ;; --help) show_help="yes" ;; @@ -169,6 +171,7 @@ if test "$show_help" = "yes" ; then echo "--extra-cflags= Specify extra CFLAGS to pass to compiler" echo "--build-32bit-win Enable 32-bit build on Windows" echo "--enable-gfio Enable building of gtk gfio" + echo "--disable-numa Disable libnuma even if found" exit $exit_val fi @@ -835,7 +838,7 @@ int main(int argc, char **argv) return numa_available(); } EOF -if compile_prog "" "-lnuma" "libnuma"; then +if test "$disable_numa" != "yes" && compile_prog "" "-lnuma" "libnuma"; then libnuma="yes" LIBS="-lnuma $LIBS" fi diff --git a/diskutil.c b/diskutil.c index e29d1c3..bc12b02 100644 --- a/diskutil.c +++ b/diskutil.c @@ -605,21 +605,19 @@ void print_disk_util(struct disk_util_stat *dus, struct disk_util_agg *agg, log_info("\n"); } -static void print_disk_util_json(struct disk_util *du, struct json_array *array) +void json_array_add_disk_util(struct disk_util_stat *dus, + struct disk_util_agg *agg, struct json_array *array) { - double util = 0; - struct disk_util_stat *dus = &du->dus; - struct disk_util_agg *agg = &du->agg; struct json_object *obj; - - obj = json_create_object(); - json_array_add_value_object(array, obj); + double util = 0; if (dus->msec) util = (double) 100 * dus->io_ticks / (double) dus->msec; if (util > 100.0) util = 100.0; + obj = json_create_object(); + json_array_add_value_object(array, obj); json_object_add_value_string(obj, "name", dus->name); json_object_add_value_int(obj, "read_ios", dus->ios[0]); @@ -654,11 +652,27 @@ static void print_disk_util_json(struct disk_util *du, struct json_array *array) json_object_add_value_float(obj, "aggr_util", agg->max_util.u.f); } +void json_object_add_disk_utils(struct json_object *obj, + struct flist_head *head) +{ + struct json_array *array = json_create_array(); + struct flist_head *entry; + struct disk_util *du; + + json_object_add_value_array(obj, "disk_util", array); + + flist_for_each(entry, head) { + du = flist_entry(entry, struct disk_util, list); + + aggregate_slaves_stats(du); + json_array_add_disk_util(&du->dus, &du->agg, array); + } +} + void show_disk_util(int terse, struct json_object *parent) { struct flist_head *entry; struct disk_util *du; - struct json_array *array = NULL; fio_mutex_down(disk_util_mutex); @@ -667,23 +681,18 @@ void show_disk_util(int terse, struct json_object *parent) return; } - if (!terse) + if (!terse && !parent) log_info("\nDisk stats (read/write):\n"); if (output_format == FIO_OUTPUT_JSON) { - array = json_create_array(); - json_object_add_value_array(parent, "disk_util", array); - } - - flist_for_each(entry, &disk_list) { - du = flist_entry(entry, struct disk_util, list); + json_object_add_disk_utils(parent, &disk_list); + } else + flist_for_each(entry, &disk_list) { + du = flist_entry(entry, struct disk_util, list); - aggregate_slaves_stats(du); - if (output_format == FIO_OUTPUT_JSON) - print_disk_util_json(du, array); - else + aggregate_slaves_stats(du); print_disk_util(&du->dus, &du->agg, terse); - } + } fio_mutex_up(disk_util_mutex); } diff --git a/diskutil.h b/diskutil.h index 6ae4aee..7207c73 100644 --- a/diskutil.h +++ b/diskutil.h @@ -104,6 +104,8 @@ extern void wait_for_disk_thread_exit(void); #ifdef FIO_HAVE_DISK_UTIL extern void print_disk_util(struct disk_util_stat *, struct disk_util_agg *, int terse); extern void show_disk_util(int terse, struct json_object *parent); +extern void json_array_add_disk_util(struct disk_util_stat *dus, + struct disk_util_agg *agg, struct json_array *parent); extern void init_disk_util(struct thread_data *); extern int update_io_ticks(void); extern void setup_disk_util(void); @@ -117,6 +119,8 @@ static inline void print_disk_util(struct disk_util_stat *du, #define disk_util_prune_entries() #define init_disk_util(td) #define setup_disk_util() +#define json_array_add_disk_util(dus, agg, parent) + static inline int update_io_ticks(void) { return disk_util_exit; @@ -127,5 +131,4 @@ static inline void disk_util_start_exit(void) { disk_util_exit = 1; } - #endif diff --git a/json.h b/json.h index 4d05e82..2a798ce 100644 --- a/json.h +++ b/json.h @@ -73,5 +73,8 @@ int json_array_add_value_type(struct json_array *array, int type, ...); #define json_array_add_value_array(obj, val) \ json_array_add_value_type((obj), JSON_TYPE_ARRAY, (val)) +#define json_array_last_value_object(obj) \ + (obj->values[obj->value_cnt - 1]->object) + void json_print_object(struct json_object *obj); #endif diff --git a/stat.c b/stat.c index fec3639..ac5ff16 100644 --- a/stat.c +++ b/stat.c @@ -497,7 +497,8 @@ static void show_latencies(struct thread_stat *ts) show_lat_m(io_u_lat_m); } -void show_thread_status(struct thread_stat *ts, struct group_run_stats *rs) + +void show_thread_status_normal(struct thread_stat *ts, struct group_run_stats *rs) { double usr_cpu, sys_cpu; unsigned long runtime; @@ -883,7 +884,8 @@ static void show_thread_status_terse_v3_v4(struct thread_stat *ts, log_info(";%3.2f%%", io_u_lat_m[i]); /* disk util stats, if any */ - show_disk_util(1, NULL); + if (is_backend) + show_disk_util(1, NULL); /* Additional output if continue_on_error set - default off*/ if (ts->continue_on_error) @@ -970,7 +972,7 @@ static struct json_object *show_thread_status_json(struct thread_stat *ts, /* Additional output if continue_on_error set - default off*/ if (ts->continue_on_error) { json_object_add_value_int(root, "total_err", ts->total_err_count); - json_object_add_value_int(root, "total_err", ts->first_error); + json_object_add_value_int(root, "first_error", ts->first_error); } /* Additional output if description is set */ @@ -991,6 +993,18 @@ static void show_thread_status_terse(struct thread_stat *ts, log_err("fio: bad terse version!? %d\n", terse_version); } +struct json_object *show_thread_status(struct thread_stat *ts, + struct group_run_stats *rs) +{ + if (output_format == FIO_OUTPUT_TERSE) + show_thread_status_terse(ts, rs); + else if (output_format == FIO_OUTPUT_JSON) + return(show_thread_status_json(ts, rs)); + else + show_thread_status_normal(ts, rs); + return NULL; +} + static void sum_stat(struct io_stat *dst, struct io_stat *src, int nr) { double mean, S; @@ -1324,7 +1338,7 @@ static void __show_run_stats(void) struct json_object *tmp = show_thread_status_json(ts, rs); json_array_add_value_object(array, tmp); } else - show_thread_status(ts, rs); + show_thread_status_normal(ts, rs); } if (output_format == FIO_OUTPUT_JSON) { /* disk util stats, if any */ diff --git a/stat.h b/stat.h index 541b77e..8190d1e 100644 --- a/stat.h +++ b/stat.h @@ -202,7 +202,7 @@ struct jobs_eta { extern void stat_init(void); extern void stat_exit(void); -extern void show_thread_status(struct thread_stat *ts, struct group_run_stats *rs); +extern struct json_object * show_thread_status(struct thread_stat *ts, struct group_run_stats *rs); extern void show_group_stats(struct group_run_stats *rs); extern int calc_thread_status(struct jobs_eta *je, int force); extern void display_thread_status(struct jobs_eta *je); -- To unsubscribe from this list: send the line "unsubscribe fio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html