File: dasdstat

package info (click to toggle)
s390-tools 2.3.0-1
  • links: PTS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 6,176 kB
  • sloc: ansic: 87,755; sh: 8,398; cpp: 8,384; perl: 3,783; makefile: 1,476; asm: 654
file content (466 lines) | stat: -rwxr-xr-x 12,164 bytes parent folder | download
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
#!/bin/bash
#
# dasdstat - Tool to print DASD statistics data as formatted table
#
# Copyright IBM Corp. 2011, 2017
#
# s390-tools is free software; you can redistribute it and/or modify
# it under the terms of the MIT license. See LICENSE for details.
#

function print_usage() {
	cat <<-EOD
Usage: $CMD <options> [<statistic>]

<options> ::=
        -e|--enable
                Enable the statistics.
        -d|--disable
                Disable the statistics.
        -r|--reset
                Reset the statistics.
        -i|--directory <directory>
                Specify the directory in which the statistics can be found.
        -h|--help
                Print this text and exit.
        -l|--long
                Print more detailed information, e.g differentiate between
                read and write requests.
        -c|--columns <number>
                Format the output in a table with the given number of columns.
        -w|--column-width <width>
                Set the minimum width of the columns in the output table.
        -V|--verbose
                Print more verbose information.
        -v|--version
                Show tools and command version.

<statistic>
        Limit operation to one or more statistic.
	EOD
}

function print_version()
{
	echo "$CMD: version %S390_TOOLS_VERSION%"
	echo "Copyright IBM Corp. 2011, 2017"
}

function unset_known_variables() {
	unset start_time
	unset total_requests
	unset total_sectors
	unset total_pav
	unset total_hpf
	unset histogram_sectors
	unset histogram_io_times
	unset histogram_io_times_weighted
	unset histogram_time_build_to_ssch
	unset histogram_time_ssch_to_irq
	unset histogram_time_ssch_to_irq_weighted
	unset histogram_time_irq_to_end
	unset histogram_ccw_queue_length
	unset total_read_requests
	unset total_read_sectors
	unset total_read_pav
	unset total_read_hpf
	unset histogram_read_sectors
	unset histogram_read_times
	unset histogram_read_time_build_to_ssch
	unset histogram_read_time_ssch_to_irq
	unset histogram_read_time_irq_to_end
	unset histogram_read_ccw_queue_length
}

function print_array()
{
	local width=$1
	shift
	local linebreak=$1
	shift
	local i=1
	for element in $*
	do
		printf "%${width}s" $element
		(( 0 == i++ % linebreak )) && printf "\n"
	done
	# add an extra line break if we do not already have one
	(( 0 != (i - 1) % linebreak )) && printf "\n"
}

