Changeset 57aa979 in rtems for cpukit/libblock


Ignore:
Timestamp:
04/29/09 08:51:07 (15 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
Location:
cpukit/libblock
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • cpukit/libblock/include/rtems/bdbuf.h

    r92c70b9 r57aa979  
    11/**
    2  * @file rtems/bdbuf.h
    3  *
    4  * Block Device Buffer Management
     2 * @file
     3 *
     4 * Block device buffer management.
    55 */
    66 
     
    2929extern "C" {
    3030#endif
    31 
     31       
     32/**
     33 * @defgroup rtems_libblock Block Device Library
     34 */
     35
     36/**
     37 * @defgroup rtems_bdbuf Block Device Buffer Management
     38 *
     39 * @ingroup rtems_libblock
     40 *
     41 * The Block Device Buffer Management implements a cache between the disk
     42 * devices and file systems. The code provides read ahead and write queuing to
     43 * the drivers and fast cache look up using an AVL tree.
     44 *
     45 * The buffers are held in pools based on size. Each pool has buffers and the
     46 * buffers follow this state machine:
     47 *                                 
     48 * @dot
     49 * digraph g {
     50 *   ready [label="Ready\nRead Ahead"];
     51 *   transfer [label="Transfer"];
     52 *   accessed [label="Accessed\nAccessed Modified"];
     53 *   modified [label="Modified\nSynchronized"];
     54 *   cached [label="Cached"];
     55 *   ready -> transfer [label="Read\nRead Ahead"];
     56 *   transfer -> ready [label="Read Ahead Complete"];
     57 *   ready -> accessed [label="Get"];
     58 *   transfer -> accessed [label="Read or Write\nComplete"];
     59 *   transfer -> cached [label="Read or Write\nComplete"];
     60 *   accessed -> cached [label="Release"];
     61 *   cached -> accessed [label="Get"];
     62 *   modified -> accessed [label="Get"];
     63 *   accessed -> modified [label="Modified"];
     64 *   accessed -> transfer [label="Swap"];
     65 * }
     66 * @enddot
     67 *         
     68 * Empty buffers are added to the ready list and removed from this queue when a
     69 * caller requests a buffer. This is referred to as getting a buffer in the
     70 * code and the event get in the state diagram. The buffer is assigned to a
     71 * block and inserted to the AVL based on the block/device key. If the block is
     72 * to be read by the user and not in the cache (ready) it is transfered from
     73 * the disk into memory. If no ready buffers exist the buffer is taken from the
     74 * LRU list. If no buffers are on the LRU list the modified list is check. If
     75 * no buffers are on the modified list the request blocks. If buffers are on
     76 * the modified list the buffers hold timer is expired and the swap out task
     77 * woken.
     78 *
     79 * A block being accessed is given to the file system layer and not accessable
     80 * to another requester until released back to the cache. The same goes to a
     81 * buffer in the transfer state. The transfer state means being read or
     82 * written. If the file system has modifed the block and releases it as
     83 * modified it placed on the pool's modified list and a hold timer
     84 * initialised. The buffer is held for the hold time before being written to
     85 * disk. Buffers are held for a configurable period of time on the modified
     86 * list as a write sets the state to transfer and this locks the buffer out
     87 * from the file system until the write complete. Buffers are often repeatable
     88 * accessed and modified in a series of small updates so if sent to the disk
     89 * when released as modified the user would have to block waiting until it had
     90 * been written. This would be a performance problem.
     91 *
     92 * The code performs mulitple block reads and writes. Multiple block reads or
     93 * read ahead increases performance with hardware that supports it. It also
     94 * helps with a large cache as the disk head movement is reduced. It how-ever
     95 * is a speculative operation so excessive use can remove valuable and needed
     96 * blocks from the cache. The get call knows if a read is a for the file system
     97 * or if it is a read ahead get. If the get is for a read ahead block and the
     98 * block is already in the cache or no ready buffers are available the read
     99 * ahead is stopped. The transfer occurs with the blocks so far. If a buffer is
     100 * in the read ahead state and release it is placed on the ready list rather
     101 * than the LRU list. This means these buffers are used before buffers used by
     102 * the file system.
     103 *
     104 * The pool has the following lists of buffers:
     105 *  - @c ready: Empty buffers created when the pool is initialised.
     106 *  - @c modified: Buffers waiting to be written to disk.
     107 *  - @c sync: Buffers to be synced to disk.
     108 *  - @c lru: Accessed buffers released in least recently used order.
     109 *
     110 * @{
     111 */
    32112
    33113/**
     
    36116typedef enum
    37117{
    38   RTEMS_BDBUF_STATE_EMPTY = 0,            /*< Not in use. */
    39   RTEMS_BDBUF_STATE_READ_AHEAD = 1,       /*< Holds read ahead data only */
    40   RTEMS_BDBUF_STATE_CACHED = 2,           /*< In the cache and available */
    41   RTEMS_BDBUF_STATE_ACCESS = 3,           /*< The user has the buffer */
    42   RTEMS_BDBUF_STATE_MODIFIED = 4,         /*< In the cache but modified */
    43   RTEMS_BDBUF_STATE_ACCESS_MODIFIED = 5,  /*< With the user but modified */
    44   RTEMS_BDBUF_STATE_SYNC = 6,             /*< Requested to be sync'ed */
    45   RTEMS_BDBUF_STATE_TRANSFER = 7          /*< Being transferred to or from disk */
     118  RTEMS_BDBUF_STATE_EMPTY = 0,            /**< Not in use. */
     119  RTEMS_BDBUF_STATE_READ_AHEAD = 1,       /**< Holds read ahead data only */
     120  RTEMS_BDBUF_STATE_CACHED = 2,           /**< In the cache and available */
     121  RTEMS_BDBUF_STATE_ACCESS = 3,           /**< The user has the buffer */
     122  RTEMS_BDBUF_STATE_MODIFIED = 4,         /**< In the cache but modified */
     123  RTEMS_BDBUF_STATE_ACCESS_MODIFIED = 5,  /**< With the user but modified */
     124  RTEMS_BDBUF_STATE_SYNC = 6,             /**< Requested to be sync'ed */
     125  RTEMS_BDBUF_STATE_TRANSFER = 7          /**< Being transferred to or from disk */
    46126} rtems_bdbuf_buf_state;
    47127
     
    58138  struct rtems_bdbuf_avl_node
    59139  {
    60     signed char                cache;  /*< Cache */
    61     struct rtems_bdbuf_buffer* left;   /*< Left Child */
    62     struct rtems_bdbuf_buffer* right;  /*< Right Child */
    63     signed char                bal;    /*< The balance of the sub-tree */
     140    signed char                cache;  /**< Cache */
     141    struct rtems_bdbuf_buffer* left;   /**< Left Child */
     142    struct rtems_bdbuf_buffer* right;  /**< Right Child */
     143    signed char                bal;    /**< The balance of the sub-tree */
    64144  } avl;
    65145
    66   dev_t             dev;        /*< device number */
    67   rtems_blkdev_bnum block;      /*< block number on the device */
    68 
    69   unsigned char*    buffer;     /*< Pointer to the buffer memory area */
    70   int               error;      /*< If not 0 indicate an error value (errno)
     146  dev_t             dev;        /**< device number */
     147  rtems_blkdev_bnum block;      /**< block number on the device */
     148
     149  unsigned char*    buffer;     /**< Pointer to the buffer memory area */
     150  int               error;      /**< If not 0 indicate an error value (errno)
    71151                                 * which can be used by user later */
    72152
    73   volatile rtems_bdbuf_buf_state state;  /*< State of the buffer. */
    74 
    75   volatile uint32_t waiters;    /*< The number of threads waiting on this
     153  volatile rtems_bdbuf_buf_state state;  /**< State of the buffer. */
     154
     155  volatile uint32_t waiters;    /**< The number of threads waiting on this
    76156                                 * buffer. */
    77   rtems_bdpool_id pool;         /*< Identifier of buffer pool to which this buffer
     157  rtems_bdpool_id pool;         /**< Identifier of buffer pool to which this buffer
    78158                                    belongs */
    79159
    80   volatile uint32_t hold_timer; /*< Timer to indicate how long a buffer
     160  volatile uint32_t hold_timer; /**< Timer to indicate how long a buffer
    81161                                 * has been held in the cache modified. */
    82162} rtems_bdbuf_buffer;
     
    88168typedef struct rtems_bdbuf_pool
    89169{
    90   uint32_t            blksize;           /*< The size of the blocks (in bytes) */
    91   uint32_t            nblks;             /*< Number of blocks in this pool */
    92 
    93   uint32_t            flags;             /*< Configuration flags */
    94 
    95   rtems_id            lock;              /*< The pool lock. Lock this data and
     170  uint32_t            blksize;           /**< The size of the blocks (in bytes) */
     171  uint32_t            nblks;             /**< Number of blocks in this pool */
     172
     173  uint32_t            flags;             /**< Configuration flags */
     174
     175  rtems_id            lock;              /**< The pool lock. Lock this data and
    96176                                          * all BDs. */
    97   rtems_id            sync_lock;         /*< Sync calls lock writes. */
    98   bool                sync_active;       /*< True if a sync is active. */
    99   rtems_id            sync_requester;    /*< The sync requester. */
    100   dev_t               sync_device;       /*< The device to sync */
    101 
    102   rtems_bdbuf_buffer* tree;             /*< Buffer descriptor lookup AVL tree
     177  rtems_id            sync_lock;         /**< Sync calls lock writes. */
     178  bool                sync_active;       /**< True if a sync is active. */
     179  rtems_id            sync_requester;    /**< The sync requester. */
     180  dev_t               sync_device;       /**< The device to sync */
     181
     182  rtems_bdbuf_buffer* tree;             /**< Buffer descriptor lookup AVL tree
    103183                                         * root */
    104   rtems_chain_control ready;            /*< Free buffers list (or read-ahead) */
    105   rtems_chain_control lru;              /*< Last recently used list */
    106   rtems_chain_control modified;         /*< Modified buffers list */
    107   rtems_chain_control sync;             /*< Buffers to sync list */
    108 
    109   rtems_id            access;           /*< Obtain if waiting for a buffer in the
     184  rtems_chain_control ready;            /**< Free buffers list (or read-ahead) */
     185  rtems_chain_control lru;              /**< Last recently used list */
     186  rtems_chain_control modified;         /**< Modified buffers list */
     187  rtems_chain_control sync;             /**< Buffers to sync list */
     188
     189  rtems_id            access;           /**< Obtain if waiting for a buffer in the
    110190                                         * ACCESS state. */
    111   volatile uint32_t   access_waiters;   /*< Count of access blockers. */
    112   rtems_id            transfer;         /*< Obtain if waiting for a buffer in the
     191  volatile uint32_t   access_waiters;   /**< Count of access blockers. */
     192  rtems_id            transfer;         /**< Obtain if waiting for a buffer in the
    113193                                         * TRANSFER state. */
    114   volatile uint32_t   transfer_waiters; /*< Count of transfer blockers. */
    115   rtems_id            waiting;          /*< Obtain if waiting for a buffer and the
     194  volatile uint32_t   transfer_waiters; /**< Count of transfer blockers. */
     195  rtems_id            waiting;          /**< Obtain if waiting for a buffer and the
    116196                                         * none are available. */
    117   volatile uint32_t   wait_waiters;     /*< Count of waiting blockers. */
    118 
    119   rtems_bdbuf_buffer* bds;              /*< Pointer to table of buffer descriptors
     197  volatile uint32_t   wait_waiters;     /**< Count of waiting blockers. */
     198
     199  rtems_bdbuf_buffer* bds;              /**< Pointer to table of buffer descriptors
    120200                                         * allocated for this buffer pool. */
    121   void*               buffers;          /*< The buffer's memory. */
     201  void*               buffers;          /**< The buffer's memory. */
    122202} rtems_bdbuf_pool;
    123203
     
    127207 */
    128208typedef struct rtems_bdbuf_pool_config {
    129   int            size;      /*< Size of block */
    130   int            num;       /*< Number of blocks of appropriate size */
    131   unsigned char* mem_area;  /*< Pointer to the blocks location or NULL, in this
     209  int            size;      /**< Size of block */
     210  int            num;       /**< Number of blocks of appropriate size */
     211  unsigned char* mem_area;  /**< Pointer to the blocks location or NULL, in this
    132212                             * case memory for blocks will be allocated by
    133213                             * Buffering Layer with the help of RTEMS partition
     
    136216
    137217/**
    138  * External references provided by the user for each pool in the system.
     218 * External reference to the pool configuration table describing each pool in
     219 * the system.
     220 *
     221 * The configuration table is provided by the application.
    139222 */
    140223extern rtems_bdbuf_pool_config rtems_bdbuf_pool_configuration[];
    141 extern int                     rtems_bdbuf_pool_configuration_size;
     224
     225/**
     226 * External reference the size of the pool configuration table
     227 * @ref rtems_bdbuf_pool_configuration.
     228 *
     229 * The configuration table size is provided by the application.
     230 */
     231extern size_t rtems_bdbuf_pool_configuration_size;
    142232
    143233/**
     
    146236 */
    147237typedef struct rtems_bdbuf_config {
    148   uint32_t            max_read_ahead_blocks; /*< Number of blocks to read ahead. */
    149   uint32_t            max_write_blocks;      /*< Number of blocks to write at once. */
    150   rtems_task_priority swapout_priority;      /*< Priority of the swap out task. */
    151   uint32_t            swapout_period;        /*< Period swapout checks buf timers. */
    152   uint32_t            swap_block_hold;       /*< Period a buffer is held. */
     238  uint32_t            max_read_ahead_blocks; /**< Number of blocks to read ahead. */
     239  uint32_t            max_write_blocks;      /**< Number of blocks to write at once. */
     240  rtems_task_priority swapout_priority;      /**< Priority of the swap out task. */
     241  uint32_t            swapout_period;        /**< Period swapout checks buf timers. */
     242  uint32_t            swap_block_hold;       /**< Period a buffer is held. */
    153243} rtems_bdbuf_config;
    154244
    155245/**
    156  * External referernce to the configuration. The configuration is provided by
    157  * the user.
     246 * External reference to the configuration.
     247 *
     248 * The configuration is provided by the application.
    158249 */
    159250extern rtems_bdbuf_config rtems_bdbuf_configuration;
     
    164255 */
    165256#define RTEMS_BDBUF_MAX_READ_AHEAD_BLOCKS_DEFAULT    32
     257
     258/**
     259 * Default maximum number of blocks to write at once.
     260 */
    166261#define RTEMS_BDBUF_MAX_WRITE_BLOCKS_DEFAULT         16
     262
     263/**
     264 * Default swap-out task priority.
     265 */
    167266#define RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT    15
    168 #define RTEMS_BDBUF_SWAPOUT_TASK_SWAP_PERIOD_DEFAULT 250  /* milli-seconds */
    169 #define RTEMS_BDBUF_SWAPOUT_TASK_BLOCK_HOLD_DEFAULT  1000 /* milli-seconds */
     267
     268/**
     269 * Default swap-out task swap period in milli seconds.
     270 */
     271#define RTEMS_BDBUF_SWAPOUT_TASK_SWAP_PERIOD_DEFAULT 250
     272
     273/**
     274 * Default swap-out task block hold time in milli seconds.
     275 */
     276#define RTEMS_BDBUF_SWAPOUT_TASK_BLOCK_HOLD_DEFAULT  1000
    170277
    171278/**
     
    336443 * @note Buffer pools enumerated continuously starting from 0.
    337444 */
    338 rtems_status_code
    339 rtems_bdbuf_get_pool_info (rtems_bdpool_id pool, int *block_size, int *blocks);
     445rtems_status_code rtems_bdbuf_get_pool_info(
     446  rtems_bdpool_id pool,
     447  uint32_t *block_size,
     448  uint32_t *blocks
     449);
     450
     451/** @} */
    340452
    341453#ifdef __cplusplus
  • cpukit/libblock/include/rtems/blkdev.h

    r92c70b9 r57aa979  
    11/**
    2  * @file rtems/blkdev.h
    3  * block device driver interface definitions
     2 * @file
     3 *
     4 * Block device management.
    45 */
    56 
     
    2122#endif
    2223
    23 /*
    24  *  Interface with device drivers Block device looks, initialized and behaves
    25  * like traditional RTEMS device driver. Heart of the block device driver is in
    26  * BIOREQUEST ioctl. This call puts I/O request to the block device queue, in
    27  * priority order, for asynchronous processing. When driver executes request,
    28  * req_done function invoked, so callee knows about it. Look for details below.
    29  */
    30 
    31 /*
    32  * Block device block number datatype
     24/**
     25 * @defgroup rtems_blkdev Block Device Management
     26 *
     27 * @ingroup rtems_libblock
     28 *
     29 * Interface between device drivers and the block device library.
     30 *
     31 * The heart of the block device driver is the @ref RTEMS_BLKIO_REQUEST IO
     32 * control. This call puts IO @ref rtems_blkdev_request "requests" to the block
     33 * device for asynchronous processing. When a driver executes a request, it
     34 * invokes the request done callback function to finish the request.
     35 *
     36 * @{
     37 */
     38
     39/**
     40 * Block device block index type.
    3341 */
    3442typedef uint32_t rtems_blkdev_bnum;
    3543
    36 /* Block device request type */
     44/**
     45 * Block device request type.
     46 */
    3747typedef enum rtems_blkdev_request_op {
    38     RTEMS_BLKDEV_REQ_READ,     /* Read operation */
    39     RTEMS_BLKDEV_REQ_WRITE,    /* Write operation */
    40     RTEMS_BLKDEV_CAPABILITIES  /* Capabilities request */
     48  RTEMS_BLKDEV_REQ_READ,
     49  RTEMS_BLKDEV_REQ_WRITE,
     50  RTEMS_BLKDEV_CAPABILITIES
    4151} rtems_blkdev_request_op;
    4252
    4353/**
    44  * ATA multi-sector buffer requests only supported. This option
    45  * means the cache will only supply multiple buffers that are
    46  * inorder so the ATA multi-sector command can be used. This is a
     54 * Only consecutive multi-sector buffer requests are supported.
     55 *
     56 * This option means the cache will only supply multiple buffers that are
     57 * inorder so the ATA multi-sector command for example can be used. This is a
    4758 * hack to work around the current ATA driver.
    4859 */
    4960#define RTEMS_BLKDEV_CAP_MULTISECTOR_CONT (1 << 0)
    5061
    51 /*
    52  * @typedef rtems_blkdev_request_cb
    53  *
     62/**
    5463 * Type for block device request done callback function.
    5564 *
    56  * @param arg Argument supplied in blkdev_request
    57  * @param status RTEMS status code for this operation
    58  * @param errno errno value to be passed to the user when
    59  *              status != RTEMS_SUCCESSFUL
     65 * @param arg Argument supplied in @ref rtems_blkdev_request.
     66 * @param status Status code for this operation.
     67 * @param errno The @c errno value to be passed to the user when status is not
     68 * equal to @c RTEMS_SUCCESSFUL.
    6069 */
    6170typedef void (* rtems_blkdev_request_cb)(void *arg,
     
    6473
    6574/**
    66  * @struct rtems_blkdev_sg_buffer
    67  * Block device scatter/gather buffer structure
     75 * Block device scatter or gather buffer structure.
    6876 */
    6977typedef struct rtems_blkdev_sg_buffer {
    70     uint32_t   block;   /* The block number */
    71     uint32_t   length;  /* Buffer length */
    72     void      *buffer;  /* Buffer pointer */
    73     void      *user;    /* User pointer */
     78  /**
     79   * Block index.
     80   */
     81  rtems_blkdev_bnum block;
     82
     83  /**
     84   * Buffer length.
     85   */
     86  uint32_t length;
     87
     88  /**
     89   * Buffer pointer.
     90   */
     91  void *buffer;
     92
     93  /**
     94   * User pointer.
     95   */
     96  void *user;
    7497} rtems_blkdev_sg_buffer;
    7598
    76 /* blkdev_request (Block Device Request) structure is
    77  * used to read/write a number of blocks from/to device.
     99/**
     100 * The block device dequest structure is used to read or write a number of
     101 * blocks from or to the device.
    78102 */
    79103typedef struct rtems_blkdev_request {
    80     /* Block device operation (read or write) */
    81     rtems_blkdev_request_op req;
    82     /* Callback function */
    83     rtems_blkdev_request_cb req_done;
    84     /* Argument to be passed to callback function*/
    85     void *done_arg;
    86     /* Last I/O operation completion status */
    87     rtems_status_code status;
    88     /* If status != RTEMS_SUCCESSFUL, this field contains error code */
    89     int error;
    90     /* Number of blocks for this request. */
    91     uint32_t bufnum;
    92 
    93     /* The task requesting the IO operation. */
    94     rtems_id io_task;
    95 
    96     /* List of scatter/gather buffers */
    97     rtems_blkdev_sg_buffer bufs[0];
     104  /**
     105   * Block device operation (read or write).
     106   */
     107  rtems_blkdev_request_op req;
     108
     109  /**
     110   * Request done callback function.
     111   */
     112  rtems_blkdev_request_cb req_done;
     113
     114  /**
     115   * Argument to be passed to callback function.
     116   */
     117  void *done_arg;
     118
     119  /**
     120   * Last IO operation completion status.
     121   */
     122  rtems_status_code status;
     123
     124  /**
     125   * If @c status is not equal to @c RTEMS_SUCCESSFUL, this field contains the
     126   * error number.
     127   */
     128  int error;
     129
     130  /**
     131   * Number of blocks for this request.
     132   */
     133  uint32_t bufnum;
     134
     135  /**
     136   * The task requesting the IO operation.
     137   */
     138  rtems_id io_task;
     139
     140  /**
     141   * List of scatter or gather buffers.
     142   */
     143  rtems_blkdev_sg_buffer bufs[0];
    98144} rtems_blkdev_request;
    99145
    100 /* The start block in a request. Only valid if the driver has returned the
    101  * RTEMS_BLKDEV_CAPABILITIES of RTEMS_BLKDEV_CAP_MULTISECTOR_CONT */
    102 #define RTEMS_BLKDEV_START_BLOCK(_r) (_r->bufs[0].block)
    103 
    104 /* Block device IOCTL request codes */
    105 #define RTEMS_BLKIO_REQUEST      _IOWR('B', 1, rtems_blkdev_request)
    106 #define RTEMS_BLKIO_GETBLKSIZE   _IO('B', 2)
    107 #define RTEMS_BLKIO_GETSIZE      _IO('B', 3)
    108 #define RTEMS_BLKIO_SYNCDEV      _IO('B', 4)
    109 
    110 /* Device driver interface conventions suppose that driver may
    111  * contain initialize/open/close/read/write/ioctl entry points. These
    112  * primitives (except initialize) can be implemented in generic fashion,
    113  * based upon supplied block device driver ioctl handler. Every block
    114  * device driver should provide initialize entry point, which is register
    115  * all block devices and appropriate ioctl handlers.
    116  */
    117 
     146/**
     147 * The start block in a request.
     148 *
     149 * Only valid if the driver has returned the @ref RTEMS_BLKDEV_CAPABILITIES of
     150 * @ref RTEMS_BLKDEV_CAP_MULTISECTOR_CONT.
     151 */
     152#define RTEMS_BLKDEV_START_BLOCK(req) (req->bufs[0].block)
     153
     154/**
     155 * @name IO Control Request Codes
     156 *
     157 * @{
     158 */
     159
     160#define RTEMS_BLKIO_REQUEST _IOWR('B', 1, rtems_blkdev_request)
     161#define RTEMS_BLKIO_GETBLKSIZE _IO('B', 2)
     162#define RTEMS_BLKIO_GETSIZE _IO('B', 3)
     163#define RTEMS_BLKIO_SYNCDEV _IO('B', 4)
     164
     165/** @} */
     166
     167/**
     168 * The device driver interface conventions suppose that a driver may contain an
     169 * initialize, open, close, read, write and IO control entry points. These
     170 * primitives (except initialize) can be implemented in a generic fashion based
     171 * upon the supplied block device driver IO control handler. Every block device
     172 * driver should provide an initialize entry point, which registers the
     173 * appropriate IO control handler.
     174 */
    118175#define RTEMS_GENERIC_BLOCK_DEVICE_DRIVER_ENTRIES \
    119       rtems_blkdev_generic_open, rtems_blkdev_generic_close, \
    120       rtems_blkdev_generic_read, rtems_blkdev_generic_write, \
    121       rtems_blkdev_generic_ioctl
    122 
    123 /* blkdev_generic_read --
    124  *     Generic block device read primitive. Implemented using block device
    125  *     buffer management primitives.
     176  .open_entry = rtems_blkdev_generic_open, \
     177  .close_entry = rtems_blkdev_generic_close, \
     178  .read_entry = rtems_blkdev_generic_read, \
     179  .write_entry = rtems_blkdev_generic_write, \
     180  .control_entry = rtems_blkdev_generic_ioctl
     181
     182/**
     183 * Generic block device read primitive.
     184 *
     185 * Implemented using block device buffer management primitives.
    126186 */
    127187rtems_device_driver
     
    132192);
    133193
    134 /* blkdev_generic_write --
    135  *     Generic block device driver write primitive. Implemented using block
    136  *     device buffer management primitives.
     194/**
     195 * Generic block device write primitive.
     196 *
     197 * Implemented using block device buffer management primitives.
    137198 */
    138199rtems_device_driver
     
    143204);
    144205
    145 /* blkdev_generic_open --
    146  *     Generic block device open primitive.
     206/**
     207 * Generic block device open primitive.
     208 *
     209 * Implemented using block device buffer management primitives.
    147210 */
    148211rtems_device_driver
     
    153216);
    154217
    155 /* blkdev_generic_close --
    156  *     Generic block device close primitive.
     218/**
     219 * Generic block device close primitive.
     220 *
     221 * Implemented using block device buffer management primitives.
    157222 */
    158223rtems_device_driver
     
    163228);
    164229
    165 /* blkdev_generic_ioctl --
    166  *     Generic block device ioctl primitive.
     230/**
     231 * Generic block device IO control primitive.
     232 *
     233 * Implemented using block device buffer management primitives.
    167234 */
    168235rtems_device_driver
     
    172239    void                    * arg
    173240);
     241
     242/** @} */
    174243
    175244#ifdef __cplusplus
  • cpukit/libblock/include/rtems/diskdevs.h

    r92c70b9 r57aa979  
    11/**
    2  * @file rtems/diskdevs.h
    3  * Physical and logical block devices (disks) support
     2 * @file
     3 *
     4 * Block device disk management.
    45 */
    56 
     
    1415#define _RTEMS_DISKDEVS_H
    1516
     17#include <rtems.h>
     18#include <rtems/libio.h>
     19#include <stdlib.h>
     20
     21/**
     22 * @ingroup rtems_bdbuf
     23 *
     24 * Buffer pool identifier.
     25 */
     26typedef int rtems_bdpool_id;
     27
     28#include <rtems/blkdev.h>
     29
    1630#ifdef __cplusplus
    1731extern "C" {
    1832#endif
    1933
    20 #include <rtems.h>
    21 #include <rtems/libio.h>
    22 #include <stdlib.h>
    23 
    24 /* Buffer pool identifier */
    25 typedef int rtems_bdpool_id;
    26 
    27 #include <rtems/blkdev.h>
    28 
    29 /* Driver capabilities. */
    30 
    31 /* Block device ioctl handler */
    32 typedef int (* rtems_block_device_ioctl) (dev_t dev, uint32_t req, void *argp);
    33 
    34 /* rtems_disk_device: Entry of this type created for every disk device
    35  * (both for logical and physical disks).
    36  * Array of arrays of pointers to disk_device structures maintained. First
    37  * table indexed by major number and second table indexed by minor number.
    38  * Such data organization allow quick lookup using data structure of
    39  * moderated size.
     34/**
     35 * @defgroup rtems_disk Block Device Disk Management
     36 *
     37 * @ingroup rtems_libblock
     38 *
     39 * This module provides functions to manage disk devices.  The disk devices are
     40 * accessed via the RTEMS block device library.  A disk is a set of blocks
     41 * which are identified by a consecutive set of non-negative integers starting
     42 * at zero.  There are also logical disks which contain a subset of consecutive
     43 * disk blocks.  The logical disks are used to represent the partitions of a
     44 * disk.
     45 *
     46 * @{
     47 */
     48
     49/**
     50 * Block device IO control handler type.
     51 */
     52typedef int (*rtems_block_device_ioctl)( dev_t dev, uint32_t req, void *argp);
     53
     54/**
     55 * Description of a disk device (logical and physical disks).
     56 *
     57 * An array of pointer tables to rtems_disk_device structures is maintained.
     58 * The first table will be indexed by the major number and the second table
     59 * will be indexed by the minor number.  This allows quick lookup using a data
     60 * structure of moderated size.
    4061 */
    4162typedef struct rtems_disk_device {
    42     dev_t                     dev;          /* Device ID (major + minor) */
    43     struct rtems_disk_device *phys_dev;     /* Physical device ID (the same
    44                                                as dev if this entry specifies
    45                                                the physical device) */
    46     uint32_t                  capabilities; /* Driver capabilities. */
    47     char                     *name;         /* Disk device name */
    48     int                       uses;         /* Use counter. Device couldn't be
    49                                                removed if it is in use. */
    50     uint32_t                  start;        /* Starting block number (0 for
    51                                                physical devices, block offset
    52                                                on the related physical device
    53                                                for logical device) */
    54     uint32_t                  size;         /* Size of physical or logical disk
    55                                                in disk blocks */
    56     uint32_t                  block_size;   /* Size of device block (minimum
    57                                                transfer unit) in bytes
    58                                                (must be power of 2) */
    59     uint32_t            block_size_log2;    /* log2 of block_size */
    60     rtems_bdpool_id     pool;               /* Buffer pool assigned to this
    61                                                device */
    62     rtems_block_device_ioctl  ioctl;        /* ioctl handler for this block
    63                                                device */
     63  /**
     64   * Device identifier (concatenation of major and minor number).
     65   */
     66  dev_t dev;
     67
     68  /**
     69   * Physical device identifier (equals the @c dev entry if it specifies a
     70   * physical device).
     71   */
     72  struct rtems_disk_device *phys_dev;
     73
     74  /**
     75   * Driver capabilities.
     76   */
     77  uint32_t capabilities;
     78
     79  /**
     80   * Disk device name.
     81   */
     82  char *name;
     83
     84  /**
     85   * Usage counter.
     86   *
     87   * Devices cannot be removed if they are in use.
     88   */
     89  unsigned uses;
     90
     91  /**
     92   * Start block number.
     93   *
     94   * Equals zero for physical devices.  It is a block offset to the related
     95   * physical device for logical device.
     96   */
     97  rtems_blkdev_bnum start;
     98
     99  /**
     100   * Size of the physical or logical disk in blocks.
     101   */
     102  rtems_blkdev_bnum size;
     103
     104  /**
     105   * Device block size in bytes.
     106   *
     107   * This is the minimum transfer unit and must be power of two.
     108   */
     109  uint32_t block_size;
     110
     111  /**
     112   * Binary logarithm of the block size.
     113   */
     114  uint32_t block_size_log2;
     115
     116  /**
     117   * Buffer pool assigned to this disk.
     118   */
     119  rtems_bdpool_id pool;
     120
     121  /**
     122   * IO control handler for this disk.
     123   */
     124  rtems_block_device_ioctl ioctl;
    64125} rtems_disk_device;
    65126
    66 /* rtems_disk_create_phys --
    67  *     Create physical disk entry. This function usually invoked from
    68  *     block device driver initialization code when physical device
    69  *     detected in the system. Device driver should provide ioctl handler
    70  *     to allow block device access operations. This primitive will register
    71  *     device in rtems (invoke rtems_io_register_name).
    72  *
    73  * PARAMETERS:
    74  *     dev        - device identifier (major, minor numbers)
    75  *     block_size - size of disk block (minimum data transfer unit); must be
    76  *                  power of 2
    77  *     disk_size  - number of blocks on device
    78  *     handler    - IOCTL handler (function providing basic block input/output
    79  *                  request handling BIOREQUEST and other device management
    80  *                  operations)
    81  *     name       - character name of device (e.g. /dev/hda)
    82  *
    83  * RETURNS:
    84  *     RTEMS_SUCCESSFUL if information about new physical disk added, or
    85  *     error code if error occured (device already registered, wrong block
    86  *     size value, no memory available).
    87  */
    88 rtems_status_code
    89 rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
    90                        rtems_block_device_ioctl handler,
    91                        const char *name);
    92 
    93 /* rtems_disk_create_log --
    94  *     Create logical disk entry. Logical disk is contiguous area on physical
    95  *     disk. Disk may be splitted to several logical disks in several ways:
    96  *     manually or using information stored in blocks on physical disk
    97  *     (DOS-like partition table, BSD disk label, etc). This function usually
    98  *     invoked from application when application-specific splitting are in use,
    99  *     or from generic code which handle different logical disk organizations.
    100  *     This primitive will register device in rtems (invoke
    101  *     rtems_io_register_name).
    102  *
    103  * PARAMETERS:
    104  *     dev   - logical device identifier (major, minor numbers)
    105  *     phys  - physical device (block device which holds this logical disk)
    106  *             identifier
    107  *     start - starting block number on the physical device
    108  *     size  - logical disk size in blocks
    109  *     name  - logical disk name
    110  *
    111  * RETURNS:
    112  *     RTEMS_SUCCESSFUL if logical device successfully added, or error code
    113  *     if error occured (device already registered, no physical device
    114  *     exists, logical disk is out of physical disk boundaries, no memory
    115  *     available).
    116  */
    117 rtems_status_code
    118 rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name);
    119 
    120 /* rtems_disk_delete --
    121  *     Delete physical or logical disk device. Device may be deleted if its
    122  *     use counter (and use counters of all logical devices - if it is
    123  *     physical device) equal to 0. When physical device deleted,
    124  *     all logical devices deleted inherently. Appropriate devices removed
    125  *     from "/dev" filesystem.
    126  *
    127  * PARAMETERS:
    128  *     dev - device identifier (major, minor numbers)
    129  *
    130  * RETURNS:
    131  *     RTEMS_SUCCESSFUL if block device successfully deleted, or error code
    132  *     if error occured (device is not defined, device is in use).
    133  */
    134 rtems_status_code
    135 rtems_disk_delete(dev_t dev);
    136 
    137 /* rtems_disk_obtain --
    138  *     Find block device descriptor by its device identifier. This function
    139  *     increment usage counter to 1. User should release disk_device structure
    140  *     by invoking rtems_disk_release primitive.
    141  *
    142  * PARAMETERS:
    143  *     dev - device identifier (major, minor numbers)
    144  *
    145  * RETURNS:
    146  *     pointer to the block device descriptor, or NULL if no such device
    147  *     exists.
    148  */
    149 rtems_disk_device *
    150 rtems_disk_obtain(dev_t dev);
    151 
    152 /* rtems_disk_release --
    153  *     Release disk_device structure (decrement usage counter to 1).
    154  *
    155  * PARAMETERS:
    156  *     dd - pointer to disk device structure
    157  *
    158  * RETURNS:
    159  *     RTEMS_SUCCESSFUL
    160  *
    161  * NOTE:
    162  *     It should be implemented as inline function.
    163  */
    164 rtems_status_code
    165 rtems_disk_release(rtems_disk_device *dd);
    166 
    167 /* rtems_disk_next --
    168  *     Disk device enumerator. Looking for device having device number larger
    169  *     than dev and return disk device descriptor for it. If there are no
    170  *     such device, NULL value returned.
    171  *
    172  * PARAMETERS:
    173  *     dev - device number (use -1 to start search)
    174  *
    175  * RETURNS:
    176  *     Pointer to the disk descriptor for next disk device, or NULL if all
    177  *     devices enumerated. */
    178 rtems_disk_device *
    179 rtems_disk_next(dev_t dev);
    180 
    181 /* rtems_diskio_initialize --
    182  *     Initialization of disk device library (initialize all data structures,
    183  *     etc.)
    184  *
    185  * PARAMETERS:
    186  *     none
    187  *
    188  * RETURNS:
    189  *     RTEMS_SUCCESSFUL if library initialized, or error code if error
    190  *     occured.
    191  */
    192 rtems_status_code
    193 rtems_disk_io_initialize(void);
    194 
    195 /* rtems_diskio_done --
    196  *     Release all resources allocated for disk device interface.
    197  *
    198  * PARAMETERS:
    199  *     none
    200  *
    201  * RETURNS:
    202  *     RTEMS_SUCCESSFUL if all resources released, or error code if error
    203  *     occured.
    204  */
    205 rtems_status_code
    206 rtems_disk_io_done(void);
     127/**
     128 * Creates a physical disk with device identifier @a dev.
     129 *
     130 * The block size @a block_size must be a power of two.  The disk size @a
     131 * disk_size is the number of blocks provided by this disk.  The block index
     132 * starts with zero.  The associated disk device driver will be invoked via the
     133 * IO control handler @a handler.  A device node will be registered in the file
     134 * system with absolute path @a name.  This function is usually invoked from a
     135 * block device driver during initialization when a physical device is detected
     136 * in the system.  The device driver provides an IO control handler to allow
     137 * block device operations.
     138 */
     139rtems_status_code rtems_disk_create_phys(
     140  dev_t dev,
     141  uint32_t block_size,
     142  rtems_blkdev_bnum disk_size,
     143  rtems_block_device_ioctl handler,
     144  const char *name
     145);
     146
     147/**
     148 * Creates a logical disk with device identifier @a dev.
     149 *
     150 * A logical disk manages a subset of consecutive blocks containd in the
     151 * physical disk with identifier @a phys.  The start block index of the logical
     152 * disk device is @a start.  The block number of the logcal disk will be @a
     153 * size.  The blocks must be within the range of blocks managed by the
     154 * associated physical disk device.  A device node will be registered in the
     155 * file system with absolute path @a name.  The block size and IO control
     156 * handler are inherited by the physical disk.
     157 */
     158rtems_status_code rtems_disk_create_log(
     159  dev_t dev,
     160  dev_t phys,
     161  rtems_blkdev_bnum start,
     162  rtems_blkdev_bnum size,
     163  const char *name
     164);
     165
     166/**
     167 * Deletes a physical or logical disk device with identifier @a dev.
     168 *
     169 * Disk devices may be deleted if there usage counter (and the usage counters
     170 * of all contained logical disks devices) equals zero.  When a physical disk
     171 * device is deleted, all logical disk devices will deleted too.  The
     172 * corresponding device nodes will be removed from the file system.
     173 */
     174rtems_status_code rtems_disk_delete(dev_t dev);
     175
     176/**
     177 * Returns the disk device descriptor for the device identifier @a dev.
     178 *
     179 * Increments usage counter by one.  You should release the disk device
     180 * descriptor with rtems_disk_release().  Returns @c NULL if no corresponding
     181 * disk exists.
     182 */
     183rtems_disk_device *rtems_disk_obtain(dev_t dev);
     184
     185/**
     186 * Releases the disk device description @a dd.
     187 *
     188 * Decrements usage counter by one.
     189 */
     190rtems_status_code rtems_disk_release(rtems_disk_device *dd);
     191
     192/**
     193 * Disk device iterator.
     194 *
     195 * Returns the next disk device descriptor with a device identifier larger than
     196 * @a dev.  If there is no such device, @c NULL will be returned.  Use minus
     197 * one to start the search.
     198 *
     199 * @code
     200 * rtems_disk_device *dd = rtems_disk_next((dev_t) -1);
     201 *
     202 * while (dd != NULL) {
     203 *   dd = rtems_disk_next(dd->dev);
     204 * }
     205 * @endcode
     206 */
     207rtems_disk_device *rtems_disk_next(dev_t dev);
     208
     209/**
     210 * Initializes the disk device management.
     211 *
     212 * This functions returns successful if the disk device management is already
     213 * initialized.  There is no protection against concurrent access.
     214 */
     215rtems_status_code rtems_disk_io_initialize(void);
     216
     217/**
     218 * Releases all resources allocated for disk device management.
     219 */
     220rtems_status_code rtems_disk_io_done(void);
     221
     222/** @} */
    207223
    208224#ifdef __cplusplus
  • 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)
  • cpukit/libblock/src/blkdev.c

    r92c70b9 r57aa979  
     1/**
     2 * @file
     3 *
     4 * Block device management.
     5 */
     6 
    17/*
    28 * blkdev.h - block device driver generic support
  • cpukit/libblock/src/diskdevs.c

    r92c70b9 r57aa979  
     1/**
     2 * @file
     3 *
     4 * Block device disk management.
     5 */
     6 
    17/*
    28 * diskdevs.c - Physical and logical block devices (disks) support
     
    213219}
    214220
    215 /* rtems_disk_create_phys --
    216  *     Create physical disk entry. This function usually invoked from
    217  *     block device driver initialization code when physical device
    218  *     detected in the system. Device driver should provide ioctl handler
    219  *     to allow block device access operations. This primitive will register
    220  *     device in rtems (invoke rtems_io_register_name).
    221  *
    222  * PARAMETERS:
    223  *     dev        - device identifier (major, minor numbers)
    224  *     block_size - size of disk block (minimum data transfer unit); must be
    225  *                  power of 2
    226  *     disk_size  - number of blocks on device
    227  *     handler    - IOCTL handler (function providing basic block input/output
    228  *                  request handling BIOREQUEST and other device management
    229  *                  operations)
    230  *     name       - character name of device (e.g. /dev/hda)
    231  *
    232  * RETURNS:
    233  *     RTEMS_SUCCESSFUL if information about new physical disk added, or
    234  *     error code if error occured (device already registered, wrong block
    235  *     size value, no memory available).
    236  */
    237 rtems_status_code
    238 rtems_disk_create_phys(dev_t dev, int block_size, int disk_size,
    239                        rtems_block_device_ioctl handler,
    240                        const char *name)
     221rtems_status_code rtems_disk_create_phys(
     222  dev_t dev,
     223  uint32_t block_size,
     224  rtems_blkdev_bnum disk_size,
     225  rtems_block_device_ioctl handler,
     226  const char *name
     227)
    241228{
    242229    int bs_log2;
     
    298285}
    299286
    300 /* rtems_disk_create_log --
    301  *     Create logical disk entry. Logical disk is contiguous area on physical
    302  *     disk. Disk may be splitted to several logical disks in several ways:
    303  *     manually or using information stored in blocks on physical disk
    304  *     (DOS-like partition table, BSD disk label, etc). This function usually
    305  *     invoked from application when application-specific splitting are in use,
    306  *     or from generic code which handle different logical disk organizations.
    307  *     This primitive will register device in rtems (invoke
    308  *     rtems_io_register_name).
    309  *
    310  * PARAMETERS:
    311  *     dev   - logical device identifier (major, minor numbers)
    312  *     phys  - physical device (block device which holds this logical disk)
    313  *             identifier
    314  *     start - starting block number on the physical device
    315  *     size  - logical disk size in blocks
    316  *     name  - logical disk name
    317  *
    318  * RETURNS:
    319  *     RTEMS_SUCCESSFUL if logical device successfully added, or error code
    320  *     if error occured (device already registered, no physical device
    321  *     exists, logical disk is out of physical disk boundaries, no memory
    322  *     available).
    323  */
    324 rtems_status_code
    325 rtems_disk_create_log(dev_t dev, dev_t phys, int start, int size, char *name)
    326 {
    327     rtems_disk_device *dd;
    328     rtems_disk_device *pdd;
    329     rtems_status_code rc;
    330     rtems_device_major_number major;
    331     rtems_device_minor_number minor;
    332 
    333     rtems_filesystem_split_dev_t (dev, major, minor);
    334 
    335     rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    336     if (rc != RTEMS_SUCCESSFUL)
    337         return rc;
    338     diskdevs_protected = true;
    339 
    340     pdd = get_disk_entry(phys);
    341     if (pdd == NULL)
    342     {
    343         diskdevs_protected = false;
    344         rtems_semaphore_release(diskdevs_mutex);
    345         return RTEMS_INVALID_NUMBER;
    346     }
    347 
    348     rc = create_disk(dev, name, &dd);
    349     if (rc != RTEMS_SUCCESSFUL)
    350     {
    351         diskdevs_protected = false;
    352         rtems_semaphore_release(diskdevs_mutex);
    353         return rc;
    354     }
    355 
    356     dd->phys_dev = pdd;
    357     dd->uses = 0;
    358     dd->start = start;
    359     dd->size = size;
    360     dd->block_size = pdd->block_size;
    361     dd->block_size_log2 = pdd->block_size_log2;
    362     dd->ioctl = pdd->ioctl;
    363 
    364     rc = rtems_io_register_name(name, major, minor);
    365 
     287rtems_status_code rtems_disk_create_log(
     288  dev_t dev,
     289  dev_t phys,
     290  rtems_blkdev_bnum start,
     291  rtems_blkdev_bnum size,
     292  const char *name
     293)
     294{
     295  rtems_disk_device *dd = NULL;
     296  rtems_disk_device *pdd = NULL;
     297  rtems_status_code rc = RTEMS_SUCCESSFUL;
     298  rtems_device_major_number major = 0;
     299  rtems_device_minor_number minor = 0;
     300  rtems_blkdev_bnum end = start + size;
     301
     302  rtems_filesystem_split_dev_t (dev, major, minor);
     303
     304  rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     305  if (rc != RTEMS_SUCCESSFUL) {
     306    return rc;
     307  }
     308
     309  diskdevs_protected = true;
     310
     311  pdd = get_disk_entry(phys);
     312  if (
     313    pdd == NULL
     314      || pdd != pdd->phys_dev
     315      || start >= pdd->size
     316      || end <= start
     317      || end > pdd->size
     318  ) {
    366319    diskdevs_protected = false;
    367     rc = rtems_semaphore_release(diskdevs_mutex);
    368 
     320    rtems_semaphore_release(diskdevs_mutex);
     321    return RTEMS_INVALID_NUMBER;
     322  }
     323
     324  rc = create_disk(dev, name, &dd);
     325  if (rc != RTEMS_SUCCESSFUL) {
     326    diskdevs_protected = false;
     327    rtems_semaphore_release(diskdevs_mutex);
    369328    return rc;
    370 }
    371 
    372 /* rtems_disk_delete --
    373  *     Delete physical or logical disk device. Device may be deleted if its
    374  *     use counter (and use counters of all logical devices - if it is
    375  *     physical device) equal to 0. When physical device deleted,
    376  *     all logical devices deleted inherently. Appropriate devices removed
    377  *     from "/dev" filesystem.
    378  *
    379  * PARAMETERS:
    380  *     dev - device identifier (major, minor numbers)
    381  *
    382  * RETURNS:
    383  *     RTEMS_SUCCESSFUL if block device successfully deleted, or error code
    384  *     if error occured (device is not defined, device is in use).
    385  */
     329  }
     330
     331  dd->phys_dev = pdd;
     332  dd->uses = 0;
     333  dd->start = start;
     334  dd->size = size;
     335  dd->block_size = pdd->block_size;
     336  dd->block_size_log2 = pdd->block_size_log2;
     337  dd->ioctl = pdd->ioctl;
     338
     339  rc = rtems_io_register_name(name, major, minor);
     340
     341  diskdevs_protected = false;
     342  rc = rtems_semaphore_release(diskdevs_mutex);
     343
     344  return rc;
     345}
     346
    386347rtems_status_code
    387348rtems_disk_delete(dev_t dev)
    388349{
    389     rtems_status_code rc;
    390     int used;
    391     rtems_device_major_number maj;
    392     rtems_device_minor_number min;
    393 
    394     rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    395     if (rc != RTEMS_SUCCESSFUL)
    396         return rc;
    397     diskdevs_protected = true;
     350  rtems_status_code rc = RTEMS_SUCCESSFUL;
     351  rtems_device_major_number maj = 0;
     352  rtems_device_minor_number min = 0;
     353  rtems_disk_device *dd = NULL;
     354  bool physical_disk = true;
     355
     356  rc = rtems_semaphore_obtain(diskdevs_mutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     357  if (rc != RTEMS_SUCCESSFUL) {
     358    return rc;
     359  }
     360  diskdevs_protected = true;
     361
     362  /* Check if we have a physical or logical disk */
     363  dd = get_disk_entry(dev);
     364  if (dd == NULL) {
     365    return RTEMS_INVALID_NUMBER;
     366  }
     367  physical_disk = dd->phys_dev == dd;
     368
     369  if (physical_disk) {
     370    unsigned used = 0;
    398371
    399372    /* Check if this device is in use -- calculate usage counter */
    400     used = 0;
    401     for (maj = 0; maj < disktab_size; maj++)
    402     {
    403         rtems_disk_device_table *dtab = disktab + maj;
    404         if (dtab != NULL)
    405         {
    406             for (min = 0; min < dtab->size; min++)
    407             {
    408                 rtems_disk_device *dd = dtab->minor[min];
    409                 if ((dd != NULL) && (dd->phys_dev->dev == dev))
    410                     used += dd->uses;
    411             }
     373    for (maj = 0; maj < disktab_size; maj++) {
     374      rtems_disk_device_table *dtab = disktab + maj;
     375      if (dtab != NULL) {
     376        for (min = 0; min < dtab->size; min++) {
     377          dd = dtab->minor[min];
     378          if ((dd != NULL) && (dd->phys_dev->dev == dev)) {
     379            used += dd->uses;
     380          }
    412381        }
    413     }
    414 
    415     if (used != 0)
    416     {
    417         diskdevs_protected = false;
    418         rtems_semaphore_release(diskdevs_mutex);
    419         return RTEMS_RESOURCE_IN_USE;
     382      }
     383    }
     384
     385    if (used != 0) {
     386      diskdevs_protected = false;
     387      rtems_semaphore_release(diskdevs_mutex);
     388      return RTEMS_RESOURCE_IN_USE;
    420389    }
    421390
    422391    /* Delete this device and all of its logical devices */
    423     for (maj = 0; maj < disktab_size; maj++)
    424     {
    425         rtems_disk_device_table *dtab = disktab +maj;
    426         if (dtab != NULL)
    427         {
    428             for (min = 0; min < dtab->size; min++)
    429             {
    430                 rtems_disk_device *dd = dtab->minor[min];
    431                 if ((dd != NULL) && (dd->phys_dev->dev == dev))
    432                 {
    433                     unlink(dd->name);
    434                     free(dd->name);
    435                     free(dd);
    436                     dtab->minor[min] = NULL;
    437                 }
    438             }
     392    for (maj = 0; maj < disktab_size; maj++) {
     393      rtems_disk_device_table *dtab = disktab + maj;
     394      if (dtab != NULL) {
     395        for (min = 0; min < dtab->size; min++) {
     396          dd = dtab->minor[min];
     397          if ((dd != NULL) && (dd->phys_dev->dev == dev)) {
     398            unlink(dd->name);
     399            free(dd->name);
     400            free(dd);
     401            dtab->minor[min] = NULL;
     402          }
    439403        }
    440     }
    441 
    442     diskdevs_protected = false;
    443     rc = rtems_semaphore_release(diskdevs_mutex);
    444     return rc;
    445 }
    446 
    447 /* rtems_disk_obtain --
    448  *     Find block device descriptor by its device identifier.
    449  *
    450  * PARAMETERS:
    451  *     dev - device identifier (major, minor numbers)
    452  *
    453  * RETURNS:
    454  *     pointer to the block device descriptor, or NULL if no such device
    455  *     exists.
    456  */
     404      }
     405    }
     406  } else {
     407    rtems_filesystem_split_dev_t(dev, maj, min);
     408    disktab[maj].minor[min] = NULL;
     409    unlink(dd->name);
     410    free(dd->name);
     411    free(dd);
     412  }
     413
     414  diskdevs_protected = false;
     415  rc = rtems_semaphore_release(diskdevs_mutex);
     416  return rc;
     417}
     418
    457419rtems_disk_device *
    458420rtems_disk_obtain(dev_t dev)
     
    487449}
    488450
    489 /* rtems_disk_release --
    490  *     Release rtems_disk_device structure (decrement usage counter to 1).
    491  *
    492  * PARAMETERS:
    493  *     dd - pointer to disk device structure
    494  *
    495  * RETURNS:
    496  *     RTEMS_SUCCESSFUL
    497  */
    498451rtems_status_code
    499452rtems_disk_release(rtems_disk_device *dd)
     
    506459}
    507460
    508 /* rtems_disk_next --
    509  *     Disk device enumerator. Looking for device having device number larger
    510  *     than dev and return disk device descriptor for it. If there are no
    511  *     such device, NULL value returned.
    512  *
    513  * PARAMETERS:
    514  *     dev - device number (use -1 to start search)
    515  *
    516  * RETURNS:
    517  *     Pointer to the disk descriptor for next disk device, or NULL if all
    518  *     devices enumerated.
    519  */
    520461rtems_disk_device *
    521462rtems_disk_next(dev_t dev)
     
    550491}
    551492
    552 /* rtems_disk_initialize --
    553  *     Initialization of disk device library (initialize all data structures,
    554  *     etc.)
    555  *
    556  * PARAMETERS:
    557  *     none
    558  *
    559  * RETURNS:
    560  *     RTEMS_SUCCESSFUL if library initialized, or error code if error
    561  *     occured.
    562  */
    563493rtems_status_code
    564494rtems_disk_io_initialize(void)
     
    599529}
    600530
    601 /* rtems_disk_io_done --
    602  *     Release all resources allocated for disk device interface.
    603  *
    604  * PARAMETERS:
    605  *     none
    606  *
    607  * RETURNS:
    608  *     RTEMS_SUCCESSFUL if all resources released, or error code if error
    609  *     occured.
    610  */
    611531rtems_status_code
    612532rtems_disk_io_done(void)
Note: See TracChangeset for help on using the changeset viewer.