summaryrefslogtreecommitdiffstats
path: root/cpukit/libblock/include/rtems/bdbuf.h
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2009-04-29 08:51:07 +0000
committerChris Johns <chrisj@rtems.org>2009-04-29 08:51:07 +0000
commit57aa979e4f8ef9fcace629b22f16faa1b5bf5e73 (patch)
tree0aa45f200cbc05f58c378c3e0e0b35466edb2269 /cpukit/libblock/include/rtems/bdbuf.h
parent2009-04-29 Chris Johns <chrisj@rtems.org> (diff)
downloadrtems-57aa979e4f8ef9fcace629b22f16faa1b5bf5e73.tar.bz2
2009-04-29 Sebastian Huber <sebastian.huber@embedded-brains.de>
* sapi/include/confdefs.h, libblock/include/rtems/bdbuf.h: Changed type of rtems_bdbuf_pool_configuration_size to size_t. * libblock/include/rtems/bdbuf.h, libblock/include/rtems/blkdev.h, libblock/include/rtems/diskdevs.h, libblock/src/bdbuf.c, libblock/src/blkdev.c, libblock/src/diskdevs.c: Buffer pool allocation is now cache aligned. The cache functions are currently not available on all platforms so the cache line size is fixed to 32 bytes for now. Changed various integer types which refer to block sizes, numbers and indexes. Fixed logical block indexes in buffer get and read function. It is now possible to delete logical disks. Modified documentation
Diffstat (limited to 'cpukit/libblock/include/rtems/bdbuf.h')
-rw-r--r--cpukit/libblock/include/rtems/bdbuf.h230
1 files changed, 171 insertions, 59 deletions
diff --git a/cpukit/libblock/include/rtems/bdbuf.h b/cpukit/libblock/include/rtems/bdbuf.h
index 56dc9b44cb..52ee557054 100644
--- a/cpukit/libblock/include/rtems/bdbuf.h
+++ b/cpukit/libblock/include/rtems/bdbuf.h
@@ -1,7 +1,7 @@
/**
- * @file rtems/bdbuf.h
+ * @file
*
- * Block Device Buffer Management
+ * Block device buffer management.
*/
/*
@@ -28,21 +28,101 @@
#ifdef __cplusplus
extern "C" {
#endif
+
+/**
+ * @defgroup rtems_libblock Block Device Library
+ */
+/**
+ * @defgroup rtems_bdbuf Block Device Buffer Management
+ *
+ * @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
+ * the drivers and fast cache look up using an AVL tree.
+ *
+ * The buffers are held in pools based on size. Each pool has buffers and the
+ * buffers follow this state machine:
+ *
+ * @dot
+ * digraph g {
+ * ready [label="Ready\nRead Ahead"];
+ * transfer [label="Transfer"];
+ * accessed [label="Accessed\nAccessed Modified"];
+ * modified [label="Modified\nSynchronized"];
+ * cached [label="Cached"];
+ * ready -> transfer [label="Read\nRead Ahead"];
+ * transfer -> ready [label="Read Ahead Complete"];
+ * ready -> accessed [label="Get"];
+ * transfer -> accessed [label="Read or Write\nComplete"];
+ * transfer -> cached [label="Read or Write\nComplete"];
+ * accessed -> cached [label="Release"];
+ * cached -> accessed [label="Get"];
+ * modified -> accessed [label="Get"];
+ * accessed -> modified [label="Modified"];
+ * accessed -> transfer [label="Swap"];
+ * }
+ * @enddot
+ *
+ * Empty buffers are added to the ready list and removed from this queue when a
+ * caller requests a buffer. This is referred to as getting a buffer in the
+ * code and the event get in the state diagram. The buffer is assigned to a
+ * block and inserted to the AVL based on the block/device key. If the block is
+ * to be read by the user and not in the cache (ready) it is transfered from
+ * the disk into memory. If no ready buffers exist the buffer is taken from the
+ * LRU list. If no buffers are on the LRU list the modified list is check. If
+ * no buffers are on the modified list the request blocks. If buffers are on
+ * the modified list the buffers hold timer is expired and the swap out task
+ * woken.
+ *
+ * A block being accessed is given to the file system layer and not accessable
+ * to another requester until released back to the cache. The same goes to a
+ * buffer in the transfer state. The transfer state means being read or
+ * written. If the file system has modifed the block and releases it as
+ * modified it placed on the pool's modified list and a hold timer
+ * initialised. The buffer is held for the hold time before being written to
+ * disk. Buffers are held for a configurable period of time on the modified
+ * list as a write sets the state to transfer and this locks the buffer out
+ * from the file system until the write complete. Buffers are often repeatable
+ * accessed and modified in a series of small updates so if sent to the disk
+ * when released as modified the user would have to block waiting until it had
+ * been written. This would be a performance problem.
+ *
+ * The code performs mulitple block reads and writes. Multiple block reads or
+ * read ahead increases performance with hardware that supports it. It also
+ * helps with a large cache as the disk head movement is reduced. It how-ever
+ * is a speculative operation so excessive use can remove valuable and needed
+ * blocks from the cache. The get call knows if a read is a for the file system
+ * or if it is a read ahead get. If the get is for a read ahead block and the
+ * block is already in the cache or no ready buffers are available the read
+ * ahead is stopped. The transfer occurs with the blocks so far. If a buffer is
+ * in the read ahead state and release it is placed on the ready list rather
+ * than the LRU list. This means these buffers are used before buffers used by
+ * the file system.
+ *
+ * The pool has the following lists of buffers:
+ * - @c ready: Empty buffers created when the pool is initialised.
+ * - @c modified: Buffers waiting to be written to disk.
+ * - @c sync: Buffers to be synced to disk.
+ * - @c lru: Accessed buffers released in least recently used order.
+ *
+ * @{
+ */
/**
* State of a buffer in the cache.
*/
typedef enum
{
- RTEMS_BDBUF_STATE_EMPTY = 0, /*< Not in use. */
- RTEMS_BDBUF_STATE_READ_AHEAD = 1, /*< Holds read ahead data only */
- RTEMS_BDBUF_STATE_CACHED = 2, /*< In the cache and available */
- RTEMS_BDBUF_STATE_ACCESS = 3, /*< The user has the buffer */
- RTEMS_BDBUF_STATE_MODIFIED = 4, /*< In the cache but modified */
- RTEMS_BDBUF_STATE_ACCESS_MODIFIED = 5, /*< With the user but modified */
- RTEMS_BDBUF_STATE_SYNC = 6, /*< Requested to be sync'ed */
- RTEMS_BDBUF_STATE_TRANSFER = 7 /*< Being transferred to or from disk */
+ RTEMS_BDBUF_STATE_EMPTY = 0, /**< Not in use. */
+ RTEMS_BDBUF_STATE_READ_AHEAD = 1, /**< Holds read ahead data only */
+ RTEMS_BDBUF_STATE_CACHED = 2, /**< In the cache and available */
+ RTEMS_BDBUF_STATE_ACCESS = 3, /**< The user has the buffer */
+ RTEMS_BDBUF_STATE_MODIFIED = 4, /**< In the cache but modified */
+ RTEMS_BDBUF_STATE_ACCESS_MODIFIED = 5, /**< With the user but modified */
+ RTEMS_BDBUF_STATE_SYNC = 6, /**< Requested to be sync'ed */
+ RTEMS_BDBUF_STATE_TRANSFER = 7 /**< Being transferred to or from disk */
} rtems_bdbuf_buf_state;
/**
@@ -57,27 +137,27 @@ typedef struct rtems_bdbuf_buffer
struct rtems_bdbuf_avl_node
{
- signed char cache; /*< Cache */
- struct rtems_bdbuf_buffer* left; /*< Left Child */
- struct rtems_bdbuf_buffer* right; /*< Right Child */
- signed char bal; /*< The balance of the sub-tree */
+ signed char cache; /**< Cache */
+ struct rtems_bdbuf_buffer* left; /**< Left Child */
+ struct rtems_bdbuf_buffer* right; /**< Right Child */
+ signed char bal; /**< The balance of the sub-tree */
} avl;
- dev_t dev; /*< device number */
- rtems_blkdev_bnum block; /*< block number on the device */
+ dev_t dev; /**< device number */
+ rtems_blkdev_bnum block; /**< block number on the device */
- unsigned char* buffer; /*< Pointer to the buffer memory area */
- int error; /*< If not 0 indicate an error value (errno)
+ unsigned char* buffer; /**< Pointer to the buffer memory area */
+ int error; /**< If not 0 indicate an error value (errno)
* which can be used by user later */
- volatile rtems_bdbuf_buf_state state; /*< State of the buffer. */
+ volatile rtems_bdbuf_buf_state state; /**< State of the buffer. */
- volatile uint32_t waiters; /*< The number of threads waiting on this
+ volatile uint32_t waiters; /**< The number of threads waiting on this
* buffer. */
- rtems_bdpool_id pool; /*< Identifier of buffer pool to which this buffer
+ rtems_bdpool_id pool; /**< Identifier of buffer pool to which this buffer
belongs */
- volatile uint32_t hold_timer; /*< Timer to indicate how long a buffer
+ volatile uint32_t hold_timer; /**< Timer to indicate how long a buffer
* has been held in the cache modified. */
} rtems_bdbuf_buffer;
@@ -87,38 +167,38 @@ typedef struct rtems_bdbuf_buffer
*/
typedef struct rtems_bdbuf_pool
{
- uint32_t blksize; /*< The size of the blocks (in bytes) */
- uint32_t nblks; /*< Number of blocks in this pool */
+ uint32_t blksize; /**< The size of the blocks (in bytes) */
+ uint32_t nblks; /**< Number of blocks in this pool */
- uint32_t flags; /*< Configuration flags */
+ uint32_t flags; /**< Configuration flags */
- rtems_id lock; /*< The pool lock. Lock this data and
+ rtems_id lock; /**< The pool lock. Lock this data and
* all BDs. */
- rtems_id sync_lock; /*< Sync calls lock writes. */
- bool sync_active; /*< True if a sync is active. */
- rtems_id sync_requester; /*< The sync requester. */
- dev_t sync_device; /*< The device to sync */
+ rtems_id sync_lock; /**< Sync calls lock writes. */
+ bool sync_active; /**< True if a sync is active. */
+ rtems_id sync_requester; /**< The sync requester. */
+ dev_t sync_device; /**< The device to sync */
- rtems_bdbuf_buffer* tree; /*< Buffer descriptor lookup AVL tree
+ rtems_bdbuf_buffer* tree; /**< Buffer descriptor lookup AVL tree
* root */
- rtems_chain_control ready; /*< Free buffers list (or read-ahead) */
- rtems_chain_control lru; /*< Last recently used list */
- rtems_chain_control modified; /*< Modified buffers list */
- rtems_chain_control sync; /*< Buffers to sync list */
+ rtems_chain_control ready; /**< Free buffers list (or read-ahead) */
+ rtems_chain_control lru; /**< Last recently used list */
+ rtems_chain_control modified; /**< Modified buffers list */
+ rtems_chain_control sync; /**< Buffers to sync list */
- rtems_id access; /*< Obtain if waiting for a buffer in the
+ rtems_id access; /**< Obtain if waiting for a buffer in the
* ACCESS state. */
- volatile uint32_t access_waiters; /*< Count of access blockers. */
- rtems_id transfer; /*< Obtain if waiting for a buffer in the
+ volatile uint32_t access_waiters; /**< Count of access blockers. */
+ rtems_id transfer; /**< Obtain if waiting for a buffer in the
* TRANSFER state. */
- volatile uint32_t transfer_waiters; /*< Count of transfer blockers. */
- rtems_id waiting; /*< Obtain if waiting for a buffer and the
+ volatile uint32_t transfer_waiters; /**< Count of transfer blockers. */
+ rtems_id waiting; /**< Obtain if waiting for a buffer and the
* none are available. */
- volatile uint32_t wait_waiters; /*< Count of waiting blockers. */
+ volatile uint32_t wait_waiters; /**< Count of waiting blockers. */
- rtems_bdbuf_buffer* bds; /*< Pointer to table of buffer descriptors
+ rtems_bdbuf_buffer* bds; /**< Pointer to table of buffer descriptors
* allocated for this buffer pool. */
- void* buffers; /*< The buffer's memory. */
+ void* buffers; /**< The buffer's memory. */
} rtems_bdbuf_pool;
/**
@@ -126,35 +206,46 @@ typedef struct rtems_bdbuf_pool
* location) for buffering layer pool.
*/
typedef struct rtems_bdbuf_pool_config {
- int size; /*< Size of block */
- int num; /*< Number of blocks of appropriate size */
- unsigned char* mem_area; /*< Pointer to the blocks location or NULL, in this
+ int size; /**< Size of block */
+ int num; /**< Number of blocks of appropriate size */
+ unsigned char* mem_area; /**< Pointer to the blocks location or NULL, in this
* case memory for blocks will be allocated by
* Buffering Layer with the help of RTEMS partition
* manager */
} rtems_bdbuf_pool_config;
/**
- * External references provided by the user for each pool in the system.
+ * External reference to the pool configuration table describing each pool in
+ * the system.
+ *
+ * The configuration table is provided by the application.
*/
extern rtems_bdbuf_pool_config rtems_bdbuf_pool_configuration[];
-extern int rtems_bdbuf_pool_configuration_size;
+
+/**
+ * External reference the size of the pool configuration table
+ * @ref rtems_bdbuf_pool_configuration.
+ *
+ * The configuration table size is provided by the application.
+ */
+extern size_t rtems_bdbuf_pool_configuration_size;
/**
* Buffering configuration definition. See confdefs.h for support on using this
* structure.
*/
typedef struct rtems_bdbuf_config {
- uint32_t max_read_ahead_blocks; /*< Number of blocks to read ahead. */
- uint32_t max_write_blocks; /*< Number of blocks to write at once. */
- rtems_task_priority swapout_priority; /*< Priority of the swap out task. */
- uint32_t swapout_period; /*< Period swapout checks buf timers. */
- uint32_t swap_block_hold; /*< Period a buffer is held. */
+ uint32_t max_read_ahead_blocks; /**< Number of blocks to read ahead. */
+ uint32_t max_write_blocks; /**< Number of blocks to write at once. */
+ rtems_task_priority swapout_priority; /**< Priority of the swap out task. */
+ uint32_t swapout_period; /**< Period swapout checks buf timers. */
+ uint32_t swap_block_hold; /**< Period a buffer is held. */
} rtems_bdbuf_config;
/**
- * External referernce to the configuration. The configuration is provided by
- * the user.
+ * External reference to the configuration.
+ *
+ * The configuration is provided by the application.
*/
extern rtems_bdbuf_config rtems_bdbuf_configuration;
@@ -163,10 +254,26 @@ extern rtems_bdbuf_config rtems_bdbuf_configuration;
* than this defined max. This stops thrashing in the cache.
*/
#define RTEMS_BDBUF_MAX_READ_AHEAD_BLOCKS_DEFAULT 32
+
+/**
+ * Default maximum number of blocks to write at once.
+ */
#define RTEMS_BDBUF_MAX_WRITE_BLOCKS_DEFAULT 16
+
+/**
+ * Default swap-out task priority.
+ */
#define RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT 15
-#define RTEMS_BDBUF_SWAPOUT_TASK_SWAP_PERIOD_DEFAULT 250 /* milli-seconds */
-#define RTEMS_BDBUF_SWAPOUT_TASK_BLOCK_HOLD_DEFAULT 1000 /* milli-seconds */
+
+/**
+ * Default swap-out task swap period in milli seconds.
+ */
+#define RTEMS_BDBUF_SWAPOUT_TASK_SWAP_PERIOD_DEFAULT 250
+
+/**
+ * Default swap-out task block hold time in milli seconds.
+ */
+#define RTEMS_BDBUF_SWAPOUT_TASK_BLOCK_HOLD_DEFAULT 1000
/**
* Prepare buffering layer to work - initialize buffer descritors and (if it is
@@ -335,8 +442,13 @@ rtems_bdbuf_find_pool (uint32_t block_size, rtems_bdpool_id *pool);
*
* @note Buffer pools enumerated continuously starting from 0.
*/
-rtems_status_code
-rtems_bdbuf_get_pool_info (rtems_bdpool_id pool, int *block_size, int *blocks);
+rtems_status_code rtems_bdbuf_get_pool_info(
+ rtems_bdpool_id pool,
+ uint32_t *block_size,
+ uint32_t *blocks
+);
+
+/** @} */
#ifdef __cplusplus
}