function subtract_array()
{
	local -a a=( $1 )
	local -a b=( $2 )
	local -a c
	local i
	local cnt=${#a[@]}
	for (( i = 0 ; i < cnt ; i++ ))
	do
		(( c[i] = a[i] - b[i] ))
	done
	echo -n ${c[*]}
}

function print_line()
{
	local i
	for (( i = 0 ; i < $1 ; i++ ))
	do
		echo -n '-'
	done
	echo
}

HEADERSEXP=" __<4    ___8    __16    __32    __64    _128    _256    _512 \
             __1k    __2k    __4k    __8k    _16k    _32k    _64k    128k \
             _256    _512    __1M    __2M    __4M    __8M    _16M    _32M \
             _64M    128M    256M    512M    __1G    __2G    __4G    _>4G"

HEADERSLIN=" ___0    ___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"


function print_format_standard()
{
	local converted_time=$(date -d @$start_time)
	# all numbers in the histograms below are smaller or equal to the
	# total_requests. So we use that number to determine the column width.
	local width=${#total_requests}
	(( width++ ))
	(( width < 5 )) && width=5

	if [[ -n $COLUMN_WIDTH ]] && [[ $width -lt $COLUMN_WIDTH ]]
	then
		width=$COLUMN_WIDTH
	fi

	local linebreak=$NUMBER_COLUMNS
	local statname="$1"
	local tablewidth
	(( tablewidth = width * linebreak ))

	# Note: This function does not print the histogram_io_times_weighted
	#       and histogram_time_ssch_to_irq_weighted because the interpretation
	#       of these histograms is not intuitive and may lead to confusion.
	print_line $tablewidth
	printf "statistics data for statistic: %s\n" "$statname"
	printf "start time of data collection: %s\n\n" "$converted_time"

	printf "%d dasd I/O requests\n" ${total_requests[*]}
	printf "with %u sectors(512B each)\n" ${total_sectors[*]}
	printf "%d requests used a PAV alias device\n" ${total_pav[*]}
	printf "%d requests used HPF\n" ${total_hpf[*]}
	print_array $width $linebreak $HEADERSEXP
	printf "Histogram of sizes (512B secs)\n"
	print_array $width $linebreak ${histogram_sectors[*]}
	printf "Histogram of I/O times (microseconds)\n"
	print_array $width $linebreak ${histogram_io_times[*]}
	printf "Histogram of I/O time till ssch\n"
	print_array $width $linebreak ${histogram_time_build_to_ssch[*]}
	printf "Histogram of I/O time between ssch and irq\n"
	print_array $width $linebreak ${histogram_time_ssch_to_irq[*]}
	printf "Histogram of I/O time between irq and end\n"
	print_array $width $linebreak ${histogram_time_irq_to_end[*]}
	printf "# of req in chanq at enqueuing (0..31) \n"
	print_array $width $linebreak $HEADERSLIN
	print_array $width $linebreak ${histogram_ccw_queue_length[*]}

	if [[ $OUTPUT == "short" ]]
	then
		print_line $tablewidth
		return
	fi

	printf "\n%d dasd I/O read requests\n" ${total_read_requests[*]}
	printf "with %u sectors(512B each)\n" ${total_read_sectors[*]}
	printf "%d requests used a PAV alias device\n" ${total_read_pav[*]}
	printf "%d requests used HPF\n" ${total_read_hpf[*]}
	print_array $width $linebreak $HEADERSEXP
	printf "Histogram of sizes (512B secs)\n"
	print_array $width $linebreak ${histogram_read_sectors[*]}
	printf "Histogram of I/O times (microseconds)\n"
	print_array $width $linebreak ${histogram_read_times[*]}
	printf "Histogram of I/O time till ssch\n"
	print_array $width $linebreak ${histogram_read_time_build_to_ssch[*]}
	printf "Histogram of I/O time between ssch and irq\n"
	print_array $width $linebreak ${histogram_read_time_ssch_to_irq[*]}
	printf "Histogram of I/O time between irq and end\n"
	print_array $width $linebreak ${histogram_read_time_irq_to_end[*]}
	printf "# of req in chanq at enqueuing (0..31) \n"
	print_array $width $linebreak $HEADERSLIN
	print_array $width $linebreak ${histogram_read_ccw_queue_length[*]}

	printf "\n%d dasd I/O write requests\n" $(( total_requests[0] - total_read_requests[0] ))
	printf "with %u sectors(512B each)\n" $(( total_sectors[0] - total_read_sectors[0] ))
	printf "%d requests used a PAV alias device\n" $(( total_pav[0] - total_read_pav[0] ))
	printf "%d requests used HPF\n" $(( total_hpf[0] - total_read_hpf[0] ))
	print_array $width $linebreak $HEADERSEXP
	printf "Histogram of sizes (512B secs)\n"
	print_array $width $linebreak $(subtract_array "${histogram_sectors[*]}" "${histogram_read_sectors[*]}")
	printf "Histogram of I/O times (microseconds)\n"
	print_array $width $linebreak $(subtract_array "${histogram_io_times[*]}" "${histogram_read_times[*]}")
	printf "Histogram of I/O time till ssch\n"
	print_array $width $linebreak $(subtract_array "${histogram_time_build_to_ssch[*]}" "${histogram_read_time_build_to_ssch[*]}")
	printf "Histogram of I/O time between ssch and irq\n"
	print_array $width $linebreak $(subtract_array "${histogram_time_ssch_to_irq[*]}" "${histogram_read_time_ssch_to_irq[*]}")
	printf "Histogram of I/O time between irq and end\n"
	print_array $width $linebreak $(subtract_array "${histogram_time_irq_to_end[*]}" "${histogram_read_time_irq_to_end[*]}")
	printf "# of req in chanq at enqueuing (0..31) \n"
	print_array $width $linebreak $HEADERSLIN
	print_array $width $linebreak $(subtract_array "${histogram_ccw_queue_length[*]}" "${histogram_read_ccw_queue_length[*]}")

	print_line $tablewidth
}

function read_stat_data() {
	local file="$1"

	while read -d ' ' token
	do
		read -a $token
	done < <(cat $file) #avoid inconsistent data due to multiple reads/seeks

	# differentiate I/O error from disabled statistic
	if [[ -n $total_requests ]] || [[ "$token" == "disabled" ]]
	then
		return 0
	else
		return 1
	fi
}

function print_stat() {
	myfile="$1"
	if [[ ! -f "$myfile" ]]
	then
		print_line 80
		echo "$CMD: Statistic \"$myfile\" does not exist" >&2
		print_line 80
		echo
		return
	fi
	unset_known_variables
	if read_stat_data "$myfile"
	then
		if [[ -z "$total_requests" ]]
		then
			if [[ "$VERBOSE" == "true" ]]
			then
				print_line 80
				echo "statistics \"$f\" are disabled"
				print_line 80
				echo
			fi
		else
			print_format_standard $f
			echo
		fi
	else
		print_line 80
		echo "$CMD: Could not read statistic \"$myfile\" " >&2
		print_line 80
		echo
	fi
}

function enable_stat() {
	myfile="$1"
	if [[ ! -f "$myfile" ]]
	then
		echo "$CMD: Statistic \"$myfile\" does not exist" >&2
		return
	fi
	if echo on > "$myfile"
	then
		echo "enable statistic \"$myfile\""
	else
		echo "$CMD: Failed to enable statistic \"$myfile\"" >&2
	fi
}

function disable_stat() {
	myfile="$1"
	if [[ ! -f "$myfile" ]]
	then
		echo "$CMD: Statistic \"$myfile\" does not exist" >&2
		return
	fi
	if echo off > "$myfile"
	then
		echo "disable statistic \"$myfile\""
	else
		echo "$CMD: Failed to disable statistic \"$myfile\""
	fi
}

function reset_stat() {
	myfile="$1"
	if [[ ! -f "$myfile" ]]
	then
		echo "$CMD: Statistic \"$myfile\" does not exist" >&2
		return
	fi
	if echo reset > "$myfile"
	then
		echo "reset statistic \"$myfile\""
	else
		echo "$CMD: Failed to reset statistic \"$myfile\"" >&2
	fi
}

function verbose_msg() {
	if [[ "$VERBOSE" == "true" ]]
	then
		echo "$*"
	fi
}


# Evaluating command line options
CMD=$(basename $0)
DASD_STATISTICS_DIR=""
ALLFILES=""
VERBOSE=false
OUTPUT="short"
NUMBER_COLUMNS=16
COLUMN_WIDTH=
ACTION="print"
while [ $# -gt 0 ]; do
	case $1 in
	--help|-h)
		print_usage
		exit 0
		;;
	--enable|-e)
		ACTION="enable"
		;;
	--disable|-d)
		ACTION="disable"
		;;
	--reset|-r)
		ACTION="reset"
		;;
	--directory|-i)
		DASD_STATISTICS_DIR="$2"
		shift
		if [[ ! -d $DASD_STATISTICS_DIR ]]
		then
			echo "$CMD: $DASD_STATISTICS_DIR is not a directory" >&2
			exit 1
		fi
		;;
	--long|-l)
		OUTPUT="extended"
		;;
	--columns|-c)
		NUMBER_COLUMNS="$2"
		if [[ ! "$NUMBER_COLUMNS" -gt 0 ]]
		then
			echo "$CMD: $NUMBER_COLUMNS is not a positive integer number" >&2
			exit 1
		fi
		shift
		;;
	--column-width|-w)
		COLUMN_WIDTH="$2"
		if [[ ! "$COLUMN_WIDTH" -gt 0 ]]
		then
			echo "$CMD: $COLUMN_WIDTH is not a positive integer number" >&2
			exit 1
		fi
		shift
		;;
	--verbose|-V)
		VERBOSE=true
		;;
	--version|-v)
		print_version
		exit 0
		;;
	-*)
		echo "$CMD: Invalid option $1" >&2
		echo "Try '$CMD --help' for more information." >&2
		exit 1
		;;
	*)
		ALLFILES="$ALLFILES $1"
		;;
	esac
	shift
