Changeset beb9336 in mainline for uspace/lib/ext4/libext4_balloc.c
- Timestamp:
- 2012-08-24T14:07:52Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 041ab64
- Parents:
- bd29f9c9 (diff), db81577 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/libext4_balloc.c
rbd29f9c9 rbeb9336 29 29 /** @addtogroup libext4 30 30 * @{ 31 */ 32 31 */ 33 32 /** 34 * @file 35 * @brief 33 * @file libext4_balloc.c 34 * @brief Physical block allocator. 36 35 */ 37 36 … … 42 41 /** Compute number of block group from block address. 43 42 * 44 * @param sb superblock pointer 45 * @param block_addr absolute address of block 46 * @return block group index 43 * @param sb Superblock pointer. 44 * @param block_addr Absolute address of block. 45 * 46 * @return Block group index 47 * 47 48 */ 48 49 static uint32_t ext4_balloc_get_bgid_of_block(ext4_superblock_t *sb, 49 50 uint32_t block_addr) 50 51 { 51 uint32_t blocks_per_group = ext4_superblock_get_blocks_per_group(sb); 52 uint32_t first_block = ext4_superblock_get_first_data_block(sb); 53 52 uint32_t blocks_per_group = 53 ext4_superblock_get_blocks_per_group(sb); 54 uint32_t first_block = 55 ext4_superblock_get_first_data_block(sb); 56 54 57 /* First block == 0 or 1 */ 55 if (first_block == 0) {58 if (first_block == 0) 56 59 return block_addr / blocks_per_group; 57 } else {60 else 58 61 return (block_addr - 1) / blocks_per_group; 59 }60 62 } 61 63 62 64 /** Free block. 63 65 * 64 * @param inode_ref inode, where the block is allocated 65 * @param block_addr absolute block address to free 66 * @return error code 66 * @param inode_ref Inode, where the block is allocated 67 * @param block_addr Absolute block address to free 68 * 69 * @return Error code 70 * 67 71 */ 68 72 int ext4_balloc_free_block(ext4_inode_ref_t *inode_ref, uint32_t block_addr) 69 73 { 70 int rc;71 72 74 ext4_filesystem_t *fs = inode_ref->fs; 73 75 ext4_superblock_t *sb = fs->superblock; 74 76 75 77 /* Compute indexes */ 76 78 uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, block_addr); 77 79 uint32_t index_in_group = 78 79 80 ext4_filesystem_blockaddr2_index_in_group(sb, block_addr); 81 80 82 /* Load block group reference */ 81 83 ext4_block_group_ref_t *bg_ref; 82 rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref); 83 if (rc != EOK) { 84 return rc; 85 } 86 84 int rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref); 85 if (rc != EOK) 86 return rc; 87 87 88 /* Load block with bitmap */ 88 uint32_t bitmap_block_addr = ext4_block_group_get_block_bitmap(89 89 uint32_t bitmap_block_addr = 90 ext4_block_group_get_block_bitmap(bg_ref->block_group, sb); 90 91 block_t *bitmap_block; 91 92 rc = block_get(&bitmap_block, fs->device, bitmap_block_addr, 0); 92 if (rc != EOK) { 93 return rc; 94 } 95 93 if (rc != EOK) 94 return rc; 95 96 96 /* Modify bitmap */ 97 97 ext4_bitmap_free_bit(bitmap_block->data, index_in_group); 98 98 bitmap_block->dirty = true; 99 100 99 101 100 /* Release block with bitmap */ 102 101 rc = block_put(bitmap_block); … … 106 105 return rc; 107 106 } 108 107 109 108 uint32_t block_size = ext4_superblock_get_block_size(sb); 110 109 111 110 /* Update superblock free blocks count */ 112 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb); 111 uint32_t sb_free_blocks = 112 ext4_superblock_get_free_blocks_count(sb); 113 113 sb_free_blocks++; 114 114 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks); 115 115 116 116 /* Update inode blocks count */ 117 uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode); 117 uint64_t ino_blocks = 118 ext4_inode_get_blocks_count(sb, inode_ref->inode); 118 119 ino_blocks -= block_size / EXT4_INODE_BLOCK_SIZE; 119 120 ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks); 120 121 inode_ref->dirty = true; 121 122 122 123 /* Update block group free blocks count */ 123 uint32_t free_blocks = ext4_block_group_get_free_blocks_count(124 124 uint32_t free_blocks = 125 ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb); 125 126 free_blocks++; 126 127 ext4_block_group_set_free_blocks_count(bg_ref->block_group, 127 128 sb, free_blocks); 128 129 bg_ref->dirty = true; 129 130 130 131 /* Release block group reference */ 131 132 rc = ext4_filesystem_put_block_group_ref(bg_ref); 132 if (rc != EOK) { 133 return rc; 134 } 135 133 if (rc != EOK) 134 return rc; 135 136 136 return EOK; 137 137 } 138 138 139 140 139 /** Free continuous set of blocks. 141 140 * 142 * @param inode_ref inode, where the blocks are allocated 143 * @param first first block to release 144 * @param count number of blocks to release 141 * @param inode_ref Inode, where the blocks are allocated 142 * @param first First block to release 143 * @param count Number of blocks to release 144 * 145 145 */ 146 146 int ext4_balloc_free_blocks(ext4_inode_ref_t *inode_ref, 147 147 uint32_t first, uint32_t count) 148 148 { 149 int rc;150 151 149 ext4_filesystem_t *fs = inode_ref->fs; 152 150 ext4_superblock_t *sb = fs->superblock; 153 151 154 152 /* Compute indexes */ 155 153 uint32_t block_group_first = 156 154 ext4_balloc_get_bgid_of_block(sb, first); 157 155 uint32_t block_group_last = 158 159 156 ext4_balloc_get_bgid_of_block(sb, first + count - 1); 157 160 158 assert(block_group_first == block_group_last); 161 159 162 160 /* Load block group reference */ 163 161 ext4_block_group_ref_t *bg_ref; 164 rc = ext4_filesystem_get_block_group_ref(fs, block_group_first, &bg_ref); 165 if (rc != EOK) { 166 return rc; 167 } 168 162 int rc = ext4_filesystem_get_block_group_ref(fs, block_group_first, &bg_ref); 163 if (rc != EOK) 164 return rc; 165 169 166 uint32_t index_in_group_first = 170 ext4_filesystem_blockaddr2_index_in_group(sb, first); 171 172 167 ext4_filesystem_blockaddr2_index_in_group(sb, first); 168 173 169 /* Load block with bitmap */ 174 uint32_t bitmap_block_addr = ext4_block_group_get_block_bitmap(175 176 170 uint32_t bitmap_block_addr = 171 ext4_block_group_get_block_bitmap(bg_ref->block_group, sb); 172 177 173 block_t *bitmap_block; 178 174 rc = block_get(&bitmap_block, fs->device, bitmap_block_addr, 0); 179 if (rc != EOK) { 180 return rc; 181 } 182 175 if (rc != EOK) 176 return rc; 177 183 178 /* Modify bitmap */ 184 179 ext4_bitmap_free_bits(bitmap_block->data, index_in_group_first, count); 185 180 bitmap_block->dirty = true; 186 181 187 182 /* Release block with bitmap */ 188 183 rc = block_put(bitmap_block); … … 192 187 return rc; 193 188 } 194 189 195 190 uint32_t block_size = ext4_superblock_get_block_size(sb); 196 191 197 192 /* Update superblock free blocks count */ 198 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb); 193 uint32_t sb_free_blocks = 194 ext4_superblock_get_free_blocks_count(sb); 199 195 sb_free_blocks += count; 200 196 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks); 201 197 202 198 /* Update inode blocks count */ 203 uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode); 199 uint64_t ino_blocks = 200 ext4_inode_get_blocks_count(sb, inode_ref->inode); 204 201 ino_blocks -= count * (block_size / EXT4_INODE_BLOCK_SIZE); 205 202 ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks); 206 203 inode_ref->dirty = true; 207 204 208 205 /* Update block group free blocks count */ 209 uint32_t free_blocks = ext4_block_group_get_free_blocks_count(210 206 uint32_t free_blocks = 207 ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb); 211 208 free_blocks += count; 212 209 ext4_block_group_set_free_blocks_count(bg_ref->block_group, 213 210 sb, free_blocks); 214 211 bg_ref->dirty = true; 215 212 216 213 /* Release block group reference */ 217 214 rc = ext4_filesystem_put_block_group_ref(bg_ref); 218 if (rc != EOK) { 219 return rc; 220 } 221 215 if (rc != EOK) 216 return rc; 217 222 218 return EOK; 223 219 } … … 225 221 /** Compute first block for data in block group. 226 222 * 227 * @param sb pointer to superblock 228 * @param bg pointer to block group 229 * @param bgid index of block group 230 * @return absolute block index of first block 231 */ 232 uint32_t ext4_balloc_get_first_data_block_in_group( 233 ext4_superblock_t *sb, ext4_block_group_ref_t *bg_ref) 223 * @param sb Pointer to superblock 224 * @param bg Pointer to block group 225 * @param bgid Index of block group 226 * 227 * @return Absolute block index of first block 228 * 229 */ 230 uint32_t ext4_balloc_get_first_data_block_in_group(ext4_superblock_t *sb, 231 ext4_block_group_ref_t *bg_ref) 234 232 { 235 233 uint32_t block_group_count = ext4_superblock_get_block_group_count(sb); 236 uint32_t inode_table_first_block = ext4_block_group_get_inode_table_first_block(237 234 uint32_t inode_table_first_block = 235 ext4_block_group_get_inode_table_first_block(bg_ref->block_group, sb); 238 236 uint16_t inode_table_item_size = ext4_superblock_get_inode_size(sb); 239 237 uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb); 240 238 uint32_t block_size = ext4_superblock_get_block_size(sb); 241 239 uint32_t inode_table_bytes; 242 240 243 241 if (bg_ref->index < block_group_count - 1) { 244 242 inode_table_bytes = inodes_per_group * inode_table_item_size; 245 243 } else { 246 /* last block group could be smaller */244 /* Last block group could be smaller */ 247 245 uint32_t inodes_count_total = ext4_superblock_get_inodes_count(sb); 248 246 inode_table_bytes = 249 (inodes_count_total - ((block_group_count - 1) * inodes_per_group))250 *inode_table_item_size;251 } 252 247 (inodes_count_total - ((block_group_count - 1) * inodes_per_group)) * 248 inode_table_item_size; 249 } 250 253 251 uint32_t inode_table_blocks = inode_table_bytes / block_size; 254 255 if (inode_table_bytes % block_size) {252 253 if (inode_table_bytes % block_size) 256 254 inode_table_blocks++; 257 } 258 255 259 256 return inode_table_first_block + inode_table_blocks; 260 257 } … … 262 259 /** Compute 'goal' for allocation algorithm. 263 260 * 264 * @param inode_ref reference to inode, to allocate block for 265 * @return goal block number 261 * @param inode_ref Reference to inode, to allocate block for 262 * 263 * @return Goal block number 264 * 266 265 */ 267 266 static uint32_t ext4_balloc_find_goal(ext4_inode_ref_t *inode_ref) 268 267 { 269 int rc;270 268 uint32_t goal = 0; 271 269 272 270 ext4_superblock_t *sb = inode_ref->fs->superblock; 273 271 274 272 uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode); 275 273 uint32_t block_size = ext4_superblock_get_block_size(sb); 276 274 uint32_t inode_block_count = inode_size / block_size; 277 278 if (inode_size % block_size != 0) {275 276 if (inode_size % block_size != 0) 279 277 inode_block_count++; 280 } 281 278 282 279 /* If inode has some blocks, get last block address + 1 */ 283 280 if (inode_block_count > 0) { 284 285 rc = ext4_filesystem_get_inode_data_block_index(inode_ref,inode_block_count - 1, &goal);286 if (rc != EOK) {281 int rc = ext4_filesystem_get_inode_data_block_index(inode_ref, 282 inode_block_count - 1, &goal); 283 if (rc != EOK) 287 284 return 0; 288 } 289 285 290 286 if (goal != 0) { 291 287 goal++; 292 288 return goal; 293 289 } 294 295 /* if goal == 0, sparse file -> continue */296 } 297 290 291 /* If goal == 0, sparse file -> continue */ 292 } 293 298 294 /* Identify block group of inode */ 299 295 uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb); 300 296 uint32_t block_group = (inode_ref->index - 1) / inodes_per_group; 301 297 block_size = ext4_superblock_get_block_size(sb); 302 298 303 299 /* Load block group reference */ 304 300 ext4_block_group_ref_t *bg_ref; 305 rc = ext4_filesystem_get_block_group_ref(inode_ref->fs, block_group, &bg_ref); 306 if (rc != EOK) { 301 int rc = ext4_filesystem_get_block_group_ref(inode_ref->fs, 302 block_group, &bg_ref); 303 if (rc != EOK) 307 304 return 0; 308 } 309 305 310 306 /* Compute indexes */ 311 307 uint32_t block_group_count = ext4_superblock_get_block_group_count(sb); 312 uint32_t inode_table_first_block = ext4_block_group_get_inode_table_first_block(313 308 uint32_t inode_table_first_block = 309 ext4_block_group_get_inode_table_first_block(bg_ref->block_group, sb); 314 310 uint16_t inode_table_item_size = ext4_superblock_get_inode_size(sb); 315 311 uint32_t inode_table_bytes; 316 312 317 313 /* Check for last block group */ 318 314 if (block_group < block_group_count - 1) { 319 315 inode_table_bytes = inodes_per_group * inode_table_item_size; 320 316 } else { 321 /* last block group could be smaller */317 /* Last block group could be smaller */ 322 318 uint32_t inodes_count_total = ext4_superblock_get_inodes_count(sb); 323 319 inode_table_bytes = 324 (inodes_count_total - ((block_group_count - 1) * inodes_per_group))325 *inode_table_item_size;326 } 327 320 (inodes_count_total - ((block_group_count - 1) * inodes_per_group)) * 321 inode_table_item_size; 322 } 323 328 324 uint32_t inode_table_blocks = inode_table_bytes / block_size; 329 330 if (inode_table_bytes % block_size) {325 326 if (inode_table_bytes % block_size) 331 327 inode_table_blocks++; 332 } 333 328 334 329 goal = inode_table_first_block + inode_table_blocks; 335 330 336 331 ext4_filesystem_put_block_group_ref(bg_ref); 337 332 338 333 return goal; 339 334 } … … 341 336 /** Data block allocation algorithm. 342 337 * 343 * @param inode_ref inode to allocate block for 344 * @param fblock allocated block address 345 * @return error code 346 */ 347 int ext4_balloc_alloc_block( 348 ext4_inode_ref_t *inode_ref, uint32_t *fblock) 338 * @param inode_ref Inode to allocate block for 339 * @param fblock Allocated block address 340 * 341 * @return Error code 342 * 343 */ 344 int ext4_balloc_alloc_block(ext4_inode_ref_t *inode_ref, uint32_t *fblock) 349 345 { 350 int rc;351 346 uint32_t allocated_block = 0; 352 347 353 348 uint32_t bitmap_block_addr; 354 349 block_t *bitmap_block; 355 350 uint32_t rel_block_idx = 0; 356 351 357 352 /* Find GOAL */ 358 353 uint32_t goal = ext4_balloc_find_goal(inode_ref); … … 361 356 return ENOSPC; 362 357 } 363 358 364 359 ext4_superblock_t *sb = inode_ref->fs->superblock; 365 360 366 361 /* Load block group number for goal and relative index */ 367 362 uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, goal); 368 363 uint32_t index_in_group = 369 ext4_filesystem_blockaddr2_index_in_group(sb, goal); 370 371 364 ext4_filesystem_blockaddr2_index_in_group(sb, goal); 365 372 366 /* Load block group reference */ 373 367 ext4_block_group_ref_t *bg_ref; 374 rc = ext4_filesystem_get_block_group_ref(inode_ref->fs, block_group, &bg_ref);375 if (rc != EOK) {376 return rc;377 }378 368 int rc = ext4_filesystem_get_block_group_ref(inode_ref->fs, 369 block_group, &bg_ref); 370 if (rc != EOK) 371 return rc; 372 379 373 /* Compute indexes */ 380 374 uint32_t first_in_group = 381 382 383 uint32_t first_in_group_index = ext4_filesystem_blockaddr2_index_in_group(384 385 386 if (index_in_group < first_in_group_index) {375 ext4_balloc_get_first_data_block_in_group(sb, bg_ref); 376 377 uint32_t first_in_group_index = 378 ext4_filesystem_blockaddr2_index_in_group(sb, first_in_group); 379 380 if (index_in_group < first_in_group_index) 387 381 index_in_group = first_in_group_index; 388 } 389 382 390 383 /* Load block with bitmap */ 391 bitmap_block_addr = ext4_block_group_get_block_bitmap(392 393 384 bitmap_block_addr = 385 ext4_block_group_get_block_bitmap(bg_ref->block_group, sb); 386 394 387 rc = block_get(&bitmap_block, inode_ref->fs->device, 395 388 bitmap_block_addr, BLOCK_FLAGS_NONE); 396 389 if (rc != EOK) { 397 390 ext4_filesystem_put_block_group_ref(bg_ref); 398 391 return rc; 399 392 } 400 393 401 394 /* Check if goal is free */ 402 395 if (ext4_bitmap_is_free_bit(bitmap_block->data, index_in_group)) { … … 408 401 return rc; 409 402 } 410 411 allocated_block = ext4_filesystem_index_in_group2blockaddr( 412 sb, index_in_group, block_group); 413 403 404 allocated_block = 405 ext4_filesystem_index_in_group2blockaddr(sb, index_in_group, 406 block_group); 407 414 408 goto success; 415 416 }417 418 uint32_t blocks_in_group =ext4_superblock_get_blocks_in_group(sb, block_group);419 409 } 410 411 uint32_t blocks_in_group = 412 ext4_superblock_get_blocks_in_group(sb, block_group); 413 420 414 uint32_t end_idx = (index_in_group + 63) & ~63; 421 if (end_idx > blocks_in_group) {415 if (end_idx > blocks_in_group) 422 416 end_idx = blocks_in_group; 423 } 424 417 425 418 /* Try to find free block near to goal */ 426 for (uint32_t tmp_idx = index_in_group + 1; tmp_idx < end_idx; ++tmp_idx) { 419 for (uint32_t tmp_idx = index_in_group + 1; tmp_idx < end_idx; 420 ++tmp_idx) { 427 421 if (ext4_bitmap_is_free_bit(bitmap_block->data, tmp_idx)) { 428 429 422 ext4_bitmap_set_bit(bitmap_block->data, tmp_idx); 430 423 bitmap_block->dirty = true; 431 424 rc = block_put(bitmap_block); 432 if (rc != EOK) {425 if (rc != EOK) 433 426 return rc; 434 }435 436 allocated_block = ext4_filesystem_index_in_group2blockaddr(437 sb, tmp_idx,block_group);438 427 428 allocated_block = 429 ext4_filesystem_index_in_group2blockaddr(sb, tmp_idx, 430 block_group); 431 439 432 goto success; 440 433 } 441 442 } 443 434 } 435 444 436 /* Find free BYTE in bitmap */ 445 rc = ext4_bitmap_find_free_byte_and_set_bit(bitmap_block->data, index_in_group, &rel_block_idx, blocks_in_group); 437 rc = ext4_bitmap_find_free_byte_and_set_bit(bitmap_block->data, 438 index_in_group, &rel_block_idx, blocks_in_group); 446 439 if (rc == EOK) { 447 440 bitmap_block->dirty = true; 448 441 rc = block_put(bitmap_block); 449 if (rc != EOK) {442 if (rc != EOK) 450 443 return rc; 451 }452 453 allocated_block = ext4_filesystem_index_in_group2blockaddr(454 sb, rel_block_idx,block_group);455 444 445 allocated_block = 446 ext4_filesystem_index_in_group2blockaddr(sb, rel_block_idx, 447 block_group); 448 456 449 goto success; 457 450 } 458 451 459 452 /* Find free bit in bitmap */ 460 rc = ext4_bitmap_find_free_bit_and_set(bitmap_block->data, index_in_group, &rel_block_idx, blocks_in_group); 453 rc = ext4_bitmap_find_free_bit_and_set(bitmap_block->data, 454 index_in_group, &rel_block_idx, blocks_in_group); 461 455 if (rc == EOK) { 462 456 bitmap_block->dirty = true; 463 457 rc = block_put(bitmap_block); 464 if (rc != EOK) {458 if (rc != EOK) 465 459 return rc; 466 }467 468 allocated_block = ext4_filesystem_index_in_group2blockaddr(469 sb, rel_block_idx,block_group);470 460 461 allocated_block = 462 ext4_filesystem_index_in_group2blockaddr(sb, rel_block_idx, 463 block_group); 464 471 465 goto success; 472 466 } 473 467 474 468 /* No free block found yet */ 475 469 block_put(bitmap_block); 476 470 ext4_filesystem_put_block_group_ref(bg_ref); 477 471 478 472 /* Try other block groups */ 479 473 uint32_t block_group_count = ext4_superblock_get_block_group_count(sb); 480 474 481 475 uint32_t bgid = (block_group + 1) % block_group_count; 482 476 uint32_t count = block_group_count; 483 477 484 478 while (count > 0) { 485 rc = ext4_filesystem_get_block_group_ref(inode_ref->fs, bgid, &bg_ref); 486 if (rc != EOK) { 479 rc = ext4_filesystem_get_block_group_ref(inode_ref->fs, bgid, 480 &bg_ref); 481 if (rc != EOK) 487 482 return rc; 488 } 489 483 490 484 /* Load block with bitmap */ 491 bitmap_block_addr = ext4_block_group_get_block_bitmap( 492 bg_ref->block_group, sb); 493 494 rc = block_get(&bitmap_block, inode_ref->fs->device, bitmap_block_addr, 0); 485 bitmap_block_addr = 486 ext4_block_group_get_block_bitmap(bg_ref->block_group, sb); 487 488 rc = block_get(&bitmap_block, inode_ref->fs->device, 489 bitmap_block_addr, 0); 495 490 if (rc != EOK) { 496 491 ext4_filesystem_put_block_group_ref(bg_ref); 497 492 return rc; 498 493 } 499 494 500 495 /* Compute indexes */ 501 first_in_group = ext4_balloc_get_first_data_block_in_group(502 503 index_in_group = ext4_filesystem_blockaddr2_index_in_group(sb,504 496 first_in_group = 497 ext4_balloc_get_first_data_block_in_group(sb, bg_ref); 498 index_in_group = 499 ext4_filesystem_blockaddr2_index_in_group(sb, first_in_group); 505 500 blocks_in_group = ext4_superblock_get_blocks_in_group(sb, bgid); 506 507 first_in_group_index = ext4_filesystem_blockaddr2_index_in_group(508 509 510 if (index_in_group < first_in_group_index) {501 502 first_in_group_index = 503 ext4_filesystem_blockaddr2_index_in_group(sb, first_in_group); 504 505 if (index_in_group < first_in_group_index) 511 506 index_in_group = first_in_group_index; 512 } 513 507 514 508 /* Try to find free byte in bitmap */ 515 509 rc = ext4_bitmap_find_free_byte_and_set_bit(bitmap_block->data, 516 510 index_in_group, &rel_block_idx, blocks_in_group); 517 511 if (rc == EOK) { 518 512 bitmap_block->dirty = true; 519 513 rc = block_put(bitmap_block); 520 if (rc != EOK) {514 if (rc != EOK) 521 515 return rc; 522 }523 524 allocated_block = ext4_filesystem_index_in_group2blockaddr(525 sb, rel_block_idx,bgid);526 516 517 allocated_block = 518 ext4_filesystem_index_in_group2blockaddr(sb, rel_block_idx, 519 bgid); 520 527 521 goto success; 528 522 } 529 523 530 524 /* Try to find free bit in bitmap */ 531 rc = ext4_bitmap_find_free_bit_and_set(bitmap_block->data, index_in_group, &rel_block_idx, blocks_in_group); 525 rc = ext4_bitmap_find_free_bit_and_set(bitmap_block->data, 526 index_in_group, &rel_block_idx, blocks_in_group); 532 527 if (rc == EOK) { 533 528 bitmap_block->dirty = true; 534 529 rc = block_put(bitmap_block); 535 if (rc != EOK) {530 if (rc != EOK) 536 531 return rc; 537 }538 539 allocated_block = ext4_filesystem_index_in_group2blockaddr(540 sb, rel_block_idx,bgid);541 532 533 allocated_block = 534 ext4_filesystem_index_in_group2blockaddr(sb, rel_block_idx, 535 bgid); 536 542 537 goto success; 543 538 } 544 539 545 540 block_put(bitmap_block); 546 541 ext4_filesystem_put_block_group_ref(bg_ref); 547 542 548 543 /* Goto next group */ 549 544 bgid = (bgid + 1) % block_group_count; 550 545 count--; 551 546 } 552 547 553 548 return ENOSPC; 554 549 555 550 success: 556 ; /* Empty command - because of syntax */ 551 /* Empty command - because of syntax */ 552 ; 557 553 558 554 uint32_t block_size = ext4_superblock_get_block_size(sb); 559 555 560 556 /* Update superblock free blocks count */ 561 557 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb); 562 558 sb_free_blocks--; 563 559 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks); 564 560 565 561 /* Update inode blocks (different block size!) count */ 566 uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode); 562 uint64_t ino_blocks = 563 ext4_inode_get_blocks_count(sb, inode_ref->inode); 567 564 ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE; 568 565 ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks); 569 566 inode_ref->dirty = true; 570 567 571 568 /* Update block group free blocks count */ 572 uint32_t bg_free_blocks = ext4_block_group_get_free_blocks_count(573 569 uint32_t bg_free_blocks = 570 ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb); 574 571 bg_free_blocks--; 575 ext4_block_group_set_free_blocks_count(bg_ref->block_group, sb, bg_free_blocks); 572 ext4_block_group_set_free_blocks_count(bg_ref->block_group, sb, 573 bg_free_blocks); 576 574 bg_ref->dirty = true; 577 575 578 576 ext4_filesystem_put_block_group_ref(bg_ref); 579 577 580 578 *fblock = allocated_block; 581 579 return EOK; … … 584 582 /** Try to allocate concrete block. 585 583 * 586 * @param inode_ref inode to allocate block for 587 * @param fblock block address to allocate 588 * @param free output value - if target block is free 589 * @return error code 590 */ 591 int ext4_balloc_try_alloc_block(ext4_inode_ref_t *inode_ref, 592 uint32_t fblock, bool *free) 584 * @param inode_ref Inode to allocate block for 585 * @param fblock Block address to allocate 586 * @param free Output value - if target block is free 587 * 588 * @return Error code 589 * 590 */ 591 int ext4_balloc_try_alloc_block(ext4_inode_ref_t *inode_ref, uint32_t fblock, 592 bool *free) 593 593 { 594 594 int rc = EOK; 595 595 596 596 ext4_filesystem_t *fs = inode_ref->fs; 597 597 ext4_superblock_t *sb = fs->superblock; 598 598 599 599 /* Compute indexes */ 600 600 uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, fblock); 601 601 uint32_t index_in_group = 602 603 602 ext4_filesystem_blockaddr2_index_in_group(sb, fblock); 603 604 604 /* Load block group reference */ 605 605 ext4_block_group_ref_t *bg_ref; 606 606 rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref); 607 if (rc != EOK) { 608 return rc; 609 } 610 607 if (rc != EOK) 608 return rc; 609 611 610 /* Load block with bitmap */ 612 uint32_t bitmap_block_addr = ext4_block_group_get_block_bitmap(613 611 uint32_t bitmap_block_addr = 612 ext4_block_group_get_block_bitmap(bg_ref->block_group, sb); 614 613 block_t *bitmap_block; 615 614 rc = block_get(&bitmap_block, fs->device, bitmap_block_addr, 0); 616 if (rc != EOK) { 617 return rc; 618 } 619 615 if (rc != EOK) 616 return rc; 617 620 618 /* Check if block is free */ 621 619 *free = ext4_bitmap_is_free_bit(bitmap_block->data, index_in_group); 622 620 623 621 /* Allocate block if possible */ 624 622 if (*free) { … … 626 624 bitmap_block->dirty = true; 627 625 } 628 626 629 627 /* Release block with bitmap */ 630 628 rc = block_put(bitmap_block); … … 634 632 return rc; 635 633 } 636 634 637 635 /* If block is not free, return */ 638 if (!(*free)) {636 if (!(*free)) 639 637 goto terminate; 640 } 641 638 642 639 uint32_t block_size = ext4_superblock_get_block_size(sb); 643 640 644 641 /* Update superblock free blocks count */ 645 642 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb); 646 643 sb_free_blocks--; 647 644 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks); 648 645 649 646 /* Update inode blocks count */ 650 uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode); 647 uint64_t ino_blocks = 648 ext4_inode_get_blocks_count(sb, inode_ref->inode); 651 649 ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE; 652 650 ext4_inode_set_blocks_count(sb, inode_ref->inode, ino_blocks); 653 651 inode_ref->dirty = true; 654 652 655 653 /* Update block group free blocks count */ 656 uint32_t free_blocks = ext4_block_group_get_free_blocks_count(657 654 uint32_t free_blocks = 655 ext4_block_group_get_free_blocks_count(bg_ref->block_group, sb); 658 656 free_blocks--; 659 657 ext4_block_group_set_free_blocks_count(bg_ref->block_group, 660 658 sb, free_blocks); 661 659 bg_ref->dirty = true; 662 660 663 661 terminate: 664 665 rc = ext4_filesystem_put_block_group_ref(bg_ref); 666 if (rc != EOK) { 667 return rc; 668 } 669 670 return rc; 662 return ext4_filesystem_put_block_group_ref(bg_ref); 671 663 } 672 664 673 665 /** 674 666 * @} 675 */ 667 */
Note:
See TracChangeset
for help on using the changeset viewer.