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
|
/*
* Oracle Linux DTrace.
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/*
* NAME
* diskact.d - for block devices show the distribution of I/O throughput
*
* SYNOPSIS
* sudo dtrace -s diskact.d
*
* DESCRIPTION
* The io provider is used to gather the I/O throughput for the block
* devices on the system. A histogram of the results is printed.
*
* NOTES
* - The script needs to be terminated with ctrl-C. In case the
* script is running in the background, get it to run in the
* foreground first by using the fg command and then use ctrl-C
* to terminate the process. Otherwise, typing in ctrl-C will do.
*
* - The bufinfo_t structure is the abstraction that describes an I/O
* request. The buffer that corresponds to an I/O request is pointed
* to by args[0] in the start, done, wait-start, and wait-done probes
* available through the io provider.
*
* - Detailed information about this data structure can be found in
* the DTrace User Guide. For more details, you can also check
* /usr/lib64/dtrace/<version>/io.d, where <version> denotes the
* kernel version.
*
* - Although the results of an aggregation are automatically
* printed when the tracing terminates, in this case, we want to
* control the format of the output. This is why the results are
* printed using printa() in the END probe
*/
/*
* To avoid that the carefully crafted output is mixed with the
* default output by the dtrace command, enable quiet mode.
*/
#pragma D option quiet
/*
* The pointer to bufinfo_t is in args[0]. Here it is used to get
* b_edev (the extended device) and b_blkno (the expanded block
* number on the device). These two fields are used in the key for
* associative array io_start.
*/
io:::start
{
io_start[args[0]->b_edev, args[0]->b_blkno] = timestamp;
}
io:::done
/ io_start[args[0]->b_edev, args[0]->b_blkno] /
{
/*
* We would like to show the throughput to a device in KB/sec, but
* the values that are measured are in bytes and nanoseconds.
* You want to calculate the following:
*
* bytes / 1024
* ------------------------
* nanoseconds / 1000000000
*
* As DTrace uses integer arithmetic and the denominator is usually
* between 0 and 1 for most I/O, the calculation as shown will lose
* precision. So, restate the fraction as:
*
* bytes 1000000000 bytes * 976562
* ----------- * ------------- = --------------
* nanoseconds 1024 nanoseconds
*
* This is easy to calculate using integer arithmetic.
*/
this->elapsed = timestamp - io_start[args[0]->b_edev, args[0]->b_blkno];
/*
* The pointer to structure devinfo_t is in args[1]. Use this to get the
* name (+ instance/minor) and the pathname of the device.
*
* Use the formula above to compute the throughput. The number of bytes
* transferred is in bufinfo_t->b_bcount
*/
@io_throughput[strjoin("device name = ",args[1]->dev_statname),
strjoin("path = ",args[1]->dev_pathname)] =
quantize((args[0]->b_bcount * 976562) / this->elapsed);
/*
* Free the storage for the entry in the associative array.
*/
io_start[args[0]->b_edev, args[0]->b_blkno] = 0;
}
/*
* Use a format string to print the aggregation.
*/
END
{
printa(" %s (%s)\n%@d\n", @io_throughput);
}
|