Changeset 57aa979 in rtems for cpukit/libblock
- Timestamp:
- 04/29/09 08:51:07 (15 years ago)
- Branches:
- 4.10, 4.11, 5, master
- Children:
- 24cdb7d
- Parents:
- 92c70b9
- Location:
- cpukit/libblock
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
cpukit/libblock/include/rtems/bdbuf.h
r92c70b9 r57aa979 1 1 /** 2 * @file rtems/bdbuf.h3 * 4 * Block Device Buffer Management2 * @file 3 * 4 * Block device buffer management. 5 5 */ 6 6 … … 29 29 extern "C" { 30 30 #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 */ 32 112 33 113 /** … … 36 116 typedef enum 37 117 { 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 */ 46 126 } rtems_bdbuf_buf_state; 47 127 … … 58 138 struct rtems_bdbuf_avl_node 59 139 { 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 */ 64 144 } avl; 65 145 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) 71 151 * which can be used by user later */ 72 152 73 volatile rtems_bdbuf_buf_state state; /* < State of the buffer. */74 75 volatile uint32_t waiters; /* < The number of threads waiting on this153 volatile rtems_bdbuf_buf_state state; /**< State of the buffer. */ 154 155 volatile uint32_t waiters; /**< The number of threads waiting on this 76 156 * buffer. */ 77 rtems_bdpool_id pool; /* < Identifier of buffer pool to which this buffer157 rtems_bdpool_id pool; /**< Identifier of buffer pool to which this buffer 78 158 belongs */ 79 159 80 volatile uint32_t hold_timer; /* < Timer to indicate how long a buffer160 volatile uint32_t hold_timer; /**< Timer to indicate how long a buffer 81 161 * has been held in the cache modified. */ 82 162 } rtems_bdbuf_buffer; … … 88 168 typedef struct rtems_bdbuf_pool 89 169 { 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 and170 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 96 176 * 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 tree177 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 103 183 * 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 the184 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 110 190 * ACCESS state. */ 111 volatile uint32_t access_waiters; /* < Count of access blockers. */112 rtems_id transfer; /* < Obtain if waiting for a buffer in the191 volatile uint32_t access_waiters; /**< Count of access blockers. */ 192 rtems_id transfer; /**< Obtain if waiting for a buffer in the 113 193 * TRANSFER state. */ 114 volatile uint32_t transfer_waiters; /* < Count of transfer blockers. */115 rtems_id waiting; /* < Obtain if waiting for a buffer and the194 volatile uint32_t transfer_waiters; /**< Count of transfer blockers. */ 195 rtems_id waiting; /**< Obtain if waiting for a buffer and the 116 196 * none are available. */ 117 volatile uint32_t wait_waiters; /* < Count of waiting blockers. */118 119 rtems_bdbuf_buffer* bds; /* < Pointer to table of buffer descriptors197 volatile uint32_t wait_waiters; /**< Count of waiting blockers. */ 198 199 rtems_bdbuf_buffer* bds; /**< Pointer to table of buffer descriptors 120 200 * allocated for this buffer pool. */ 121 void* buffers; /* < The buffer's memory. */201 void* buffers; /**< The buffer's memory. */ 122 202 } rtems_bdbuf_pool; 123 203 … … 127 207 */ 128 208 typedef 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 this209 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 132 212 * case memory for blocks will be allocated by 133 213 * Buffering Layer with the help of RTEMS partition … … 136 216 137 217 /** 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. 139 222 */ 140 223 extern 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 */ 231 extern size_t rtems_bdbuf_pool_configuration_size; 142 232 143 233 /** … … 146 236 */ 147 237 typedef 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. */ 153 243 } rtems_bdbuf_config; 154 244 155 245 /** 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. 158 249 */ 159 250 extern rtems_bdbuf_config rtems_bdbuf_configuration; … … 164 255 */ 165 256 #define RTEMS_BDBUF_MAX_READ_AHEAD_BLOCKS_DEFAULT 32 257 258 /** 259 * Default maximum number of blocks to write at once. 260 */ 166 261 #define RTEMS_BDBUF_MAX_WRITE_BLOCKS_DEFAULT 16 262 263 /** 264 * Default swap-out task priority. 265 */ 167 266 #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 170 277 171 278 /** … … 336 443 * @note Buffer pools enumerated continuously starting from 0. 337 444 */ 338 rtems_status_code 339 rtems_bdbuf_get_pool_info (rtems_bdpool_id pool, int *block_size, int *blocks); 445 rtems_status_code rtems_bdbuf_get_pool_info( 446 rtems_bdpool_id pool, 447 uint32_t *block_size, 448 uint32_t *blocks 449 ); 450 451 /** @} */ 340 452 341 453 #ifdef __cplusplus -
cpukit/libblock/include/rtems/blkdev.h
r92c70b9 r57aa979 1 1 /** 2 * @file rtems/blkdev.h 3 * block device driver interface definitions 2 * @file 3 * 4 * Block device management. 4 5 */ 5 6 … … 21 22 #endif 22 23 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. 33 41 */ 34 42 typedef uint32_t rtems_blkdev_bnum; 35 43 36 /* Block device request type */ 44 /** 45 * Block device request type. 46 */ 37 47 typedef 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 41 51 } rtems_blkdev_request_op; 42 52 43 53 /** 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 47 58 * hack to work around the current ATA driver. 48 59 */ 49 60 #define RTEMS_BLKDEV_CAP_MULTISECTOR_CONT (1 << 0) 50 61 51 /* 52 * @typedef rtems_blkdev_request_cb 53 * 62 /** 54 63 * Type for block device request done callback function. 55 64 * 56 * @param arg Argument supplied in blkdev_request57 * @param status RTEMS status code for this operation58 * @param errno errno value to be passed to the user when59 * status != RTEMS_SUCCESSFUL65 * @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. 60 69 */ 61 70 typedef void (* rtems_blkdev_request_cb)(void *arg, … … 64 73 65 74 /** 66 * @struct rtems_blkdev_sg_buffer 67 * Block device scatter/gather buffer structure 75 * Block device scatter or gather buffer structure. 68 76 */ 69 77 typedef 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; 74 97 } rtems_blkdev_sg_buffer; 75 98 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. 78 102 */ 79 103 typedef 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]; 98 144 } rtems_blkdev_request; 99 145 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 */ 118 175 #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. 126 186 */ 127 187 rtems_device_driver … … 132 192 ); 133 193 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. 137 198 */ 138 199 rtems_device_driver … … 143 204 ); 144 205 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. 147 210 */ 148 211 rtems_device_driver … … 153 216 ); 154 217 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. 157 222 */ 158 223 rtems_device_driver … … 163 228 ); 164 229 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. 167 234 */ 168 235 rtems_device_driver … … 172 239 void * arg 173 240 ); 241 242 /** @} */ 174 243 175 244 #ifdef __cplusplus -
cpukit/libblock/include/rtems/diskdevs.h
r92c70b9 r57aa979 1 1 /** 2 * @file rtems/diskdevs.h 3 * Physical and logical block devices (disks) support 2 * @file 3 * 4 * Block device disk management. 4 5 */ 5 6 … … 14 15 #define _RTEMS_DISKDEVS_H 15 16 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 */ 26 typedef int rtems_bdpool_id; 27 28 #include <rtems/blkdev.h> 29 16 30 #ifdef __cplusplus 17 31 extern "C" { 18 32 #endif 19 33 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 */ 52 typedef 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. 40 61 */ 41 62 typedef 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; 64 125 } rtems_disk_device; 65 126 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 */ 139 rtems_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 */ 158 rtems_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 */ 174 rtems_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 */ 183 rtems_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 */ 190 rtems_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 */ 207 rtems_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 */ 215 rtems_status_code rtems_disk_io_initialize(void); 216 217 /** 218 * Releases all resources allocated for disk device management. 219 */ 220 rtems_status_code rtems_disk_io_done(void); 221 222 /** @} */ 207 223 208 224 #ifdef __cplusplus -
cpukit/libblock/src/bdbuf.c
r92c70b9 r57aa979 1 /** 2 * @file 3 * 4 * Block device buffer management. 5 */ 6 1 7 /* 2 8 * Disk I/O buffering … … 16 22 17 23 /** 18 * @file19 *20 * The Buffer Descriptor Buffer code implements a cache between the disk21 * devices and file systems. The code provides read ahead and write queuing to22 * 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 the25 * buffers follow this state machine:26 *27 * read/read ahead28 * +-------------------------------+29 * | v30 * +-----------+ 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 a49 * caller requests a buffer. This is referred to as getting a buffer in the50 * code and the event get in the state diagram. The buffer is assigned to a51 * block and inserted to the AVL based on the block/device key. If the block is52 * to be read by the user and not in the cache (ready) it is transfered from53 * the disk into memory. If no ready buffers exist the buffer is taken from the54 * LRU list. If no buffers are on the LRU list the modified list is check. If55 * no buffers are on the modified list the request blocks. If buffers are on56 * the modified list the buffers hold timer is expired and the swap out task57 * woken.58 *59 * A block being accessed is given to the file system layer and not accessable60 * to another requester until released back to the cache. The same goes to a61 * buffer in the transfer state. The transfer state means being read or62 * written. If the file system has modifed the block and releases it as63 * modified it placed on the pool's modified list and a hold timer64 * initialised. The buffer is held for the hold time before being written to65 * disk. Buffers are held for a configurable period of time on the modified66 * list as a write sets the state to transfer and this locks the buffer out67 * from the file system until the write complete. Buffers are often repeatable68 * accessed and modified in a series of small updates so if sent to the disk69 * when released as modified the user would have to block waiting until it had70 * been written. This would be a performance problem.71 *72 * The code performs mulitple block reads and writes. Multiple block reads or73 * read ahead increases performance with hardware that supports it. It also74 * helps with a large cache as the disk head movement is reduced. It how-ever75 * is a speculative operation so excessive use can remove valuable and needed76 * blocks from the cache. The get call knows if a read is a for the file system77 * or if it is a read ahead get. If the get is for a read ahead block and the78 * block is already in the cache or no ready buffers are available the read79 * ahead is stopped. The transfer occurs with the blocks so far. If a buffer is80 * in the read ahead state and release it is placed on the ready list rather81 * than the LRU list. This means these buffers are used before buffers used by82 * 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 /**93 24 * Set to 1 to enable debug tracing. 94 25 */ … … 101 32 #include <rtems.h> 102 33 #include <rtems/error.h> 34 #include <rtems/malloc.h> 103 35 #include <limits.h> 104 36 #include <errno.h> … … 431 363 * Removes the node from the tree. 432 364 * 433 * @param root _addrPointer to pointer to the root node365 * @param root Pointer to pointer to the root node 434 366 * @param node Pointer to the node to remove 435 367 * @retval 0 Item removed … … 705 637 * Get the pool for the device. 706 638 * 707 * @param p dd Physical disk device.639 * @param pid Physical disk device. 708 640 */ 709 641 static rtems_bdbuf_pool* … … 924 856 rtems_bdpool_id pid) 925 857 { 858 int rv = 0; 926 859 unsigned char* buffer = config->mem_area; 927 860 rtems_bdbuf_pool* pool; … … 929 862 rtems_status_code sc; 930 863 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 } 931 871 932 872 pool = rtems_bdbuf_get_pool (pid); … … 962 902 963 903 /* 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(). 965 907 */ 966 908 if (buffer == NULL) 967 909 { 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) 970 914 { 971 915 free (pool->bds); 972 916 return RTEMS_NO_MEMORY; 973 917 } 918 pool->buffers = buffer; 974 919 } 975 920 … … 1080 1025 } 1081 1026 1082 /**1083 * Prepare buffering layer to work - initialize buffer descritors and (if it is1084 * neccessary) buffers. Buffers will be allocated accoriding to the1085 * configuration table, each entry describes the size of block and the size of1086 * the pool. After initialization all blocks is placed into the ready state.1087 * lists.1088 *1089 * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed1090 * successfully or error code if error is occured)1091 */1092 1027 rtems_status_code 1093 1028 rtems_bdbuf_init (void) … … 1210 1145 * unlocked if the call could block. 1211 1146 * 1212 * @param deviceThe physical disk device1147 * @param pdd The physical disk device 1213 1148 * @param pool The pool reference 1214 1149 * @param block Absolute media block number … … 1402 1337 } 1403 1338 1404 /**1405 * Get block buffer for data to be written into. The buffers is set to the1406 * access or modifed access state. If the buffer is in the cache and modified1407 * the state is access modified else the state is access. This buffer contents1408 * are not initialised if the buffer is not already in the cache. If the block1409 * is already resident in memory it is returned how-ever if not in memory the1410 * buffer is not read from disk. This call is used when writing the whole block1411 * on a disk rather than just changing a part of it. If there is no buffers1412 * available this call will block. A buffer obtained with this call will not be1413 * involved in a transfer request and will not be returned to another user1414 * until released. If the buffer is already with a user when this call is made1415 * the call is blocked until the buffer is returned. The highest priority1416 * waiter will obtain the buffer first.1417 *1418 * The block number is the linear block number. This is relative to the start1419 * 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 number1423 * @param bd Reference to the buffer descriptor pointer.1424 *1425 * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed1426 * successfully or error code if error is occured)1427 */1428 1339 rtems_status_code 1429 1340 rtems_bdbuf_get (dev_t device, … … 1448 1359 } 1449 1360 1450 block += dd->start;1451 1452 1361 pool = rtems_bdbuf_get_pool (dd->phys_dev->pool); 1453 1362 … … 1455 1364 1456 1365 #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); 1458 1368 #endif 1459 1369 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); 1461 1371 1462 1372 if (bd->state == RTEMS_BDBUF_STATE_MODIFIED) … … 1495 1405 } 1496 1406 1497 /**1498 * Get the block buffer and if not already in the cache read from the disk. If1499 * specified block already cached return. The buffer is set to the access or1500 * modifed access state. If the buffer is in the cache and modified the state1501 * is access modified else the state is access. If block is already being read1502 * from disk for being written to disk this call blocks. If the buffer is1503 * waiting to be written it is removed from modified queue and returned to the1504 * user. If the buffer is not in the cache a new buffer is obtained and the1505 * data read from disk. The call may block until these operations complete. A1506 * buffer obtained with this call will not be involved in a transfer request1507 * and will not be returned to another user until released. If the buffer is1508 * already with a user when this call is made the call is blocked until the1509 * buffer is returned. The highest priority waiter will obtain the buffer1510 * first.1511 *1512 * @note Read ahead always reads buffers in sequence. All multi-block reads1513 * read consecutive blocks.1514 *1515 * @param device Device number (constructed of major and minor device number)1516 * @param block Linear media block number1517 * @param bd Reference to the buffer descriptor pointer.1518 *1519 * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed1520 * successfully or error code if error is occured)1521 */1522 1407 rtems_status_code 1523 1408 rtems_bdbuf_read (dev_t device, … … 1546 1431 if (dd == NULL) 1547 1432 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) { 1557 1435 rtems_disk_release(dd); 1558 1436 return RTEMS_INVALID_NUMBER; 1559 1437 } 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 1560 1443 1561 1444 req->bufnum = 0; … … 1588 1471 */ 1589 1472 bd = rtems_bdbuf_get_buffer (dd->phys_dev, pool, 1590 block + req->bufnum,1473 block + dd->start + req->bufnum, 1591 1474 req->bufnum == 0 ? false : true); 1592 1475 … … 1712 1595 } 1713 1596 1714 /**1715 * Release the buffer obtained by a read call back to the cache. If the buffer1716 * was obtained by a get call and was not already in the cache the release1717 * modified call should be used. A buffer released with this call obtained by a1718 * get call may not be in sync with the contents on disk. If the buffer was in1719 * the cache and modified before this call it will be returned to the modified1720 * 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 completed1725 * successfully or error code if error is occured)1726 */1727 1597 rtems_status_code 1728 1598 rtems_bdbuf_release (rtems_bdbuf_buffer* bd) … … 1786 1656 } 1787 1657 1788 /**1789 * Release the buffer allocated with a get or read call placing it on the1790 * modidied list. If the buffer was not released modified before the hold1791 * timer is set to the configuration value. If the buffer had been released1792 * modified before but not written to disk the hold timer is not updated. The1793 * buffer will be written to disk when the hold timer has expired, there are1794 * not more buffers available in the cache and a get or read buffer needs one1795 * or a sync call has been made. If the buffer is obtained with a get or read1796 * 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 completed1801 * successfully or error code if error is occured)1802 */1803 1658 rtems_status_code 1804 1659 rtems_bdbuf_release_modified (rtems_bdbuf_buffer* bd) … … 1829 1684 } 1830 1685 1831 /**1832 * Release the buffer as modified and wait until it has been synchronized with1833 * the disk by writing it. This buffer will be the first to be transfer to disk1834 * and other buffers may also be written if the maximum number of blocks in a1835 * requests allows it.1836 *1837 * @note This code does not lock the sync mutex and stop additions to the1838 * modified queue.1839 *1840 * @param bd Reference to the buffer descriptor.1841 *1842 * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed1843 * successfully or error code if error is occured)1844 */1845 1686 rtems_status_code 1846 1687 rtems_bdbuf_sync (rtems_bdbuf_buffer* bd) … … 1896 1737 } 1897 1738 1898 /**1899 * Synchronize all modified buffers for this device with the disk and wait1900 * until the transfers have completed. The sync mutex for the pool is locked1901 * stopping the addition of any further modifed buffers. It is only the1902 * currently modified buffers that are written.1903 *1904 * @param dev Block device number1905 *1906 * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed1907 * successfully or error code if error is occured)1908 */1909 1739 rtems_status_code 1910 1740 rtems_bdbuf_syncdev (dev_t dev) … … 2428 2258 } 2429 2259 2430 /**2431 * Find first appropriate buffer pool. This primitive returns the index of2432 * first buffer pool which block size is greater than or equal to specified2433 * size.2434 *2435 * @param block_size Requested block size2436 * @param pool The pool to use for the requested pool size.2437 *2438 * @return RTEMS status code (RTEMS_SUCCESSFUL if operation completed2439 * successfully or error code if error is occured)2440 * @retval RTEMS_INVALID_SIZE The specified block size is invalid (not a power2441 * of 2)2442 * @retval RTEMS_NOT_DEFINED The buffer pool for this or greater block size2443 * is not configured.2444 */2445 2260 rtems_status_code 2446 2261 rtems_bdbuf_find_pool (uint32_t block_size, rtems_bdpool_id *pool) … … 2481 2296 } 2482 2297 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) 2298 rtems_status_code rtems_bdbuf_get_pool_info( 2299 rtems_bdpool_id pool, 2300 uint32_t *block_size, 2301 uint32_t *blocks 2302 ) 2500 2303 { 2501 2304 if (pool >= rtems_bdbuf_ctx.npools) -
cpukit/libblock/src/blkdev.c
r92c70b9 r57aa979 1 /** 2 * @file 3 * 4 * Block device management. 5 */ 6 1 7 /* 2 8 * 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 1 7 /* 2 8 * diskdevs.c - Physical and logical block devices (disks) support … … 213 219 } 214 220 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) 221 rtems_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 ) 241 228 { 242 229 int bs_log2; … … 298 285 } 299 286 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 287 rtems_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 ) { 366 319 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); 369 328 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 386 347 rtems_status_code 387 348 rtems_disk_delete(dev_t dev) 388 349 { 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; 398 371 399 372 /* 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 } 412 381 } 413 }414 415 if (used != 0) 416 {417 418 419 382 } 383 } 384 385 if (used != 0) { 386 diskdevs_protected = false; 387 rtems_semaphore_release(diskdevs_mutex); 388 return RTEMS_RESOURCE_IN_USE; 420 389 } 421 390 422 391 /* 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 } 439 403 } 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 457 419 rtems_disk_device * 458 420 rtems_disk_obtain(dev_t dev) … … 487 449 } 488 450 489 /* rtems_disk_release --490 * Release rtems_disk_device structure (decrement usage counter to 1).491 *492 * PARAMETERS:493 * dd - pointer to disk device structure494 *495 * RETURNS:496 * RTEMS_SUCCESSFUL497 */498 451 rtems_status_code 499 452 rtems_disk_release(rtems_disk_device *dd) … … 506 459 } 507 460 508 /* rtems_disk_next --509 * Disk device enumerator. Looking for device having device number larger510 * than dev and return disk device descriptor for it. If there are no511 * 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 all518 * devices enumerated.519 */520 461 rtems_disk_device * 521 462 rtems_disk_next(dev_t dev) … … 550 491 } 551 492 552 /* rtems_disk_initialize --553 * Initialization of disk device library (initialize all data structures,554 * etc.)555 *556 * PARAMETERS:557 * none558 *559 * RETURNS:560 * RTEMS_SUCCESSFUL if library initialized, or error code if error561 * occured.562 */563 493 rtems_status_code 564 494 rtems_disk_io_initialize(void) … … 599 529 } 600 530 601 /* rtems_disk_io_done --602 * Release all resources allocated for disk device interface.603 *604 * PARAMETERS:605 * none606 *607 * RETURNS:608 * RTEMS_SUCCESSFUL if all resources released, or error code if error609 * occured.610 */611 531 rtems_status_code 612 532 rtems_disk_io_done(void)
Note: See TracChangeset
for help on using the changeset viewer.