diff options
Diffstat (limited to 'debug/iprtest.c')
-rw-r--r-- | debug/iprtest.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/debug/iprtest.c b/debug/iprtest.c new file mode 100644 index 0000000..ed8c7b3 --- /dev/null +++ b/debug/iprtest.c @@ -0,0 +1,184 @@ +/** + * IBM IPR adapter performance utility + * + * (C) Copyright 2005 + * International Business Machines Corporation and others. + * All Rights Reserved. This program and the accompanying + * materials are made available under the terms of the + * Common Public License v1.0 which accompanies this distribution. + * + */ + +/* + * $Header: /cvsroot/iprdd/iprutils/debug/iprtest.c,v 1.1 2005/09/26 20:19:36 brking Exp $ + */ + +#include <unistd.h> +#include <sys/ioctl.h> +#include <scsi/sg.h> +#include <scsi/scsi.h> +#include <sys/stat.h> + +#ifndef iprlib_h +#include "iprlib.h" +#endif + +#include <sys/mman.h> + +char *tool_name = "iprperf"; + +struct log_sense { + u8 page_code; + u8 reserved; + u16 len; + u8 reserved2[3]; + u8 parm_len; + u16 num_seeks_0; + u16 num_seeks_gt_2_3; + u16 num_seeks_gt_1_3; + u16 num_seeks_gt_1_6; + u16 num_seeks_gt_1_12; + u16 num_seeks_gt_0; + u8 reserved3[4]; + u16 num_dev_read_buf_overruns; + u16 num_dev_write_buf_overruns; + u32 num_dev_cache_read_hits; + u32 num_dev_cache_partial_read_hits; + u32 num_dev_cache_write_hits; + u32 num_dev_cache_fast_writes; + u32 reserved4[2]; + u32 num_device_read_ops; + u32 num_device_write_ops; + u32 num_ioa_cache_read_hits; + u32 num_ioa_cache_partial_read_hits; + u32 num_ioa_cache_write_hits; + u32 num_ioa_cache_fast_writes; + u32 num_ioa_emul_read_cache_hits; + u32 ioa_idle_loop_count[2]; + u32 ioa_idle_loop_count_value; + u8 ioa_idle_count_value_units; + u8 reserved5[3]; +}; + +static int get_counters(struct ipr_dev *dev, struct log_sense *log) +{ + int fd; + u8 cdb[IPR_CCB_CDB_LEN]; + struct sense_data_t sense_data; + int rc; + + if (strlen(dev->gen_name) == 0) + return -ENOENT; + + fd = open(dev->gen_name, O_RDWR); + if (fd <= 1) { + syslog(LOG_ERR, "Could not open %s. %m\n", dev->gen_name); + return errno; + } + + memset(cdb, 0, IPR_CCB_CDB_LEN); + memset(log, 0, sizeof(*log)); + + cdb[0] = LOG_SENSE; + cdb[2] = 0x70; + cdb[7] = sizeof(*log) >> 8; + cdb[8] = sizeof(*log) & 0xff; + + rc = sg_ioctl(fd, cdb, log, + sizeof(*log), SG_DXFER_FROM_DEV, + &sense_data, IPR_ARRAY_CMD_TIMEOUT); + + if (rc != 0) + scsi_cmd_err(dev, &sense_data, "Log Sense", rc); + + close(fd); + return rc; +} + +#define logd(item, desc, xlate) \ +if (old_log->item != new_log->item) \ + printf("%s: %d\n", desc, xlate(new_log->item) - xlate(old_log->item)); \ + +#define logs(desc, item) logd(item, desc, ntohs) +#define logl(desc, item) logd(item, desc, ntohl) + +static void print_counters(struct ipr_dev *dev, struct log_sense *old_log, struct log_sense *new_log) +{ + printf("===============================================\n"); + scsi_info(dev, "Device counters\n"); + logs("Number of seeks = zero length ", num_seeks_0); + logs("Number of seeks >= 2/3 disk ", num_seeks_gt_2_3); + logs("Number of seeks >= 1/3 and < 2/3 disk ", num_seeks_gt_1_3); + logs("Number of seeks >= 1/6 and < 1/3 disk ", num_seeks_gt_1_6); + logs("Number of seeks >= 1/12 and < 1/6 disk ", num_seeks_gt_1_12); + logs("Number of seeks > 0 and < 1/12 disk ", num_seeks_gt_0); + logs("Number of device read buffer overruns ", num_dev_read_buf_overruns); + logs("Number of device write buffer underruns ", num_dev_write_buf_overruns); + logl("Number of device cache read hits ", num_dev_cache_read_hits); + logl("Number of device cache partial read hits ", num_dev_cache_partial_read_hits); + logl("Number of device cache write hits ", num_dev_cache_write_hits); + logl("Number of device cache fast writes ", num_dev_cache_fast_writes); + + if (ipr_is_gscsi(dev)) { + printf("===============================================\n"); + return; + } + + logl("Number of device read ops ", num_device_read_ops); + logl("Number of device write ops ", num_device_write_ops); + logl("Number of IOA cache read hits ", num_ioa_cache_read_hits); + logl("Number of IOA cache partial read hits ", num_ioa_cache_partial_read_hits); + logl("Number of IOA cache write hits ", num_ioa_cache_write_hits); + logl("Number of IOA cache fast writes ", num_ioa_cache_fast_writes); + logl("Number of IOA emulated read cache hits ", num_ioa_emul_read_cache_hits); + logl("IOA Idle loop count[0] ", ioa_idle_loop_count[0]); + logl("IOA Idle loop count[1] ", ioa_idle_loop_count[1]); + printf("IOA Idle loop count value : %X\n", ntohl(new_log->ioa_idle_loop_count_value)); + printf("IOA Idle count value units : %d\n", new_log->ioa_idle_count_value_units); + printf("===============================================\n"); +} + +int main(int argc, char *argv[]) +{ + struct ipr_dev *dev[2]; + struct log_sense old_log[2], new_log[2]; + int rc, i; + + openlog("iprperf", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER); + tool_init(1); + check_current_config(false); + + for (i = 0; i < 2; i++) { + dev[i] = find_gen_dev(argv[1+i]); + if (!dev[i]) + dev[i] = find_blk_dev(argv[1+i]); + + if (!dev[i]) { + fprintf(stderr, "Cannot find %s\n", argv[1+i]); + return -EINVAL; + } + } + + for (i = 0; i < 2; i++) { + rc = get_counters(dev[i], &old_log[i]); + if (rc) + return rc; + } + + printf("***********************************************\n"); + system(argv[3]); + + for (i = 0; i < 2; i++) { + rc = get_counters(dev[i], &new_log[i]); + if (rc) + return rc; + } + + for (i = 0; i < 2; i++) { + print_counters(dev[i], &old_log[i], &new_log[i]); + } + + printf("***********************************************\n"); + + return 0; +} |