Recent changes (master)
Subsystems (2)
The following changes since commit d2235e56057f54fc63ccbf789d4c54f9e99978af:
client: remove duplicated code (2015-10-20 09:07:31 -0600)
are available in the git repository at:
git://git.kernel.dk/fio.git master
for you to fetch changes up to 01cfefcc6255420a9e19d5774053ed2fb705b150:
client/backend: fix incomplete output_format checks (2015-10-27 18:34:33 +0900)
----------------------------------------------------------------
Jens Axboe (12):
Add support for multiple output formats
Enable the use of multiple output formats
Update fio man page
Re-instate --append-terse
Proper size return from output buffers
Don't setup output buffers we are not going to use jobs_eta alloc padding
log: abstract out and use generic buffer logger Unbreak output buffer logging over the network
stat: collapse buf output flush and free
stat: fix potential segfault for json output on network client client/backend: fix incomplete output_format checks
Makefile | 1 + backend.c | 2 +- client.c | 21 ++-- diskutil.c | 35 ++++--- diskutil.h | 11 +- eta.c | 4 +- filesetup.c | 2 +- fio.1 | 2 + fio.h | 11 +- idletime.c | 21 ++-- idletime.h | 3 +- init.c | 50 +++++++--- json.c | 62 ++++++------ json.h | 5 +- lib/output_buffer.c | 48 +++++++++ lib/output_buffer.h | 17 ++++ log.c | 50 ++++++---- log.h | 20 +++- parse.c | 4 +- stat.c | 282 +++++++++++++++++++++++++++------------------------- stat.h | 5 +- 21 files changed, 403 insertions(+), 253 deletions(-) create mode 100644 lib/output_buffer.c create mode 100644 lib/output_buffer.h
---
Diff of recent changes:
Makefile +1 -0
@@ -47,6 +47,7 @@ SOURCE := gettime.c ioengines.c init.c stat.c log.c time.c filesetup.c \ lib/hweight.c lib/getrusage.c idletime.c td_error.c \ profiles/tiobench.c profiles/act.c io_u_queue.c filelock.c \ lib/tp.c lib/bloom.c lib/gauss.c lib/mountcheck.c workqueue.c \ + lib/output_buffer.c \ $(patsubst $(SRCDIR)/%,%,$(wildcard $(SRCDIR)/crc/*.c)) ifdef CONFIG_LIBHDFS
backend.c +1 -1
@@ -1977,7 +1977,7 @@ static void run_threads(void) nr_process++; } -if (output_format ==FIO_OUTPUT_NORMAL ) { +if (output_format &FIO_OUTPUT_NORMAL ) {log_info ("Starting " );if (nr_thread) log_info("%d thread%s", nr_thread,
client.c +12 -9
@@ -117,7 +117,7 @@ static int read_data(int fd, void *data, size_t size)static void fio_client_json_init (void ) { -if (output_format !=FIO_OUTPUT_JSON ) +if (!(output_format &FIO_OUTPUT_JSON ))return ; root =json_create_object ();json_object_add_value_string (root,"fio version" , fio_version_string);
@@ -129,9 +129,9 @@ static void fio_client_json_init(void)static void fio_client_json_fini (void ) { -if (output_format !=FIO_OUTPUT_JSON ) +if (!(output_format &FIO_OUTPUT_JSON ))return ; -json_print_object (root); +json_print_object (root,NULL );log_info ("\n" );json_free_object (root); root =NULL ;
@@ -936,7 +936,7 @@ 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; - tsobj =show_thread_status (&p->ts, &p->rs); + tsobj =show_thread_status (&p->ts, &p->rs,NULL ); client->did_stat =1 ;if (tsobj) {json_object_add_client_info (tsobj, client);
@@ -956,7 +956,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); + tsobj =show_thread_status (&client_ts, &client_gs,NULL );if (tsobj) {json_object_add_client_info (tsobj, client);json_array_add_value_object (clients_array, tsobj);
@@ -968,7 +968,7 @@ 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); +show_group_stats (gs,NULL ); }static void handle_text (struct fio_client *client,struct fio_net_cmd *cmd)
@@ -1029,13 +1029,16 @@ static void handle_du(struct fio_client *client, struct fio_net_cmd *cmd)log_info ("\nDisk stats (read/write):\n" ); } -if (output_format ==FIO_OUTPUT_JSON ) { +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 ); + } +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 ); }static void convert_jobs_eta (struct jobs_eta *je)
diskutil.c +19 -16
@@ -495,13 +495,14 @@ void init_disk_util(struct thread_data *td) f->du =__init_disk_util (td, f); } -static void show_agg_stats (struct disk_util_agg *agg,int terse) +static void show_agg_stats (struct disk_util_agg *agg,int terse, +struct buf_output *out) {if (!agg->slavecount)return ;if (!terse) { - log_info(", aggrios=%llu/%llu, aggrmerge=%llu/%llu, " + log_buf(out, ", aggrios=%llu/%llu, aggrmerge=%llu/%llu, " "aggrticks=%llu/%llu, aggrin_queue=%llu, " "aggrutil=%3.2f%%", (unsigned long long) agg->ios[0] / agg->slavecount,
@@ -513,7 +514,7 @@ static void show_agg_stats(struct disk_util_agg *agg, int terse) (unsigned long long ) agg->time_in_queue / agg->slavecount, agg->max_util.u.f); }else { - log_info(";slaves;%llu;%llu;%llu;%llu;%llu;%llu;%llu;%3.2f%%", + log_buf(out, ";slaves;%llu;%llu;%llu;%llu;%llu;%llu;%llu;%3.2f%%", (unsigned long long) agg->ios[0] / agg->slavecount, (unsigned long long) agg->ios[1] / agg->slavecount, (unsigned long long) agg->merges[0] / agg->slavecount,
@@ -578,7 +579,7 @@ void disk_util_prune_entries(void) }void print_disk_util (struct disk_util_stat *dus,struct disk_util_agg *agg, -int terse) +int terse,struct buf_output *out) {double util =0 ;
@@ -589,9 +590,9 @@ void print_disk_util(struct disk_util_stat *dus, struct disk_util_agg *agg,if (!terse) {if (agg->slavecount) -log_info (" " ); +log_buf (out," " ); - log_info(" %s: ios=%llu/%llu, merge=%llu/%llu, " + log_buf(out, " %s: ios=%llu/%llu, merge=%llu/%llu, " "ticks=%llu/%llu, in_queue=%llu, util=%3.2f%%", dus->name, (unsigned long long) dus->s.ios[0],
@@ -603,7 +604,7 @@ void print_disk_util(struct disk_util_stat *dus, struct disk_util_agg *agg, (unsigned long long ) dus->s.time_in_queue, util); }else { - log_info(";%s;%llu;%llu;%llu;%llu;%llu;%llu;%llu;%3.2f%%", + log_buf(out, ";%s;%llu;%llu;%llu;%llu;%llu;%llu;%llu;%3.2f%%", dus->name, (unsigned long long) dus->s.ios[0], (unsigned long long) dus->s.ios[1],
@@ -619,10 +620,10 @@ void print_disk_util(struct disk_util_stat *dus, struct disk_util_agg *agg,* If the device has slaves, aggregate the stats for * those slave devices also. */ -show_agg_stats (agg, terse); +show_agg_stats (agg, terse, out);if (!terse) -log_info ("\n" ); +log_buf (out,"\n" ); } void json_array_add_disk_util(struct disk_util_stat *dus,
@@ -689,7 +690,8 @@ static void json_object_add_disk_utils(struct json_object *obj, } } -void show_disk_util (int terse,struct json_object *parent) +void show_disk_util (int terse,struct json_object *parent, +struct buf_output *out) {struct flist_head *entry;struct disk_util *du;
@@ -704,21 +706,22 @@ void show_disk_util(int terse, struct json_object *parent)return ; } -if (output_format ==FIO_OUTPUT_JSON ) +if (output_format &FIO_OUTPUT_JSON )assert (parent); -if (!terse && output_format !=FIO_OUTPUT_JSON ) -log_info ("\nDisk stats (read/write):\n" ); +if (!terse && !(output_format &FIO_OUTPUT_JSON )) +log_buf (out,"\nDisk stats (read/write):\n" ); -if (output_format ==FIO_OUTPUT_JSON ) +if (output_format &FIO_OUTPUT_JSON )json_object_add_disk_utils (parent, &disk_list); -else +if (output_format & ~(FIO_OUTPUT_JSON )) {flist_for_each (entry, &disk_list) { du = flist_entry(entry, struct disk_util, list);aggregate_slaves_stats (du); -print_disk_util (&du->dus, &du->agg, terse); +print_disk_util (&du->dus, &du->agg, terse, out); } + }fio_mutex_up (disk_util_mutex); }
diskutil.h +7 -4
@@ -3,6 +3,8 @@#include "json.h" #define FIO_DU_NAME_SZ 64 +#include "lib/output_buffer.h" +extern volatile int helper_exit;struct disk_util_stats {
@@ -105,8 +107,8 @@ extern struct flist_head disk_list;* disk util stuff */ #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 print_disk_util (struct disk_util_stat *,struct disk_util_agg *,int terse,struct buf_output *); +extern void show_disk_util (int terse,struct json_object *parent,struct buf_output *);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 *);
@@ -115,10 +117,11 @@ extern void setup_disk_util(void);extern void disk_util_prune_entries (void );#else static inline void print_disk_util (struct disk_util_stat *du, -struct disk_util_agg *agg,int terse) +struct disk_util_agg *agg,int terse, +struct buf_output *out) { } -#define show_disk_util (terse, parent) +#define show_disk_util (terse, parent, out)#define disk_util_prune_entries ()#define init_disk_util (td)#define setup_disk_util ()
eta.c +2 -2
@@ -352,7 +352,7 @@ int calc_thread_status(struct jobs_eta *je, int force)static struct timeval rate_prev_time, disp_prev_time;if (!force) { -if (output_format !=FIO_OUTPUT_NORMAL && +if (!(output_format &FIO_OUTPUT_NORMAL ) && f_out == stdout)return 0 ;if (temp_stall_ts || eta_print ==FIO_ETA_NEVER )
@@ -590,7 +590,7 @@ struct jobs_eta *get_jobs_eta(int force, size_t *size)if (!thread_number)return NULL ; - *size =sizeof (*je) +THREAD_RUNSTR_SZ +1 ; + *size =sizeof (*je) +THREAD_RUNSTR_SZ +8 ; je =malloc (*size);if (!je)return NULL ;
filesetup.c +1 -1
@@ -936,7 +936,7 @@ int setup_files(struct thread_data *td)*/ if (need_extend) { temp_stall_ts =1 ; -if (output_format ==FIO_OUTPUT_NORMAL ) +if (output_format &FIO_OUTPUT_NORMAL )log_info ("%s: Laying out IO file(s) (%u file(s) /" " %lluMB)\n" , o->name, need_extend, extend_size >>20 );
fio.1 +2 -0
@@ -22,6 +22,7 @@ Write output to \fIfilename\fR. .TP .BI \-\-output-format \fR=\fPformat Set the reporting format to \fInormal\fR, \fIterse\fR, or \fIjson\fR. +Multiple formats can be selected, separate by a comma. .TP .BI \-\-runtime \fR=\fPruntime Limit run time to \fIruntime\fR seconds.
@@ -34,6 +35,7 @@ Print statistics in a terse, semicolon-delimited format. .TP .B \-\-append-terse Print statistics in selected mode AND terse, semicolon-delimited format. +Deprecated, use \-\-output-format instead to select multiple formats. .TP .B \-\-version Display version information and exit.
fio.h +8 -3
@@ -674,9 +674,14 @@ extern const char *fio_get_os_string(int);#endif enum { -FIO_OUTPUT_TERSE =0 , -FIO_OUTPUT_JSON , -FIO_OUTPUT_NORMAL , + __FIO_OUTPUT_TERSE =0 , + __FIO_OUTPUT_JSON =1 , + __FIO_OUTPUT_NORMAL =2 , +FIO_OUTPUT_NR =3 , + +FIO_OUTPUT_TERSE =1U << __FIO_OUTPUT_TERSE, +FIO_OUTPUT_JSON =1U << __FIO_OUTPUT_JSON, +FIO_OUTPUT_NORMAL =1U << __FIO_OUTPUT_NORMAL, };enum {
idletime.c +11 -10
@@ -428,7 +428,7 @@ int fio_idle_prof_parse_opt(const char *args)fio_idle_prof_init ();fio_idle_prof_start ();fio_idle_prof_stop (); -show_idle_prof_stats (FIO_OUTPUT_NORMAL ,NULL ); +show_idle_prof_stats (FIO_OUTPUT_NORMAL ,NULL ,NULL );return 1 ; }else if (strcmp ("system" , args) ==0 ) { ipc.opt =IDLE_PROF_OPT_SYSTEM ;
@@ -446,7 +446,8 @@ int fio_idle_prof_parse_opt(const char *args)#endif } -void show_idle_prof_stats (int output,struct json_object *parent) +void show_idle_prof_stats (int output,struct json_object *parent, +struct buf_output *out) {int i, nr_cpus = ipc.nr_cpus;struct json_object *tmp;
@@ -454,23 +455,23 @@ void show_idle_prof_stats(int output, struct json_object *parent)if (output ==FIO_OUTPUT_NORMAL ) {if (ipc.opt >IDLE_PROF_OPT_CALI ) -log_info ("\nCPU idleness:\n" ); +log_buf (out,"\nCPU idleness:\n" );else if (ipc.opt ==IDLE_PROF_OPT_CALI ) -log_info ("CPU idleness:\n" ); +log_buf (out,"CPU idleness:\n" );if (ipc.opt >=IDLE_PROF_OPT_SYSTEM ) -log_info (" system: %3.2f%%\n" ,fio_idle_prof_cpu_stat (-1 )); +log_buf (out," system: %3.2f%%\n" ,fio_idle_prof_cpu_stat (-1 ));if (ipc.opt ==IDLE_PROF_OPT_PERCPU ) { -log_info (" percpu: %3.2f%%" ,fio_idle_prof_cpu_stat (0 )); +log_buf (out," percpu: %3.2f%%" ,fio_idle_prof_cpu_stat (0 ));for (i =1 ; i < nr_cpus; i++) -log_info (", %3.2f%%" ,fio_idle_prof_cpu_stat (i)); -log_info ("\n" ); +log_buf (out,", %3.2f%%" ,fio_idle_prof_cpu_stat (i)); +log_buf (out,"\n" ); }if (ipc.opt >=IDLE_PROF_OPT_CALI ) { -log_info (" unit work: mean=%3.2fus," , ipc.cali_mean); -log_info (" stddev=%3.2f\n" , ipc.cali_stddev); +log_buf (out," unit work: mean=%3.2fus," , ipc.cali_mean); +log_buf (out," stddev=%3.2f\n" , ipc.cali_stddev); }/* dynamic mem allocations can now be freed */
idletime.h +2 -1
@@ -2,6 +2,7 @@#define FIO_IDLETIME_H #include "fio.h" +#include "lib/output_buffer.h" #define CALIBRATE_RUNS 10#define CALIBRATE_SCALE 1000
@@ -54,6 +55,6 @@ extern void fio_idle_prof_init(void);extern void fio_idle_prof_start (void );extern void fio_idle_prof_stop (void ); -extern void show_idle_prof_stats (int ,struct json_object *); +extern void show_idle_prof_stats (int ,struct json_object *,struct buf_output *);#endif
init.c +38 -12
82 lines not on this page · raw message
json.c +31 -31
108 lines not on this page · raw message
json.h +4 -1
@@ -1,5 +1,8 @@#ifndef __JSON__H#define __JSON__H + +#include "lib/output_buffer.h" +struct json_object ;struct json_array ;struct json_pair ;
@@ -76,5 +79,5 @@ int json_array_add_value_type(struct json_array *array, int type, ...);#define json_array_last_value_object (obj) \ (obj->values[obj->value_cnt - 1]->object) -void json_print_object (struct json_object *obj); +void json_print_object (struct json_object *obj,struct buf_output *out);#endif
lib/output_buffer.c new file +48 -0
48 lines not on this page · raw message
lib/output_buffer.h new file +17 -0
@@ -0,0 +1,17 @@ +#ifndef FIO_OUTPUT_BUFFER_H +#define FIO_OUTPUT_BUFFER_H + +#include <unistd.h> + +struct buf_output { +char *buf; +size_t buflen; +size_t max_buflen; +}; + +void buf_output_init (struct buf_output *out); +void buf_output_free (struct buf_output *out); +size_t buf_output_add (struct buf_output *out,const char *buf,size_t len); +size_t buf_output_flush (struct buf_output *out); + +#endif
log.c +30 -20
82 lines not on this page · raw message
log.h +16 -4
@@ -4,15 +4,27 @@#include <stdio.h> #include <stdarg.h> +#include "lib/output_buffer.h" +extern FILE *f_out;extern FILE *f_err; -extern int log_err (const char *format, ...) __attribute__ ((__format__ (__printf__,1 ,2 ))); -extern int log_info (const char *format, ...) __attribute__ ((__format__ (__printf__,1 ,2 ))); -extern int log_valist (const char *str,va_list ); -extern int log_local_buf (const char *buf,size_t ); +extern size_t log_err (const char *format, ...) __attribute__ ((__format__ (__printf__,1 ,2 ))); +extern size_t log_info (const char *format, ...) __attribute__ ((__format__ (__printf__,1 ,2 ))); +extern size_t __log_buf (struct buf_output *,const char *format, ...) __attribute__ ((__format__ (__printf__,2 ,3 ))); +extern size_t log_valist (const char *str,va_list ); +extern size_t log_local_buf (const char *buf,size_t ); +extern size_t log_info_buf (const char *buf,size_t len);extern int log_info_flush (void ); +#define log_buf(buf, format, args...) \ +do { \ + if ((buf) != NULL) \ + __log_buf(buf, format, ##args); \ + else \ + log_info(format, ##args); \ +} while (0) +enum {FIO_LOG_DEBUG =1 ,FIO_LOG_INFO =2 ,
parse.c +2 -2
@@ -52,7 +52,7 @@ static void posval_sort(struct fio_option *o, struct value_pair *vpmap) }static void show_option_range (struct fio_option *o, -int (*logger)(const char *format, ...)) +size_t (*logger)(const char *format, ...)) {if (o->type ==FIO_OPT_FLOAT_LIST ) {if (o->minfp ==DBL_MIN && o->maxfp ==DBL_MAX )
@@ -109,7 +109,7 @@ static void show_option_help(struct fio_option *o, int is_err)"no argument (opt)" , "deprecated", }; -int (*logger)(const char *format, ...); +size_t (*logger)(const char *format, ...);if (is_err) logger = log_err;
stat.c +148 -134
701 lines not on this page · raw message
stat.h +3 -2
@@ -2,6 +2,7 @@#define FIO_STAT_H #include "iolog.h" +#include "lib/output_buffer.h" struct group_run_stats {uint64_t max_run[DDIR_RWDIR_CNT ], min_run[DDIR_RWDIR_CNT ];
@@ -246,8 +247,8 @@ extern struct jobs_eta *get_jobs_eta(int 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); -extern void show_group_stats (struct group_run_stats *rs); +extern struct json_object *show_thread_status (struct thread_stat *ts,struct group_run_stats *rs,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);extern void show_run_stats (void );