diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2012-06-12 09:46:09 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2012-06-12 10:12:40 +0200 |
commit | 9f527308d7248d1ec1d63f0911757bb5faa7ea10 (patch) | |
tree | 27943302132f4b86a1ea3c6089407b45d23c66cb /cpukit/libblock | |
parent | libblock: Remove const qualifier (diff) | |
download | rtems-9f527308d7248d1ec1d63f0911757bb5faa7ea10.tar.bz2 |
libblock: Add block device statistics
Diffstat (limited to 'cpukit/libblock')
-rw-r--r-- | cpukit/libblock/Makefile.am | 2 | ||||
-rw-r--r-- | cpukit/libblock/include/rtems/bdbuf.h | 13 | ||||
-rw-r--r-- | cpukit/libblock/include/rtems/blkdev.h | 35 | ||||
-rw-r--r-- | cpukit/libblock/include/rtems/diskdevs.h | 67 | ||||
-rw-r--r-- | cpukit/libblock/src/bdbuf.c | 34 | ||||
-rw-r--r-- | cpukit/libblock/src/blkdev-blkstats.c | 70 | ||||
-rw-r--r-- | cpukit/libblock/src/blkdev-ioctl.c | 8 | ||||
-rw-r--r-- | cpukit/libblock/src/blkdev-print-stats.c | 52 |
8 files changed, 281 insertions, 0 deletions
diff --git a/cpukit/libblock/Makefile.am b/cpukit/libblock/Makefile.am index 6ddc52418d..d07eb5e177 100644 --- a/cpukit/libblock/Makefile.am +++ b/cpukit/libblock/Makefile.am @@ -7,6 +7,8 @@ libblock_a_SOURCES = src/bdbuf.c \ src/blkdev-imfs.c \ src/blkdev-ioctl.c \ src/blkdev-ops.c \ + src/blkdev-print-stats.c \ + src/blkdev-blkstats.c \ src/diskdevs.c \ src/diskdevs-init.c \ src/flashdisk.c \ diff --git a/cpukit/libblock/include/rtems/bdbuf.h b/cpukit/libblock/include/rtems/bdbuf.h index f63c1c548c..6c6eb76a42 100644 --- a/cpukit/libblock/include/rtems/bdbuf.h +++ b/cpukit/libblock/include/rtems/bdbuf.h @@ -662,6 +662,19 @@ rtems_bdbuf_purge_dev (rtems_disk_device *dd); rtems_status_code rtems_bdbuf_set_block_size (rtems_disk_device *dd, uint32_t block_size); +/** + * @brief Returns the block device statistics. + */ +void +rtems_bdbuf_get_device_stats (const rtems_disk_device *dd, + rtems_blkdev_stats *stats); + +/** + * @brief Resets the block device statistics. + */ +void +rtems_bdbuf_reset_device_stats (rtems_disk_device *dd); + /** @} */ #ifdef __cplusplus diff --git a/cpukit/libblock/include/rtems/blkdev.h b/cpukit/libblock/include/rtems/blkdev.h index 7c2787204a..ccc8981c35 100644 --- a/cpukit/libblock/include/rtems/blkdev.h +++ b/cpukit/libblock/include/rtems/blkdev.h @@ -16,7 +16,9 @@ #include <rtems.h> #include <rtems/diskdevs.h> +#include <rtems/bspIo.h> #include <sys/ioctl.h> +#include <stdio.h> #ifdef __cplusplus extern "C" { @@ -161,6 +163,8 @@ typedef struct rtems_blkdev_request { #define RTEMS_BLKIO_CAPABILITIES _IO('B', 8) #define RTEMS_BLKIO_GETDISKDEV _IOR('B', 9, rtems_disk_device *) #define RTEMS_BLKIO_PURGEDEV _IO('B', 10) +#define RTEMS_BLKIO_GETDEVSTATS _IOR('B', 11, rtems_blkdev_stats *) +#define RTEMS_BLKIO_RESETDEVSTATS _IO('B', 12) /** @} */ @@ -208,6 +212,19 @@ static inline int rtems_disk_fd_purge(int fd) return ioctl(fd, RTEMS_BLKIO_PURGEDEV); } +static inline int rtems_disk_fd_get_device_stats( + int fd, + rtems_blkdev_stats *stats +) +{ + return ioctl(fd, RTEMS_BLKIO_GETDEVSTATS, stats); +} + +static inline int rtems_disk_fd_reset_device_stats(int fd) +{ + return ioctl(fd, RTEMS_BLKIO_RESETDEVSTATS); +} + /** * Only consecutive multi-sector buffer requests are supported. * @@ -361,6 +378,24 @@ rtems_status_code rtems_blkdev_create_partition( rtems_blkdev_bnum block_count ); +/** + * @brief Prints the block device statistics. + */ +void rtems_blkdev_print_stats( + const rtems_blkdev_stats *stats, + rtems_printk_plugin_t print, + void *print_arg +); + +/** + * @brief Block device statistics command. + */ +void rtems_blkstats( + FILE *output, + const char *device, + bool reset +); + /** @} */ #ifdef __cplusplus diff --git a/cpukit/libblock/include/rtems/diskdevs.h b/cpukit/libblock/include/rtems/diskdevs.h index 6e6be5e9b7..3a9967ecb2 100644 --- a/cpukit/libblock/include/rtems/diskdevs.h +++ b/cpukit/libblock/include/rtems/diskdevs.h @@ -87,6 +87,68 @@ typedef struct { } rtems_blkdev_read_ahead; /** + * @brief Block device statistics. + * + * Integer overflows in the statistic counters may happen. + */ +typedef struct { + /** + * @brief Read hit count. + * + * A read hit occurs in the rtems_bdbuf_read() function in case the block is + * in the cached or modified state. + */ + uint32_t read_hits; + + /** + * @brief Read miss count. + * + * A read miss occurs in the rtems_bdbuf_read() function in case the block is + * in the empty state and a read transfer must be initiated to read the data + * from the device. + */ + uint32_t read_misses; + + /** + * @brief Read-ahead transfer count. + * + * Each read-ahead transfer may read multiple blocks. + */ + uint32_t read_ahead_transfers; + + /** + * @brief Count of blocks transfered from the device. + */ + uint32_t read_blocks; + + /** + * @brief Read error count. + * + * Error count of transfers issued by the read or read-ahead requests. + */ + uint32_t read_errors; + + /** + * @brief Write transfer count. + * + * Each write transfer may write multiple blocks. + */ + uint32_t write_transfers; + + /** + * @brief Count of blocks transfered to the device. + */ + uint32_t write_blocks; + + /** + * @brief Write error count. + * + * Error count of transfers issued by write requests. + */ + uint32_t write_errors; +} rtems_blkdev_stats; + +/** * @brief Description of a disk device (logical and physical disks). * * An array of pointer tables to rtems_disk_device structures is maintained. @@ -202,6 +264,11 @@ struct rtems_disk_device { bool deleted; /** + * @brief Device statistics for this disk. + */ + rtems_blkdev_stats stats; + + /** * @brief Read-ahead control for this disk. */ rtems_blkdev_read_ahead read_ahead; diff --git a/cpukit/libblock/src/bdbuf.c b/cpukit/libblock/src/bdbuf.c index 1d683b3f89..81c8b81fb8 100644 --- a/cpukit/libblock/src/bdbuf.c +++ b/cpukit/libblock/src/bdbuf.c @@ -1899,6 +1899,21 @@ rtems_bdbuf_execute_transfer_request (rtems_disk_device *dd, rtems_bdbuf_lock_cache (); + /* Statistics */ + if (req->req == RTEMS_BLKDEV_REQ_READ) + { + dd->stats.read_blocks += req->bufnum; + if (sc != RTEMS_SUCCESSFUL) + ++dd->stats.read_errors; + } + else + { + dd->stats.write_blocks += req->bufnum; + ++dd->stats.write_transfers; + if (sc != RTEMS_SUCCESSFUL) + ++dd->stats.write_errors; + } + for (transfer_index = 0; transfer_index < req->bufnum; ++transfer_index) { rtems_bdbuf_buffer *bd = req->bufs [transfer_index].user; @@ -2074,12 +2089,15 @@ rtems_bdbuf_read (rtems_disk_device *dd, switch (bd->state) { case RTEMS_BDBUF_STATE_CACHED: + ++dd->stats.read_hits; rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_ACCESS_CACHED); break; case RTEMS_BDBUF_STATE_MODIFIED: + ++dd->stats.read_hits; rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_ACCESS_MODIFIED); break; case RTEMS_BDBUF_STATE_EMPTY: + ++dd->stats.read_misses; rtems_bdbuf_set_read_ahead_trigger (dd, block); sc = rtems_bdbuf_execute_read_request (dd, bd, 1); if (sc == RTEMS_SUCCESSFUL) @@ -3025,6 +3043,7 @@ rtems_bdbuf_read_ahead_task (rtems_task_argument arg) dd->read_ahead.trigger = RTEMS_DISK_READ_AHEAD_NO_TRIGGER; } + ++dd->stats.read_ahead_transfers; rtems_bdbuf_execute_read_request (dd, bd, transfer_count); } } @@ -3039,3 +3058,18 @@ rtems_bdbuf_read_ahead_task (rtems_task_argument arg) rtems_task_delete (RTEMS_SELF); } + +void rtems_bdbuf_get_device_stats (const rtems_disk_device *dd, + rtems_blkdev_stats *stats) +{ + rtems_bdbuf_lock_cache (); + *stats = dd->stats; + rtems_bdbuf_unlock_cache (); +} + +void rtems_bdbuf_reset_device_stats (rtems_disk_device *dd) +{ + rtems_bdbuf_lock_cache (); + memset (&dd->stats, 0, sizeof(dd->stats)); + rtems_bdbuf_unlock_cache (); +} diff --git a/cpukit/libblock/src/blkdev-blkstats.c b/cpukit/libblock/src/blkdev-blkstats.c new file mode 100644 index 0000000000..c870fe1080 --- /dev/null +++ b/cpukit/libblock/src/blkdev-blkstats.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/blkdev.h> + +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +void rtems_blkstats(FILE *output, const char *device, bool reset) +{ + int fd = open(device, O_RDONLY); + + if (fd >= 0) { + struct stat st; + int rv; + + rv = fstat(fd, &st); + if (rv == 0) { + if (S_ISBLK(st.st_mode)) { + if (reset) { + rv = rtems_disk_fd_reset_device_stats(fd); + if (rv != 0) { + fprintf(output, "error: reset stats: %s\n", strerror(errno)); + } + } else { + rtems_blkdev_stats stats; + + rv = rtems_disk_fd_get_device_stats(fd, &stats); + if (rv == 0) { + rtems_blkdev_print_stats( + &stats, + (rtems_printk_plugin_t) fprintf, + output + ); + } else { + fprintf(output, "error: get stats: %s\n", strerror(errno)); + } + } + } else { + fprintf(output, "error: not a block device\n"); + } + } else { + fprintf(output, "error: get file stats: %s\n", strerror(errno)); + } + + rv = close(fd); + if (rv != 0) { + fprintf(output, "error: close device: %s\n", strerror(errno)); + } + } else { + fprintf(output, "error: open device: %s\n", strerror(errno)); + } +} diff --git a/cpukit/libblock/src/blkdev-ioctl.c b/cpukit/libblock/src/blkdev-ioctl.c index d775d1e833..b2215f17c2 100644 --- a/cpukit/libblock/src/blkdev-ioctl.c +++ b/cpukit/libblock/src/blkdev-ioctl.c @@ -64,6 +64,14 @@ rtems_blkdev_ioctl(rtems_disk_device *dd, uint32_t req, void *argp) rtems_bdbuf_purge_dev(dd); break; + case RTEMS_BLKIO_GETDEVSTATS: + rtems_bdbuf_get_device_stats(dd, (rtems_blkdev_stats *) argp); + break; + + case RTEMS_BLKIO_RESETDEVSTATS: + rtems_bdbuf_reset_device_stats(dd); + break; + default: errno = EINVAL; rc = -1; diff --git a/cpukit/libblock/src/blkdev-print-stats.c b/cpukit/libblock/src/blkdev-print-stats.c new file mode 100644 index 0000000000..8cebeaf812 --- /dev/null +++ b/cpukit/libblock/src/blkdev-print-stats.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include <rtems/blkdev.h> + +#include <inttypes.h> + +void rtems_blkdev_print_stats( + const rtems_blkdev_stats *stats, + rtems_printk_plugin_t print, + void *print_arg +) +{ + (*print)( + print_arg, + "-------------------------------------------------------------------------------\n" + " DEVICE STATISTICS\n" + "----------------------+--------------------------------------------------------\n" + " READ HITS | %" PRIu32 "\n" + " READ MISSES | %" PRIu32 "\n" + " READ AHEAD TRANSFERS | %" PRIu32 "\n" + " READ BLOCKS | %" PRIu32 "\n" + " READ ERRORS | %" PRIu32 "\n" + " WRITE TRANSFERS | %" PRIu32 "\n" + " WRITE BLOCKS | %" PRIu32 "\n" + " WRITE ERRORS | %" PRIu32 "\n" + "----------------------+--------------------------------------------------------\n", + stats->read_hits, + stats->read_misses, + stats->read_ahead_transfers, + stats->read_blocks, + stats->read_errors, + stats->write_transfers, + stats->write_blocks, + stats->write_errors + ); +} |