X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=stat.c;h=d2720a4b1a177de4d8f70480ff50cfec41db01c3;hp=e5ec22374b8c2d410fdfa1e841ba93c0ad8ecd08;hb=e6989e10964f5ae30e0ba8f0cd27a663baf5617b;hpb=210dd0fc66b8956065e098bb9314febe8993e849 diff --git a/stat.c b/stat.c index e5ec2237..d2720a4b 100644 --- a/stat.c +++ b/stat.c @@ -1086,8 +1086,34 @@ static void show_thread_status_terse_v3_v4(struct thread_stat *ts, log_buf(out, "\n"); } +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; + struct print_option *p; + + if (flist_empty(opt_list)) + return; + + dir_object = json_create_object(); + json_object_add_value_object(root, name, dir_object); + + flist_for_each(entry, opt_list) { + const char *pos = ""; + + p = flist_entry(entry, struct print_option, list); + if (!num_jobs && !strcmp(p->name, "numjobs")) + continue; + if (p->value) + pos = p->value; + json_object_add_value_string(dir_object, p->name, pos); + } +} + static struct json_object *show_thread_status_json(struct thread_stat *ts, - struct group_run_stats *rs) + struct group_run_stats *rs, + struct flist_head *opt_list) { struct json_object *root, *tmp; struct jobs_eta *je; @@ -1104,12 +1130,15 @@ static struct json_object *show_thread_status_json(struct thread_stat *ts, json_object_add_value_int(root, "error", ts->error); /* ETA Info */ - je = get_jobs_eta(1, &size); + je = get_jobs_eta(true, &size); if (je) { json_object_add_value_int(root, "eta", je->eta_sec); json_object_add_value_int(root, "elapsed", je->elapsed_sec); } + if (opt_list) + json_add_job_opts(root, "job options", opt_list, true); + add_ddir_status_json(ts, rs, DDIR_READ, root); add_ddir_status_json(ts, rs, DDIR_WRITE, root); add_ddir_status_json(ts, rs, DDIR_TRIM, root); @@ -1239,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; @@ -1246,14 +1276,14 @@ 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); + ret = show_thread_status_json(ts, rs, opt_list); if (output_format & FIO_OUTPUT_NORMAL) show_thread_status_normal(ts, rs, out); return ret; } -static void sum_stat(struct io_stat *dst, struct io_stat *src, int nr) +static void sum_stat(struct io_stat *dst, struct io_stat *src, bool first) { double mean, S; @@ -1268,7 +1298,7 @@ static void sum_stat(struct io_stat *dst, struct io_stat *src, int nr) * */ - if (nr == 1) { + if (first) { mean = src->mean.u.f; S = src->S.u.f; } else { @@ -1312,31 +1342,38 @@ void sum_group_stats(struct group_run_stats *dst, struct group_run_stats *src) dst->unit_base = src->unit_base; } -void sum_thread_stats(struct thread_stat *dst, struct thread_stat *src, int nr) +void sum_thread_stats(struct thread_stat *dst, struct thread_stat *src, + bool first) { int l, k; for (l = 0; l < DDIR_RWDIR_CNT; l++) { if (!dst->unified_rw_rep) { - sum_stat(&dst->clat_stat[l], &src->clat_stat[l], nr); - sum_stat(&dst->slat_stat[l], &src->slat_stat[l], nr); - sum_stat(&dst->lat_stat[l], &src->lat_stat[l], nr); - sum_stat(&dst->bw_stat[l], &src->bw_stat[l], nr); + sum_stat(&dst->clat_stat[l], &src->clat_stat[l], first); + sum_stat(&dst->slat_stat[l], &src->slat_stat[l], first); + sum_stat(&dst->lat_stat[l], &src->lat_stat[l], first); + sum_stat(&dst->bw_stat[l], &src->bw_stat[l], first); dst->io_bytes[l] += src->io_bytes[l]; if (dst->runtime[l] < src->runtime[l]) dst->runtime[l] = src->runtime[l]; } else { - sum_stat(&dst->clat_stat[0], &src->clat_stat[l], nr); - sum_stat(&dst->slat_stat[0], &src->slat_stat[l], nr); - sum_stat(&dst->lat_stat[0], &src->lat_stat[l], nr); - sum_stat(&dst->bw_stat[0], &src->bw_stat[l], nr); + sum_stat(&dst->clat_stat[0], &src->clat_stat[l], first); + sum_stat(&dst->slat_stat[0], &src->slat_stat[l], first); + sum_stat(&dst->lat_stat[0], &src->lat_stat[l], first); + sum_stat(&dst->bw_stat[0], &src->bw_stat[l], first); dst->io_bytes[0] += src->io_bytes[l]; if (dst->runtime[0] < src->runtime[l]) dst->runtime[0] = src->runtime[l]; + + /* + * We're summing to the same destination, so override + * 'first' after the first iteration of the loop + */ + first = false; } } @@ -1420,6 +1457,7 @@ void __show_run_stats(void) struct json_object *root = NULL; struct json_array *array = NULL; struct buf_output output[FIO_OUTPUT_NR]; + struct flist_head **opt_lists; runstats = malloc(sizeof(struct group_run_stats) * (groupid + 1)); @@ -1445,9 +1483,12 @@ void __show_run_stats(void) } threadstats = malloc(nr_ts * sizeof(struct thread_stat)); + opt_lists = malloc(nr_ts * sizeof(struct flist_head *)); - for (i = 0; i < nr_ts; i++) + for (i = 0; i < nr_ts; i++) { init_thread_stat(&threadstats[i]); + opt_lists[i] = NULL; + } j = 0; last_ts = -1; @@ -1466,6 +1507,7 @@ void __show_run_stats(void) ts->clat_percentiles = td->o.clat_percentiles; ts->percentile_precision = td->o.percentile_precision; memcpy(ts->percentile_list, td->o.percentile_list, sizeof(td->o.percentile_list)); + opt_lists[j] = &td->opt_list; idx++; ts->members++; @@ -1531,7 +1573,7 @@ void __show_run_stats(void) for (k = 0; k < ts->nr_block_infos; k++) ts->block_infos[k] = td->ts.block_infos[k]; - sum_thread_stats(ts, &td->ts, idx); + sum_thread_stats(ts, &td->ts, idx == 1); } for (i = 0; i < nr_ts; i++) { @@ -1589,6 +1631,7 @@ void __show_run_stats(void) if (output_format & FIO_OUTPUT_NORMAL) log_buf(&output[__FIO_OUTPUT_NORMAL], "\n"); if (output_format & FIO_OUTPUT_JSON) { + struct thread_data *global; char time_buf[32]; time_t time_p; @@ -1601,21 +1644,27 @@ void __show_run_stats(void) 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); + global = get_global_options(); + json_add_job_opts(root, "global options", &global->opt_list, false); array = json_create_array(); 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) { - struct json_object *tmp = show_thread_status_json(ts, rs); + struct json_object *tmp = show_thread_status_json(ts, rs, opt_lists[i]); json_array_add_value_object(array, tmp); } if (output_format & FIO_OUTPUT_NORMAL) @@ -1658,6 +1707,7 @@ void __show_run_stats(void) log_info_flush(); free(runstats); free(threadstats); + free(opt_lists); } void show_run_stats(void) @@ -1680,19 +1730,19 @@ void __show_running_run_stats(void) fio_gettime(&tv, NULL); for_each_td(td, i) { - rt[i] = mtime_since(&td->start, &tv); - if (td_read(td) && td->io_bytes[DDIR_READ]) - td->ts.runtime[DDIR_READ] += rt[i]; - if (td_write(td) && td->io_bytes[DDIR_WRITE]) - td->ts.runtime[DDIR_WRITE] += rt[i]; - if (td_trim(td) && td->io_bytes[DDIR_TRIM]) - td->ts.runtime[DDIR_TRIM] += rt[i]; - td->update_rusage = 1; td->ts.io_bytes[DDIR_READ] = td->io_bytes[DDIR_READ]; td->ts.io_bytes[DDIR_WRITE] = td->io_bytes[DDIR_WRITE]; td->ts.io_bytes[DDIR_TRIM] = td->io_bytes[DDIR_TRIM]; td->ts.total_run_time = mtime_since(&td->epoch, &tv); + + rt[i] = mtime_since(&td->start, &tv); + if (td_read(td) && td->ts.io_bytes[DDIR_READ]) + td->ts.runtime[DDIR_READ] += rt[i]; + if (td_write(td) && td->ts.io_bytes[DDIR_WRITE]) + td->ts.runtime[DDIR_WRITE] += rt[i]; + if (td_trim(td) && td->ts.io_bytes[DDIR_TRIM]) + td->ts.runtime[DDIR_TRIM] += rt[i]; } for_each_td(td, i) { @@ -1708,11 +1758,11 @@ void __show_running_run_stats(void) __show_run_stats(); for_each_td(td, i) { - if (td_read(td) && td->io_bytes[DDIR_READ]) + if (td_read(td) && td->ts.io_bytes[DDIR_READ]) td->ts.runtime[DDIR_READ] -= rt[i]; - if (td_write(td) && td->io_bytes[DDIR_WRITE]) + if (td_write(td) && td->ts.io_bytes[DDIR_WRITE]) td->ts.runtime[DDIR_WRITE] -= rt[i]; - if (td_trim(td) && td->io_bytes[DDIR_TRIM]) + if (td_trim(td) && td->ts.io_bytes[DDIR_TRIM]) td->ts.runtime[DDIR_TRIM] -= rt[i]; } @@ -1892,35 +1942,35 @@ void reset_io_stats(struct thread_data *td) } } -static void _add_stat_to_log(struct io_log *iolog, unsigned long elapsed) +static void __add_stat_to_log(struct io_log *iolog, enum fio_ddir ddir, + unsigned long elapsed, bool log_max) { /* * Note an entry in the log. Use the mean from the logged samples, * making sure to properly round up. Only write a log entry if we * had actual samples done. */ - if (iolog->avg_window[DDIR_READ].samples) { - unsigned long mr; + if (iolog->avg_window[ddir].samples) { + unsigned long val; - mr = iolog->avg_window[DDIR_READ].mean.u.f + 0.50; - __add_log_sample(iolog, mr, DDIR_READ, 0, elapsed, 0); - } - if (iolog->avg_window[DDIR_WRITE].samples) { - unsigned long mw; + if (log_max) + val = iolog->avg_window[ddir].max_val; + else + val = iolog->avg_window[ddir].mean.u.f + 0.50; - mw = iolog->avg_window[DDIR_WRITE].mean.u.f + 0.50; - __add_log_sample(iolog, mw, DDIR_WRITE, 0, elapsed, 0); + __add_log_sample(iolog, val, ddir, 0, elapsed, 0); } - if (iolog->avg_window[DDIR_TRIM].samples) { - unsigned long mw; - mw = iolog->avg_window[DDIR_TRIM].mean.u.f + 0.50; - __add_log_sample(iolog, mw, DDIR_TRIM, 0, elapsed, 0); - } + reset_io_stat(&iolog->avg_window[ddir]); +} + +static void _add_stat_to_log(struct io_log *iolog, unsigned long elapsed, + bool log_max) +{ + int ddir; - reset_io_stat(&iolog->avg_window[DDIR_READ]); - reset_io_stat(&iolog->avg_window[DDIR_WRITE]); - reset_io_stat(&iolog->avg_window[DDIR_TRIM]); + for (ddir = 0; ddir < DDIR_RWDIR_CNT; ddir++) + __add_stat_to_log(iolog, ddir, elapsed, log_max); } static void add_log_sample(struct thread_data *td, struct io_log *iolog, @@ -1956,7 +2006,7 @@ static void add_log_sample(struct thread_data *td, struct io_log *iolog, if (this_window < iolog->avg_msec) return; - _add_stat_to_log(iolog, elapsed); + _add_stat_to_log(iolog, elapsed, td->o.log_max != 0); iolog->avg_last = elapsed; } @@ -1968,15 +2018,15 @@ void finalize_logs(struct thread_data *td) elapsed = mtime_since_now(&td->epoch); if (td->clat_log) - _add_stat_to_log(td->clat_log, elapsed); + _add_stat_to_log(td->clat_log, elapsed, td->o.log_max != 0); if (td->slat_log) - _add_stat_to_log(td->slat_log, elapsed); + _add_stat_to_log(td->slat_log, elapsed, td->o.log_max != 0); if (td->lat_log) - _add_stat_to_log(td->lat_log, elapsed); + _add_stat_to_log(td->lat_log, elapsed, td->o.log_max != 0); if (td->bw_log) - _add_stat_to_log(td->bw_log, elapsed); + _add_stat_to_log(td->bw_log, elapsed, td->o.log_max != 0); if (td->iops_log) - _add_stat_to_log(td->iops_log, elapsed); + _add_stat_to_log(td->iops_log, elapsed, td->o.log_max != 0); } void add_agg_sample(unsigned long val, enum fio_ddir ddir, unsigned int bs)