Changeset 5c587596 in rtems for cpukit/libblock
- Timestamp:
- 01/19/10 09:10:03 (14 years ago)
- Branches:
- 4.10, 4.11, 5, master
- Children:
- 1ba96ef9
- Parents:
- 64734fc
- Location:
- cpukit/libblock
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
cpukit/libblock/include/rtems/bdbuf.h
r64734fc r5c587596 81 81 * digraph state { 82 82 * size="16,8"; 83 * e [label="EMPTY",style="filled",fillcolor="aquamarine"];84 * f [label="FRESH",style="filled",fillcolor="seagreen"];83 * f [label="FREE",style="filled",fillcolor="aquamarine"]; 84 * e [label="EMPTY",style="filled",fillcolor="seagreen"]; 85 85 * c [label="CACHED",style="filled",fillcolor="chartreuse"]; 86 * a [label="ACCESS",style="filled",fillcolor="royalblue"];86 * ac [label="ACCESS CACHED",style="filled",fillcolor="royalblue"]; 87 87 * am [label="ACCESS MODIFIED",style="filled",fillcolor="royalblue"]; 88 * ae [label="ACCESS EMPTY",style="filled",fillcolor="royalblue"]; 88 89 * t [label="TRANSFER",style="filled",fillcolor="red"]; 89 90 * s [label="SYNC",style="filled",fillcolor="red"]; … … 94 95 * legend_access [label="Access Wake-Up",fontcolor="royalblue",shape="none"]; 95 96 * 96 * i -> e [label="Init"]; 97 * e -> f [label="Buffer Recycle"]; 98 * f -> a [label="Get"]; 99 * f -> t [label="Read\nRead Ahead"]; 100 * c -> e [label="Reallocate\nBlock Size Changed"]; 101 * c -> a [label="Get\nRead"]; 102 * c -> f [label="Buffer Recycle"]; 103 * t -> c [label="Write Transfer Done\nRead Transfer Done\nRead Ahead Transfer Done",color="red",fontcolor="red"]; 97 * i -> f [label="Init"]; 98 * f -> e [label="Buffer Recycle"]; 99 * e -> ae [label="Get"]; 100 * e -> t [label="Read\nRead Ahead"]; 101 * c -> f [label="Reallocate\nBlock Size Changed"]; 102 * c -> ac [label="Get\nRead"]; 103 * c -> e [label="Buffer Recycle"]; 104 * t -> c [label="Transfer Done",color="red",fontcolor="red"]; 105 * t -> e [label="Transfer Error With Waiter",color="red",fontcolor="red"]; 106 * t -> f [label="Transfer Error Without Waiter",color="red",fontcolor="red"]; 104 107 * m -> t [label="Swapout"]; 105 108 * m -> s [label="Block Size Changed"]; 106 109 * m -> am [label="Get\nRead"]; 107 * a -> m [label="Release Modified",color="royalblue",fontcolor="royalblue"];108 * a -> s [label="Sync",color="royalblue",fontcolor="royalblue"];109 * a -> c [label="Release",color="royalblue",fontcolor="royalblue"];110 * ac -> m [label="Release Modified",color="royalblue",fontcolor="royalblue"]; 111 * ac -> s [label="Sync",color="royalblue",fontcolor="royalblue"]; 112 * ac -> c [label="Release",color="royalblue",fontcolor="royalblue"]; 110 113 * am -> m [label="Release\nRelease Modified",color="royalblue",fontcolor="royalblue"]; 111 114 * am -> s [label="Sync",color="royalblue",fontcolor="royalblue"]; 115 * ae -> m [label="Release Modified",color="royalblue",fontcolor="royalblue"]; 116 * ae -> s [label="Sync",color="royalblue",fontcolor="royalblue"]; 117 * ae -> e [label="Release With Waiter",color="royalblue",fontcolor="royalblue"]; 118 * ae -> f [label="Release Without Waiter",color="royalblue",fontcolor="royalblue"]; 112 119 * s -> t [label="Swapout"]; 113 120 * } … … 165 172 * The state has several implications. Depending on the state a buffer can be 166 173 * in the AVL tree, in a list, in use by an entity and a group user or not. 174 * 175 * <table> 176 * <tr> 177 * <th>State</th><th>Valid Data</th><th>AVL Tree</th> 178 * <th>LRU List</th><th>Modified List</th><th>Synchronization List</th> 179 * <th>Group User</th><th>External User</th> 180 * </tr> 181 * <tr> 182 * <td>FREE</td><td></td><td></td> 183 * <td>X</td><td></td><td></td><td></td><td></td> 184 * </tr> 185 * <tr> 186 * <td>EMPTY</td><td></td><td>X</td> 187 * <td>X</td><td></td><td></td><td></td><td></td> 188 * </tr> 189 * <tr> 190 * <td>CACHED</td><td>X</td><td>X</td> 191 * <td>X</td><td></td><td></td><td></td><td></td> 192 * </tr> 193 * <tr> 194 * <td>ACCESS_CACHED</td><td>X</td><td>X</td> 195 * <td></td><td></td><td></td><td>X</td><td>X</td> 196 * </tr> 197 * <tr> 198 * <td>ACCESS_MODIFIED</td><td>X</td><td>X</td> 199 * <td></td><td></td><td></td><td>X</td><td>X</td> 200 * </tr> 201 * <tr> 202 * <td>ACCESS_EMPTY</td><td></td><td>X</td> 203 * <td></td><td></td><td></td><td>X</td><td>X</td> 204 * </tr> 205 * <tr> 206 * <td>MODIFIED</td><td>X</td><td>X</td> 207 * <td></td><td>X</td><td></td><td>X</td><td></td> 208 * </tr> 209 * <tr> 210 * <td>SYNC</td><td>X</td><td>X</td> 211 * <td></td><td></td><td>X</td><td>X</td><td></td> 212 * </tr> 213 * <tr> 214 * <td>TRANSFER</td><td>X</td><td>X</td> 215 * <td></td><td></td><td></td><td>X</td><td>X</td> 216 * </tr> 217 * </table> 167 218 */ 168 219 typedef enum 169 220 { 170 221 /** 222 * @brief Free. 223 */ 224 RTEMS_BDBUF_STATE_FREE = 0, 225 226 /** 171 227 * @brief Empty. 172 * 173 * Not in the AVL tree. Not in a list. Not in use. Not a user of its 174 * group. 175 */ 176 RTEMS_BDBUF_STATE_EMPTY = 0, 177 178 /** 179 * @brief Fresh. 180 * 181 * In the AVL tree. Not in a list. In use by a get or read request. A user 182 * of its group. 183 */ 184 RTEMS_BDBUF_STATE_FRESH, 228 */ 229 RTEMS_BDBUF_STATE_EMPTY, 185 230 186 231 /** 187 232 * @brief Cached. 188 *189 * In the AVL tree. In the LRU list. Not in use. Not a user of its group.190 233 */ 191 234 RTEMS_BDBUF_STATE_CACHED, 192 235 193 236 /** 194 * @brief Accessed by upper layer. 195 * 196 * In the AVL tree. Not in a list. In use by an upper layer. A user of its 197 * group. 198 */ 199 RTEMS_BDBUF_STATE_ACCESS, 200 201 /** 202 * @brief Accessed and modified by upper layer. 203 * 204 * In the AVL tree. Not in a list. In use by an upper layer. A user of its 205 * group. 237 * @brief Accessed by upper layer with cached data. 238 */ 239 RTEMS_BDBUF_STATE_ACCESS_CACHED, 240 241 /** 242 * @brief Accessed by upper layer with modified data. 206 243 */ 207 244 RTEMS_BDBUF_STATE_ACCESS_MODIFIED, 208 245 209 246 /** 247 * @brief Accessed by upper layer with invalid data. 248 */ 249 RTEMS_BDBUF_STATE_ACCESS_EMPTY, 250 251 /** 210 252 * @brief Modified by upper layer. 211 *212 * In the AVL tree. In the modified list. In use by swapout mechanic. A213 * user of its group.214 253 */ 215 254 RTEMS_BDBUF_STATE_MODIFIED, … … 217 256 /** 218 257 * @brief Scheduled for synchronization. 219 *220 * In the AVL tree. In the sync list. In use by swapout mechanic. A user221 * of its group.222 258 */ 223 259 RTEMS_BDBUF_STATE_SYNC, … … 225 261 /** 226 262 * @brief In transfer by block device driver. 227 *228 * In the AVL tree. Not in a list. In use by the block device driver. A229 * user of its group.230 263 */ 231 264 RTEMS_BDBUF_STATE_TRANSFER … … 261 294 262 295 unsigned char* buffer; /**< Pointer to the buffer memory area */ 263 int error; /**< If not 0 indicate an error value (errno)264 * which can be used by user later */265 296 266 297 volatile rtems_bdbuf_buf_state state; /**< State of the buffer. */ -
cpukit/libblock/include/rtems/blkdev.h
r64734fc r5c587596 60 60 61 61 /** 62 * Type for block device request done callback function. 63 * 64 * @param arg Argument supplied in @ref rtems_blkdev_request. 65 * @param status Status code for this operation. 66 * @param errno The @c errno value to be passed to the user when status is not 67 * equal to @c RTEMS_SUCCESSFUL. 68 */ 69 typedef void (* rtems_blkdev_request_cb)(void *arg, 70 rtems_status_code status, 71 int error); 62 * @brief Block device request done callback function type. 63 * 64 * The first parameter @a arg must be the argument provided by the block device 65 * request structure @ref rtems_blkdev_request. 66 * 67 * The second parameter @a status should contain the status of the operation: 68 * - @c RTEMS_SUCCESSFUL Operation was successful. 69 * - @c RTEMS_IO_ERROR Some sort of input or output error. 70 * - @c RTEMS_UNSATISFIED Media no more present. 71 */ 72 typedef void (*rtems_blkdev_request_cb)(void *arg, rtems_status_code status); 72 73 73 74 /** … … 127 128 */ 128 129 rtems_status_code status; 129 130 /**131 * If @c status is not equal to @c RTEMS_SUCCESSFUL, this field contains the132 * error number.133 */134 int error;135 130 136 131 /** -
cpukit/libblock/src/bdbuf.c
r64734fc r5c587596 124 124 rtems_chain_control sync; /**< Buffers to sync list */ 125 125 126 rtems_bdbuf_waiters access_waiters; /**< Wait for a buffer in ACCESS 126 rtems_bdbuf_waiters access_waiters; /**< Wait for a buffer in 127 * ACCESS_CACHED, ACCESS_MODIFIED or 128 * ACCESS_EMPTY 127 129 * state. */ 128 130 rtems_bdbuf_waiters transfer_waiters; /**< Wait for a buffer in TRANSFER … … 143 145 (((uint32_t)'B' << 24) | ((uint32_t)(n) & (uint32_t)0x00FFFFFF)) 144 146 145 #define RTEMS_BLKDEV_FATAL_BDBUF_STATE_3 RTEMS_BLKDEV_FATAL_ERROR(1)146 147 #define RTEMS_BLKDEV_FATAL_BDBUF_STATE_4 RTEMS_BLKDEV_FATAL_ERROR(2) 147 148 #define RTEMS_BLKDEV_FATAL_BDBUF_STATE_5 RTEMS_BLKDEV_FATAL_ERROR(3) … … 151 152 #define RTEMS_BLKDEV_FATAL_BDBUF_STATE_9 RTEMS_BLKDEV_FATAL_ERROR(7) 152 153 #define RTEMS_BLKDEV_FATAL_BDBUF_STATE_10 RTEMS_BLKDEV_FATAL_ERROR(8) 153 #define RTEMS_BLKDEV_FATAL_BDBUF_ CACHE_RMRTEMS_BLKDEV_FATAL_ERROR(9)154 #define RTEMS_BLKDEV_FATAL_BDBUF_TREE_RM RTEMS_BLKDEV_FATAL_ERROR(9) 154 155 #define RTEMS_BLKDEV_FATAL_BDBUF_SWAPOUT RTEMS_BLKDEV_FATAL_ERROR(10) 155 156 #define RTEMS_BLKDEV_FATAL_BDBUF_SYNC_LOCK RTEMS_BLKDEV_FATAL_ERROR(11) … … 1055 1056 * buffer never getting to 0 and never being forced onto disk. This raises a 1056 1057 * difficult question. Is a snapshot of a block that is changing better than 1057 * nothing being written 1058 * nothing being written? We have tended to think we should hold changes for 1058 1059 * only a specific period of time even if still changing and get onto disk 1059 1060 * and letting the file system try and recover this position if it can. 1060 1061 */ 1061 if (bd->state == RTEMS_BDBUF_STATE_ACCESS) 1062 if (bd->state == RTEMS_BDBUF_STATE_ACCESS_CACHED 1063 || bd->state == RTEMS_BDBUF_STATE_ACCESS_EMPTY) 1062 1064 bd->hold_timer = bdbuf_config.swap_block_hold; 1063 1065 1064 1066 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_MODIFIED); 1065 1066 1067 rtems_chain_append (&bdbuf_cache.modified, &bd->link); 1067 1068 … … 1076 1077 { 1077 1078 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_CACHED); 1078 1079 1079 rtems_chain_append (&bdbuf_cache.lru, &bd->link); 1080 1081 1080 rtems_bdbuf_group_release (bd); 1082 1081 … … 1123 1122 1124 1123 static void 1125 rtems_bdbuf_remove_from_cache_and_lru_list (rtems_bdbuf_buffer *bd) 1124 rtems_bdbuf_remove_from_tree (rtems_bdbuf_buffer *bd) 1125 { 1126 if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0) 1127 rtems_bdbuf_fatal (bd->state, RTEMS_BLKDEV_FATAL_BDBUF_TREE_RM); 1128 } 1129 1130 static void 1131 rtems_bdbuf_remove_from_tree_and_lru_list (rtems_bdbuf_buffer *bd) 1126 1132 { 1127 1133 switch (bd->state) 1128 1134 { 1129 case RTEMS_BDBUF_STATE_ EMPTY:1135 case RTEMS_BDBUF_STATE_FREE: 1130 1136 break; 1131 1137 case RTEMS_BDBUF_STATE_CACHED: 1132 if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0) 1133 rtems_bdbuf_fatal (bd->state, RTEMS_BLKDEV_FATAL_BDBUF_STATE_3); 1138 rtems_bdbuf_remove_from_tree (bd); 1134 1139 break; 1135 1140 default: … … 1141 1146 1142 1147 static void 1148 rtems_bdbuf_make_free_and_add_to_lru_list (rtems_bdbuf_buffer *bd) 1149 { 1150 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_FREE); 1151 rtems_chain_prepend (&bdbuf_cache.lru, &bd->link); 1152 } 1153 1154 static void 1143 1155 rtems_bdbuf_make_empty_and_add_to_lru_list (rtems_bdbuf_buffer *bd) 1144 1156 { 1145 1157 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_EMPTY); 1146 rtems_chain_prepend (&bdbuf_cache.lru, &bd->link); 1158 rtems_chain_append (&bdbuf_cache.lru, &bd->link); 1159 } 1160 1161 static void 1162 rtems_bdbuf_release_empty_buffer (rtems_bdbuf_buffer *bd) 1163 { 1164 rtems_bdbuf_group_release (bd); 1165 1166 if (bd->waiters) 1167 { 1168 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_EMPTY); 1169 rtems_chain_append (&bdbuf_cache.lru, &bd->link); 1170 rtems_bdbuf_wake (&bdbuf_cache.access_waiters); 1171 } 1172 else 1173 { 1174 rtems_bdbuf_remove_from_tree (bd); 1175 rtems_bdbuf_make_free_and_add_to_lru_list (bd); 1176 rtems_bdbuf_wake (&bdbuf_cache.buffer_waiters); 1177 } 1147 1178 } 1148 1179 … … 1173 1204 b < group->bds_per_group; 1174 1205 b++, bd += bufs_per_bd) 1175 rtems_bdbuf_remove_from_ cache_and_lru_list (bd);1206 rtems_bdbuf_remove_from_tree_and_lru_list (bd); 1176 1207 1177 1208 group->bds_per_group = new_bds_per_group; … … 1181 1212 b < group->bds_per_group; 1182 1213 b++, bd += bufs_per_bd) 1183 rtems_bdbuf_make_ empty_and_add_to_lru_list (bd);1214 rtems_bdbuf_make_free_and_add_to_lru_list (bd); 1184 1215 1185 1216 if (b > 1) … … 1194 1225 rtems_blkdev_bnum block) 1195 1226 { 1196 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_FRESH);1197 1198 1227 bd->dev = dev; 1199 1228 bd->block = block; 1200 1229 bd->avl.left = NULL; 1201 1230 bd->avl.right = NULL; 1202 bd->error = 0;1203 1231 bd->waiters = 0; 1204 1232 1205 1233 if (rtems_bdbuf_avl_insert (&bdbuf_cache.tree, bd) != 0) 1206 1234 rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_RECYCLE); 1235 1236 rtems_bdbuf_make_empty_and_add_to_lru_list (bd); 1207 1237 } 1208 1238 … … 1232 1262 if (bd->group->bds_per_group == bds_per_group) 1233 1263 { 1234 rtems_bdbuf_remove_from_ cache_and_lru_list (bd);1264 rtems_bdbuf_remove_from_tree_and_lru_list (bd); 1235 1265 1236 1266 recycle_bd = bd; … … 1490 1520 switch (bd->state) 1491 1521 { 1492 case RTEMS_BDBUF_STATE_FRESH:1493 return;1494 1522 case RTEMS_BDBUF_STATE_MODIFIED: 1495 1523 rtems_bdbuf_group_release (bd); 1496 1524 /* Fall through */ 1497 1525 case RTEMS_BDBUF_STATE_CACHED: 1526 case RTEMS_BDBUF_STATE_EMPTY: 1498 1527 rtems_chain_extract (&bd->link); 1499 1528 return; 1529 case RTEMS_BDBUF_STATE_ACCESS_CACHED: 1530 case RTEMS_BDBUF_STATE_ACCESS_EMPTY: 1500 1531 case RTEMS_BDBUF_STATE_ACCESS_MODIFIED: 1501 case RTEMS_BDBUF_STATE_ACCESS:1502 1532 rtems_bdbuf_wait (bd, &bdbuf_cache.access_waiters); 1503 1533 break; … … 1534 1564 switch (bd->state) 1535 1565 { 1536 case RTEMS_BDBUF_STATE_ EMPTY:1566 case RTEMS_BDBUF_STATE_FREE: 1537 1567 return true; 1538 1568 case RTEMS_BDBUF_STATE_MODIFIED: … … 1540 1570 break; 1541 1571 case RTEMS_BDBUF_STATE_CACHED: 1572 case RTEMS_BDBUF_STATE_EMPTY: 1542 1573 if (bd->waiters == 0) 1543 1574 return true; … … 1553 1584 return false; 1554 1585 } 1586 case RTEMS_BDBUF_STATE_ACCESS_CACHED: 1587 case RTEMS_BDBUF_STATE_ACCESS_EMPTY: 1555 1588 case RTEMS_BDBUF_STATE_ACCESS_MODIFIED: 1556 case RTEMS_BDBUF_STATE_ACCESS:1557 1589 rtems_bdbuf_wait (bd, &bdbuf_cache.access_waiters); 1558 1590 break; … … 1565 1597 } 1566 1598 } 1567 1568 return true;1569 1599 } 1570 1600 … … 1577 1607 { 1578 1608 case RTEMS_BDBUF_STATE_CACHED: 1609 case RTEMS_BDBUF_STATE_EMPTY: 1579 1610 case RTEMS_BDBUF_STATE_MODIFIED: 1580 case RTEMS_BDBUF_STATE_ACCESS: 1611 case RTEMS_BDBUF_STATE_ACCESS_CACHED: 1612 case RTEMS_BDBUF_STATE_ACCESS_EMPTY: 1581 1613 case RTEMS_BDBUF_STATE_ACCESS_MODIFIED: 1582 1614 return; … … 1643 1675 if (rtems_bdbuf_wait_for_recycle (bd)) 1644 1676 { 1645 rtems_bdbuf_remove_from_ cache_and_lru_list (bd);1646 rtems_bdbuf_make_ empty_and_add_to_lru_list (bd);1677 rtems_bdbuf_remove_from_tree_and_lru_list (bd); 1678 rtems_bdbuf_make_free_and_add_to_lru_list (bd); 1647 1679 rtems_bdbuf_wake (&bdbuf_cache.buffer_waiters); 1648 1680 } … … 1761 1793 { 1762 1794 case RTEMS_BDBUF_STATE_CACHED: 1763 case RTEMS_BDBUF_STATE_FRESH: 1764 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_ACCESS); 1795 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_ACCESS_CACHED); 1796 break; 1797 case RTEMS_BDBUF_STATE_EMPTY: 1798 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_ACCESS_EMPTY); 1765 1799 break; 1766 1800 case RTEMS_BDBUF_STATE_MODIFIED: … … 1802 1836 * block device request structure). 1803 1837 * @param status I/O completion status 1804 * @param error errno error code if status != RTEMS_SUCCESSFUL 1805 */ 1806 static void 1807 rtems_bdbuf_read_done (void* arg, rtems_status_code status, int error) 1838 */ 1839 static void 1840 rtems_bdbuf_transfer_done (void* arg, rtems_status_code status) 1808 1841 { 1809 1842 rtems_blkdev_request* req = (rtems_blkdev_request*) arg; 1810 1843 1811 req->error = error;1812 1844 req->status = status; 1813 1845 … … 1816 1848 1817 1849 static void 1818 rtems_bdbuf_create_read_request (rtems_blkdev_request *req, 1819 rtems_disk_device *dd, 1820 rtems_blkdev_bnum media_block, 1821 size_t bds_per_group) 1850 rtems_bdbuf_create_read_request (const rtems_disk_device *dd, 1851 rtems_blkdev_bnum media_block, 1852 size_t bds_per_group, 1853 rtems_blkdev_request *req, 1854 rtems_bdbuf_buffer **bd_ptr) 1822 1855 { 1823 1856 rtems_bdbuf_buffer *bd = NULL; … … 1832 1865 transfer_count = media_block_end - media_block; 1833 1866 1867 req->req = RTEMS_BLKDEV_REQ_READ; 1868 req->req_done = rtems_bdbuf_transfer_done; 1869 req->done_arg = req; 1870 req->io_task = rtems_task_self (); 1871 req->status = RTEMS_RESOURCE_IN_USE; 1834 1872 req->bufnum = 0; 1835 1873 1836 1874 bd = rtems_bdbuf_get_buffer_for_access (dev, media_block, bds_per_group); 1875 1876 *bd_ptr = bd; 1837 1877 1838 1878 req->bufs [0].user = bd; … … 1849 1889 case RTEMS_BDBUF_STATE_MODIFIED: 1850 1890 return; 1851 case RTEMS_BDBUF_STATE_ FRESH:1891 case RTEMS_BDBUF_STATE_EMPTY: 1852 1892 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_TRANSFER); 1853 1893 break; … … 1883 1923 } 1884 1924 1885 static rtems_bdbuf_buffer * 1886 rtems_bdbuf_execute_read_request (rtems_blkdev_request *req, 1887 rtems_disk_device *dd) 1888 { 1889 if (req->bufnum) 1890 { 1891 /* 1892 * Unlock the cache. We have the buffer for the block and it will be in the 1893 * access or transfer state. We may also have a number of read ahead blocks 1894 * if we need to transfer data. At this point any other threads can gain 1895 * access to the cache and if they are after any of the buffers we have 1896 * they will block and be woken when the buffer is returned to the cache. 1897 * 1898 * If a transfer is needed the I/O operation will occur with pre-emption 1899 * enabled and the cache unlocked. This is a change to the previous version 1900 * of the bdbuf code. 1901 */ 1902 int result = 0; 1903 int error = 0; 1904 uint32_t transfer_index = 0; 1905 bool wake_transfer = false; 1906 bool wake_buffer = false; 1907 1925 static rtems_status_code 1926 rtems_bdbuf_execute_transfer_request (const rtems_disk_device *dd, 1927 rtems_blkdev_request *req, 1928 bool cache_locked) 1929 { 1930 rtems_status_code sc = RTEMS_SUCCESSFUL; 1931 int result = 0; 1932 uint32_t transfer_index = 0; 1933 bool wake_transfer = false; 1934 bool wake_buffer = false; 1935 1936 if (cache_locked) 1908 1937 rtems_bdbuf_unlock_cache (); 1909 1938 1910 req->req = RTEMS_BLKDEV_REQ_READ; 1911 req->req_done = rtems_bdbuf_read_done; 1912 req->done_arg = req; 1913 req->io_task = rtems_task_self (); 1914 req->status = RTEMS_RESOURCE_IN_USE; 1915 req->error = 0; 1916 1917 result = dd->ioctl (dd->phys_dev, RTEMS_BLKIO_REQUEST, req); 1918 1919 if (result == 0) 1920 { 1921 rtems_bdbuf_wait_for_event (RTEMS_BDBUF_TRANSFER_SYNC); 1922 error = req->error; 1923 } 1939 result = dd->ioctl (dd->phys_dev, RTEMS_BLKIO_REQUEST, req); 1940 1941 if (result == 0) 1942 { 1943 rtems_bdbuf_wait_for_event (RTEMS_BDBUF_TRANSFER_SYNC); 1944 sc = req->status; 1945 } 1946 else 1947 sc = RTEMS_IO_ERROR; 1948 1949 rtems_bdbuf_lock_cache (); 1950 1951 for (transfer_index = 0; transfer_index < req->bufnum; ++transfer_index) 1952 { 1953 rtems_bdbuf_buffer *bd = req->bufs [transfer_index].user; 1954 bool waiters = bd->waiters > 0; 1955 1956 if (waiters) 1957 wake_transfer = true; 1924 1958 else 1925 error = errno; 1926 1927 rtems_bdbuf_lock_cache (); 1928 1929 for (transfer_index = 0; transfer_index < req->bufnum; ++transfer_index) 1930 { 1931 rtems_bdbuf_buffer *bd = req->bufs [transfer_index].user; 1932 bool waiters = bd->waiters; 1933 1959 wake_buffer = true; 1960 1961 rtems_bdbuf_group_release (bd); 1962 1963 if (sc == RTEMS_SUCCESSFUL) 1964 { 1934 1965 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_CACHED); 1935 1936 if (waiters) 1937 wake_transfer = true; 1938 1939 bd->error = error; 1940 1941 if (rtems_bdbuf_tracer) 1942 rtems_bdbuf_show_users ("read-ahead", bd); 1943 1944 if (transfer_index > 0) 1945 { 1946 /* 1947 * This is a read ahead buffer. 1948 */ 1949 1950 rtems_bdbuf_group_release (bd); 1951 1952 if (!waiters) 1953 wake_buffer = true; 1954 1955 if (error == 0 || waiters) 1956 rtems_chain_append (&bdbuf_cache.lru, &bd->link); 1957 else 1958 { 1959 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_EMPTY); 1960 rtems_chain_prepend (&bdbuf_cache.lru, &bd->link); 1961 if (rtems_bdbuf_avl_remove (&bdbuf_cache.tree, bd) != 0) 1962 rtems_fatal_error_occurred (RTEMS_BLKDEV_FATAL_BDBUF_CACHE_RM); 1963 } 1964 } 1965 } 1966 1967 if (wake_transfer) 1968 rtems_bdbuf_wake (&bdbuf_cache.transfer_waiters); 1969 1970 if (wake_buffer) 1971 rtems_bdbuf_wake (&bdbuf_cache.buffer_waiters); 1972 } 1973 1974 return req->bufs [0].user; 1966 rtems_chain_append (&bdbuf_cache.lru, &bd->link); 1967 } 1968 else if (waiters) 1969 { 1970 rtems_bdbuf_make_empty_and_add_to_lru_list (bd); 1971 } 1972 else 1973 { 1974 rtems_bdbuf_remove_from_tree (bd); 1975 rtems_bdbuf_make_free_and_add_to_lru_list (bd); 1976 } 1977 1978 if (rtems_bdbuf_tracer) 1979 rtems_bdbuf_show_users ("transfer", bd); 1980 } 1981 1982 if (wake_transfer) 1983 rtems_bdbuf_wake (&bdbuf_cache.transfer_waiters); 1984 1985 if (wake_buffer) 1986 rtems_bdbuf_wake (&bdbuf_cache.buffer_waiters); 1987 1988 if (!cache_locked) 1989 rtems_bdbuf_unlock_cache (); 1990 1991 if (sc == RTEMS_SUCCESSFUL || sc == RTEMS_UNSATISFIED) 1992 return sc; 1993 else 1994 return RTEMS_IO_ERROR; 1975 1995 } 1976 1996 … … 1982 2002 rtems_status_code sc = RTEMS_SUCCESSFUL; 1983 2003 rtems_disk_device *dd = NULL; 2004 rtems_blkdev_request *req = NULL; 1984 2005 rtems_bdbuf_buffer *bd = NULL; 1985 rtems_blkdev_request *req = NULL;1986 2006 rtems_blkdev_bnum media_block = 0; 1987 2007 size_t bds_per_group = 0; … … 2005 2025 2006 2026 rtems_bdbuf_lock_cache (); 2007 rtems_bdbuf_create_read_request (req, dd, media_block, bds_per_group); 2008 2009 bd = rtems_bdbuf_execute_read_request (req, dd); 2010 2011 switch (bd->state) 2012 { 2013 case RTEMS_BDBUF_STATE_CACHED: 2014 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_ACCESS); 2015 break; 2016 case RTEMS_BDBUF_STATE_MODIFIED: 2017 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_ACCESS_MODIFIED); 2018 break; 2019 default: 2020 rtems_bdbuf_fatal (bd->state, RTEMS_BLKDEV_FATAL_BDBUF_STATE_4); 2021 break; 2022 } 2023 2024 if (rtems_bdbuf_tracer) 2025 { 2026 rtems_bdbuf_show_users ("read", bd); 2027 rtems_bdbuf_show_usage (); 2028 } 2027 rtems_bdbuf_create_read_request (dd, media_block, bds_per_group, req, &bd); 2028 2029 if (req->bufnum > 0) 2030 { 2031 sc = rtems_bdbuf_execute_transfer_request (dd, req, true); 2032 if (sc == RTEMS_SUCCESSFUL) 2033 { 2034 rtems_chain_extract (&bd->link); 2035 rtems_bdbuf_group_obtain (bd); 2036 } 2037 } 2038 2039 if (sc == RTEMS_SUCCESSFUL) 2040 { 2041 switch (bd->state) 2042 { 2043 case RTEMS_BDBUF_STATE_CACHED: 2044 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_ACCESS_CACHED); 2045 break; 2046 case RTEMS_BDBUF_STATE_MODIFIED: 2047 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_ACCESS_MODIFIED); 2048 break; 2049 default: 2050 rtems_bdbuf_fatal (bd->state, RTEMS_BLKDEV_FATAL_BDBUF_STATE_4); 2051 break; 2052 } 2053 2054 if (rtems_bdbuf_tracer) 2055 { 2056 rtems_bdbuf_show_users ("read", bd); 2057 rtems_bdbuf_show_usage (); 2058 } 2059 2060 *bd_ptr = bd; 2061 } 2062 else 2063 *bd_ptr = NULL; 2029 2064 2030 2065 rtems_bdbuf_unlock_cache (); 2031 2066 rtems_bdbuf_release_disk (dd); 2032 2067 2033 *bd_ptr = bd; 2034 2035 return RTEMS_SUCCESSFUL; 2068 return sc; 2036 2069 } 2037 2070 … … 2064 2097 switch (bd->state) 2065 2098 { 2066 case RTEMS_BDBUF_STATE_ACCESS :2099 case RTEMS_BDBUF_STATE_ACCESS_CACHED: 2067 2100 rtems_bdbuf_add_to_lru_list_after_access (bd); 2101 break; 2102 case RTEMS_BDBUF_STATE_ACCESS_EMPTY: 2103 rtems_bdbuf_release_empty_buffer (bd); 2068 2104 break; 2069 2105 case RTEMS_BDBUF_STATE_ACCESS_MODIFIED: … … 2094 2130 switch (bd->state) 2095 2131 { 2096 case RTEMS_BDBUF_STATE_ACCESS: 2132 case RTEMS_BDBUF_STATE_ACCESS_CACHED: 2133 case RTEMS_BDBUF_STATE_ACCESS_EMPTY: 2097 2134 case RTEMS_BDBUF_STATE_ACCESS_MODIFIED: 2098 2135 rtems_bdbuf_add_to_modified_list_after_access (bd); … … 2122 2159 switch (bd->state) 2123 2160 { 2124 case RTEMS_BDBUF_STATE_ACCESS: 2161 case RTEMS_BDBUF_STATE_ACCESS_CACHED: 2162 case RTEMS_BDBUF_STATE_ACCESS_EMPTY: 2125 2163 case RTEMS_BDBUF_STATE_ACCESS_MODIFIED: 2126 2164 rtems_bdbuf_add_to_sync_list_after_access (bd); … … 2141 2179 * recycled. 2142 2180 */ 2143 if (bd->state == RTEMS_BDBUF_STATE_CACHED && bd->waiters == 0) 2181 if (bd->waiters == 0 2182 && (bd->state == RTEMS_BDBUF_STATE_CACHED 2183 || bd->state == RTEMS_BDBUF_STATE_EMPTY)) 2184 { 2185 if (bd->state == RTEMS_BDBUF_STATE_EMPTY) 2186 { 2187 rtems_bdbuf_remove_from_tree (bd); 2188 rtems_bdbuf_make_free_and_add_to_lru_list (bd); 2189 } 2144 2190 rtems_bdbuf_wake (&bdbuf_cache.buffer_waiters); 2191 } 2145 2192 2146 2193 rtems_bdbuf_unlock_cache (); … … 2191 2238 } 2192 2239 2193 /** 2194 * Call back handler called by the low level driver when the transfer has 2195 * completed. This function may be invoked from interrupt handlers. 2196 * 2197 * @param arg Arbitrary argument specified in block device request 2198 * structure (in this case - pointer to the appropriate 2199 * block device request structure). 2200 * @param status I/O completion status 2201 * @param error errno error code if status != RTEMS_SUCCESSFUL 2202 */ 2203 static void 2204 rtems_bdbuf_write_done(void *arg, rtems_status_code status, int error) 2205 { 2206 rtems_blkdev_request* req = (rtems_blkdev_request*) arg; 2207 2208 req->error = error; 2209 req->status = status; 2210 2211 rtems_event_send (req->io_task, RTEMS_BDBUF_TRANSFER_SYNC); 2240 static int 2241 rtems_bdbuf_null_disk_ioctl (rtems_disk_device *dd, uint32_t req, void *arg) 2242 { 2243 return -1; 2212 2244 } 2213 2245 … … 2222 2254 rtems_bdbuf_swapout_write (rtems_bdbuf_swapout_transfer* transfer) 2223 2255 { 2224 rtems_disk_device* dd; 2256 static rtems_disk_device null_disk = { 2257 .capabilities = 0, 2258 .ioctl = rtems_bdbuf_null_disk_ioctl 2259 }; 2225 2260 2226 2261 if (rtems_bdbuf_tracer) … … 2232 2267 if (!rtems_chain_is_empty (&transfer->bds)) 2233 2268 { 2269 /* 2270 * The last block number used when the driver only supports 2271 * continuous blocks in a single request. 2272 */ 2273 uint32_t last_block = 0; 2274 2275 /* 2276 * Number of buffers per bd. This is used to detect the next 2277 * block. 2278 */ 2279 uint32_t bufs_per_bd = 0; 2280 2234 2281 /* 2235 2282 * Obtain the disk device. The cache's mutex has been released to avoid a 2236 2283 * dead lock. 2237 2284 */ 2238 dd = rtems_disk_obtain (transfer->dev); 2239 if (dd) 2240 { 2285 rtems_disk_device *dd = rtems_disk_obtain (transfer->dev); 2286 2287 if (dd == NULL) 2288 dd = &null_disk; 2289 2290 bufs_per_bd = dd->block_size / bdbuf_config.buffer_min; 2291 2292 /* 2293 * Take as many buffers as configured and pass to the driver. Note, the 2294 * API to the drivers has an array of buffers and if a chain was passed 2295 * we could have just passed the list. If the driver API is updated it 2296 * should be possible to make this change with little effect in this 2297 * code. The array that is passed is broken in design and should be 2298 * removed. Merging members of a struct into the first member is 2299 * trouble waiting to happen. 2300 */ 2301 transfer->write_req->status = RTEMS_RESOURCE_IN_USE; 2302 transfer->write_req->bufnum = 0; 2303 2304 while (!rtems_chain_is_empty (&transfer->bds)) 2305 { 2306 rtems_bdbuf_buffer* bd = 2307 (rtems_bdbuf_buffer*) rtems_chain_get (&transfer->bds); 2308 2309 bool write = false; 2310 2241 2311 /* 2242 * The last block number used when the driver only supports 2243 * continuous blocks in a single request. 2312 * If the device only accepts sequential buffers and this is not the 2313 * first buffer (the first is always sequential, and the buffer is not 2314 * sequential then put the buffer back on the transfer chain and write 2315 * the committed buffers. 2244 2316 */ 2245 uint32_t last_block = 0; 2317 2318 if (rtems_bdbuf_tracer) 2319 printf ("bdbuf:swapout write: bd:%" PRIu32 ", bufnum:%" PRIu32 " mode:%s\n", 2320 bd->block, transfer->write_req->bufnum, 2321 dd->phys_dev->capabilities & 2322 RTEMS_BLKDEV_CAP_MULTISECTOR_CONT ? "MULIT" : "SCAT"); 2323 2324 if ((dd->phys_dev->capabilities & RTEMS_BLKDEV_CAP_MULTISECTOR_CONT) && 2325 transfer->write_req->bufnum && 2326 (bd->block != (last_block + bufs_per_bd))) 2327 { 2328 rtems_chain_prepend (&transfer->bds, &bd->link); 2329 write = true; 2330 } 2331 else 2332 { 2333 rtems_blkdev_sg_buffer* buf; 2334 buf = &transfer->write_req->bufs[transfer->write_req->bufnum]; 2335 transfer->write_req->bufnum++; 2336 buf->user = bd; 2337 buf->block = bd->block; 2338 buf->length = dd->block_size; 2339 buf->buffer = bd->buffer; 2340 last_block = bd->block; 2341 } 2246 2342 2247 2343 /* 2248 * Number of buffers per bd. This is used to detect the next2249 * block.2344 * Perform the transfer if there are no more buffers, or the transfer 2345 * size has reached the configured max. value. 2250 2346 */ 2251 uint32_t bufs_per_bd = dd->block_size / bdbuf_config.buffer_min; 2252 2253 /* 2254 * Take as many buffers as configured and pass to the driver. Note, the 2255 * API to the drivers has an array of buffers and if a chain was passed 2256 * we could have just passed the list. If the driver API is updated it 2257 * should be possible to make this change with little effect in this 2258 * code. The array that is passed is broken in design and should be 2259 * removed. Merging members of a struct into the first member is 2260 * trouble waiting to happen. 2261 */ 2262 transfer->write_req->status = RTEMS_RESOURCE_IN_USE; 2263 transfer->write_req->error = 0; 2264 transfer->write_req->bufnum = 0; 2265 2266 while (!rtems_chain_is_empty (&transfer->bds)) 2347 2348 if (rtems_chain_is_empty (&transfer->bds) || 2349 (transfer->write_req->bufnum >= bdbuf_config.max_write_blocks)) 2350 write = true; 2351 2352 if (write) 2267 2353 { 2268 rtems_bdbuf_buffer* bd = 2269 (rtems_bdbuf_buffer*) rtems_chain_get (&transfer->bds); 2270 2271 bool write = false; 2272 2273 /* 2274 * If the device only accepts sequential buffers and this is not the 2275 * first buffer (the first is always sequential, and the buffer is not 2276 * sequential then put the buffer back on the transfer chain and write 2277 * the committed buffers. 2278 */ 2279 2280 if (rtems_bdbuf_tracer) 2281 printf ("bdbuf:swapout write: bd:%" PRIu32 ", bufnum:%" PRIu32 " mode:%s\n", 2282 bd->block, transfer->write_req->bufnum, 2283 dd->phys_dev->capabilities & 2284 RTEMS_BLKDEV_CAP_MULTISECTOR_CONT ? "MULIT" : "SCAT"); 2285 2286 if ((dd->phys_dev->capabilities & RTEMS_BLKDEV_CAP_MULTISECTOR_CONT) && 2287 transfer->write_req->bufnum && 2288 (bd->block != (last_block + bufs_per_bd))) 2289 { 2290 rtems_chain_prepend (&transfer->bds, &bd->link); 2291 write = true; 2292 } 2293 else 2294 { 2295 rtems_blkdev_sg_buffer* buf; 2296 buf = &transfer->write_req->bufs[transfer->write_req->bufnum]; 2297 transfer->write_req->bufnum++; 2298 buf->user = bd; 2299 buf->block = bd->block; 2300 buf->length = dd->block_size; 2301 buf->buffer = bd->buffer; 2302 last_block = bd->block; 2303 } 2304 2305 /* 2306 * Perform the transfer if there are no more buffers, or the transfer 2307 * size has reached the configured max. value. 2308 */ 2309 2310 if (rtems_chain_is_empty (&transfer->bds) || 2311 (transfer->write_req->bufnum >= bdbuf_config.max_write_blocks)) 2312 write = true; 2313 2314 if (write) 2315 { 2316 int result; 2317 uint32_t b; 2318 2319 if (rtems_bdbuf_tracer) 2320 printf ("bdbuf:swapout write: writing bufnum:%" PRIu32 "\n", 2321 transfer->write_req->bufnum); 2322 2323 /* 2324 * Perform the transfer. No cache locks, no preemption, only the disk 2325 * device is being held. 2326 */ 2327 result = dd->ioctl (dd->phys_dev, RTEMS_BLKIO_REQUEST, 2328 transfer->write_req); 2329 if (result < 0) 2330 { 2331 rtems_bdbuf_lock_cache (); 2332 2333 for (b = 0; b < transfer->write_req->bufnum; b++) 2334 { 2335 bd = transfer->write_req->bufs[b].user; 2336 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_MODIFIED); 2337 bd->error = errno; 2338 2339 /* 2340 * Place back on the cache's modified queue and try again. 2341 * 2342 * @warning Not sure this is the best option but I do not know 2343 * what else can be done. 2344 */ 2345 rtems_chain_append (&bdbuf_cache.modified, &bd->link); 2346 } 2347 } 2348 else 2349 { 2350 rtems_bdbuf_wait_for_event (RTEMS_BDBUF_TRANSFER_SYNC); 2351 2352 rtems_bdbuf_lock_cache (); 2353 2354 for (b = 0; b < transfer->write_req->bufnum; b++) 2355 { 2356 bd = transfer->write_req->bufs[b].user; 2357 rtems_bdbuf_set_state (bd, RTEMS_BDBUF_STATE_CACHED); 2358 bd->error = 0; 2359 2360 rtems_bdbuf_group_release (bd); 2361 2362 if (rtems_bdbuf_tracer) 2363 rtems_bdbuf_show_users ("write", bd); 2364 2365 rtems_chain_append (&bdbuf_cache.lru, &bd->link); 2366 2367 if (bd->waiters) 2368 rtems_bdbuf_wake (&bdbuf_cache.transfer_waiters); 2369 else 2370 rtems_bdbuf_wake (&bdbuf_cache.buffer_waiters); 2371 } 2372 } 2373 2374 if (rtems_bdbuf_tracer) 2375 rtems_bdbuf_show_usage (); 2376 2377 rtems_bdbuf_unlock_cache (); 2378 2379 transfer->write_req->status = RTEMS_RESOURCE_IN_USE; 2380 transfer->write_req->error = 0; 2381 transfer->write_req->bufnum = 0; 2382 } 2354 rtems_bdbuf_execute_transfer_request (dd, transfer->write_req, false); 2355 2356 transfer->write_req->status = RTEMS_RESOURCE_IN_USE; 2357 transfer->write_req->bufnum = 0; 2383 2358 } 2384 2359 } 2360 2361 if (dd != &null_disk) 2385 2362 rtems_disk_release (dd); 2386 }2387 else2388 {2389 /*2390 * We have buffers but no device. Put the BDs back onto the2391 * ready queue and exit.2392 */2393 /* @todo fixme */2394 }2395 2363 } 2396 2364 } … … 2645 2613 2646 2614 write_req->req = RTEMS_BLKDEV_REQ_WRITE; 2647 write_req->req_done = rtems_bdbuf_ write_done;2615 write_req->req_done = rtems_bdbuf_transfer_done; 2648 2616 write_req->done_arg = write_req; 2649 2617 write_req->io_task = rtems_task_self (); -
cpukit/libblock/src/flashdisk.c
r64734fc r5c587596 2072 2072 } 2073 2073 2074 req->req_done (req->done_arg, 2075 ret ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR, ret); 2074 req->req_done (req->done_arg, ret ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR); 2076 2075 2077 2076 return ret; … … 2108 2107 } 2109 2108 2110 req->req_done (req->done_arg, 2111 ret ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR, ret); 2109 req->req_done (req->done_arg, ret ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR); 2112 2110 2113 2111 return 0; -
cpukit/libblock/src/nvdisk.c
r64734fc r5c587596 596 596 } 597 597 598 req->req_done (req->done_arg, 599 ret ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR, ret); 598 req->req_done (req->done_arg, ret ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR); 600 599 601 600 return ret; … … 636 635 } 637 636 638 req->req_done (req->done_arg, 639 ret ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR, ret); 637 req->req_done (req->done_arg, ret ? RTEMS_SUCCESSFUL : RTEMS_IO_ERROR); 640 638 641 639 return 0; -
cpukit/libblock/src/ramdisk-driver.c
r64734fc r5c587596 66 66 memcpy(sg->buffer, from + (sg->block * rd->block_size), sg->length); 67 67 } 68 req->req_done(req->done_arg, RTEMS_SUCCESSFUL , 0);68 req->req_done(req->done_arg, RTEMS_SUCCESSFUL); 69 69 return 0; 70 70 } … … 90 90 memcpy(to + (sg->block * rd->block_size), sg->buffer, sg->length); 91 91 } 92 req->req_done(req->done_arg, RTEMS_SUCCESSFUL , 0);92 req->req_done(req->done_arg, RTEMS_SUCCESSFUL); 93 93 return 0; 94 94 }
Note: See TracChangeset
for help on using the changeset viewer.