source: rtems/cpukit/libblock/include/rtems/bdbuf.h @ 4670d91

4.104.115
Last change on this file since 4670d91 was 4670d91, checked in by Joel Sherrill <joel.sherrill@…>, on 05/15/09 at 12:52:12

2009-05-15 Sebastian Huber <sebastian.huber@…>

  • Doxygen.in: Fixed project name. Added project number. Enabled auto brief. Disabled include graphs.
  • include/rtems/irq-extension.h, libblock/include/rtems/bdpart.h, libblock/include/rtems/bdbuf.h, libblock/include/rtems/bdpart.h, libblock/include/rtems/blkdev.h, libblock/include/rtems/diskdevs.h, libblock/include/rtems/ramdisk.h, libblock/src/bdbuf.c, libblock/src/blkdev.c, libblock/src/diskdevs.c, libblock/src/ramdisk.c: Documentation.
  • libblock/src/bdpart.c: Documentation. Fixed NULL pointer access.
  • Property mode set to 100644
File size: 18.6 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup rtems_bdbuf
5 *
6 * Block device buffer management.
7 */
8 
9/*
10 * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
11 * Author: Victor V. Vengerov <vvv@oktet.ru>
12 *
13 * Copyright (C) 2008 Chris Johns <chrisj@rtems.org>
14 *    Rewritten to remove score mutex access. Fixes many performance
15 *    issues.
16 *
17 * @(#) bdbuf.h,v 1.9 2005/02/02 00:06:18 joel Exp
18 */
19
20#ifndef _RTEMS_BDBUF_H
21#define _RTEMS_BDBUF_H
22
23#include <rtems.h>
24#include <rtems/libio.h>
25#include <rtems/chain.h>
26
27#include <rtems/blkdev.h>
28#include <rtems/diskdevs.h>
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33       
34/**
35 * @defgroup rtems_libblock Block Device Library
36 */
37
38/**
39 * @defgroup rtems_bdbuf Block Device Buffer Management
40 *
41 * @ingroup rtems_libblock
42 *
43 * The Block Device Buffer Management implements a cache between the disk
44 * devices and file systems. The code provides read ahead and write queuing to
45 * the drivers and fast cache look up using an AVL tree.
46 *
47 * The buffers are held in pools based on size. Each pool has buffers and the
48 * buffers follow this state machine:
49 *                                 
50 * @dot
51 * digraph g {
52 *   ready [label="Ready\nRead Ahead"];
53 *   transfer [label="Transfer"];
54 *   accessed [label="Accessed\nAccessed Modified"];
55 *   modified [label="Modified\nSynchronized"];
56 *   cached [label="Cached"];
57 *   ready -> transfer [label="Read\nRead Ahead"];
58 *   transfer -> ready [label="Read Ahead Complete"];
59 *   ready -> accessed [label="Get"];
60 *   transfer -> accessed [label="Read or Write\nComplete"];
61 *   transfer -> cached [label="Read or Write\nComplete"];
62 *   accessed -> cached [label="Release"];
63 *   cached -> accessed [label="Get"];
64 *   modified -> accessed [label="Get"];
65 *   accessed -> modified [label="Modified"];
66 *   accessed -> transfer [label="Swap"];
67 * }
68 * @enddot
69 *         
70 * Empty buffers are added to the ready list and removed from this queue when a
71 * caller requests a buffer. This is referred to as getting a buffer in the
72 * code and the event get in the state diagram. The buffer is assigned to a
73 * block and inserted to the AVL based on the block/device key. If the block is
74 * to be read by the user and not in the cache (ready) it is transfered from
75 * the disk into memory. If no ready buffers exist the buffer is taken from the
76 * LRU list. If no buffers are on the LRU list the modified list is check. If
77 * no buffers are on the modified list the request blocks. If buffers are on
78 * the modified list the buffers hold timer is expired and the swap out task
79 * woken.
80 *
81 * A block being accessed is given to the file system layer and not accessable
82 * to another requester until released back to the cache. The same goes to a
83 * buffer in the transfer state. The transfer state means being read or
84 * written. If the file system has modifed the block and releases it as
85 * modified it placed on the pool's modified list and a hold timer
86 * initialised. The buffer is held for the hold time before being written to
87 * disk. Buffers are held for a configurable period of time on the modified
88 * list as a write sets the state to transfer and this locks the buffer out
89 * from the file system until the write complete. Buffers are often repeatable
90 * accessed and modified in a series of small updates so if sent to the disk
91 * when released as modified the user would have to block waiting until it had
92 * been written. This would be a performance problem.
93 *
94 * The code performs mulitple block reads and writes. Multiple block reads or
95 * read ahead increases performance with hardware that supports it. It also
96 * helps with a large cache as the disk head movement is reduced. It how-ever
97 * is a speculative operation so excessive use can remove valuable and needed
98 * blocks from the cache. The get call knows if a read is a for the file system
99 * or if it is a read ahead get. If the get is for a read ahead block and the
100 * block is already in the cache or no ready buffers are available the read
101 * ahead is stopped. The transfer occurs with the blocks so far. If a buffer is
102 * in the read ahead state and release it is placed on the ready list rather
103 * than the LRU list. This means these buffers are used before buffers used by
104 * the file system.
105 *
106 * The pool has the following lists of buffers:
107 *  - @c ready: Empty buffers created when the pool is initialised.
108 *  - @c modified: Buffers waiting to be written to disk.
109 *  - @c sync: Buffers to be synced to disk.
110 *  - @c lru: Accessed buffers released in least recently used order.
111 *
112 * @{
113 */
114
115/**
116 * State of a buffer in the cache.
117 */
118typedef enum
119{
120  RTEMS_BDBUF_STATE_EMPTY = 0,            /**< Not in use. */
121  RTEMS_BDBUF_STATE_READ_AHEAD = 1,       /**< Holds read ahead data only */
122  RTEMS_BDBUF_STATE_CACHED = 2,           /**< In the cache and available */
123  RTEMS_BDBUF_STATE_ACCESS = 3,           /**< The user has the buffer */
124  RTEMS_BDBUF_STATE_MODIFIED = 4,         /**< In the cache but modified */
125  RTEMS_BDBUF_STATE_ACCESS_MODIFIED = 5,  /**< With the user but modified */
126  RTEMS_BDBUF_STATE_SYNC = 6,             /**< Requested to be sync'ed */
127  RTEMS_BDBUF_STATE_TRANSFER = 7          /**< Being transferred to or from disk */
128} rtems_bdbuf_buf_state;
129
130/**
131 * To manage buffers we using buffer descriptors (BD). A BD holds a buffer plus
132 * a range of other information related to managing the buffer in the cache. To
133 * speed-up buffer lookup descriptors are organized in AVL-Tree.  The fields
134 * 'dev' and 'block' are search keys.
135 */
136typedef struct rtems_bdbuf_buffer
137{
138  rtems_chain_node link;       /* Link in the BD onto a number of lists. */
139
140  struct rtems_bdbuf_avl_node
141  {
142    signed char                cache;  /**< Cache */
143    struct rtems_bdbuf_buffer* left;   /**< Left Child */
144    struct rtems_bdbuf_buffer* right;  /**< Right Child */
145    signed char                bal;    /**< The balance of the sub-tree */
146  } avl;
147
148  dev_t             dev;        /**< device number */
149  rtems_blkdev_bnum block;      /**< block number on the device */
150
151  unsigned char*    buffer;     /**< Pointer to the buffer memory area */
152  int               error;      /**< If not 0 indicate an error value (errno)
153                                 * which can be used by user later */
154
155  volatile rtems_bdbuf_buf_state state;  /**< State of the buffer. */
156
157  volatile uint32_t waiters;    /**< The number of threads waiting on this
158                                 * buffer. */
159  rtems_bdpool_id pool;         /**< Identifier of buffer pool to which this buffer
160                                    belongs */
161
162  volatile uint32_t hold_timer; /**< Timer to indicate how long a buffer
163                                 * has been held in the cache modified. */
164} rtems_bdbuf_buffer;
165
166/**
167 * The groups of the blocks with the same size are collected in a pool. Note
168 * that a several of the buffer's groups with the same size can exists.
169 */
170typedef struct rtems_bdbuf_pool
171{
172  uint32_t            blksize;           /**< The size of the blocks (in bytes) */
173  uint32_t            nblks;             /**< Number of blocks in this pool */
174
175  uint32_t            flags;             /**< Configuration flags */
176
177  rtems_id            lock;              /**< The pool lock. Lock this data and
178                                          * all BDs. */
179  rtems_id            sync_lock;         /**< Sync calls lock writes. */
180  bool                sync_active;       /**< True if a sync is active. */
181  rtems_id            sync_requester;    /**< The sync requester. */
182  dev_t               sync_device;       /**< The device to sync */
183
184  rtems_bdbuf_buffer* tree;             /**< Buffer descriptor lookup AVL tree
185                                         * root */
186  rtems_chain_control ready;            /**< Free buffers list (or read-ahead) */
187  rtems_chain_control lru;              /**< Last recently used list */
188  rtems_chain_control modified;         /**< Modified buffers list */
189  rtems_chain_control sync;             /**< Buffers to sync list */
190
191  rtems_id            access;           /**< Obtain if waiting for a buffer in the
192                                         * ACCESS state. */
193  volatile uint32_t   access_waiters;   /**< Count of access blockers. */
194  rtems_id            transfer;         /**< Obtain if waiting for a buffer in the
195                                         * TRANSFER state. */
196  volatile uint32_t   transfer_waiters; /**< Count of transfer blockers. */
197  rtems_id            waiting;          /**< Obtain if waiting for a buffer and the
198                                         * none are available. */
199  volatile uint32_t   wait_waiters;     /**< Count of waiting blockers. */
200
201  rtems_bdbuf_buffer* bds;              /**< Pointer to table of buffer descriptors
202                                         * allocated for this buffer pool. */
203  void*               buffers;          /**< The buffer's memory. */
204} rtems_bdbuf_pool;
205
206/**
207 * Configuration structure describes block configuration (size, amount, memory
208 * location) for buffering layer pool.
209 */
210typedef struct rtems_bdbuf_pool_config {
211  int            size;      /**< Size of block */
212  int            num;       /**< Number of blocks of appropriate size */
213  unsigned char* mem_area;  /**< Pointer to the blocks location or NULL, in this
214                             * case memory for blocks will be allocated by
215                             * Buffering Layer with the help of RTEMS partition
216                             * manager */
217} rtems_bdbuf_pool_config;
218
219/**
220 * External reference to the pool configuration table describing each pool in
221 * the system.
222 *
223 * The configuration table is provided by the application.
224 */
225extern rtems_bdbuf_pool_config rtems_bdbuf_pool_configuration[];
226
227/**
228 * External reference the size of the pool configuration table
229 * @ref rtems_bdbuf_pool_configuration.
230 *
231 * The configuration table size is provided by the application.
232 */
233extern size_t rtems_bdbuf_pool_configuration_size;
234
235/**
236 * Buffering configuration definition. See confdefs.h for support on using this
237 * structure.
238 */
239typedef struct rtems_bdbuf_config {
240  uint32_t            max_read_ahead_blocks; /**< Number of blocks to read ahead. */
241  uint32_t            max_write_blocks;      /**< Number of blocks to write at once. */
242  rtems_task_priority swapout_priority;      /**< Priority of the swap out task. */
243  uint32_t            swapout_period;        /**< Period swapout checks buf timers. */
244  uint32_t            swap_block_hold;       /**< Period a buffer is held. */
245} rtems_bdbuf_config;
246
247/**
248 * External reference to the configuration.
249 *
250 * The configuration is provided by the application.
251 */
252extern rtems_bdbuf_config rtems_bdbuf_configuration;
253
254/**
255 * The max_read_ahead_blocks value is altered if there are fewer buffers
256 * than this defined max. This stops thrashing in the cache.
257 */
258#define RTEMS_BDBUF_MAX_READ_AHEAD_BLOCKS_DEFAULT    32
259
260/**
261 * Default maximum number of blocks to write at once.
262 */
263#define RTEMS_BDBUF_MAX_WRITE_BLOCKS_DEFAULT         16
264
265/**
266 * Default swap-out task priority.
267 */
268#define RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT    15
269
270/**
271 * Default swap-out task swap period in milli seconds.
272 */
273#define RTEMS_BDBUF_SWAPOUT_TASK_SWAP_PERIOD_DEFAULT 250
274
275/**
276 * Default swap-out task block hold time in milli seconds.
277 */
278#define RTEMS_BDBUF_SWAPOUT_TASK_BLOCK_HOLD_DEFAULT  1000
279
280/**
281 * Prepare buffering layer to work - initialize buffer descritors and (if it is
282 * neccessary) buffers. Buffers will be allocated accoriding to the
283 * configuration table, each entry describes the size of block and the size of
284 * the pool. After initialization all blocks is placed into the ready state.
285 * lists.
286 *
287 * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
288 *         successfully or error code if error is occured)
289 */
290rtems_status_code
291rtems_bdbuf_init (void);
292
293/**
294 * Get block buffer for data to be written into. The buffers is set to the
295 * access or modifed access state. If the buffer is in the cache and modified
296 * the state is access modified else the state is access. This buffer contents
297 * are not initialised if the buffer is not already in the cache. If the block
298 * is already resident in memory it is returned how-ever if not in memory the
299 * buffer is not read from disk. This call is used when writing the whole block
300 * on a disk rather than just changing a part of it. If there is no buffers
301 * available this call will block. A buffer obtained with this call will not be
302 * involved in a transfer request and will not be returned to another user
303 * until released. If the buffer is already with a user when this call is made
304 * the call is blocked until the buffer is returned. The highest priority
305 * waiter will obtain the buffer first.
306 *
307 * The block number is the linear block number. This is relative to the start
308 * of the partition on the media.
309 *
310 * @param device Device number (constructed of major and minor device number)
311 * @param block  Linear media block number
312 * @param bd     Reference to the buffer descriptor pointer.
313 *
314 * @return       RTEMS status code (RTEMS_SUCCESSFUL if operation completed
315 *               successfully or error code if error is occured)
316 */
317rtems_status_code
318rtems_bdbuf_get (dev_t device, rtems_blkdev_bnum block, rtems_bdbuf_buffer** bd);
319
320/**
321 * Get the block buffer and if not already in the cache read from the disk. If
322 * specified block already cached return. The buffer is set to the access or
323 * modifed access state. If the buffer is in the cache and modified the state
324 * is access modified else the state is access. If block is already being read
325 * from disk for being written to disk this call blocks. If the buffer is
326 * waiting to be written it is removed from modified queue and returned to the
327 * user. If the buffer is not in the cache a new buffer is obtained and the
328 * data read from disk. The call may block until these operations complete. A
329 * buffer obtained with this call will not be involved in a transfer request
330 * and will not be returned to another user until released. If the buffer is
331 * already with a user when this call is made the call is blocked until the
332 * buffer is returned. The highest priority waiter will obtain the buffer
333 * first.
334 *
335 * @param device Device number (constructed of major and minor device number)
336 * @param block  Linear media block number
337 * @param bd     Reference to the buffer descriptor pointer.
338 *
339 * @return       RTEMS status code (RTEMS_SUCCESSFUL if operation completed
340 *               successfully or error code if error is occured)
341 */
342rtems_status_code
343rtems_bdbuf_read (dev_t device, rtems_blkdev_bnum block, rtems_bdbuf_buffer** bd);
344
345/**
346 * Release the buffer obtained by a read call back to the cache. If the buffer
347 * was obtained by a get call and was not already in the cache the release
348 * modified call should be used. A buffer released with this call obtained by a
349 * get call may not be in sync with the contents on disk. If the buffer was in
350 * the cache and modified before this call it will be returned to the modified
351 * queue. The buffers is returned to the end of the LRU list.
352 *
353 * @param bd Reference to the buffer descriptor.
354 *
355 * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
356 *         successfully or error code if error is occured)
357 */
358rtems_status_code
359rtems_bdbuf_release (rtems_bdbuf_buffer* bd);
360
361/**
362 * Release the buffer allocated with a get or read call placing it on the
363 * modidied list.  If the buffer was not released modified before the hold
364 * timer is set to the configuration value. If the buffer had been released
365 * modified before but not written to disk the hold timer is not updated. The
366 * buffer will be written to disk when the hold timer has expired, there are
367 * not more buffers available in the cache and a get or read buffer needs one
368 * or a sync call has been made. If the buffer is obtained with a get or read
369 * before the hold timer has expired the buffer will be returned to the user.
370 *
371 * @param bd Reference to the buffer descriptor.
372 *
373 * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
374 *         successfully or error code if error is occured)
375 */
376rtems_status_code
377rtems_bdbuf_release_modified (rtems_bdbuf_buffer* bd);
378
379/**
380 * Release the buffer as modified and wait until it has been synchronized with
381 * the disk by writing it. This buffer will be the first to be transfer to disk
382 * and other buffers may also be written if the maximum number of blocks in a
383 * requests allows it.
384 *
385 * @note This code does not lock the sync mutex and stop additions to the
386 *       modified queue.
387
388 * @param bd Reference to the buffer descriptor.
389 *
390 * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
391 *         successfully or error code if error is occured)
392 */
393rtems_status_code
394rtems_bdbuf_sync (rtems_bdbuf_buffer* bd);
395
396/**
397 * Synchronize all modified buffers for this device with the disk and wait
398 * until the transfers have completed. The sync mutex for the pool is locked
399 * stopping the addition of any further modifed buffers. It is only the
400 * currently modified buffers that are written.
401 *
402 * @note Nesting calls to sync multiple devices attached to a single pool will
403 * be handled sequentially. A nested call will be blocked until the first sync
404 * request has complete. This is only true for device using the same pool.
405 *
406 * @param dev Block device number
407 *
408 * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
409 *         successfully or error code if error is occured)
410 */
411rtems_status_code
412rtems_bdbuf_syncdev (dev_t dev);
413
414/**
415 * Find first appropriate buffer pool. This primitive returns the index of
416 * first buffer pool which block size is greater than or equal to specified
417 * size.
418 *
419 * @param block_size Requested block size
420 * @param pool The pool to use for the requested pool size.
421 *
422 * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
423 *         successfully or error code if error is occured)
424 * @retval RTEMS_INVALID_SIZE The specified block size is invalid (not a power
425 *         of 2)
426 * @retval RTEMS_NOT_DEFINED The buffer pool for this or greater block size
427 *         is not configured.
428 */
429rtems_status_code
430rtems_bdbuf_find_pool (uint32_t block_size, rtems_bdpool_id *pool);
431
432/**
433 * Obtain characteristics of buffer pool with specified number.
434 *
435 * @param pool Buffer pool number
436 * @param block_size Block size for which buffer pool is configured returned
437 *                   there
438 * @param blocks Number of buffers in buffer pool.
439 *
440 * RETURNS:
441 * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
442 *         successfully or error code if error is occured)
443 * @retval RTEMS_INVALID_SIZE The appropriate buffer pool is not configured.
444 *
445 * @note Buffer pools enumerated continuously starting from 0.
446 */
447rtems_status_code rtems_bdbuf_get_pool_info(
448  rtems_bdpool_id pool,
449  uint32_t *block_size,
450  uint32_t *blocks
451);
452
453/** @} */
454
455#ifdef __cplusplus
456}
457#endif
458
459#endif
Note: See TracBrowser for help on using the repository browser.