Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.2
s390-tools
s390-tools-sles11-ziomon-fix-qdio-statistics.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File s390-tools-sles11-ziomon-fix-qdio-statistics.patch of Package s390-tools
Description: Fix qdio statistics. Symptom: qdio statistics show high usage even if only brief bursts of activity happen in an interval. Furthermore, the min value cannot be tracked in a meaningful way via the blktrace mechanism. Problem: Previous implementation's qdio usage was not accurate since only the fill level but not its duration was monitored. Plus the interpretation of the qdio fill level values as received via blktrace was wrong. Solution: Account both fill level and duration in-kernel, export it via sysfs and query it via ziomon_util. Hence this change requires a respective kernel patch that exports an accurate qdio utilization statistic via sysfs. Furthermore remove the full-fledged qdio statistics from the zfcpdd messages and report the maximum queue fill level only. Note that these changes require changes in the binary file format, which makes data files collected with previous versions incompatible. --- ziomon/ziomon_dacc.c | 6 ++-- ziomon/ziomon_dacc.h | 2 - ziomon/ziomon_util.c | 70 +++++++++++++++++++++++++++++++++++++++++-------- ziomon/ziomon_util.h | 8 ++++- ziomon/ziomon_zfcpdd.c | 25 +++++++++++------ ziomon/ziomon_zfcpdd.h | 2 - 6 files changed, 87 insertions(+), 26 deletions(-) --- a/ziomon/ziomon_dacc.c +++ b/ziomon/ziomon_dacc.c @@ -372,7 +372,7 @@ int add_msg(FILE *fp, struct message *ms int init_file(FILE *fp, struct file_header *f_hdr) { f_hdr->magic = DATA_MGR_MAGIC; - f_hdr->version = DATA_MGR_V1; + f_hdr->version = DATA_MGR_V2; f_hdr->first_msg_offset = 0; f_hdr->end_time = 0; @@ -396,7 +396,7 @@ int get_header(FILE *fp, struct file_hea fprintf(stderr, ZIOMON_DACC_NAME ": No valid header\n"); return -2; } - if (hdr->version != DATA_MGR_V1) { + if (hdr->version != DATA_MGR_V2) { fprintf(stderr, ZIOMON_DACC_NAME ": Wrong version\n"); return -2; } @@ -572,7 +572,7 @@ int write_aggr_file(FILE *fp, struct agg void init_aggr_data_struct(struct aggr_data *data) { data->magic = DATA_MGR_MAGIC_AGGR; - data->version = DATA_MGR_V1; + data->version = DATA_MGR_V2; data->num_zfcpdd = 0; data->num_blkiomon = 0; data->end_time = 0; --- a/ziomon/ziomon_dacc.h +++ b/ziomon/ziomon_dacc.h @@ -17,7 +17,7 @@ #define DATA_MGR_MAGIC 0x64616d67 #define DATA_MGR_MAGIC_AGGR 0x61676772 -#define DATA_MGR_V1 1u +#define DATA_MGR_V2 2u /** --- a/ziomon/ziomon_util.c +++ b/ziomon/ziomon_util.c @@ -98,6 +98,8 @@ static void swap_overall_result(struct o u_res = &a_res->result; swap_64(u_res->count); swap_32(u_res->queue_full); + swap_64(u_res->queue_util_integral); + swap_64(u_res->queue_util_interval); swap_stat_variance(&u_res->adapter); swap_stat_variance(&u_res->bus); swap_stat_variance(&u_res->cpu); @@ -152,6 +154,10 @@ void aggregate_utilization_data(struct o continue; tgt_a_res = get_result_no(tgt, src_a_res->adapter_no); tgt_a_res->result.queue_full += src_a_res->result.queue_full; + tgt_a_res->result.queue_util_integral += + src_a_res->result.queue_util_integral; + tgt_a_res->result.queue_util_interval += + src_a_res->result.queue_util_interval; tgt_a_res->result.count += src_a_res->result.count; aggregate_stat_variance(&src_a_res->result.adapter, &tgt_a_res->result.adapter); @@ -237,7 +243,12 @@ int verbose=0; struct util_data { int queue_full; /* # queue full instances in frame */ int queue_full_prev; /* previous absolut value - of queue_full */ + of queue_full */ + __u64 queue_util_integral; + __u64 queue_util_interval; + __u64 queue_util_prev; /* previous absolut value + of queue_util_integral */ + struct timeval queue_util_timestamp; struct stat_variance adapter; struct stat_variance bus; struct stat_variance cpu; @@ -466,7 +477,9 @@ static int poll_queue_full(int init, str struct adapter_data *adpt; struct util_data *u_data; int queue_full_tmp; + long long unsigned int queue_util_tmp; int i; + struct timeval tmp, cur_time; for (i = 0; i < all_adapters->num_adapters; ++i) { adpt = &all_adapters->adapters[i]; @@ -475,20 +488,38 @@ static int poll_queue_full(int init, str /* read queue_full attribute */ if (read_attribute(adpt->q_full_path, line, &adpt->status)) continue; - rc = sscanf(line, "%d", &queue_full_tmp); - if (rc != 1) { + rc = sscanf(line, "%d %Lu", &queue_full_tmp, &queue_util_tmp); + if (rc == 1) { + fprintf(stderr, ZIOMON_UTIL_NAME ": Only one value in" + " %s, your kernel level is probably too old.\n", + adpt->q_full_path); + return -1; + } + if (rc != 2) { fprintf(stderr, ZIOMON_UTIL_NAME ": Warning:" " Could not parse %s: %s\n", line, strerror(errno)); adpt->status = 6; continue; } + gettimeofday(&cur_time, NULL); if (!init) { - u_data->queue_full = queue_full_tmp - u_data->queue_full_prev; - verbose_msg("data read for adapter %d: queue_full=%d\n", - adpt->host_nr, u_data->queue_full); + u_data->queue_full = queue_full_tmp + - u_data->queue_full_prev; + u_data->queue_util_integral = queue_util_tmp + - u_data->queue_util_prev; + timersub(&cur_time, &u_data->queue_util_timestamp, + &tmp); + u_data->queue_util_interval = tmp.tv_sec * 1000000 + + tmp.tv_usec; + verbose_msg("data read for adapter %d: queue_full=%d," + " queue_util=%Lu\n", adpt->host_nr, + u_data->queue_full, (long long unsigned int) + u_data->queue_util_integral); } u_data->queue_full_prev = queue_full_tmp; + u_data->queue_util_prev = queue_util_tmp; + u_data->queue_util_timestamp = cur_time; } return 0; @@ -530,6 +561,15 @@ static int poll_ioerr_cnt(int init, stru } +static void reinit_adapters(struct adapters *adptrs) +{ + int i; + + for (i = 0; i < adptrs->num_adapters; ++i) + init_util_data(&adptrs->adapters[i].data); +} + + static int init_adapters(struct adapters *all_adapters, struct options *opts) { struct adapter_data *adapter; @@ -553,11 +593,8 @@ static int init_adapters(struct adapters } init_util_data(&all_adapters->adapters[i].data); } - if (poll_queue_full(1, all_adapters, opts)) { - fprintf(stderr, ZIOMON_UTIL_NAME ": Error: Could not read " - "initial values of queue_full attributes\n"); + if (poll_queue_full(1, all_adapters, opts)) return -1; - } return 0; } @@ -826,6 +863,10 @@ static void generate_result(struct overa if (a_res->valid) { u_res = &a_res->result; u_res->queue_full = u_data->queue_full; + u_res->queue_util_integral + = u_data->queue_util_integral; + u_res->queue_util_interval + = u_data->queue_util_interval; u_res->count = u_data->count; copy_stat_variance(&u_res->adapter, &u_data->adapter); copy_stat_variance(&u_res->bus, &u_data->bus); @@ -1092,6 +1133,13 @@ static int has_adapter_traffic(struct ov return 1; if (a_res->result.queue_full != 0) return 1; + /* this makes sure that we don't send messages when essentially + no data is processed - reading the 'utilization' attribute + causes always traffic, hence we would always send a message + without this threshold! */ + if (a_res->result.queue_util_integral + / (double)a_res->result.queue_util_interval >= 0.05) + return 1; if (has_non_null_stats(&a_res->result.adapter) || has_non_null_stats(&a_res->result.bus) || has_non_null_stats(&a_res->result.cpu)) @@ -1226,7 +1274,7 @@ int main(int argc, char **argv) duration_end.tv_sec += opts.duration; do { interval_end.tv_sec += opts.i_duration; - init_adapters(all_adapters, NULL); + reinit_adapters(all_adapters); do { sample_end.tv_sec += opts.s_duration; sleep_until(&sample_end); --- a/ziomon/ziomon_util.h +++ b/ziomon/ziomon_util.h @@ -18,11 +18,15 @@ struct util_result { __u64 count; - __u32 queue_full; /* number of queue_full - instances within the given timeframe */ struct stat_variance adapter; struct stat_variance bus; struct stat_variance cpu; + __u64 queue_util_integral; /* integral of the queue + utilization over microseconds */ + __u64 queue_util_interval; /* interval length + in microseconds */ + __u32 queue_full; /* number of queue_full + instances within the given timeframe */ } __attribute__ ((packed)); struct adapter_result { --- a/ziomon/ziomon_zfcpdd.c +++ b/ziomon/ziomon_zfcpdd.c @@ -21,6 +21,7 @@ #include <sys/stat.h> #include <sys/msg.h> #include <limits.h> +#include <stdint.h> #include "blktrace.h" #include "ziomon_zfcpdd.h" @@ -40,7 +41,7 @@ static void swap_dstat(struct zfcpdd_dst swap_stat_variance(&stat->chan_lat); swap_stat_variance(&stat->fabr_lat); swap_stat_variance(&stat->inb); - swap_stat_variance(&stat->outb); + swap_16(stat->outb_max); for (i=0; i<BLKIOMON_CHAN_LAT_BUCKETS; ++i) swap_32(stat->chan_lat_hist[i]); for (i=0; i<BLKIOMON_FABR_LAT_BUCKETS; ++i) @@ -70,10 +71,12 @@ void aggregate_dstat(struct zfcpdd_dstat aggregate_stat_variance(&src->chan_lat, &tgt->chan_lat); aggregate_stat_variance(&src->fabr_lat, &tgt->fabr_lat); aggregate_stat_variance(&src->inb, &tgt->inb); - aggregate_stat_variance(&src->outb, &tgt->outb); + if (src->outb_max > tgt->outb_max) + tgt->outb_max = src->outb_max; } -void zfcpdd_print_stats(struct zfcpdd_dstat *stat) { +void zfcpdd_print_stats(struct zfcpdd_dstat *stat) +{ int i; printf("timestamp : %s", ctime((time_t*)&stat->time)); @@ -91,8 +94,7 @@ void zfcpdd_print_stats(struct zfcpdd_ds printf(" %u", stat->fabr_lat_hist[i]); printf("\n\tinbound latency:\n"); print_stat_variance(&stat->inb, stat->count); - printf("\toutbound latency:\n"); - print_stat_variance(&stat->outb, stat->count); + printf("\toutbound q max : %hu\n", stat->outb_max); } #ifdef WITH_MAIN @@ -171,7 +173,6 @@ static struct dstat *zfcpdd_dstat_alloc( init_stat_variance(&dstat->msg.stat.chan_lat); init_stat_variance(&dstat->msg.stat.fabr_lat); init_stat_variance(&dstat->msg.stat.inb); - init_stat_variance(&dstat->msg.stat.outb); return dstat; } @@ -218,6 +219,14 @@ static void zfcpdd_account_hist_log2(__u bucket[index]++; } +static void zfcpdd_account_outb(struct zfcpdd_dstat *stat, + struct zfcp_blk_drv_data *dd) +{ + dd->outb_usage = 128 - dd->outb_usage; + if (dd->outb_usage > stat->outb_max) + stat->outb_max = dd->outb_usage; +} + static int zfcpdd_account(struct blk_io_trace *bit, struct zfcp_blk_drv_data *dd) { @@ -245,7 +254,7 @@ static int zfcpdd_account(struct blk_io_ update_stat_variance(&stat->chan_lat, dd->chan_lat); update_stat_variance(&stat->fabr_lat, dd->fabr_lat / 1000); update_stat_variance(&stat->inb, dd->inb_usage); - update_stat_variance(&stat->outb, dd->outb_usage); + zfcpdd_account_outb(stat, dd); zfcpdd_account_hist_log2(stat->chan_lat_hist, dd->chan_lat, &clat); zfcpdd_account_hist_log2(stat->fabr_lat_hist, dd->fabr_lat / 1000, @@ -325,7 +334,7 @@ static int zfcpdd_output_ascii(struct ds fprintf(fp, "device: %d\t", p->device); fprintf(fp, "interval end: %ld\n", (unsigned long)p->time); - print_var(fp, "outbound", &p->outb); + fprintf(fp, "outbound q max: %hu", p->outb_max); print_var(fp, "inbound", &p->inb); print_var(fp, "channel latency", &p->chan_lat); print_var(fp, "fabric latency", &p->fabr_lat); --- a/ziomon/ziomon_zfcpdd.h +++ b/ziomon/ziomon_zfcpdd.h @@ -23,9 +23,9 @@ struct zfcpdd_dstat { struct stat_variance chan_lat; struct stat_variance fabr_lat; struct stat_variance inb; - struct stat_variance outb; __u64 count; __u32 device; /* device identifier */ + __u16 outb_max; } __attribute__ ((packed)); struct hist_log2 {
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor