summaryrefslogtreecommitdiff
path: root/debug/iprperf.c
blob: 15a5bad9d437485164b1cf139a1124856ddc7913 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/**
  * IBM IPR adapter performance analysis 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/iprperf.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;
}

static void print_counters(struct ipr_dev *dev, struct log_sense *log)
{
	printf("Number of seeks  = zero length           : %d\n", ntohs(log->num_seeks_0));
	printf("Number of seeks >= 2/3 disk              : %d\n", ntohs(log->num_seeks_gt_2_3));
	printf("Number of seeks >= 1/3  and < 2/3 disk   : %d\n", ntohs(log->num_seeks_gt_1_3));
	printf("Number of seeks >= 1/6  and < 1/3 disk   : %d\n", ntohs(log->num_seeks_gt_1_6));
	printf("Number of seeks >= 1/12 and < 1/6 disk   : %d\n", ntohs(log->num_seeks_gt_1_12));
	printf("Number of seeks >  0    and < 1/12 disk  : %d\n", ntohs(log->num_seeks_gt_0));
	printf("Number of device read buffer overruns    : %d\n", ntohs(log->num_dev_read_buf_overruns));
	printf("Number of device write buffer underruns  : %d\n", ntohs(log->num_dev_write_buf_overruns));
	printf("Number of device cache read hits         : %d\n", ntohl(log->num_dev_cache_read_hits));
	printf("Number of device cache partial read hits : %d\n", ntohl(log->num_dev_cache_partial_read_hits));
	printf("Number of device cache write hits        : %d\n", ntohl(log->num_dev_cache_write_hits));
	printf("Number of device cache fast writes       : %d\n", ntohl(log->num_dev_cache_fast_writes));

	if (ipr_is_gscsi(dev))
		return;

	printf("\n");
	printf("Number of device read ops                : %d\n", ntohl(log->num_device_read_ops));
	printf("Number of device write ops               : %d\n", ntohl(log->num_device_write_ops));
	printf("Number of IOA cache read hits            : %d\n", ntohl(log->num_ioa_cache_read_hits));
	printf("Number of IOA cache partial read hits    : %d\n", ntohl(log->num_ioa_cache_partial_read_hits));
	printf("Number of IOA cache write hits           : %d\n", ntohl(log->num_ioa_cache_write_hits));
	printf("Number of IOA cache fast writes          : %d\n", ntohl(log->num_ioa_cache_fast_writes));
	printf("Number of IOA emulated read cache hits   : %d\n", ntohl(log->num_ioa_emul_read_cache_hits));
	printf("IOA Idle loop count                      : %X%08X\n",
	       ntohl(log->ioa_idle_loop_count[0]), ntohl(log->ioa_idle_loop_count[1]));
	printf("IOA Idle loop count value                : %X\n", ntohl(log->ioa_idle_loop_count_value));
	printf("IOA Idle count value units               : %d\n", log->ioa_idle_count_value_units);
}

int main(int argc, char *argv[])
{
	struct ipr_dev *dev;
	struct log_sense log;
	int rc;

	openlog("iprperf", LOG_PERROR | LOG_PID | LOG_CONS, LOG_USER);
	tool_init(1);
	check_current_config(false);
	dev = find_gen_dev(argv[1]);
	if (!dev)
		dev = find_blk_dev(argv[1]);

	if (!dev) {
		fprintf(stderr, "Cannot find %s\n", argv[1]);
		return -EINVAL;
	}

	rc = get_counters(dev, &log);
	if (rc)
		return rc;

	print_counters(dev, &log);
	return 0;
}