Changeset 57aa979 in rtems for cpukit/libblock/src/bdbuf.c


Ignore:
Timestamp:
Apr 29, 2009, 8:51:07 AM (11 years ago)
Author:
Chris Johns <chrisj@…>
Branches:
4.10, 4.11, 5, master
Children:
24cdb7d
Parents:
92c70b9
Message:

2009-04-29 Sebastian Huber <sebastian.huber@…>

  • 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
File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libblock/src/bdbuf.c

    r92c70b9 r57aa979  
     1/**
     2 * @file
     3 *
     4 * Block device buffer management.
     5 */
     6
    17/*
    28 * Disk I/O buffering
     
    1622
    1723/**
    18  * @file
    19  *
    20  * The Buffer Descriptor Buffer code implements a cache between the disk
    21  * devices and file systems. The code provides read ahead and write queuing to
    22  * the drivers and fast cache look up using an AVL tree.
    23  *
    24  * The buffers are held in pools based on size. Each pool has buffers and the
    25  * buffers follow this state machine:
    26  *                                 
    27  *                   read/read ahead
    28  *          +-------------------------------+
    29  *          |                               v
    30  *     +-----------+ read ahead      +------------+
    31  *     | READY,    |  complete       |            |---------+
    32  *     |  READ     |<----------------|  TRANSFER  |         |
    33  *     |   AHEAD   |   +-------------|            |<--+     |
    34  *     +-----------+   | read/write  +------------+   |     |
    35  *              | get  v complete                swap |     |
    36  *              |    +-----------+ modified  +------------+ |
    37  *              +--->| ACCESSED, |---------->|  MODIFIED, | |
    38  *                   | ACCESSED  |<----------|  SYNC      | |
    39  *              +----|  MODIFIED |<--+   get |            | |
    40  *              |    +-----------+   |       +------------+ |
    41  *              | release        get |                      |
    42  *              |    +-----------+   |                      |
    43  *              +--->|           |---+        read complete |
    44  *                   |   CACHED  |           write complete |
    45  *                   |           |<-------------------------+
    46  *                   +-----------+
    47  *         
    48  * Empty buffers are added to the ready list and removed from this queue when a
    49  * caller requests a buffer. This is referred to as getting a buffer in the
    50  * code and the event get in the state diagram. The buffer is assigned to a
    51  * block and inserted to the AVL based on the block/device key. If the block is
    52  * to be read by the user and not in the cache (ready) it is transfered from
    53  * the disk into memory. If no ready buffers exist the buffer is taken from the
    54  * LRU list. If no buffers are on the LRU list the modified list is check. If
    55  * no buffers are on the modified list the request blocks. If buffers are on
    56  * the modified list the buffers hold timer is expired and the swap out task
    57  * woken.
    58  *
    59  * A block being accessed is given to the file system layer and not accessable
    60  * to another requester until released back to the cache. The same goes to a
    61  * buffer in the transfer state. The transfer state means being read or
    62  * written. If the file system has modifed the block and releases it as
    63  * modified it placed on the pool's modified list and a hold timer
    64  * initialised. The buffer is held for the hold time before being written to
    65  * disk. Buffers are held for a configurable period of time on the modified
    66  * list as a write sets the state to transfer and this locks the buffer out
    67  * from the file system until the write complete. Buffers are often repeatable
    68  * accessed and modified in a series of small updates so if sent to the disk
    69  * when released as modified the user would have to block waiting until it had
    70  * been written. This would be a performance problem.
    71  *
    72  * The code performs mulitple block reads and writes. Multiple block reads or
    73  * read ahead increases performance with hardware that supports it. It also
    74  * helps with a large cache as the disk head movement is reduced. It how-ever
    75  * is a speculative operation so excessive use can remove valuable and needed
    76  * blocks from the cache. The get call knows if a read is a for the file system
    77  * or if it is a read ahead get. If the get is for a read ahead block and the
    78  * block is already in the cache or no ready buffers are available the read
    79  * ahead is stopped. The transfer occurs with the blocks so far. If a buffer is
    80  * in the read ahead state and release it is placed on the ready list rather
    81  * than the LRU list. This means these buffers are used before buffers used by
    82  * the file system.
    83  *
    84  * The pool have the following lists of buffers:
    85  *
    86  *   ready        - Empty buffers created when the pool is initialised.
    87  *   modified     - Buffers waiting to be written to disk.
    88  *   sync         - Buffers to be synced to disk.
    89  *   lru          - Accessed buffers released in least recently used order.
    90  */
    91 
    92 /**
    9324 * Set to 1 to enable debug tracing.
    9425 */
     
    10132#include <rtems.h>
    10233#include <rtems/error.h>
     34#include <rtems/malloc.h>
    10335#include <limits.h>
    10436#include <errno.h>
     
    431363 * Removes the node from the tree.
    432364 *
    433  * @param root_addr Pointer to pointer to the root node
     365 * @param root Pointer to pointer to the root node
    434366 * @param node Pointer to the node to remove
    435367 * @retval 0 Item removed
     
    705637 * Get the pool for the device.
    706638 *
    707  * @param pdd Physical disk device.
     639 * @param pid Physical disk device.
    708640 */
    709641static rtems_bdbuf_pool*
     
    924856                             rtems_bdpool_id          pid)
    925857{
     858  int                 rv = 0;
    926859  unsigned char*      buffer = config->mem_area;
    927860  rtems_bdbuf_pool*   pool;
     
    929862  rtems_status_code   sc;
    930863  uint32_t            b;
     864  int                 cache_aligment = 32 /* FIXME rtems_cache_get_data_line_size() */;
     865
     866  /* For unspecified cache alignments we use the CPU alignment */
     867  if (cache_aligment <= 0)
     868  {
     869    cache_aligment = CPU_ALIGNMENT;
     870  }
    931871
    932872  pool = rtems_bdbuf_get_pool (pid);
     
    962902
    963903  /*
    964    * Allocate memory for buffers if required.
     904   * Allocate memory for buffers if required.  The pool memory will be cache
     905   * aligned.  It is possible to free the memory allocated by rtems_memalign()
     906   * with free().
    965907   */
    966908  if (buffer == NULL)
    967909  {
    968     buffer = pool->buffers = malloc (config->num * config->size);
    969     if (!pool->buffers)
     910    rv = rtems_memalign ((void **) &buffer,
     911                         cache_aligment,
     912                         config->num * config->size);
     913    if (rv != 0)
    970914    {
    971915      free (pool->bds);
    972916      return RTEMS_NO_MEMORY;
    973917    }
     918    pool->buffers = buffer;
    974919  }
    975920
     
    10801025}
    10811026
    1082 /**
    1083  * Prepare buffering layer to work - initialize buffer descritors and (if it is
    1084  * neccessary) buffers. Buffers will be allocated accoriding to the
    1085  * configuration table, each entry describes the size of block and the size of
    1086  * the pool. After initialization all blocks is placed into the ready state.
    1087  * lists.
    1088  *
    1089  * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
    1090  *         successfully or error code if error is occured)
    1091  */
    10921027rtems_status_code
    10931028rtems_bdbuf_init (void)
     
    12101145 * unlocked if the call could block.
    12111146 *
    1212  * @param device The physical disk device
     1147 * @param pdd The physical disk device
    12131148 * @param pool The pool reference
    12141149 * @param block Absolute media block number
     
    14021337}
    14031338
    1404 /**
    1405  * Get block buffer for data to be written into. The buffers is set to the
    1406  * access or modifed access state. If the buffer is in the cache and modified
    1407  * the state is access modified else the state is access. This buffer contents
    1408  * are not initialised if the buffer is not already in the cache. If the block
    1409  * is already resident in memory it is returned how-ever if not in memory the
    1410  * buffer is not read from disk. This call is used when writing the whole block
    1411  * on a disk rather than just changing a part of it. If there is no buffers
    1412  * available this call will block. A buffer obtained with this call will not be
    1413  * involved in a transfer request and will not be returned to another user
    1414  * until released. If the buffer is already with a user when this call is made
    1415  * the call is blocked until the buffer is returned. The highest priority
    1416  * waiter will obtain the buffer first.
    1417  *
    1418  * The block number is the linear block number. This is relative to the start
    1419  * of the partition on the media.
    1420  *
    1421  * @param device Device number (constructed of major and minor device number)
    1422  * @param block  Linear media block number
    1423  * @param bd     Reference to the buffer descriptor pointer.
    1424  *
    1425  * @return       RTEMS status code (RTEMS_SUCCESSFUL if operation completed
    1426  *               successfully or error code if error is occured)
    1427  */
    14281339rtems_status_code
    14291340rtems_bdbuf_get (dev_t                device,
     
    14481359  }
    14491360
    1450   block += dd->start;
    1451 
    14521361  pool = rtems_bdbuf_get_pool (dd->phys_dev->pool);
    14531362 
     
    14551364
    14561365#if RTEMS_BDBUF_TRACE
    1457   rtems_bdbuf_printf ("get: %d (dev = %08x)\n", block, device);
     1366  /* Print the block index relative to the physical disk */
     1367  rtems_bdbuf_printf ("get: %d (dev = %08x)\n", block + dd->start, device);
    14581368#endif
    14591369
    1460   bd = rtems_bdbuf_get_buffer (dd->phys_dev, pool, block, false);
     1370  bd = rtems_bdbuf_get_buffer (dd->phys_dev, pool, block + dd->start, false);
    14611371
    14621372  if (bd->state == RTEMS_BDBUF_STATE_MODIFIED)
     
    14951405}
    14961406
    1497 /**
    1498  * Get the block buffer and if not already in the cache read from the disk. If
    1499  * specified block already cached return. The buffer is set to the access or
    1500  * modifed access state. If the buffer is in the cache and modified the state
    1501  * is access modified else the state is access. If block is already being read
    1502  * from disk for being written to disk this call blocks. If the buffer is
    1503  * waiting to be written it is removed from modified queue and returned to the
    1504  * user. If the buffer is not in the cache a new buffer is obtained and the
    1505  * data read from disk. The call may block until these operations complete. A
    1506  * buffer obtained with this call will not be involved in a transfer request
    1507  * and will not be returned to another user until released. If the buffer is
    1508  * already with a user when this call is made the call is blocked until the
    1509  * buffer is returned. The highest priority waiter will obtain the buffer
    1510  * first.
    1511  *
    1512  * @note Read ahead always reads buffers in sequence. All multi-block reads
    1513  *       read consecutive blocks.
    1514  *
    1515  * @param device Device number (constructed of major and minor device number)
    1516  * @param block  Linear media block number
    1517  * @param bd     Reference to the buffer descriptor pointer.
    1518  *
    1519  * @return       RTEMS status code (RTEMS_SUCCESSFUL if operation completed
    1520  *               successfully or error code if error is occured)
    1521  */
    15221407rtems_status_code
    15231408rtems_bdbuf_read (dev_t                device,
     
    15461431  if (dd == NULL)
    15471432    return RTEMS_INVALID_ID;
    1548 
    1549   block += dd->start;
    1550  
    1551 #if RTEMS_BDBUF_TRACE
    1552   rtems_bdbuf_printf ("read: %d (dev = %08x)\n", block, device);
    1553 #endif
    1554  
    1555   if (block >= dd->size)
    1556   {
     1433 
     1434  if (block >= dd->size) {
    15571435    rtems_disk_release(dd);
    15581436    return RTEMS_INVALID_NUMBER;
    15591437  }
     1438 
     1439#if RTEMS_BDBUF_TRACE
     1440  /* Print the block index relative to the physical disk */
     1441  rtems_bdbuf_printf ("read: %d (dev = %08x)\n", block + dd->start, device);
     1442#endif
    15601443
    15611444  req->bufnum = 0;
     
    15881471     */
    15891472    bd = rtems_bdbuf_get_buffer (dd->phys_dev, pool,
    1590                                  block + req->bufnum,
     1473                                 block + dd->start + req->bufnum,
    15911474                                 req->bufnum == 0 ? false : true);
    15921475
     
    17121595}
    17131596
    1714 /**
    1715  * Release the buffer obtained by a read call back to the cache. If the buffer
    1716  * was obtained by a get call and was not already in the cache the release
    1717  * modified call should be used. A buffer released with this call obtained by a
    1718  * get call may not be in sync with the contents on disk. If the buffer was in
    1719  * the cache and modified before this call it will be returned to the modified
    1720  * queue. The buffers is returned to the end of the LRU list.
    1721  *
    1722  * @param bd Reference to the buffer descriptor.
    1723  *
    1724  * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
    1725  *         successfully or error code if error is occured)
    1726  */
    17271597rtems_status_code
    17281598rtems_bdbuf_release (rtems_bdbuf_buffer* bd)
     
    17861656}
    17871657
    1788 /**
    1789  * Release the buffer allocated with a get or read call placing it on the
    1790  * modidied list.  If the buffer was not released modified before the hold
    1791  * timer is set to the configuration value. If the buffer had been released
    1792  * modified before but not written to disk the hold timer is not updated. The
    1793  * buffer will be written to disk when the hold timer has expired, there are
    1794  * not more buffers available in the cache and a get or read buffer needs one
    1795  * or a sync call has been made. If the buffer is obtained with a get or read
    1796  * before the hold timer has expired the buffer will be returned to the user.
    1797  *
    1798  * @param bd Reference to the buffer descriptor.
    1799  *
    1800  * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
    1801  *         successfully or error code if error is occured)
    1802  */
    18031658rtems_status_code
    18041659rtems_bdbuf_release_modified (rtems_bdbuf_buffer* bd)
     
    18291684}
    18301685
    1831 /**
    1832  * Release the buffer as modified and wait until it has been synchronized with
    1833  * the disk by writing it. This buffer will be the first to be transfer to disk
    1834  * and other buffers may also be written if the maximum number of blocks in a
    1835  * requests allows it.
    1836  *
    1837  * @note This code does not lock the sync mutex and stop additions to the
    1838  *       modified queue.
    1839  *
    1840  * @param bd Reference to the buffer descriptor.
    1841  *
    1842  * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
    1843  *         successfully or error code if error is occured)
    1844  */
    18451686rtems_status_code
    18461687rtems_bdbuf_sync (rtems_bdbuf_buffer* bd)
     
    18961737}
    18971738
    1898 /**
    1899  * Synchronize all modified buffers for this device with the disk and wait
    1900  * until the transfers have completed. The sync mutex for the pool is locked
    1901  * stopping the addition of any further modifed buffers. It is only the
    1902  * currently modified buffers that are written.
    1903  *
    1904  * @param dev Block device number
    1905  *
    1906  * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
    1907  *         successfully or error code if error is occured)
    1908  */
    19091739rtems_status_code
    19101740rtems_bdbuf_syncdev (dev_t dev)
     
    24282258}
    24292259
    2430 /**
    2431  * Find first appropriate buffer pool. This primitive returns the index of
    2432  * first buffer pool which block size is greater than or equal to specified
    2433  * size.
    2434  *
    2435  * @param block_size Requested block size
    2436  * @param pool The pool to use for the requested pool size.
    2437  *
    2438  * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
    2439  *         successfully or error code if error is occured)
    2440  * @retval RTEMS_INVALID_SIZE The specified block size is invalid (not a power
    2441  *         of 2)
    2442  * @retval RTEMS_NOT_DEFINED The buffer pool for this or greater block size
    2443  *         is not configured.
    2444  */
    24452260rtems_status_code
    24462261rtems_bdbuf_find_pool (uint32_t block_size, rtems_bdpool_id *pool)
     
    24812296}
    24822297
    2483 /**
    2484  * Obtain characteristics of buffer pool with specified number.
    2485  *
    2486  * @param pool Buffer pool number
    2487  * @param block_size Block size for which buffer pool is configured returned
    2488  *                   there
    2489  * @param blocks Number of buffers in buffer pool.
    2490  *
    2491  * RETURNS:
    2492  * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed
    2493  *         successfully or error code if error is occured)
    2494  * @retval RTEMS_INVALID_SIZE The appropriate buffer pool is not configured.
    2495  *
    2496  * @note Buffer pools enumerated continuously starting from 0.
    2497  */
    2498 rtems_status_code
    2499 rtems_bdbuf_get_pool_info (rtems_bdpool_id pool, int* block_size, int* blocks)
     2298rtems_status_code rtems_bdbuf_get_pool_info(
     2299  rtems_bdpool_id pool,
     2300  uint32_t *block_size,
     2301  uint32_t *blocks
     2302)
    25002303{
    25012304  if (pool >= rtems_bdbuf_ctx.npools)
Note: See TracChangeset for help on using the changeset viewer.