done

# if no directory is given on command line, find dasd directory in debugfs
if [[ "$DASD_STATISTICS_DIR" == "" ]]
then
	while read -a mntentries
	do
		if [[ "${mntentries[2]}" == "debugfs" ]]
		then
			DASD_STATISTICS_DIR="${mntentries[1]}"
			verbose_msg "found debugfs mount point $DASD_STATISTICS_DIR"
			break;
		fi
	done < /etc/mtab
	if [[ "$DASD_STATISTICS_DIR" == "" ]]
	then
		echo "$CMD: No debugfs mount point found" >&2
		exit 1
	fi
	DASD_STATISTICS_DIR="$DASD_STATISTICS_DIR/dasd"
	if [[ ! -d "$DASD_STATISTICS_DIR" ]]
	then
		echo "$CMD: Default DASD debugfs directory $DASD_STATISTICS_DIR does not exist" >&2
		exit 1
	fi
fi

# look for directories that contain statistics
if [[ "$ALLFILES" == "" ]]
then
	ALLFILES=$(ls -x $DASD_STATISTICS_DIR)
	explicitstats="false"
else
	explicitstats="true"
fi
ALLSTATS=""
for f in $ALLFILES
do
	if [[ -f "$DASD_STATISTICS_DIR/$f/statistics" ]]
	then
		ALLSTATS="$ALLSTATS $f"
	elif [[ $explicitstats == "true" ]]
	then
		echo "$CMD: No statistics found for $f" >&2
	fi
done

verbose_msg "found the following statistics in directory $DASD_STATISTICS_DIR:"
verbose_msg "$ALLSTATS"

# execute the required operation
for f in $ALLSTATS
do
	case $ACTION in
	"enable")
		enable_stat "$DASD_STATISTICS_DIR/$f/statistics"
		;;
	"disable")
		disable_stat "$DASD_STATISTICS_DIR/$f/statistics"
		;;
	"reset")
		reset_stat "$DASD_STATISTICS_DIR/$f/statistics"
		;;
	"print")
		print_stat "$DASD_STATISTICS_DIR/$f/statistics"
		;;
	*)
		echo "error"
		exit 1
		;;
	esac
done