mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
During evaluation of the collected ziomon data from the system with following
multipath configuration:
$ multipath -ll
3600507630bffc3200000000000005294 dm-0 IBM,2107900
size=20G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
`-+- policy='service-time 0' prio=50 status=active
|- 1:0:0:1083457618 sdd 8:48 active ready running
`- 0:0:0:1083457618 sda 8:0 active ready running
3600507630bffc3200000000000005394 dm-1 IBM,2107900
size=20G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
`-+- policy='service-time 0' prio=50 status=active
|- 1:0:0:1083457619 sdf 8:80 active ready running
`- 0:0:0:1083457619 sdb 8:16 active ready running
3600507630bffc3200000000000005494 dm-2 IBM,2107900
size=20G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
`-+- policy='service-time 0' prio=50 status=active
|- 1:0:0:1083457620 sdg 8:96 active ready running
`- 0:0:0:1083457620 sdc 8:32 active ready running
3600507630bffc3200000000000005594 dm-3 IBM,2107900
size=20G features='1 queue_if_no_path' hwhandler='1 alua' wp=rw
`-+- policy='service-time 0' prio=50 status=active
|- 1:0:0:1083457621 sdh 8:112 active ready running
`- 0:0:0:1083457621 sde 8:64 active ready running
there were low throughput values for adapter noticed in ziorep_utilization
virtual adapter report:
$ ziorep_utilization adp_line_speed.log
...
CHP Bus-ID |qdio util.%|queu|fail|-thp in MB/s-|I/O reqs-|
ID max avg full erc rd wrt rd wrt
2021-08-18 12:56:44
61/0.0.1946 32.8 3.1 0 0 0.0 84.5 21 204K
12:57:04
...
there were also low values for throughput of devices noticed in
ziorep_traffic report. And were no aggregation of throughput for
different aggregation parameters provided:
$ ziorep_traffic adp_line_speed.log -i 0
WWPN LUN |I/O rt MB/s|thrp in MB/s-|...
min max avg stdev ...
2021-08-18 12:58:24
0x500507630b09c320:0x4052409400000000 0.0 219.2 85.7 3.352K ...
0x500507630b09c320:0x4053409400000000 0.0 348.6 84.6 3.330K ...
0x500507630b09c320:0x4054409400000000 0.0 268.6 84.0 3.317K ...
0x500507630b09c320:0x4055409400000000 0.0 354.2 83.7 3.312K ...
$ ziorep_traffic adp_line_speed.log -i 0 -Cu
Bus-ID |I/O rt MB/s|thrp in MB/s-|...
min max avg stdev ...
2021-08-18 12:58:24
0.0.1946 0.0 354.2 84.5 3.328K ...
although, iostat tool showed decent throughput values for each scsi disk, which
belongs to investigated zfcp adapter. In this example each scsi disk has
throughput more than 300MB/s, which is much larger, than 84.5MB/s
throughput for the adapter:
$ iostat -x 1
...
Device r/s w/s rkB/s wkB/s ...
dasda 0.00 0.00 0.00 0.00 ...
dasdb 0.00 0.00 0.00 0.00 ...
sda 0.00 2556.00 0.00 327168.00 ...
sdc 0.00 2554.00 0.00 326912.00 ...
sdb 0.00 2559.00 0.00 327552.00 ...
sdf 0.00 2865.00 0.00 366720.00 ...
sdd 0.00 2843.00 0.00 363904.00 ...
sdg 0.00 2845.00 0.00 364160.00 ...
sde 0.00 2471.00 0.00 315416.00 ...
sdh 0.00 2768.00 0.00 353768.00 ...
dm-0 0.00 5399.00 0.00 691072.00 ...
dm-1 0.00 5424.00 0.00 694272.00 ...
dm-2 0.00 5400.00 0.00 691200.00 ...
dm-3 0.00 5240.00 0.00 669312.00 ...
Use Frameset interval size for calculation of throughput of zfcp adapter
instead of d2c (dispatch to complete) time of request, which is used for I/O
rate calculation. Also use Frameset interval instead of total_latency.sum
(which in fact is a sum of d2c times for each repuest in specifed interval).
Use calc_avg() function for throughput calculation.
With fix applied, virtual adapter report now contains correct value for adpater
throughput for specified interval:
$ ziorep_utilization adp_line_speed.log
...
CHP Bus-ID |qdio util.%|queu|fail|-thp in MB/s-|I/O reqs-|
ID max avg full erc rd wrt rd wrt
2021-08-18 12:56:44
61/0.0.1946 32.8 3.1 0 0 0.0 1.336K 21 204K
...
With fix applied, traffic report now contains correct values of
throughput for each device and aggregation now works correctly:
$ ziorep_traffic adp_line_speed.log -i 0
WWPN LUN |I/O rt MB/s|thrp in MB/s-|...
min max avg stdev ...
2021-08-18 12:58:24
0x500507630b09c320:0x4052409400000000 0.0 219.2 339.6 3.352K ...
0x500507630b09c320:0x4053409400000000 0.0 348.6 335.4 3.330K ...
0x500507630b09c320:0x4054409400000000 0.0 268.6 333.1 3.317K ...
0x500507630b09c320:0x4055409400000000 0.0 354.2 331.9 3.312K ...
$ ziorep_traffic adp_line_speed.log -i 0 -Cu
Bus-ID |I/O rt MB/s|thrp in MB/s-|...
min max avg stdev ...
2021-08-18 12:58:24
0.0.1946 0.0 354.2 1.340K 3.328K ...
Signed-off-by: Fedor Loshakov <loshakov@linux.ibm.com>
Reviewed-by: Benjamin Block <bblock@linux.ibm.com>
Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
228 lines
6.9 KiB
C++
228 lines
6.9 KiB
C++
/*
|
|
* FCP report generators
|
|
*
|
|
* Utility classes to print framsets
|
|
*
|
|
* Copyright IBM Corp. 2008, 2021
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
*/
|
|
|
|
#ifndef ZIOREP_PRINTERS
|
|
#define ZIOREP_PRINTERS
|
|
|
|
#include "ziorep_frameset.hpp"
|
|
#include "ziorep_framer.hpp"
|
|
#include "ziorep_cfgreader.hpp"
|
|
|
|
|
|
/**
|
|
* Base class for all printer classes
|
|
*/
|
|
class Printer {
|
|
public:
|
|
Printer(const ConfigReader *cfg, bool csv_mode);
|
|
virtual ~Printer() {};
|
|
|
|
/**
|
|
* Print topline to fp.
|
|
* Returns number of characters printed or <0 in case of error */
|
|
virtual void print_topline(FILE *fp) = 0;
|
|
|
|
/**
|
|
* Print frameset to fp.
|
|
* Returns number of characters printed or <0 in case of error */
|
|
virtual int print_frame(FILE *fp, const Frameset &frameset,
|
|
const DeviceFilter &dev_filt) = 0;
|
|
|
|
/// Whether the output should be done in CSV format or not
|
|
bool print_csv() const;
|
|
|
|
protected:
|
|
/**
|
|
* Print timestamp before the actual frame is printed.
|
|
* Returns number of characters printed or <0 in case of error */
|
|
void print_timestamp(FILE *fp, const Frameset &frameset);
|
|
|
|
const ConfigReader *m_cfg;
|
|
/**
|
|
* Print a given number 'num' in 'num_digs' characters with
|
|
* as many decimal places as possible.
|
|
* NOTE: max_digits must be 4 or 5!
|
|
* E.g. print_abbrev_num(13400, 5) returns '13.4K'.
|
|
*/
|
|
void print_abbrev_num(FILE *fp, __u64 num, int max_digs) const;
|
|
void print_abbrev_num(FILE *fp, __u32 num, int max_digs) const;
|
|
|
|
/**
|
|
* Print floats always using 6 characters */
|
|
void print_abbrev_num(FILE *fp, double num) const;
|
|
void print_abbrev_num(FILE *fp, double num, int max_digs,
|
|
bool more_places = false) const;
|
|
|
|
const struct adapter_utilization* get_empty_utilization(__u32 host_id);
|
|
const struct adapter_utilization* get_invalid_utilization(__u32 host_id);
|
|
const struct ioerr_cnt* get_empty_ioerr(struct hctl_ident *identifier);
|
|
const struct zfcpdd_dstat* get_empty_zfcpdd_dstat(__u32 device = 0);
|
|
const struct blkiomon_stat* get_empty_blkiomon_stat(__u32 device = 0);
|
|
|
|
/** Print the delimiter appropriate for the output. That's usually
|
|
* a space for regular output and ',' for CSV. */
|
|
inline void print_delimiter(FILE *fp);
|
|
|
|
/// Print a character indicating that the respective value is not valid
|
|
inline void print_invalid(FILE *fp, int width);
|
|
|
|
/// set if result should be printed is csv
|
|
bool m_csv;
|
|
char m_delim;
|
|
|
|
private:
|
|
void print_abbreviated(FILE *fp, double num, int leading_places,
|
|
int max_digs) const;
|
|
void determine_mag_factor(int leading_places, char *magnitude,
|
|
double *factor) const;
|
|
void determine_digs(int leading_places, int max_digs,
|
|
int *num_full_digs, int *num_places) const;
|
|
|
|
struct adapter_utilization m_util;
|
|
struct adapter_utilization m_util_invalid;
|
|
struct ioerr_cnt m_ioerr;
|
|
struct zfcpdd_dstat m_dstat;
|
|
struct blkiomon_stat m_stat;
|
|
|
|
/// day of month of last day that was printed
|
|
int m_prev_day;
|
|
};
|
|
|
|
|
|
class PhysAdapterPrinter : public Printer {
|
|
public:
|
|
PhysAdapterPrinter(const ConfigReader *cfg, bool csv_mode);
|
|
|
|
virtual void print_topline(FILE *fp);
|
|
virtual int print_frame(FILE *fp, const Frameset &frameset,
|
|
const DeviceFilter &dev_filt);
|
|
|
|
private:
|
|
void print_phys_adpt(FILE *fp, __u32 host_id,
|
|
int *rc);
|
|
void print_utilization(FILE *fp, const struct abbrev_stat *stat,
|
|
__u64 count, bool valid);
|
|
|
|
};
|
|
|
|
|
|
class VirtAdapterPrinter : public Printer {
|
|
public:
|
|
VirtAdapterPrinter(const ConfigReader *cfg, bool csv_mode);
|
|
|
|
virtual void print_topline(FILE *fp);
|
|
virtual int print_frame(FILE *fp, const Frameset &frameset,
|
|
const DeviceFilter &dev_filt);
|
|
|
|
private:
|
|
void print_virt_adpt(FILE *fp, __u32 subchnl, int *rc);
|
|
void print_queue_fill(FILE *fp, const struct zfcpdd_dstat *stat,
|
|
const struct adapter_utilization *res);
|
|
void print_queue_full(FILE *fp, const struct adapter_utilization *res);
|
|
void print_failures(FILE *fp, const struct ioerr_cnt *cnt);
|
|
void print_throughput(FILE *fp, const struct blkiomon_stat *stat,
|
|
const __u64 interval);
|
|
void print_num_requests(FILE *fp, const struct blkiomon_stat *stat);
|
|
};
|
|
|
|
|
|
class TrafficPrinter : public Printer {
|
|
public:
|
|
virtual int print_frame(FILE *fp, const Frameset &frameset,
|
|
const DeviceFilter &dev_filt);
|
|
|
|
protected:
|
|
TrafficPrinter(const ConfigReader *cfg, Collapser &col,
|
|
bool csv_mode);
|
|
virtual ~TrafficPrinter();
|
|
|
|
/**
|
|
* Print the actual row, excluding the first column */
|
|
virtual void print_data_row(FILE *fp,
|
|
const struct blkiomon_stat *blk_stat,
|
|
const struct zfcpdd_dstat *zfcp_stat,
|
|
const __u64 interval) = 0;
|
|
|
|
void print_topline_prefix1(FILE *fp);
|
|
void print_topline_prefix2(FILE *fp);
|
|
void print_topline_whitespace(FILE *fp);
|
|
|
|
void get_device_list(list<__u64> &lst, const DeviceFilter &dev_filt);
|
|
|
|
void get_device_list(list<__u32> &lst, const DeviceFilter &dev_filt);
|
|
void print_device_wwpn(FILE *fp, __u64 wwpn);
|
|
void print_device_chpid(FILE *fp, __u32 chpid);
|
|
void print_device_devno(FILE *fp, __u32 devno);
|
|
void print_device_mp_mm(FILE *fp, __u32 mp_mm,
|
|
const ConfigReader &cfg,
|
|
int *rc);
|
|
void print_device(FILE *fp, __u32 dev,
|
|
const ConfigReader &cfg,
|
|
int *rc);
|
|
void print_device_all(FILE *fp);
|
|
|
|
Aggregator m_agg_crit;
|
|
/// Multipath devices have variable length
|
|
char *m_mp_whitespace;
|
|
char *m_mp_topline_pref1;
|
|
char *m_mp_topline_pref2;
|
|
};
|
|
|
|
|
|
class SummaryTrafficPrinter : public TrafficPrinter {
|
|
public:
|
|
SummaryTrafficPrinter(const ConfigReader *cfg,
|
|
Collapser &col, bool csv_mode);
|
|
|
|
virtual void print_topline(FILE *fp);
|
|
|
|
private:
|
|
virtual void print_data_row(FILE *fp,
|
|
const struct blkiomon_stat *blk_stat,
|
|
const struct zfcpdd_dstat *zfcp_stat,
|
|
const __u64 interval);
|
|
void print_throughput(FILE *fp, const struct blkiomon_stat *stat,
|
|
const __u64 interval);
|
|
void print_request_stats(FILE *fp, const struct blkiomon_stat *stat);
|
|
void print_io_subsystem_latency(FILE *fp, const struct blkiomon_stat *stat);
|
|
void print_channel_latency(FILE *fp, const struct zfcpdd_dstat *stat);
|
|
void print_fabric_latency(FILE *fp, const struct zfcpdd_dstat *stat);
|
|
void print_latency(FILE *fp, const struct minmax *data);
|
|
void print_latency(FILE *fp, const struct abbrev_stat *data,
|
|
__u64 count);
|
|
};
|
|
|
|
|
|
class DetailedTrafficPrinter : public TrafficPrinter {
|
|
public:
|
|
DetailedTrafficPrinter(const ConfigReader *cfg, Collapser &col,
|
|
bool csv_mode);
|
|
|
|
virtual void print_topline(FILE *fp);
|
|
|
|
private:
|
|
virtual void print_data_row(FILE *fp,
|
|
const struct blkiomon_stat *blk_stat,
|
|
const struct zfcpdd_dstat *zfcp_stat,
|
|
const __u64 interval);
|
|
void print_histogram_io_reqs(FILE *fp,
|
|
const struct blkiomon_stat *stat);
|
|
void print_histogram_io_subs_lat(FILE *fp,
|
|
const struct blkiomon_stat *stat);
|
|
void print_histogram_channel_lat(FILE *fp,
|
|
const struct zfcpdd_dstat *stat);
|
|
void print_histogram_fabric_lat(FILE *fp,
|
|
const struct zfcpdd_dstat *stat);
|
|
};
|
|
|
|
#endif
|
|
|