[b80dd59d] | 1 | /** |
---|
[57aa979] | 2 | * @file |
---|
[e51bd96] | 3 | * |
---|
[4670d91] | 4 | * @ingroup rtems_bdbuf |
---|
| 5 | * |
---|
[57aa979] | 6 | * Block device buffer management. |
---|
[b80dd59d] | 7 | */ |
---|
[33c3b54d] | 8 | |
---|
[b80dd59d] | 9 | /* |
---|
[e51bd96] | 10 | * Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia |
---|
| 11 | * Author: Victor V. Vengerov <vvv@oktet.ru> |
---|
| 12 | * |
---|
[0d15414e] | 13 | * Copyright (C) 2008,2009 Chris Johns <chrisj@rtems.org> |
---|
[c21c850e] | 14 | * Rewritten to remove score mutex access. Fixes many performance |
---|
| 15 | * issues. |
---|
[6d612944] | 16 | * Change to support demand driven variable buffer sizes. |
---|
| 17 | * |
---|
[1024561] | 18 | * Copyright (c) 2009-2012 embedded brains GmbH. |
---|
[c21c850e] | 19 | * |
---|
[3d14a45] | 20 | * @(#) bdbuf.h,v 1.9 2005/02/02 00:06:18 joel Exp |
---|
[e51bd96] | 21 | */ |
---|
| 22 | |
---|
[a6f5d89] | 23 | #ifndef _RTEMS_BDBUF_H |
---|
| 24 | #define _RTEMS_BDBUF_H |
---|
[e51bd96] | 25 | |
---|
| 26 | #include <rtems.h> |
---|
| 27 | #include <rtems/libio.h> |
---|
[ebbe119e] | 28 | #include <rtems/chain.h> |
---|
[e51bd96] | 29 | |
---|
[90b2c072] | 30 | #include <rtems/blkdev.h> |
---|
| 31 | #include <rtems/diskdevs.h> |
---|
[e51bd96] | 32 | |
---|
[4f971343] | 33 | #ifdef __cplusplus |
---|
| 34 | extern "C" { |
---|
| 35 | #endif |
---|
[b5b07cad] | 36 | |
---|
[57aa979] | 37 | /** |
---|
| 38 | * @defgroup rtems_libblock Block Device Library |
---|
[c85ab23] | 39 | * |
---|
| 40 | * Block device modules. |
---|
[57aa979] | 41 | */ |
---|
[4f971343] | 42 | |
---|
[57aa979] | 43 | /** |
---|
| 44 | * @defgroup rtems_bdbuf Block Device Buffer Management |
---|
| 45 | * |
---|
| 46 | * @ingroup rtems_libblock |
---|
| 47 | * |
---|
| 48 | * The Block Device Buffer Management implements a cache between the disk |
---|
[6d612944] | 49 | * devices and file systems. The code provides read ahead and write queuing to |
---|
| 50 | * the drivers and fast cache look-up using an AVL tree. |
---|
[57aa979] | 51 | * |
---|
[0d15414e] | 52 | * The block size used by a file system can be set at runtime and must be a |
---|
[6d612944] | 53 | * multiple of the disk device block size. The disk device's physical block |
---|
| 54 | * size is called the media block size. The file system can set the block size |
---|
| 55 | * it uses to a larger multiple of the media block size. The driver must be |
---|
[0d15414e] | 56 | * able to handle buffers sizes larger than one media block. |
---|
| 57 | * |
---|
| 58 | * The user configures the amount of memory to be used as buffers in the cache, |
---|
[6d612944] | 59 | * and the minimum and maximum buffer size. The cache will allocate additional |
---|
| 60 | * memory for the buffer descriptors and groups. There are enough buffer |
---|
[0d15414e] | 61 | * descriptors allocated so all the buffer memory can be used as minimum sized |
---|
| 62 | * buffers. |
---|
| 63 | * |
---|
[6d612944] | 64 | * The cache is a single pool of buffers. The buffer memory is divided into |
---|
[0d15414e] | 65 | * groups where the size of buffer memory allocated to a group is the maximum |
---|
[6d612944] | 66 | * buffer size. A group's memory can be divided down into small buffer sizes |
---|
| 67 | * that are a multiple of 2 of the minimum buffer size. A group is the minimum |
---|
| 68 | * allocation unit for buffers of a specific size. If a buffer of maximum size |
---|
| 69 | * is request the group will have a single buffer. If a buffer of minimum size |
---|
[0d15414e] | 70 | * is requested the group is divided into minimum sized buffers and the |
---|
[6d612944] | 71 | * remaining buffers are held ready for use. A group keeps track of which |
---|
[0d15414e] | 72 | * buffers are with a file system or driver and groups who have buffer in use |
---|
[6d612944] | 73 | * cannot be realloced. Groups with no buffers in use can be taken and |
---|
| 74 | * realloced to a new size. This is how buffers of different sizes move around |
---|
[0d15414e] | 75 | * the cache. |
---|
| 76 | |
---|
[6d612944] | 77 | * The buffers are held in various lists in the cache. All buffers follow this |
---|
[0d15414e] | 78 | * state machine: |
---|
[33c3b54d] | 79 | * |
---|
[57aa979] | 80 | * @dot |
---|
[6d612944] | 81 | * digraph state { |
---|
[47c2327] | 82 | * size="16,8"; |
---|
[5c587596] | 83 | * f [label="FREE",style="filled",fillcolor="aquamarine"]; |
---|
| 84 | * e [label="EMPTY",style="filled",fillcolor="seagreen"]; |
---|
[6d612944] | 85 | * c [label="CACHED",style="filled",fillcolor="chartreuse"]; |
---|
[5c587596] | 86 | * ac [label="ACCESS CACHED",style="filled",fillcolor="royalblue"]; |
---|
[6d612944] | 87 | * am [label="ACCESS MODIFIED",style="filled",fillcolor="royalblue"]; |
---|
[5c587596] | 88 | * ae [label="ACCESS EMPTY",style="filled",fillcolor="royalblue"]; |
---|
[e7fb54e] | 89 | * ap [label="ACCESS PURGED",style="filled",fillcolor="royalblue"]; |
---|
[6d612944] | 90 | * t [label="TRANSFER",style="filled",fillcolor="red"]; |
---|
[e7fb54e] | 91 | * tp [label="TRANSFER PURGED",style="filled",fillcolor="red"]; |
---|
[6d612944] | 92 | * s [label="SYNC",style="filled",fillcolor="red"]; |
---|
| 93 | * m [label="MODIFIED",style="filled",fillcolor="gold"]; |
---|
| 94 | * i [label="INITIAL"]; |
---|
[33c3b54d] | 95 | * |
---|
[6d612944] | 96 | * legend_transfer [label="Transfer Wake-Up",fontcolor="red",shape="none"]; |
---|
| 97 | * legend_access [label="Access Wake-Up",fontcolor="royalblue",shape="none"]; |
---|
[33c3b54d] | 98 | * |
---|
[5c587596] | 99 | * i -> f [label="Init"]; |
---|
| 100 | * f -> e [label="Buffer Recycle"]; |
---|
| 101 | * e -> ae [label="Get"]; |
---|
[e7fb54e] | 102 | * e -> t [label="Read"]; |
---|
| 103 | * e -> f [label="Nobody Waits"]; |
---|
[5c587596] | 104 | * c -> ac [label="Get\nRead"]; |
---|
[e7fb54e] | 105 | * c -> e [label="Buffer Recycle\nPurge"]; |
---|
| 106 | * c -> f [label="Reallocate\nBlock Size Changed"]; |
---|
[5c587596] | 107 | * t -> c [label="Transfer Done",color="red",fontcolor="red"]; |
---|
[e7fb54e] | 108 | * t -> e [label="Transfer Error",color="red",fontcolor="red"]; |
---|
| 109 | * t -> tp [label="Purge"]; |
---|
| 110 | * tp -> e [label="Transfer Done\nTransfer Error",color="red",fontcolor="red"]; |
---|
[6d612944] | 111 | * m -> t [label="Swapout"]; |
---|
| 112 | * m -> s [label="Block Size Changed"]; |
---|
| 113 | * m -> am [label="Get\nRead"]; |
---|
[e7fb54e] | 114 | * m -> e [label="Purge"]; |
---|
[5c587596] | 115 | * ac -> m [label="Release Modified",color="royalblue",fontcolor="royalblue"]; |
---|
| 116 | * ac -> s [label="Sync",color="royalblue",fontcolor="royalblue"]; |
---|
| 117 | * ac -> c [label="Release",color="royalblue",fontcolor="royalblue"]; |
---|
[e7fb54e] | 118 | * ac -> ap [label="Purge"]; |
---|
[6d612944] | 119 | * am -> m [label="Release\nRelease Modified",color="royalblue",fontcolor="royalblue"]; |
---|
| 120 | * am -> s [label="Sync",color="royalblue",fontcolor="royalblue"]; |
---|
[e7fb54e] | 121 | * am -> ap [label="Purge"]; |
---|
[5c587596] | 122 | * ae -> m [label="Release Modified",color="royalblue",fontcolor="royalblue"]; |
---|
| 123 | * ae -> s [label="Sync",color="royalblue",fontcolor="royalblue"]; |
---|
[e7fb54e] | 124 | * ae -> e [label="Release",color="royalblue",fontcolor="royalblue"]; |
---|
| 125 | * ae -> ap [label="Purge"]; |
---|
| 126 | * ap -> e [label="Release\nRelease Modified\nSync",color="royalblue",fontcolor="royalblue"]; |
---|
[6d612944] | 127 | * s -> t [label="Swapout"]; |
---|
[e7fb54e] | 128 | * s -> e [label="Purge",color="red",fontcolor="red"]; |
---|
[57aa979] | 129 | * } |
---|
| 130 | * @enddot |
---|
[33c3b54d] | 131 | * |
---|
[6d612944] | 132 | * Empty or cached buffers are added to the LRU list and removed from this |
---|
| 133 | * queue when a caller requests a buffer. This is referred to as getting a |
---|
| 134 | * buffer in the code and the event get in the state diagram. The buffer is |
---|
| 135 | * assigned to a block and inserted to the AVL based on the block/device key. |
---|
| 136 | * If the block is to be read by the user and not in the cache it is transfered |
---|
| 137 | * from the disk into memory. If no buffers are on the LRU list the modified |
---|
| 138 | * list is checked. If buffers are on the modified the swap out task will be |
---|
[33c3b54d] | 139 | * woken. The request blocks until a buffer is available for recycle. |
---|
[57aa979] | 140 | * |
---|
[6d612944] | 141 | * A block being accessed is given to the file system layer and not accessible |
---|
| 142 | * to another requester until released back to the cache. The same goes to a |
---|
| 143 | * buffer in the transfer state. The transfer state means being read or |
---|
| 144 | * written. If the file system has modifed the block and releases it as |
---|
[0d15414e] | 145 | * modified it placed on the cache's modified list and a hold timer |
---|
[6d612944] | 146 | * initialised. The buffer is held for the hold time before being written to |
---|
| 147 | * disk. Buffers are held for a configurable period of time on the modified |
---|
[57aa979] | 148 | * list as a write sets the state to transfer and this locks the buffer out |
---|
[6d612944] | 149 | * from the file system until the write completes. Buffers are often accessed |
---|
[0d15414e] | 150 | * and modified in a series of small updates so if sent to the disk when |
---|
| 151 | * released as modified the user would have to block waiting until it had been |
---|
[6d612944] | 152 | * written. This would be a performance problem. |
---|
[57aa979] | 153 | * |
---|
[6d612944] | 154 | * The code performs multiple block reads and writes. Multiple block reads or |
---|
| 155 | * read ahead increases performance with hardware that supports it. It also |
---|
| 156 | * helps with a large cache as the disk head movement is reduced. It however |
---|
[57aa979] | 157 | * is a speculative operation so excessive use can remove valuable and needed |
---|
[6d612944] | 158 | * blocks from the cache. |
---|
[57aa979] | 159 | * |
---|
[0d15414e] | 160 | * The cache has the following lists of buffers: |
---|
[6d612944] | 161 | * - LRU: Accessed or transfered buffers released in least recently used |
---|
| 162 | * order. Empty buffers will be placed to the front. |
---|
| 163 | * - Modified: Buffers waiting to be written to disk. |
---|
| 164 | * - Sync: Buffers to be synchronized with the disk. |
---|
[57aa979] | 165 | * |
---|
[6d612944] | 166 | * A cache look-up will be performed to find a suitable buffer. A suitable |
---|
| 167 | * buffer is one that matches the same allocation size as the device the buffer |
---|
| 168 | * is for. The a buffer's group has no buffers in use with the file system or |
---|
| 169 | * driver the group is reallocated. This means the buffers in the group are |
---|
| 170 | * invalidated, resized and placed on the LRU queue. There is a performance |
---|
| 171 | * issue with this design. The reallocation of a group may forced recently |
---|
| 172 | * accessed buffers out of the cache when they should not. The design should be |
---|
| 173 | * change to have groups on a LRU list if they have no buffers in use. |
---|
[0d15414e] | 174 | * |
---|
[57aa979] | 175 | * @{ |
---|
| 176 | */ |
---|
[4f971343] | 177 | |
---|
[3899a537] | 178 | /** |
---|
[47c2327] | 179 | * @brief State of a buffer of the cache. |
---|
| 180 | * |
---|
| 181 | * The state has several implications. Depending on the state a buffer can be |
---|
| 182 | * in the AVL tree, in a list, in use by an entity and a group user or not. |
---|
[5c587596] | 183 | * |
---|
| 184 | * <table> |
---|
| 185 | * <tr> |
---|
| 186 | * <th>State</th><th>Valid Data</th><th>AVL Tree</th> |
---|
| 187 | * <th>LRU List</th><th>Modified List</th><th>Synchronization List</th> |
---|
| 188 | * <th>Group User</th><th>External User</th> |
---|
| 189 | * </tr> |
---|
| 190 | * <tr> |
---|
| 191 | * <td>FREE</td><td></td><td></td> |
---|
| 192 | * <td>X</td><td></td><td></td><td></td><td></td> |
---|
| 193 | * </tr> |
---|
| 194 | * <tr> |
---|
| 195 | * <td>EMPTY</td><td></td><td>X</td> |
---|
[e7fb54e] | 196 | * <td></td><td></td><td></td><td></td><td></td> |
---|
[5c587596] | 197 | * </tr> |
---|
| 198 | * <tr> |
---|
| 199 | * <td>CACHED</td><td>X</td><td>X</td> |
---|
| 200 | * <td>X</td><td></td><td></td><td></td><td></td> |
---|
| 201 | * </tr> |
---|
| 202 | * <tr> |
---|
[e7fb54e] | 203 | * <td>ACCESS CACHED</td><td>X</td><td>X</td> |
---|
| 204 | * <td></td><td></td><td></td><td>X</td><td>X</td> |
---|
| 205 | * </tr> |
---|
| 206 | * <tr> |
---|
| 207 | * <td>ACCESS MODIFIED</td><td>X</td><td>X</td> |
---|
[5c587596] | 208 | * <td></td><td></td><td></td><td>X</td><td>X</td> |
---|
| 209 | * </tr> |
---|
| 210 | * <tr> |
---|
[e7fb54e] | 211 | * <td>ACCESS EMPTY</td><td></td><td>X</td> |
---|
[5c587596] | 212 | * <td></td><td></td><td></td><td>X</td><td>X</td> |
---|
| 213 | * </tr> |
---|
| 214 | * <tr> |
---|
[e7fb54e] | 215 | * <td>ACCESS PURGED</td><td></td><td>X</td> |
---|
[5c587596] | 216 | * <td></td><td></td><td></td><td>X</td><td>X</td> |
---|
| 217 | * </tr> |
---|
| 218 | * <tr> |
---|
| 219 | * <td>MODIFIED</td><td>X</td><td>X</td> |
---|
| 220 | * <td></td><td>X</td><td></td><td>X</td><td></td> |
---|
| 221 | * </tr> |
---|
| 222 | * <tr> |
---|
| 223 | * <td>SYNC</td><td>X</td><td>X</td> |
---|
| 224 | * <td></td><td></td><td>X</td><td>X</td><td></td> |
---|
| 225 | * </tr> |
---|
| 226 | * <tr> |
---|
| 227 | * <td>TRANSFER</td><td>X</td><td>X</td> |
---|
| 228 | * <td></td><td></td><td></td><td>X</td><td>X</td> |
---|
| 229 | * </tr> |
---|
[e7fb54e] | 230 | * <tr> |
---|
| 231 | * <td>TRANSFER PURGED</td><td></td><td>X</td> |
---|
| 232 | * <td></td><td></td><td></td><td>X</td><td>X</td> |
---|
| 233 | * </tr> |
---|
[5c587596] | 234 | * </table> |
---|
[e51bd96] | 235 | */ |
---|
[3899a537] | 236 | typedef enum |
---|
| 237 | { |
---|
[6d612944] | 238 | /** |
---|
[5c587596] | 239 | * @brief Free. |
---|
[6d612944] | 240 | */ |
---|
[5c587596] | 241 | RTEMS_BDBUF_STATE_FREE = 0, |
---|
[6d612944] | 242 | |
---|
| 243 | /** |
---|
[5c587596] | 244 | * @brief Empty. |
---|
[6d612944] | 245 | */ |
---|
[5c587596] | 246 | RTEMS_BDBUF_STATE_EMPTY, |
---|
[6d612944] | 247 | |
---|
| 248 | /** |
---|
[47c2327] | 249 | * @brief Cached. |
---|
[6d612944] | 250 | */ |
---|
[47c2327] | 251 | RTEMS_BDBUF_STATE_CACHED, |
---|
[6d612944] | 252 | |
---|
| 253 | /** |
---|
[5c587596] | 254 | * @brief Accessed by upper layer with cached data. |
---|
[6d612944] | 255 | */ |
---|
[5c587596] | 256 | RTEMS_BDBUF_STATE_ACCESS_CACHED, |
---|
[6d612944] | 257 | |
---|
| 258 | /** |
---|
[5c587596] | 259 | * @brief Accessed by upper layer with modified data. |
---|
[6d612944] | 260 | */ |
---|
| 261 | RTEMS_BDBUF_STATE_ACCESS_MODIFIED, |
---|
| 262 | |
---|
[5c587596] | 263 | /** |
---|
| 264 | * @brief Accessed by upper layer with invalid data. |
---|
| 265 | */ |
---|
| 266 | RTEMS_BDBUF_STATE_ACCESS_EMPTY, |
---|
| 267 | |
---|
[e7fb54e] | 268 | /** |
---|
| 269 | * @brief Accessed by upper layer with purged data. |
---|
| 270 | */ |
---|
| 271 | RTEMS_BDBUF_STATE_ACCESS_PURGED, |
---|
| 272 | |
---|
[6d612944] | 273 | /** |
---|
[47c2327] | 274 | * @brief Modified by upper layer. |
---|
[6d612944] | 275 | */ |
---|
| 276 | RTEMS_BDBUF_STATE_MODIFIED, |
---|
| 277 | |
---|
| 278 | /** |
---|
[47c2327] | 279 | * @brief Scheduled for synchronization. |
---|
[6d612944] | 280 | */ |
---|
| 281 | RTEMS_BDBUF_STATE_SYNC, |
---|
| 282 | |
---|
| 283 | /** |
---|
[47c2327] | 284 | * @brief In transfer by block device driver. |
---|
[6d612944] | 285 | */ |
---|
[e7fb54e] | 286 | RTEMS_BDBUF_STATE_TRANSFER, |
---|
| 287 | |
---|
| 288 | /** |
---|
| 289 | * @brief In transfer by block device driver and purged. |
---|
| 290 | */ |
---|
| 291 | RTEMS_BDBUF_STATE_TRANSFER_PURGED |
---|
[3899a537] | 292 | } rtems_bdbuf_buf_state; |
---|
[e51bd96] | 293 | |
---|
[0d15414e] | 294 | /** |
---|
| 295 | * Forward reference to the block. |
---|
| 296 | */ |
---|
| 297 | struct rtems_bdbuf_group; |
---|
| 298 | typedef struct rtems_bdbuf_group rtems_bdbuf_group; |
---|
| 299 | |
---|
[3899a537] | 300 | /** |
---|
| 301 | * To manage buffers we using buffer descriptors (BD). A BD holds a buffer plus |
---|
| 302 | * a range of other information related to managing the buffer in the cache. To |
---|
[0d15414e] | 303 | * speed-up buffer lookup descriptors are organized in AVL-Tree. The fields |
---|
[796967c] | 304 | * 'dd' and 'block' are search keys. |
---|
[e51bd96] | 305 | */ |
---|
[3899a537] | 306 | typedef struct rtems_bdbuf_buffer |
---|
| 307 | { |
---|
[0d15414e] | 308 | rtems_chain_node link; /**< Link the BD onto a number of lists. */ |
---|
[e51bd96] | 309 | |
---|
[3899a537] | 310 | struct rtems_bdbuf_avl_node |
---|
| 311 | { |
---|
[57aa979] | 312 | struct rtems_bdbuf_buffer* left; /**< Left Child */ |
---|
| 313 | struct rtems_bdbuf_buffer* right; /**< Right Child */ |
---|
[b5b07cad] | 314 | signed char cache; /**< Cache */ |
---|
[57aa979] | 315 | signed char bal; /**< The balance of the sub-tree */ |
---|
[3899a537] | 316 | } avl; |
---|
[e51bd96] | 317 | |
---|
[796967c] | 318 | const rtems_disk_device *dd; /**< disk device */ |
---|
[eb649786] | 319 | |
---|
[57aa979] | 320 | rtems_blkdev_bnum block; /**< block number on the device */ |
---|
[e51bd96] | 321 | |
---|
[57aa979] | 322 | unsigned char* buffer; /**< Pointer to the buffer memory area */ |
---|
[df6348bb] | 323 | |
---|
[c42b03f4] | 324 | rtems_bdbuf_buf_state state; /**< State of the buffer. */ |
---|
[048dcd2b] | 325 | |
---|
[c42b03f4] | 326 | uint32_t waiters; /**< The number of threads waiting on this |
---|
[0d15414e] | 327 | * buffer. */ |
---|
| 328 | rtems_bdbuf_group* group; /**< Pointer to the group of BDs this BD is |
---|
| 329 | * part of. */ |
---|
[c42b03f4] | 330 | uint32_t hold_timer; /**< Timer to indicate how long a buffer |
---|
[0d15414e] | 331 | * has been held in the cache modified. */ |
---|
[eb649786] | 332 | |
---|
| 333 | int references; /**< Allow reference counting by owner. */ |
---|
| 334 | void* user; /**< User data. */ |
---|
[3899a537] | 335 | } rtems_bdbuf_buffer; |
---|
[e51bd96] | 336 | |
---|
[3899a537] | 337 | /** |
---|
[0d15414e] | 338 | * A group is a continuous block of buffer descriptors. A group covers the |
---|
| 339 | * maximum configured buffer size and is the allocation size for the buffers to |
---|
| 340 | * a specific buffer size. If you allocate a buffer to be a specific size, all |
---|
| 341 | * buffers in the group, if there are more than 1 will also be that size. The |
---|
| 342 | * number of buffers in a group is a multiple of 2, ie 1, 2, 4, 8, etc. |
---|
[3899a537] | 343 | */ |
---|
[0d15414e] | 344 | struct rtems_bdbuf_group |
---|
[3899a537] | 345 | { |
---|
[0d15414e] | 346 | rtems_chain_node link; /**< Link the groups on a LRU list if they |
---|
| 347 | * have no buffers in use. */ |
---|
| 348 | size_t bds_per_group; /**< The number of BD allocated to this |
---|
| 349 | * group. This value must be a multiple of |
---|
| 350 | * 2. */ |
---|
| 351 | uint32_t users; /**< How many users the block has. */ |
---|
| 352 | rtems_bdbuf_buffer* bdbuf; /**< First BD this block covers. */ |
---|
| 353 | }; |
---|
[3899a537] | 354 | |
---|
| 355 | /** |
---|
| 356 | * Buffering configuration definition. See confdefs.h for support on using this |
---|
| 357 | * structure. |
---|
[e51bd96] | 358 | */ |
---|
| 359 | typedef struct rtems_bdbuf_config { |
---|
[0d15414e] | 360 | uint32_t max_read_ahead_blocks; /**< Number of blocks to read |
---|
| 361 | * ahead. */ |
---|
| 362 | uint32_t max_write_blocks; /**< Number of blocks to write |
---|
| 363 | * at once. */ |
---|
| 364 | rtems_task_priority swapout_priority; /**< Priority of the swap out |
---|
| 365 | * task. */ |
---|
| 366 | uint32_t swapout_period; /**< Period swapout checks buf |
---|
| 367 | * timers. */ |
---|
| 368 | uint32_t swap_block_hold; /**< Period a buffer is held. */ |
---|
[b36a7d8] | 369 | size_t swapout_workers; /**< The number of worker |
---|
[0d15414e] | 370 | * threads for the swapout |
---|
| 371 | * task. */ |
---|
| 372 | rtems_task_priority swapout_worker_priority; /**< Priority of the swap out |
---|
| 373 | * task. */ |
---|
| 374 | size_t size; /**< Size of memory in the |
---|
| 375 | * cache */ |
---|
| 376 | uint32_t buffer_min; /**< Minimum buffer size. */ |
---|
| 377 | uint32_t buffer_max; /**< Maximum buffer size |
---|
| 378 | * supported. It is also the |
---|
| 379 | * allocation size. */ |
---|
[e51bd96] | 380 | } rtems_bdbuf_config; |
---|
| 381 | |
---|
[3899a537] | 382 | /** |
---|
[57aa979] | 383 | * External reference to the configuration. |
---|
| 384 | * |
---|
| 385 | * The configuration is provided by the application. |
---|
[3899a537] | 386 | */ |
---|
[0d15414e] | 387 | extern const rtems_bdbuf_config rtems_bdbuf_configuration; |
---|
[e51bd96] | 388 | |
---|
[3899a537] | 389 | /** |
---|
| 390 | * The max_read_ahead_blocks value is altered if there are fewer buffers |
---|
| 391 | * than this defined max. This stops thrashing in the cache. |
---|
| 392 | */ |
---|
[6d612944] | 393 | #define RTEMS_BDBUF_MAX_READ_AHEAD_BLOCKS_DEFAULT 0 |
---|
[57aa979] | 394 | |
---|
| 395 | /** |
---|
| 396 | * Default maximum number of blocks to write at once. |
---|
| 397 | */ |
---|
[3899a537] | 398 | #define RTEMS_BDBUF_MAX_WRITE_BLOCKS_DEFAULT 16 |
---|
[57aa979] | 399 | |
---|
| 400 | /** |
---|
| 401 | * Default swap-out task priority. |
---|
| 402 | */ |
---|
[3899a537] | 403 | #define RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT 15 |
---|
[57aa979] | 404 | |
---|
| 405 | /** |
---|
| 406 | * Default swap-out task swap period in milli seconds. |
---|
| 407 | */ |
---|
| 408 | #define RTEMS_BDBUF_SWAPOUT_TASK_SWAP_PERIOD_DEFAULT 250 |
---|
| 409 | |
---|
| 410 | /** |
---|
| 411 | * Default swap-out task block hold time in milli seconds. |
---|
| 412 | */ |
---|
| 413 | #define RTEMS_BDBUF_SWAPOUT_TASK_BLOCK_HOLD_DEFAULT 1000 |
---|
[c9b005a9] | 414 | |
---|
[0d15414e] | 415 | /** |
---|
| 416 | * Default swap-out worker tasks. Currently disabled. |
---|
| 417 | */ |
---|
| 418 | #define RTEMS_BDBUF_SWAPOUT_WORKER_TASKS_DEFAULT 0 |
---|
| 419 | |
---|
| 420 | /** |
---|
| 421 | * Default swap-out worker task priority. The same as the swapout task. |
---|
| 422 | */ |
---|
| 423 | #define RTEMS_BDBUF_SWAPOUT_WORKER_TASK_PRIORITY_DEFAULT \ |
---|
| 424 | RTEMS_BDBUF_SWAPOUT_TASK_PRIORITY_DEFAULT |
---|
| 425 | |
---|
| 426 | /** |
---|
| 427 | * Default size of memory allocated to the cache. |
---|
| 428 | */ |
---|
| 429 | #define RTEMS_BDBUF_CACHE_MEMORY_SIZE_DEFAULT (64 * 512) |
---|
| 430 | |
---|
| 431 | /** |
---|
| 432 | * Default minimum size of buffers. |
---|
| 433 | */ |
---|
| 434 | #define RTEMS_BDBUF_BUFFER_MIN_SIZE_DEFAULT (512) |
---|
| 435 | |
---|
| 436 | /** |
---|
| 437 | * Default maximum size of buffers. |
---|
| 438 | */ |
---|
| 439 | #define RTEMS_BDBUF_BUFFER_MAX_SIZE_DEFAULT (4096) |
---|
| 440 | |
---|
[c21c850e] | 441 | /** |
---|
| 442 | * Prepare buffering layer to work - initialize buffer descritors and (if it is |
---|
[0d15414e] | 443 | * neccessary) buffers. After initialization all blocks is placed into the |
---|
| 444 | * ready state. |
---|
[e51bd96] | 445 | * |
---|
[1024561] | 446 | * @retval RTEMS_SUCCESSFUL Successful operation. |
---|
| 447 | * @retval RTEMS_CALLED_FROM_ISR Called from an interrupt context. |
---|
| 448 | * @retval RTEMS_INVALID_NUMBER The buffer maximum is not an integral multiple |
---|
| 449 | * of the buffer minimum. |
---|
| 450 | * @retval RTEMS_RESOURCE_IN_USE Already initialized. |
---|
| 451 | * @retval RTEMS_UNSATISFIED Not enough resources. |
---|
[e51bd96] | 452 | */ |
---|
| 453 | rtems_status_code |
---|
[a5fb40cf] | 454 | rtems_bdbuf_init (void); |
---|
[e51bd96] | 455 | |
---|
[c21c850e] | 456 | /** |
---|
| 457 | * Get block buffer for data to be written into. The buffers is set to the |
---|
| 458 | * access or modifed access state. If the buffer is in the cache and modified |
---|
| 459 | * the state is access modified else the state is access. This buffer contents |
---|
| 460 | * are not initialised if the buffer is not already in the cache. If the block |
---|
| 461 | * is already resident in memory it is returned how-ever if not in memory the |
---|
| 462 | * buffer is not read from disk. This call is used when writing the whole block |
---|
| 463 | * on a disk rather than just changing a part of it. If there is no buffers |
---|
| 464 | * available this call will block. A buffer obtained with this call will not be |
---|
| 465 | * involved in a transfer request and will not be returned to another user |
---|
| 466 | * until released. If the buffer is already with a user when this call is made |
---|
| 467 | * the call is blocked until the buffer is returned. The highest priority |
---|
| 468 | * waiter will obtain the buffer first. |
---|
[e51bd96] | 469 | * |
---|
[c21c850e] | 470 | * The block number is the linear block number. This is relative to the start |
---|
| 471 | * of the partition on the media. |
---|
[e51bd96] | 472 | * |
---|
[796967c] | 473 | * @param dd [in] The disk device. |
---|
[1024561] | 474 | * @param block [in] Linear media block number. |
---|
| 475 | * @param bd [out] Reference to the buffer descriptor pointer. |
---|
[e51bd96] | 476 | * |
---|
[1024561] | 477 | * @retval RTEMS_SUCCESSFUL Successful operation. |
---|
| 478 | * @retval RTEMS_NOT_CONFIGURED Not initialized. |
---|
| 479 | * @retval RTEMS_INVALID_ID No such device. |
---|
| 480 | * @retval RTEMS_INVALID_NUMBER Invalid block size. |
---|
[e51bd96] | 481 | */ |
---|
[c21c850e] | 482 | rtems_status_code |
---|
[796967c] | 483 | rtems_bdbuf_get ( |
---|
| 484 | const rtems_disk_device *dd, |
---|
| 485 | rtems_blkdev_bnum block, |
---|
| 486 | rtems_bdbuf_buffer** bd |
---|
| 487 | ); |
---|
[c21c850e] | 488 | |
---|
| 489 | /** |
---|
| 490 | * Get the block buffer and if not already in the cache read from the disk. If |
---|
| 491 | * specified block already cached return. The buffer is set to the access or |
---|
| 492 | * modifed access state. If the buffer is in the cache and modified the state |
---|
| 493 | * is access modified else the state is access. If block is already being read |
---|
| 494 | * from disk for being written to disk this call blocks. If the buffer is |
---|
| 495 | * waiting to be written it is removed from modified queue and returned to the |
---|
| 496 | * user. If the buffer is not in the cache a new buffer is obtained and the |
---|
| 497 | * data read from disk. The call may block until these operations complete. A |
---|
| 498 | * buffer obtained with this call will not be involved in a transfer request |
---|
| 499 | * and will not be returned to another user until released. If the buffer is |
---|
| 500 | * already with a user when this call is made the call is blocked until the |
---|
| 501 | * buffer is returned. The highest priority waiter will obtain the buffer |
---|
[33c3b54d] | 502 | * first. |
---|
[e51bd96] | 503 | * |
---|
[796967c] | 504 | * @param dd [in] The disk device. |
---|
[1024561] | 505 | * @param block [in] Linear media block number. |
---|
| 506 | * @param bd [out] Reference to the buffer descriptor pointer. |
---|
[e51bd96] | 507 | * |
---|
[1024561] | 508 | * @retval RTEMS_SUCCESSFUL Successful operation. |
---|
| 509 | * @retval RTEMS_NOT_CONFIGURED Not initialized. |
---|
| 510 | * @retval RTEMS_INVALID_ID No such device. |
---|
| 511 | * @retval RTEMS_INVALID_NUMBER Invalid block size. |
---|
| 512 | * @retval RTEMS_IO_ERROR IO error. |
---|
[e51bd96] | 513 | */ |
---|
[c21c850e] | 514 | rtems_status_code |
---|
[796967c] | 515 | rtems_bdbuf_read ( |
---|
| 516 | const rtems_disk_device *dd, |
---|
| 517 | rtems_blkdev_bnum block, |
---|
| 518 | rtems_bdbuf_buffer** bd |
---|
| 519 | ); |
---|
[c21c850e] | 520 | |
---|
| 521 | /** |
---|
| 522 | * Release the buffer obtained by a read call back to the cache. If the buffer |
---|
| 523 | * was obtained by a get call and was not already in the cache the release |
---|
| 524 | * modified call should be used. A buffer released with this call obtained by a |
---|
| 525 | * get call may not be in sync with the contents on disk. If the buffer was in |
---|
| 526 | * the cache and modified before this call it will be returned to the modified |
---|
| 527 | * queue. The buffers is returned to the end of the LRU list. |
---|
[e51bd96] | 528 | * |
---|
[1024561] | 529 | * @param bd [in] Reference to the buffer descriptor. |
---|
[e51bd96] | 530 | * |
---|
[1024561] | 531 | * @retval RTEMS_SUCCESSFUL Successful operation. |
---|
| 532 | * @retval RTEMS_NOT_CONFIGURED Not initialized. |
---|
| 533 | * @retval RTEMS_INVALID_ADDRESS The reference is NULL. |
---|
[e51bd96] | 534 | */ |
---|
[c21c850e] | 535 | rtems_status_code |
---|
| 536 | rtems_bdbuf_release (rtems_bdbuf_buffer* bd); |
---|
| 537 | |
---|
| 538 | /** |
---|
| 539 | * Release the buffer allocated with a get or read call placing it on the |
---|
[f3ea4992] | 540 | * modified list. If the buffer was not released modified before the hold |
---|
[c21c850e] | 541 | * timer is set to the configuration value. If the buffer had been released |
---|
| 542 | * modified before but not written to disk the hold timer is not updated. The |
---|
| 543 | * buffer will be written to disk when the hold timer has expired, there are |
---|
| 544 | * not more buffers available in the cache and a get or read buffer needs one |
---|
| 545 | * or a sync call has been made. If the buffer is obtained with a get or read |
---|
| 546 | * before the hold timer has expired the buffer will be returned to the user. |
---|
[e51bd96] | 547 | * |
---|
[1024561] | 548 | * @param bd [in] Reference to the buffer descriptor. |
---|
[e51bd96] | 549 | * |
---|
[1024561] | 550 | * @retval RTEMS_SUCCESSFUL Successful operation. |
---|
| 551 | * @retval RTEMS_NOT_CONFIGURED Not initialized. |
---|
| 552 | * @retval RTEMS_INVALID_ADDRESS The reference is NULL. |
---|
[e51bd96] | 553 | */ |
---|
[c21c850e] | 554 | rtems_status_code |
---|
| 555 | rtems_bdbuf_release_modified (rtems_bdbuf_buffer* bd); |
---|
| 556 | |
---|
| 557 | /** |
---|
| 558 | * Release the buffer as modified and wait until it has been synchronized with |
---|
| 559 | * the disk by writing it. This buffer will be the first to be transfer to disk |
---|
| 560 | * and other buffers may also be written if the maximum number of blocks in a |
---|
| 561 | * requests allows it. |
---|
[e51bd96] | 562 | * |
---|
[c21c850e] | 563 | * @note This code does not lock the sync mutex and stop additions to the |
---|
| 564 | * modified queue. |
---|
| 565 | |
---|
[1024561] | 566 | * @param bd [in] Reference to the buffer descriptor. |
---|
[e51bd96] | 567 | * |
---|
[1024561] | 568 | * @retval RTEMS_SUCCESSFUL Successful operation. |
---|
| 569 | * @retval RTEMS_NOT_CONFIGURED Not initialized. |
---|
| 570 | * @retval RTEMS_INVALID_ADDRESS The reference is NULL. |
---|
[e51bd96] | 571 | */ |
---|
[c21c850e] | 572 | rtems_status_code |
---|
| 573 | rtems_bdbuf_sync (rtems_bdbuf_buffer* bd); |
---|
[e51bd96] | 574 | |
---|
[c21c850e] | 575 | /** |
---|
| 576 | * Synchronize all modified buffers for this device with the disk and wait |
---|
[0d15414e] | 577 | * until the transfers have completed. The sync mutex for the cache is locked |
---|
[c21c850e] | 578 | * stopping the addition of any further modifed buffers. It is only the |
---|
| 579 | * currently modified buffers that are written. |
---|
[e51bd96] | 580 | * |
---|
[0d15414e] | 581 | * @note Nesting calls to sync multiple devices will be handled sequentially. A |
---|
| 582 | * nested call will be blocked until the first sync request has complete. |
---|
[e51bd96] | 583 | * |
---|
[796967c] | 584 | * @param dd [in] The disk device. |
---|
[c21c850e] | 585 | * |
---|
[1024561] | 586 | * @retval RTEMS_SUCCESSFUL Successful operation. |
---|
| 587 | * @retval RTEMS_NOT_CONFIGURED Not initialized. |
---|
| 588 | * @retval RTEMS_INVALID_ID No such device. |
---|
[e51bd96] | 589 | */ |
---|
[c21c850e] | 590 | rtems_status_code |
---|
[796967c] | 591 | rtems_bdbuf_syncdev (const rtems_disk_device *dd); |
---|
[e51bd96] | 592 | |
---|
[e7fb54e] | 593 | /** |
---|
[796967c] | 594 | * @brief Purges all buffers corresponding to the disk device @a dd. |
---|
[e7fb54e] | 595 | * |
---|
| 596 | * This may result in loss of data. |
---|
| 597 | */ |
---|
| 598 | void |
---|
[796967c] | 599 | rtems_bdbuf_purge_dev (const rtems_disk_device *dd); |
---|
[e7fb54e] | 600 | |
---|
[57aa979] | 601 | /** @} */ |
---|
[e51bd96] | 602 | |
---|
| 603 | #ifdef __cplusplus |
---|
| 604 | } |
---|
| 605 | #endif |
---|
| 606 | |
---|
| 607 | #endif |
---|