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 | |
parent | libblock: Remove const qualifier (diff) | |
download | rtems-9f527308d7248d1ec1d63f0911757bb5faa7ea10.tar.bz2 |
libblock: Add block device statistics
-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 | ||||
-rw-r--r-- | cpukit/libmisc/Makefile.am | 1 | ||||
-rw-r--r-- | cpukit/libmisc/shell/main_blkstats.c | 56 | ||||
-rw-r--r-- | cpukit/libmisc/shell/shellconfig.h | 6 | ||||
-rw-r--r-- | testsuites/libtests/Makefile.am | 1 | ||||
-rw-r--r-- | testsuites/libtests/block14/Makefile.am | 19 | ||||
-rw-r--r-- | testsuites/libtests/block14/block14.doc | 11 | ||||
-rw-r--r-- | testsuites/libtests/block14/block14.scn | 21 | ||||
-rw-r--r-- | testsuites/libtests/block14/init.c | 222 | ||||
-rw-r--r-- | testsuites/libtests/configure.ac | 1 |
17 files changed, 619 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 + ); +} diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am index 654c0505aa..b0b219569a 100644 --- a/cpukit/libmisc/Makefile.am +++ b/cpukit/libmisc/Makefile.am @@ -104,6 +104,7 @@ libshell_a_SOURCES = shell/cat_file.c shell/cmds.c shell/internal.h \ shell/main_setenv.c shell/main_getenv.c shell/main_unsetenv.c \ shell/main_mkrfs.c shell/main_debugrfs.c \ shell/main_lsof.c \ + shell/main_blkstats.c \ shell/shell-wait-for-input.c if LIBNETWORKING diff --git a/cpukit/libmisc/shell/main_blkstats.c b/cpukit/libmisc/shell/main_blkstats.c new file mode 100644 index 0000000000..4871cb5c4e --- /dev/null +++ b/cpukit/libmisc/shell/main_blkstats.c @@ -0,0 +1,56 @@ +/* + * 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 <rtems/shellconfig.h> + +static bool is_reset_option(const char *opt) +{ + return strcmp(opt, "-r") == 0 || strcmp(opt, "--reset") == 0; +} + +static int rtems_shell_main_blkstats(int argc, char **argv) +{ + bool ok = false; + bool reset = false; + const char *device; + + if (argc == 2) { + ok = true; + device = argv [1]; + } else if (argc == 3 && is_reset_option(argv [1])) { + ok = true; + reset = true; + device = argv [2]; + } + + if (ok) { + rtems_blkstats(stdout, device, reset); + } else { + fprintf(stdout, "usage: %s\n", rtems_shell_BLKSTATS_Command.usage); + } + + return 0; +} + +rtems_shell_cmd_t rtems_shell_BLKSTATS_Command = { + .name = "blkstats", + .usage = "blkstats [-r|--reset] PATH_TO_DEVICE", + .topic = "files", + .command = rtems_shell_main_blkstats +}; diff --git a/cpukit/libmisc/shell/shellconfig.h b/cpukit/libmisc/shell/shellconfig.h index 85fb3d0a6d..9f451512a0 100644 --- a/cpukit/libmisc/shell/shellconfig.h +++ b/cpukit/libmisc/shell/shellconfig.h @@ -65,6 +65,7 @@ extern rtems_shell_cmd_t rtems_shell_LSOF_Command; extern rtems_shell_cmd_t rtems_shell_MOUNT_Command; extern rtems_shell_cmd_t rtems_shell_UNMOUNT_Command; extern rtems_shell_cmd_t rtems_shell_BLKSYNC_Command; +extern rtems_shell_cmd_t rtems_shell_BLKSTATS_Command; extern rtems_shell_cmd_t rtems_shell_FDISK_Command; extern rtems_shell_cmd_t rtems_shell_DD_Command; extern rtems_shell_cmd_t rtems_shell_HEXDUMP_Command; @@ -350,6 +351,11 @@ extern rtems_shell_alias_t *rtems_shell_Initial_aliases[]; &rtems_shell_BLKSYNC_Command, #endif #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \ + !defined(CONFIGURE_SHELL_NO_COMMAND_BLKSTATS)) || \ + defined(CONFIGURE_SHELL_COMMAND_BLKSTATS) + &rtems_shell_BLKSTATS_Command, + #endif + #if (defined(CONFIGURE_SHELL_COMMANDS_ALL) && \ !defined(CONFIGURE_SHELL_NO_COMMAND_FDISK)) || \ defined(CONFIGURE_SHELL_COMMAND_FDISK) &rtems_shell_FDISK_Command, diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am index 9747ad19c6..6a0d20f50d 100644 --- a/testsuites/libtests/Makefile.am +++ b/testsuites/libtests/Makefile.am @@ -1,6 +1,7 @@ ACLOCAL_AMFLAGS = -I ../aclocal SUBDIRS = POSIX +SUBDIRS += block14 SUBDIRS += block13 SUBDIRS += rbheap01 SUBDIRS += flashdisk01 diff --git a/testsuites/libtests/block14/Makefile.am b/testsuites/libtests/block14/Makefile.am new file mode 100644 index 0000000000..a7769de3e0 --- /dev/null +++ b/testsuites/libtests/block14/Makefile.am @@ -0,0 +1,19 @@ +rtems_tests_PROGRAMS = block14 +block14_SOURCES = init.c + +dist_rtems_tests_DATA = block14.scn block14.doc + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../automake/compile.am +include $(top_srcdir)/../automake/leaf.am + +AM_CPPFLAGS += -I$(top_srcdir)/../support/include + +LINK_OBJS = $(block14_OBJECTS) +LINK_LIBS = $(block14_LDLIBS) + +block14$(EXEEXT): $(block14_OBJECTS) $(block14_DEPENDENCIES) + @rm -f block14$(EXEEXT) + $(make-exe) + +include $(top_srcdir)/../automake/local.am diff --git a/testsuites/libtests/block14/block14.doc b/testsuites/libtests/block14/block14.doc new file mode 100644 index 0000000000..de5bc68cbc --- /dev/null +++ b/testsuites/libtests/block14/block14.doc @@ -0,0 +1,11 @@ +This file describes the directives and concepts tested by this test set. + +test set name: block14 + +directives: + + TBD + +concepts: + + Ensure that the block device statistics work. diff --git a/testsuites/libtests/block14/block14.scn b/testsuites/libtests/block14/block14.scn new file mode 100644 index 0000000000..009ebb0698 --- /dev/null +++ b/testsuites/libtests/block14/block14.scn @@ -0,0 +1,21 @@ +*** TEST BLOCK 14 *** +action 0 +action 1 +action 2 +action 3 +action 4 +action 5 +action 6 +------------------------------------------------------------------------------- + DEVICE STATISTICS +----------------------+-------------------------------------------------------- + READ HITS | 2 + READ MISSES | 3 + READ AHEAD TRANSFERS | 2 + READ BLOCKS | 5 + READ ERRORS | 1 + WRITE TRANSFERS | 2 + WRITE BLOCKS | 2 + WRITE ERRORS | 1 +----------------------+-------------------------------------------------------- +*** END OF TEST BLOCK 14 *** diff --git a/testsuites/libtests/block14/init.c b/testsuites/libtests/block14/init.c new file mode 100644 index 0000000000..b95b86d740 --- /dev/null +++ b/testsuites/libtests/block14/init.c @@ -0,0 +1,222 @@ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + +#include "tmacros.h" + +#include <errno.h> +#include <string.h> + +#include <rtems/blkdev.h> +#include <rtems/bdbuf.h> + +#define ACTION_COUNT 7 + +#define BLOCK_COUNT 6 + +typedef struct { + rtems_blkdev_bnum block; + rtems_status_code (*get)( + rtems_disk_device *dd, + rtems_blkdev_bnum block, + rtems_bdbuf_buffer **bd_ptr + ); + rtems_status_code expected_get_status; + rtems_status_code (*release)(rtems_bdbuf_buffer *bd); +} test_action; + +static const test_action actions [ACTION_COUNT] = { + { 0, rtems_bdbuf_read, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, + { 1, rtems_bdbuf_read, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, + { 2, rtems_bdbuf_read, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, + { 0, rtems_bdbuf_read, RTEMS_SUCCESSFUL, rtems_bdbuf_release }, + { 4, rtems_bdbuf_get, RTEMS_SUCCESSFUL, rtems_bdbuf_sync }, + { 5, rtems_bdbuf_read, RTEMS_IO_ERROR, rtems_bdbuf_release }, + { 5, rtems_bdbuf_get, RTEMS_SUCCESSFUL, rtems_bdbuf_sync } +}; + +#define STATS(a, b, c, d, e, f, g, h) \ + { \ + .read_hits = a, \ + .read_misses = b, \ + .read_ahead_transfers = c, \ + .read_blocks = d, \ + .read_errors = e, \ + .write_transfers = f, \ + .write_blocks = g, \ + .write_errors = h \ + } + +static const rtems_blkdev_stats expected_stats [ACTION_COUNT] = { + STATS(0, 1, 0, 1, 0, 0, 0, 0), + STATS(0, 2, 1, 3, 0, 0, 0, 0), + STATS(1, 2, 2, 4, 0, 0, 0, 0), + STATS(2, 2, 2, 4, 0, 0, 0, 0), + STATS(2, 2, 2, 4, 0, 1, 1, 0), + STATS(2, 3, 2, 5, 1, 1, 1, 0), + STATS(2, 3, 2, 5, 1, 2, 2, 1) +}; + +static const int expected_block_access_counts [ACTION_COUNT] [BLOCK_COUNT] = { + { 1, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 0, 0, 0 }, + { 1, 1, 1, 1, 0, 0 }, + { 1, 1, 1, 1, 0, 0 }, + { 1, 1, 1, 1, 1, 0 }, + { 1, 1, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 1, 2 } +}; + +static int block_access_counts [BLOCK_COUNT]; + +static int test_disk_ioctl(rtems_disk_device *dd, uint32_t req, void *arg) +{ + int rv = 0; + + if (req == RTEMS_BLKIO_REQUEST) { + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_blkdev_request *breq = arg; + rtems_blkdev_sg_buffer *sg = breq->bufs; + uint32_t i; + + for (i = 0; i < breq->bufnum; ++i) { + rtems_blkdev_bnum block = sg [i].block; + + rtems_test_assert(block < BLOCK_COUNT); + + ++block_access_counts [block]; + + if (block == 5) { + sc = RTEMS_IO_ERROR; + } + } + + (*breq->req_done)(breq->done_arg, sc); + } else { + errno = EINVAL; + rv = -1; + } + + return rv; +} + +static void test_actions(rtems_disk_device *dd) +{ + int i; + + for (i = 0; i < ACTION_COUNT; ++i) { + const test_action *action = &actions [i]; + rtems_status_code sc; + rtems_bdbuf_buffer *bd; + rtems_blkdev_stats stats; + + printf("action %i\n", i); + + sc = (*action->get)(dd, action->block, &bd); + rtems_test_assert(sc == action->expected_get_status); + + if (sc == RTEMS_SUCCESSFUL) { + sc = (*action->release)(bd); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + } + + rtems_test_assert( + memcmp( + block_access_counts, + expected_block_access_counts [i], + sizeof(block_access_counts) + ) == 0 + ); + + rtems_bdbuf_get_device_stats(dd, &stats); + + rtems_test_assert( + memcmp( + &stats, + &expected_stats [i], + sizeof(stats) + ) == 0 + ); + } + + rtems_blkdev_print_stats(&dd->stats, rtems_printf_plugin, NULL); +} + +static void test(void) +{ + rtems_status_code sc; + dev_t dev = 0; + rtems_disk_device *dd; + + sc = rtems_disk_io_initialize(); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_disk_create_phys( + dev, + 1, + BLOCK_COUNT, + test_disk_ioctl, + NULL, + NULL + ); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + dd = rtems_disk_obtain(dev); + rtems_test_assert(dd != NULL); + + test_actions(dd); + + sc = rtems_disk_release(dd); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); + + sc = rtems_disk_delete(dev); + rtems_test_assert(sc == RTEMS_SUCCESSFUL); +} + +static void Init(rtems_task_argument arg) +{ + puts("\n\n*** TEST BLOCK 14 ***"); + + test(); + + puts("*** END OF TEST BLOCK 14 ***"); + + rtems_test_exit(0); +} + +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK + +#define CONFIGURE_BDBUF_BUFFER_MIN_SIZE 1 +#define CONFIGURE_BDBUF_BUFFER_MAX_SIZE 1 +#define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE BLOCK_COUNT +#define CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS 1 +#define CONFIGURE_BDBUF_READ_AHEAD_TASK_PRIORITY 1 + +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM + +#define CONFIGURE_MAXIMUM_TASKS 1 + +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE + +#define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES +#define CONFIGURE_INIT_TASK_PRIORITY 2 + +#define CONFIGURE_INIT + +#include <rtems/confdefs.h> diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac index 7df0520f87..f383ac17a4 100644 --- a/testsuites/libtests/configure.ac +++ b/testsuites/libtests/configure.ac @@ -41,6 +41,7 @@ AM_CONDITIONAL(NETTESTS,test "$rtems_cv_RTEMS_NETWORKING" = "yes") # Explicitly list all Makefiles here AC_CONFIG_FILES([Makefile +block14/Makefile block13/Makefile rbheap01/Makefile syscall01/Makefile |