libblock: Add read-ahead task

Read-ahead requests were previously executed in the context of the
reading task.  This blocks the reading task until the complete read
with read-ahead transfer is finished.  A read-ahead task is introduced
to off-load the read-ahead transfer.  This allows the reading task to
work with the requested block more quickly.  The read-ahead is triggered
after two misses of ascending consecutive blocks or a read hit of a
block read by the most-recent read-ahead transfer.  The read-ahead
feature is configurable and can be disabled.
This commit is contained in:
Sebastian Huber committed 2012-06-04 09:54:31 +02:00
1 parent 6273201b14
commit 39ee704e75
11 files changed
+568 -130

No files matched your search

+19 -7
View File
@@ -46,7 +46,7 @@ extern "C" {
* @ingroup rtems_libblock
*
* The Block Device Buffer Management implements a cache between the disk
* devices and file systems. The code provides read ahead and write queuing to
* devices and file systems. The code provides read-ahead and write queuing to
* the drivers and fast cache look-up using an AVL tree.
*
* The block size used by a file system can be set at runtime and must be a
@@ -152,10 +152,13 @@ extern "C" {
* written. This would be a performance problem.
*
* The code performs multiple block reads and writes. Multiple block reads or
* read ahead increases performance with hardware that supports it. It also
* read-ahead increases performance with hardware that supports it. It also
* helps with a large cache as the disk head movement is reduced. It however
* is a speculative operation so excessive use can remove valuable and needed
* blocks from the cache.
* blocks from the cache. The read-ahead is triggered after two misses of
* ascending consecutive blocks or a read hit of a block read by the
* most-resent read-ahead transfer. The read-ahead works per disk, but all
* transfers are issued by the read-ahead task.
*
* The cache has the following lists of buffers:
* - LRU: Accessed or transfered buffers released in least recently used
@@ -379,6 +382,8 @@ typedef struct rtems_bdbuf_config {
uint32_t buffer_max; /**< Maximum buffer size
* supported. It is also the
* allocation size. */
rtems_task_priority read_ahead_priority; /**< Priority of the read-ahead
* task. */
} rtems_bdbuf_config;
/**
@@ -389,8 +394,8 @@ typedef struct rtems_bdbuf_config {
extern const rtems_bdbuf_config rtems_bdbuf_configuration;
/**
* The max_read_ahead_blocks value is altered if there are fewer buffers
* than this defined max. This stops thrashing in the cache.
* The default value for the maximum read-ahead blocks disables the read-ahead
* feature.
*/
#define RTEMS_BDBUF_MAX_READ_AHEAD_BLOCKS_DEFAULT 0
@@ -425,6 +430,12 @@ extern const rtems_bdbuf_config rtems_bdbuf_configuration;
#define RTEMS_BDBUF_SWAPOUT_WORKER_TASK_PRIORITY_DEFAULT \
RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT
/**
* Default read-ahead task priority. The same as the swap-out task.
*/
#define RTEMS_BDBUF_READ_AHEAD_TASK_PRIORITY_DEFAULT \
RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT
/**
* Default task stack size for swap-out and worker tasks.
*/
@@ -621,7 +632,7 @@ rtems_bdbuf_syncdev (rtems_disk_device *dd);
/**
* @brief Purges all buffers corresponding to the disk device @a dd.
*
* This may result in loss of data.
* This may result in loss of data. The read-ahead state of this device is reset.
*
* Before you can use this function, the rtems_bdbuf_init() routine must be
* called at least once to initialize the cache, otherwise a fatal error will
@@ -635,7 +646,8 @@ rtems_bdbuf_purge_dev (rtems_disk_device *dd);
/**
* @brief Sets the block size of a disk device.
*
* This will set the block size derived fields of the disk device.
* This will set the block size derived fields of the disk device. The
* read-ahead state of this device is reset.
*
* Before you can use this function, the rtems_bdbuf_init() routine must be
* called at least once to initialize the cache, otherwise a fatal error will
+37
View File
@@ -16,6 +16,7 @@
#include <rtems.h>
#include <rtems/libio.h>
#include <rtems/chain.h>
#include <stdlib.h>
#ifdef __cplusplus
@@ -54,6 +55,37 @@ typedef int (*rtems_block_device_ioctl)(
void *argp
);
/**
* @brief Trigger value to disable further read-ahead requests.
*/
#define RTEMS_DISK_READ_AHEAD_NO_TRIGGER ((rtems_blkdev_bnum) -1)
/**
* @brief Read-ahead control.
*/
typedef struct {
/**
* @brief Chain node for the read-ahead request queue of the read-ahead task.
*/
rtems_chain_node node;
/**
* @brief Block value to trigger the read-ahead request.
*
* A value of @ref RTEMS_DISK_READ_AHEAD_NO_TRIGGER will disable further
* read-ahead requests since no valid block can have this value.
*/
rtems_blkdev_bnum trigger;
/**
* @brief Start block for the next read-ahead request.
*
* In case the trigger value is out of range of valid blocks, this value my
* be arbitrary.
*/
rtems_blkdev_bnum next;
} rtems_disk_read_ahread;
/**
* @brief Description of a disk device (logical and physical disks).
*
@@ -168,6 +200,11 @@ struct rtems_disk_device {
* releases this disk.
*/
bool deleted;
/**
* @brief Read-ahead control for this disk.
*/
rtems_disk_read_ahread read_ahead;
};
/**
File diff suppressed because it is too large. Load diff
+2
View File
@@ -36,6 +36,7 @@ rtems_status_code rtems_disk_init_phys(
dd->media_block_size = block_size;
dd->ioctl = handler;
dd->driver_data = driver_data;
dd->read_ahead.trigger = RTEMS_DISK_READ_AHEAD_NO_TRIGGER;
if (block_count > 0) {
if ((*handler)(dd, RTEMS_BLKIO_CAPABILITIES, &dd->capabilities) != 0) {
@@ -67,6 +68,7 @@ rtems_status_code rtems_disk_init_log(
dd->media_block_size = phys_dd->media_block_size;
dd->ioctl = phys_dd->ioctl;
dd->driver_data = phys_dd->driver_data;
dd->read_ahead.trigger = RTEMS_DISK_READ_AHEAD_NO_TRIGGER;
if (phys_dd->phys_dev == phys_dd) {
rtems_blkdev_bnum phys_block_count = phys_dd->size;
+9 -2
View File
@@ -1241,6 +1241,10 @@ rtems_fs_init_functions_t rtems_fs_init_helper =
#define CONFIGURE_BDBUF_BUFFER_MAX_SIZE \
RTEMS_BDBUF_BUFFER_MAX_SIZE_DEFAULT
#endif
#ifndef CONFIGURE_BDBUF_READ_AHEAD_TASK_PRIORITY
#define CONFIGURE_BDBUF_READ_AHEAD_TASK_PRIORITY \
RTEMS_BDBUF_READ_AHEAD_TASK_PRIORITY_DEFAULT
#endif
#ifdef CONFIGURE_INIT
const rtems_bdbuf_config rtems_bdbuf_configuration = {
CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS,
@@ -1253,11 +1257,14 @@ rtems_fs_init_functions_t rtems_fs_init_helper =
CONFIGURE_BDBUF_TASK_STACK_SIZE,
CONFIGURE_BDBUF_CACHE_MEMORY_SIZE,
CONFIGURE_BDBUF_BUFFER_MIN_SIZE,
CONFIGURE_BDBUF_BUFFER_MAX_SIZE
CONFIGURE_BDBUF_BUFFER_MAX_SIZE,
CONFIGURE_BDBUF_READ_AHEAD_TASK_PRIORITY
};
#endif
#define CONFIGURE_LIBBLOCK_TASKS (1 + CONFIGURE_SWAPOUT_WORKER_TASKS)
#define CONFIGURE_LIBBLOCK_TASKS \
(1 + CONFIGURE_SWAPOUT_WORKER_TASKS + \
(CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS != 0))
#define CONFIGURE_LIBBLOCK_TASK_EXTRA_STACKS \
(CONFIGURE_LIBBLOCK_TASKS * \
+1
View File
@@ -1,6 +1,7 @@
ACLOCAL_AMFLAGS = -I ../aclocal
SUBDIRS = POSIX
SUBDIRS += block13
SUBDIRS += rbheap01
SUBDIRS += flashdisk01
+19
View File
@@ -0,0 +1,19 @@
rtems_tests_PROGRAMS = block13
block13_SOURCES = init.c
dist_rtems_tests_DATA = block13.scn block13.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 = $(block13_OBJECTS)
LINK_LIBS = $(block13_LDLIBS)
block13$(EXEEXT): $(block13_OBJECTS) $(block13_DEPENDENCIES)
@rm -f block13$(EXEEXT)
$(make-exe)
include $(top_srcdir)/../automake/local.am
+11
View File
@@ -0,0 +1,11 @@
This file describes the directives and concepts tested by this test set.
test set name: block13
directives:
TBD
concepts:
Tests the read-ahead feature of bdbuf.
+11
View File
@@ -0,0 +1,11 @@
*** TEST BLOCK 13 ***
0 2 3 4 5 6 7 8
reset
8
reset
7
reset
6 7
reset
5 6 8
*** END OF TEST BLOCK 13 ***
File diff suppressed because it is too large. Load diff
+1
View File
@@ -41,6 +41,7 @@ AM_CONDITIONAL(NETTESTS,test "$rtems_cv_RTEMS_NETWORKING" = "yes")
# Explicitly list all Makefiles here
AC_CONFIG_FILES([Makefile
block13/Makefile
rbheap01/Makefile
syscall01/Makefile
flashdisk01/Makefile