Changeset 06d85e5 in mainline
- Timestamp:
- 2012-06-18T11:09:34Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 2616a75b
- Parents:
- 9a487cc
- Location:
- uspace
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/libext4_balloc.c
r9a487cc r06d85e5 52 52 uint32_t first_block = ext4_superblock_get_first_data_block(sb); 53 53 54 / / First block == 0 or 154 /* First block == 0 or 1 */ 55 55 if (first_block == 0) { 56 56 return block_addr % blocks_per_group; … … 92 92 uint32_t first_block = ext4_superblock_get_first_data_block(sb); 93 93 94 / / First block == 0 or 194 /* First block == 0 or 1 */ 95 95 if (first_block == 0) { 96 96 return block_addr / blocks_per_group; … … 114 114 ext4_superblock_t *sb = fs->superblock; 115 115 116 / / Compute indexes116 /* Compute indexes */ 117 117 uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, block_addr); 118 118 uint32_t index_in_group = ext4_balloc_blockaddr2_index_in_group(sb, block_addr); 119 119 120 / / Load block group reference120 /* Load block group reference */ 121 121 ext4_block_group_ref_t *bg_ref; 122 122 rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref); … … 126 126 } 127 127 128 / / Load block with bitmap128 /* Load block with bitmap */ 129 129 uint32_t bitmap_block_addr = ext4_block_group_get_block_bitmap( 130 130 bg_ref->block_group, sb); … … 136 136 } 137 137 138 / / Modify bitmap138 /* Modify bitmap */ 139 139 ext4_bitmap_free_bit(bitmap_block->data, index_in_group); 140 140 bitmap_block->dirty = true; 141 141 142 142 143 / / Release block with bitmap143 /* Release block with bitmap */ 144 144 rc = block_put(bitmap_block); 145 145 if (rc != EOK) { 146 / / Error in saving bitmap146 /* Error in saving bitmap */ 147 147 ext4_filesystem_put_block_group_ref(bg_ref); 148 148 EXT4FS_DBG("error in saving bitmap \%d", rc); … … 152 152 uint32_t block_size = ext4_superblock_get_block_size(sb); 153 153 154 / / Update superblock free blocks count154 /* Update superblock free blocks count */ 155 155 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb); 156 156 sb_free_blocks++; 157 157 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks); 158 158 159 / / Update inode blocks count159 /* Update inode blocks count */ 160 160 uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode); 161 161 ino_blocks -= block_size / EXT4_INODE_BLOCK_SIZE; … … 163 163 inode_ref->dirty = true; 164 164 165 / / Update block group free blocks count165 /* Update block group free blocks count */ 166 166 uint32_t free_blocks = ext4_block_group_get_free_blocks_count( 167 167 bg_ref->block_group, sb); … … 171 171 bg_ref->dirty = true; 172 172 173 / / Release block group reference173 /* Release block group reference */ 174 174 rc = ext4_filesystem_put_block_group_ref(bg_ref); 175 175 if (rc != EOK) { … … 196 196 ext4_superblock_t *sb = fs->superblock; 197 197 198 / / Compute indexes198 /* Compute indexes */ 199 199 uint32_t block_group_first = 200 200 ext4_balloc_get_bgid_of_block(sb, first); … … 204 204 assert(block_group_first == block_group_last); 205 205 206 / / Load block group reference206 /* Load block group reference */ 207 207 ext4_block_group_ref_t *bg_ref; 208 208 rc = ext4_filesystem_get_block_group_ref(fs, block_group_first, &bg_ref); … … 216 216 217 217 218 / / Load block with bitmap218 /* Load block with bitmap */ 219 219 uint32_t bitmap_block_addr = ext4_block_group_get_block_bitmap( 220 220 bg_ref->block_group, sb); … … 227 227 } 228 228 229 / / Modify bitmap229 /* Modify bitmap */ 230 230 ext4_bitmap_free_bits(bitmap_block->data, index_in_group_first, count); 231 231 bitmap_block->dirty = true; 232 232 233 / / Release block with bitmap233 /* Release block with bitmap */ 234 234 rc = block_put(bitmap_block); 235 235 if (rc != EOK) { 236 / / Error in saving bitmap236 /* Error in saving bitmap */ 237 237 ext4_filesystem_put_block_group_ref(bg_ref); 238 238 EXT4FS_DBG("error in saving bitmap \%d", rc); … … 242 242 uint32_t block_size = ext4_superblock_get_block_size(sb); 243 243 244 / / Update superblock free blocks count244 /* Update superblock free blocks count */ 245 245 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb); 246 246 sb_free_blocks += count; 247 247 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks); 248 248 249 / / Update inode blocks count249 /* Update inode blocks count */ 250 250 uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode); 251 251 ino_blocks -= count * (block_size / EXT4_INODE_BLOCK_SIZE); … … 253 253 inode_ref->dirty = true; 254 254 255 / / Update block group free blocks count255 /* Update block group free blocks count */ 256 256 uint32_t free_blocks = ext4_block_group_get_free_blocks_count( 257 257 bg_ref->block_group, sb); … … 261 261 bg_ref->dirty = true; 262 262 263 / / Release block group reference263 /* Release block group reference */ 264 264 rc = ext4_filesystem_put_block_group_ref(bg_ref); 265 265 if (rc != EOK) { … … 292 292 inode_table_bytes = inodes_per_group * inode_table_item_size; 293 293 } else { 294 / / last block group could be smaller294 /* last block group could be smaller */ 295 295 uint32_t inodes_count_total = ext4_superblock_get_inodes_count(sb); 296 296 inode_table_bytes = … … 328 328 } 329 329 330 / / If inode has some blocks, get last block address + 1330 /* If inode has some blocks, get last block address + 1 */ 331 331 if (inode_block_count > 0) { 332 332 … … 341 341 } 342 342 343 / / if goal == 0, sparse file -> continue344 } 345 346 / / Identify block group of inode343 /* if goal == 0, sparse file -> continue */ 344 } 345 346 /* Identify block group of inode */ 347 347 uint32_t inodes_per_group = ext4_superblock_get_inodes_per_group(sb); 348 348 uint32_t block_group = (inode_ref->index - 1) / inodes_per_group; 349 349 block_size = ext4_superblock_get_block_size(sb); 350 350 351 / / Load block group reference351 /* Load block group reference */ 352 352 ext4_block_group_ref_t *bg_ref; 353 353 rc = ext4_filesystem_get_block_group_ref(inode_ref->fs, block_group, &bg_ref); … … 356 356 } 357 357 358 / / Compute indexes358 /* Compute indexes */ 359 359 uint32_t block_group_count = ext4_superblock_get_block_group_count(sb); 360 360 uint32_t inode_table_first_block = ext4_block_group_get_inode_table_first_block( … … 363 363 uint32_t inode_table_bytes; 364 364 365 / / Check for last block group365 /* Check for last block group */ 366 366 if (block_group < block_group_count - 1) { 367 367 inode_table_bytes = inodes_per_group * inode_table_item_size; 368 368 } else { 369 / / last block group could be smaller369 /* last block group could be smaller */ 370 370 uint32_t inodes_count_total = ext4_superblock_get_inodes_count(sb); 371 371 inode_table_bytes = … … 403 403 uint32_t rel_block_idx = 0; 404 404 405 / / Find GOAL405 /* Find GOAL */ 406 406 uint32_t goal = ext4_balloc_find_goal(inode_ref); 407 407 if (goal == 0) { 408 / / no goal found => partition is full409 EXT4FS_DBG("ERROR R(goal == 0)");408 /* no goal found => partition is full */ 409 EXT4FS_DBG("ERROR (goal == 0)"); 410 410 return ENOSPC; 411 411 } … … 413 413 ext4_superblock_t *sb = inode_ref->fs->superblock; 414 414 415 / / Load block group number for goal and relative index415 /* Load block group number for goal and relative index */ 416 416 uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, goal); 417 417 uint32_t index_in_group = ext4_balloc_blockaddr2_index_in_group(sb, goal); 418 418 419 419 420 / / Load block group reference420 /* Load block group reference */ 421 421 ext4_block_group_ref_t *bg_ref; 422 422 rc = ext4_filesystem_get_block_group_ref(inode_ref->fs, block_group, &bg_ref); … … 426 426 } 427 427 428 / / Compute indexes428 /* Compute indexes */ 429 429 uint32_t first_in_group = 430 430 ext4_balloc_get_first_data_block_in_group(sb, … … 438 438 } 439 439 440 / / Load block with bitmap440 /* Load block with bitmap */ 441 441 bitmap_block_addr = ext4_block_group_get_block_bitmap(bg_ref->block_group, 442 442 sb); … … 449 449 } 450 450 451 / / Check if goal is free451 /* Check if goal is free */ 452 452 if (ext4_bitmap_is_free_bit(bitmap_block->data, index_in_group)) { 453 453 ext4_bitmap_set_bit(bitmap_block->data, index_in_group); … … 472 472 } 473 473 474 / / Try to find free block near to goal474 /* Try to find free block near to goal */ 475 475 for (uint32_t tmp_idx = index_in_group + 1; tmp_idx < end_idx; ++tmp_idx) { 476 476 if (ext4_bitmap_is_free_bit(bitmap_block->data, tmp_idx)) { … … 492 492 } 493 493 494 / / Find free BYTE in bitmap494 /* Find free BYTE in bitmap */ 495 495 rc = ext4_bitmap_find_free_byte_and_set_bit(bitmap_block->data, index_in_group, &rel_block_idx, blocks_in_group); 496 496 if (rc == EOK) { … … 508 508 } 509 509 510 / / Find free bit in bitmap510 /* Find free bit in bitmap */ 511 511 rc = ext4_bitmap_find_free_bit_and_set(bitmap_block->data, index_in_group, &rel_block_idx, blocks_in_group); 512 512 if (rc == EOK) { … … 524 524 } 525 525 526 / / No free block found yet526 /* No free block found yet */ 527 527 block_put(bitmap_block); 528 528 ext4_filesystem_put_block_group_ref(bg_ref); 529 529 530 / / Try other block groups530 /* Try other block groups */ 531 531 uint32_t block_group_count = ext4_superblock_get_block_group_count(sb); 532 532 … … 541 541 } 542 542 543 / / Load block with bitmap543 /* Load block with bitmap */ 544 544 bitmap_block_addr = ext4_block_group_get_block_bitmap( 545 545 bg_ref->block_group, sb); … … 552 552 } 553 553 554 / / Compute indexes554 /* Compute indexes */ 555 555 first_in_group = ext4_balloc_get_first_data_block_in_group( 556 556 sb, bg_ref->block_group, bgid); … … 566 566 } 567 567 568 / / Try to find free byte in bitmap568 /* Try to find free byte in bitmap */ 569 569 rc = ext4_bitmap_find_free_byte_and_set_bit(bitmap_block->data, index_in_group, &rel_block_idx, blocks_in_group); 570 570 if (rc == EOK) { … … 582 582 } 583 583 584 / / Try to find free bit in bitmap584 /* Try to find free bit in bitmap */ 585 585 rc = ext4_bitmap_find_free_bit_and_set(bitmap_block->data, index_in_group, &rel_block_idx, blocks_in_group); 586 586 if (rc == EOK) { … … 601 601 ext4_filesystem_put_block_group_ref(bg_ref); 602 602 603 / / Goto next group603 /* Goto next group */ 604 604 bgid = (bgid + 1) % block_group_count; 605 605 count--; … … 609 609 610 610 success: 611 ; / / Empty command - because of syntax611 ; /* Empty command - because of syntax */ 612 612 613 613 uint32_t block_size = ext4_superblock_get_block_size(sb); 614 614 615 / / Update superblock free blocks count615 /* Update superblock free blocks count */ 616 616 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb); 617 617 sb_free_blocks--; 618 618 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks); 619 619 620 / / Update inode blocks (different block size!) count620 /* Update inode blocks (different block size!) count */ 621 621 uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode); 622 622 ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE; … … 624 624 inode_ref->dirty = true; 625 625 626 / / Update block group free blocks count626 /* Update block group free blocks count */ 627 627 uint32_t bg_free_blocks = ext4_block_group_get_free_blocks_count( 628 628 bg_ref->block_group, sb); … … 652 652 ext4_superblock_t *sb = fs->superblock; 653 653 654 / / Compute indexes654 /* Compute indexes */ 655 655 uint32_t block_group = ext4_balloc_get_bgid_of_block(sb, fblock); 656 656 uint32_t index_in_group = ext4_balloc_blockaddr2_index_in_group(sb, fblock); 657 657 658 / / Load block group reference658 /* Load block group reference */ 659 659 ext4_block_group_ref_t *bg_ref; 660 660 rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref); … … 664 664 } 665 665 666 / / Load block with bitmap666 /* Load block with bitmap */ 667 667 uint32_t bitmap_block_addr = ext4_block_group_get_block_bitmap( 668 668 bg_ref->block_group, sb); … … 674 674 } 675 675 676 / / Check if block is free676 /* Check if block is free */ 677 677 *free = ext4_bitmap_is_free_bit(bitmap_block->data, index_in_group); 678 678 679 / / Allocate block if possible679 /* Allocate block if possible */ 680 680 if (*free) { 681 681 ext4_bitmap_set_bit(bitmap_block->data, index_in_group); … … 683 683 } 684 684 685 / / Release block with bitmap685 /* Release block with bitmap */ 686 686 rc = block_put(bitmap_block); 687 687 if (rc != EOK) { 688 / / Error in saving bitmap688 /* Error in saving bitmap */ 689 689 ext4_filesystem_put_block_group_ref(bg_ref); 690 690 EXT4FS_DBG("error in saving bitmap \%d", rc); … … 692 692 } 693 693 694 / / If block is not free, return694 /* If block is not free, return */ 695 695 if (!(*free)) { 696 696 goto terminate; … … 699 699 uint32_t block_size = ext4_superblock_get_block_size(sb); 700 700 701 / / Update superblock free blocks count701 /* Update superblock free blocks count */ 702 702 uint32_t sb_free_blocks = ext4_superblock_get_free_blocks_count(sb); 703 703 sb_free_blocks--; 704 704 ext4_superblock_set_free_blocks_count(sb, sb_free_blocks); 705 705 706 / / Update inode blocks count706 /* Update inode blocks count */ 707 707 uint64_t ino_blocks = ext4_inode_get_blocks_count(sb, inode_ref->inode); 708 708 ino_blocks += block_size / EXT4_INODE_BLOCK_SIZE; … … 710 710 inode_ref->dirty = true; 711 711 712 / / Update block group free blocks count712 /* Update block group free blocks count */ 713 713 uint32_t free_blocks = ext4_block_group_get_free_blocks_count( 714 714 bg_ref->block_group, sb); -
uspace/lib/ext4/libext4_bitmap.c
r9a487cc r06d85e5 73 73 uint32_t byte_index; 74 74 75 / / Align index to multiple of 875 /* Align index to multiple of 8 */ 76 76 while (((idx % 8) != 0) && (remaining > 0)) { 77 77 … … 87 87 } 88 88 89 / / For < 8 bits this check necessary89 /* For < 8 bits this check necessary */ 90 90 if (remaining == 0) { 91 91 return; … … 97 97 target = bitmap + byte_index; 98 98 99 / / Zero the whole bytes99 /* Zero the whole bytes */ 100 100 while (remaining >= 8) { 101 101 *target = 0; … … 108 108 assert(remaining < 8); 109 109 110 / / Zero remaining bytes110 /* Zero remaining bytes */ 111 111 while (remaining != 0) { 112 112 … … 174 174 uint32_t idx; 175 175 176 / / Align idx176 /* Align idx */ 177 177 if (start % 8) { 178 178 idx = start + (8 - (start % 8)); … … 183 183 uint8_t *pos = bitmap + (idx / 8); 184 184 185 / / Try to find free byte185 /* Try to find free byte */ 186 186 while (idx < max) { 187 187 … … 197 197 } 198 198 199 / / Free byte not found199 /* Free byte not found */ 200 200 return ENOSPC; 201 201 } … … 218 218 bool byte_part = false; 219 219 220 / / Check the rest of first byte220 /* Check the rest of first byte */ 221 221 while ((idx % 8) != 0) { 222 222 byte_part = true; … … 235 235 } 236 236 237 / / Check the whole bytes (255 = 11111111 binary)237 /* Check the whole bytes (255 = 11111111 binary) */ 238 238 while (idx < max) { 239 239 240 240 if ((*pos & 255) != 255) { 241 / / free bit found241 /* free bit found */ 242 242 break; 243 243 } … … 247 247 } 248 248 249 / / If idx < max, some free bit found249 /* If idx < max, some free bit found */ 250 250 if (idx < max) { 251 251 252 / / Check which bit from byte is free252 /* Check which bit from byte is free */ 253 253 for (uint8_t i = 0; i < 8; ++i) { 254 254 if ((*pos & (1 << i)) == 0) { 255 / / free bit found255 /* free bit found */ 256 256 *pos |= (1 << i); 257 257 *index = idx; … … 262 262 } 263 263 264 / / Free bit not found264 /* Free bit not found */ 265 265 return ENOSPC; 266 266 } -
uspace/lib/ext4/libext4_directory.c
r9a487cc r06d85e5 159 159 } 160 160 161 / / else do nothing161 /* else do nothing */ 162 162 163 163 } … … 237 237 } 238 238 239 / / Compute next block address239 /* Compute next block address */ 240 240 uint32_t block_size = ext4_superblock_get_block_size( 241 241 it->inode_ref->fs->superblock); … … 313 313 } 314 314 315 / / Everything OK - "publish" the entry315 /* Everything OK - "publish" the entry */ 316 316 it->current = entry; 317 317 return EOK; … … 357 357 { 358 358 359 / / Check maximum entry length359 /* Check maximum entry length */ 360 360 uint32_t block_size = ext4_superblock_get_block_size(sb); 361 361 assert(entry_len <= block_size); 362 362 363 / / Set basic attributes363 /* Set basic attributes */ 364 364 ext4_directory_entry_ll_set_inode(entry, child->index); 365 365 ext4_directory_entry_ll_set_entry_length(entry, entry_len); 366 366 ext4_directory_entry_ll_set_name_length(sb, entry, name_len); 367 367 368 / / Write name368 /* Write name */ 369 369 memcpy(entry->name, name, name_len); 370 370 371 / / Set type of entry371 /* Set type of entry */ 372 372 if (ext4_inode_is_type(sb, child->inode, EXT4_INODE_MODE_DIRECTORY)) { 373 373 ext4_directory_entry_ll_set_inode_type( … … 394 394 ext4_filesystem_t *fs = parent->fs; 395 395 396 / / Index adding (if allowed)396 /* Index adding (if allowed) */ 397 397 if (ext4_superblock_has_feature_compatible(fs->superblock, EXT4_FEATURE_COMPAT_DIR_INDEX) && 398 398 ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX)) { … … 400 400 rc = ext4_directory_dx_add_entry(parent, child, name); 401 401 402 / / Check if index is not corrupted402 /* Check if index is not corrupted */ 403 403 if (rc != EXT4_ERR_BAD_DX_DIR) { 404 404 … … 410 410 } 411 411 412 / / Needed to clear dir index flag if corrupted412 /* Needed to clear dir index flag if corrupted */ 413 413 ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX); 414 414 parent->dirty = true; … … 417 417 } 418 418 419 / / Linear algorithm419 /* Linear algorithm */ 420 420 421 421 uint32_t iblock = 0, fblock = 0; … … 426 426 uint32_t name_len = strlen(name); 427 427 428 / / Find block, where is space for new entry and try to add428 /* Find block, where is space for new entry and try to add */ 429 429 bool success = false; 430 430 for (iblock = 0; iblock < total_blocks; ++iblock) { … … 441 441 } 442 442 443 / / If adding is successful, function can finish443 /* If adding is successful, function can finish */ 444 444 rc = ext4_directory_try_insert_entry(fs->superblock, block, child, name, name_len); 445 445 if (rc == EOK) { … … 457 457 } 458 458 459 / / No free block found - needed to allocate next data block459 /* No free block found - needed to allocate next data block */ 460 460 461 461 iblock = 0; … … 466 466 } 467 467 468 / / Load new block468 /* Load new block */ 469 469 block_t *new_block; 470 470 rc = block_get(&new_block, fs->device, fblock, BLOCK_FLAGS_NOREAD); … … 473 473 } 474 474 475 / / Fill block with zeroes475 /* Fill block with zeroes */ 476 476 memset(new_block->data, 0, block_size); 477 477 ext4_directory_entry_ll_t *block_entry = new_block->data; 478 478 ext4_directory_write_entry(fs->superblock, block_entry, block_size, child, name, name_len); 479 479 480 / / Save new block480 /* Save new block */ 481 481 new_block->dirty = true; 482 482 rc = block_put(new_block); … … 503 503 ext4_superblock_t *sb = parent->fs->superblock; 504 504 505 / / Index search505 /* Index search */ 506 506 if (ext4_superblock_has_feature_compatible(sb, EXT4_FEATURE_COMPAT_DIR_INDEX) && 507 507 ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX)) { … … 509 509 rc = ext4_directory_dx_find_entry(result, parent, name_len, name); 510 510 511 / / Check if index is not corrupted511 /* Check if index is not corrupted */ 512 512 if (rc != EXT4_ERR_BAD_DX_DIR) { 513 513 … … 518 518 } 519 519 520 / / Needed to clear dir index flag if corrupted520 /* Needed to clear dir index flag if corrupted */ 521 521 ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX); 522 522 parent->dirty = true; … … 525 525 } 526 526 527 / / Linear algorithm527 /* Linear algorithm */ 528 528 529 529 uint32_t iblock, fblock; … … 532 532 uint32_t total_blocks = inode_size / block_size; 533 533 534 / / Walk through all data blocks534 /* Walk through all data blocks */ 535 535 for (iblock = 0; iblock < total_blocks; ++iblock) { 536 536 537 / / Load block address537 /* Load block address */ 538 538 rc = ext4_filesystem_get_inode_data_block_index(parent, iblock, &fblock); 539 539 if (rc != EOK) { … … 541 541 } 542 542 543 / / Load data block543 /* Load data block */ 544 544 block_t *block; 545 545 rc = block_get(&block, parent->fs->device, fblock, BLOCK_FLAGS_NONE); … … 548 548 } 549 549 550 / / Try to find entry in block550 /* Try to find entry in block */ 551 551 ext4_directory_entry_ll_t *res_entry; 552 552 rc = ext4_directory_find_in_block(block, sb, name_len, name, &res_entry); … … 557 557 } 558 558 559 / / Entry not found - put block and continue to the next block559 /* Entry not found - put block and continue to the next block */ 560 560 561 561 rc = block_put(block); … … 565 565 } 566 566 567 / / Entry was not found567 /* Entry was not found */ 568 568 569 569 result->block = NULL; … … 584 584 int rc; 585 585 586 / / Check if removing from directory586 /* Check if removing from directory */ 587 587 if (!ext4_inode_is_type(parent->fs->superblock, parent->inode, 588 588 EXT4_INODE_MODE_DIRECTORY)) { … … 590 590 } 591 591 592 / / Try to find entry592 /* Try to find entry */ 593 593 ext4_directory_search_result_t result; 594 594 rc = ext4_directory_find_entry(&result, parent, name); … … 597 597 } 598 598 599 / / Invalidate entry599 /* Invalidate entry */ 600 600 ext4_directory_entry_ll_set_inode(result.dentry, 0); 601 601 602 / / Store entry position in block602 /* Store entry position in block */ 603 603 uint32_t pos = (void *)result.dentry - result.block->data; 604 604 605 // If entry is not the first in block, it must be merged 606 // with previous entry 605 /* If entry is not the first in block, it must be merged 606 * with previous entry 607 */ 607 608 if (pos != 0) { 608 609 609 610 uint32_t offset = 0; 610 611 611 / / Start from the first entry in block612 /* Start from the first entry in block */ 612 613 ext4_directory_entry_ll_t *tmp_dentry = result.block->data; 613 614 uint16_t tmp_dentry_length = 614 615 ext4_directory_entry_ll_get_entry_length(tmp_dentry); 615 616 616 / / Find direct predecessor of removed entry617 /* Find direct predecessor of removed entry */ 617 618 while ((offset + tmp_dentry_length) < pos) { 618 619 offset += ext4_directory_entry_ll_get_entry_length(tmp_dentry); … … 624 625 assert(tmp_dentry_length + offset == pos); 625 626 626 / / Add to removed entry length to predecessor's length627 /* Add to removed entry length to predecessor's length */ 627 628 uint16_t del_entry_length = 628 629 ext4_directory_entry_ll_get_entry_length(result.dentry); … … 650 651 const char *name, uint32_t name_len) 651 652 { 652 / / Compute required length entry and align it to 4 bytes653 /* Compute required length entry and align it to 4 bytes */ 653 654 uint32_t block_size = ext4_superblock_get_block_size(sb); 654 655 uint16_t required_len = sizeof(ext4_fake_directory_entry_t) + name_len; … … 657 658 } 658 659 659 / / Initialize pointers, stop means to upper bound660 /* Initialize pointers, stop means to upper bound */ 660 661 ext4_directory_entry_ll_t *dentry = target_block->data; 661 662 ext4_directory_entry_ll_t *stop = target_block->data + block_size; 662 663 663 // Walk through the block and check for invalid entries 664 // or entries with free space for new entry 664 /* Walk through the block and check for invalid entries 665 * or entries with free space for new entry 666 */ 665 667 while (dentry < stop) { 666 668 … … 668 670 uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(dentry); 669 671 670 / / If invalid and large enough entry, use it672 /* If invalid and large enough entry, use it */ 671 673 if ((inode == 0) && (rec_len >= required_len)) { 672 674 ext4_directory_write_entry(sb, dentry, rec_len, child, name, name_len); … … 675 677 } 676 678 677 / / Valid entry, try to split it679 /* Valid entry, try to split it */ 678 680 if (inode != 0) { 679 681 uint16_t used_name_len = … … 687 689 uint16_t free_space = rec_len - used_space; 688 690 689 / / There is free space for new entry691 /* There is free space for new entry */ 690 692 if (free_space >= required_len) { 691 693 692 / / Cut tail of current entry694 /* Cut tail of current entry */ 693 695 ext4_directory_entry_ll_set_entry_length(dentry, used_space); 694 696 ext4_directory_entry_ll_t *new_entry = … … 702 704 } 703 705 704 / / Jump to the next entry706 /* Jump to the next entry */ 705 707 dentry = (void *)dentry + rec_len; 706 708 } 707 709 708 / / No free space found for new entry710 /* No free space found for new entry */ 709 711 710 712 return ENOSPC; … … 724 726 ext4_directory_entry_ll_t **res_entry) 725 727 { 726 / / Start from the first entry in block728 /* Start from the first entry in block */ 727 729 ext4_directory_entry_ll_t *dentry = (ext4_directory_entry_ll_t *)block->data; 728 / /Set upper bound for cycling730 /*Set upper bound for cycling */ 729 731 uint8_t *addr_limit = block->data + ext4_superblock_get_block_size(sb); 730 732 731 / / Walk through the block and check entries733 /* Walk through the block and check entries */ 732 734 while ((uint8_t *)dentry < addr_limit) { 733 735 734 / / Termination condition736 /* Termination condition */ 735 737 if ((uint8_t*) dentry + name_len > addr_limit) { 736 738 break; 737 739 } 738 740 739 / / Valid entry - check it741 /* Valid entry - check it */ 740 742 if (dentry->inode != 0) { 741 743 742 / / For more effectivity compare firstly only lengths744 /* For more effectivity compare firstly only lengths */ 743 745 if (name_len == ext4_directory_entry_ll_get_name_length(sb, dentry)) { 744 / / Compare names746 /* Compare names */ 745 747 if (bcmp((uint8_t *)name, dentry->name, name_len) == 0) { 746 748 *res_entry = dentry; … … 752 754 uint16_t dentry_len = ext4_directory_entry_ll_get_entry_length(dentry); 753 755 754 / / Corrupted entry756 /* Corrupted entry */ 755 757 if (dentry_len == 0) { 756 758 return EINVAL; 757 759 } 758 760 759 / / Jump to next entry761 /* Jump to next entry */ 760 762 dentry = (ext4_directory_entry_ll_t *)((uint8_t *)dentry + dentry_len); 761 763 } 762 764 763 / / Entry not found765 /* Entry not found */ 764 766 return ENOENT; 765 767 } -
uspace/lib/ext4/libext4_directory_index.c
r9a487cc r06d85e5 218 218 int rc; 219 219 220 / / Load block 0, where will be index root located220 /* Load block 0, where will be index root located */ 221 221 uint32_t fblock; 222 222 rc = ext4_filesystem_get_inode_data_block_index(dir, 0, &fblock); … … 231 231 } 232 232 233 / / Initialize pointers to data structures233 /* Initialize pointers to data structures */ 234 234 ext4_directory_dx_root_t *root = block->data; 235 235 ext4_directory_dx_root_info_t *info = &(root->info); 236 236 237 / / Initialize root info structure237 /* Initialize root info structure */ 238 238 uint8_t hash_version = 239 239 ext4_superblock_get_default_hash_version(dir->fs->superblock); … … 243 243 ext4_directory_dx_root_info_set_info_length(info, 8); 244 244 245 / / Set limit and current number of entries245 /* Set limit and current number of entries */ 246 246 ext4_directory_dx_countlimit_t *countlimit = 247 247 (ext4_directory_dx_countlimit_t *)&root->entries; … … 254 254 ext4_directory_dx_countlimit_set_limit(countlimit, root_limit); 255 255 256 / / Append new block, where will be new entries inserted in the future256 /* Append new block, where will be new entries inserted in the future */ 257 257 uint32_t iblock; 258 258 rc = ext4_filesystem_append_inode_block(dir, &fblock, &iblock); … … 269 269 } 270 270 271 / / Fill the whole block with empty entry271 /* Fill the whole block with empty entry */ 272 272 ext4_directory_entry_ll_t *block_entry = new_block->data; 273 273 ext4_directory_entry_ll_set_entry_length(block_entry, block_size); … … 281 281 } 282 282 283 / / Connect new block to the only entry in index283 /* Connect new block to the only entry in index */ 284 284 ext4_directory_dx_entry_t *entry = root->entries; 285 285 ext4_directory_dx_entry_set_block(entry, iblock); … … 316 316 } 317 317 318 / / Check unused flags318 /* Check unused flags */ 319 319 if (root->info.unused_flags != 0) { 320 320 EXT4FS_DBG("ERR: unused_flags = \%u", root->info.unused_flags); … … 322 322 } 323 323 324 / / Check indirect levels324 /* Check indirect levels */ 325 325 if (root->info.indirect_levels > 1) { 326 326 EXT4FS_DBG("ERR: indirect_levels = \%u", root->info.indirect_levels); … … 328 328 } 329 329 330 / / Check if node limit is correct330 /* Check if node limit is correct */ 331 331 uint32_t block_size = ext4_superblock_get_block_size(sb); 332 332 uint32_t entry_space = block_size; … … 340 340 } 341 341 342 / / Check hash version and modify if necessary342 /* Check hash version and modify if necessary */ 343 343 hinfo->hash_version = ext4_directory_dx_root_info_get_hash_version(&root->info); 344 344 if ((hinfo->hash_version <= EXT4_HASH_VERSION_TEA) 345 345 && (ext4_superblock_has_flag(sb, EXT4_SUPERBLOCK_FLAGS_UNSIGNED_HASH))) { 346 / / 3 is magic from ext4 linux implementation346 /* 3 is magic from ext4 linux implementation */ 347 347 hinfo->hash_version += 3; 348 348 } 349 349 350 / / Load hash seed from superblock350 /* Load hash seed from superblock */ 351 351 hinfo->seed = ext4_superblock_get_hash_seed(sb); 352 352 353 / / Compute hash value of name353 /* Compute hash value of name */ 354 354 if (name) { 355 355 ext4_hash_string(hinfo, name_len, name); … … 385 385 ext4_directory_dx_entry_t *p, *q, *m, *at; 386 386 387 / / Walk through the index tree387 /* Walk through the index tree */ 388 388 while (true) { 389 389 … … 394 394 395 395 396 / / Do binary search in every node396 /* Do binary search in every node */ 397 397 p = entries + 1; 398 398 q = entries + count - 1; … … 409 409 at = p - 1; 410 410 411 / / Write results411 /* Write results */ 412 412 tmp_dx_block->block = tmp_block; 413 413 tmp_dx_block->entries = entries; 414 414 tmp_dx_block->position = at; 415 415 416 / / Is algorithm in the leaf?416 /* Is algorithm in the leaf? */ 417 417 if (indirect_level == 0) { 418 418 *dx_block = tmp_dx_block; … … 420 420 } 421 421 422 / / Goto child node422 /* Goto child node */ 423 423 uint32_t next_block = ext4_directory_dx_entry_get_block(at); 424 424 … … 454 454 } 455 455 456 / / Unreachable456 /* Unreachable */ 457 457 return EOK; 458 458 } … … 475 475 ext4_directory_dx_block_t *p = dx_block; 476 476 477 / / Try to find data block with next bunch of entries477 /* Try to find data block with next bunch of entries */ 478 478 while (1) { 479 479 … … 494 494 } 495 495 496 / / Check hash collision (if not occured - no next block cannot be used)496 /* Check hash collision (if not occured - no next block cannot be used) */ 497 497 uint32_t current_hash = ext4_directory_dx_entry_get_hash(p->position); 498 498 if ((hash & 1) == 0) { … … 502 502 } 503 503 504 / / Fill new path504 /* Fill new path */ 505 505 while (num_handles--) { 506 506 … … 520 520 p++; 521 521 522 / / Don't forget to put old block (prevent memory leak)522 /* Don't forget to put old block (prevent memory leak) */ 523 523 block_put(p->block); 524 524 … … 546 546 int rc; 547 547 548 / / Load direct block 0 (index root)548 /* Load direct block 0 (index root) */ 549 549 uint32_t root_block_addr; 550 550 rc = ext4_filesystem_get_inode_data_block_index(inode_ref, 0, &root_block_addr); … … 561 561 } 562 562 563 / / Initialize hash info (compute hash value)563 /* Initialize hash info (compute hash value) */ 564 564 ext4_hash_info_t hinfo; 565 565 rc = ext4_directory_hinfo_init(&hinfo, root_block, fs->superblock, name_len, name); … … 569 569 } 570 570 571 / / Hardcoded number 2 means maximum height of index tree, specified in linux driver571 /* Hardcoded number 2 means maximum height of index tree, specified in linux driver */ 572 572 ext4_directory_dx_block_t dx_blocks[2]; 573 573 ext4_directory_dx_block_t *dx_block, *tmp; … … 579 579 580 580 do { 581 / / Load leaf block581 /* Load leaf block */ 582 582 uint32_t leaf_block_idx = ext4_directory_dx_entry_get_block(dx_block->position); 583 583 uint32_t leaf_block_addr; … … 593 593 } 594 594 595 / / Linear search inside block595 /* Linear search inside block */ 596 596 ext4_directory_entry_ll_t *res_dentry; 597 597 rc = ext4_directory_find_in_block(leaf_block, fs->superblock, name_len, name, &res_dentry); 598 598 599 / / Found => return it599 /* Found => return it */ 600 600 if (rc == EOK) { 601 601 result->block = leaf_block; … … 604 604 } 605 605 606 / / Not found, leave untouched606 /* Not found, leave untouched */ 607 607 block_put(leaf_block); 608 608 … … 611 611 } 612 612 613 / / check if the next block could be checked613 /* check if the next block could be checked */ 614 614 rc = ext4_directory_dx_next_block(inode_ref, hinfo.hash, dx_block, &dx_blocks[0]); 615 615 if (rc < 0) { … … 619 619 } while (rc == 1); 620 620 621 / / Entry not found621 /* Entry not found */ 622 622 rc = ENOENT; 623 623 624 624 cleanup: 625 625 626 / / The whole path must be released (preventing memory leak)626 /* The whole path must be released (preventing memory leak) */ 627 627 tmp = dx_blocks; 628 628 while (tmp <= dx_block) { … … 705 705 int rc = EOK; 706 706 707 / / Allocate buffer for directory entries707 /* Allocate buffer for directory entries */ 708 708 uint32_t block_size = 709 709 ext4_superblock_get_block_size(inode_ref->fs->superblock); … … 713 713 } 714 714 715 / / dot entry has the smallest size available715 /* dot entry has the smallest size available */ 716 716 uint32_t max_entry_count = block_size / sizeof(ext4_directory_dx_dot_entry_t); 717 717 718 / / Allocate sort entry718 /* Allocate sort entry */ 719 719 ext4_dx_sort_entry_t *sort_array = malloc(max_entry_count * sizeof(ext4_dx_sort_entry_t)); 720 720 if (sort_array == NULL) { … … 726 726 uint32_t real_size = 0; 727 727 728 / / Initialize hinfo728 /* Initialize hinfo */ 729 729 ext4_hash_info_t tmp_hinfo; 730 730 memcpy(&tmp_hinfo, hinfo, sizeof(ext4_hash_info_t)); 731 731 732 / / Load all valid entries to the buffer732 /* Load all valid entries to the buffer */ 733 733 ext4_directory_entry_ll_t *dentry = old_data_block->data; 734 734 void *entry_buffer_ptr = entry_buffer; 735 735 while ((void *)dentry < old_data_block->data + block_size) { 736 736 737 / / Read only valid entries737 /* Read only valid entries */ 738 738 if (ext4_directory_entry_ll_get_inode(dentry) != 0) { 739 739 … … 762 762 } 763 763 764 / / Sort all entries764 /* Sort all entries */ 765 765 qsort(sort_array, idx, sizeof(ext4_dx_sort_entry_t), 766 766 ext4_directory_dx_entry_comparator, NULL); 767 767 768 / / Allocate new block for store the second part of entries768 /* Allocate new block for store the second part of entries */ 769 769 uint32_t new_fblock; 770 770 uint32_t new_iblock; … … 776 776 } 777 777 778 / / Load new block778 /* Load new block */ 779 779 block_t *new_data_block_tmp; 780 780 rc = block_get(&new_data_block_tmp, inode_ref->fs->device, … … 786 786 } 787 787 788 // Distribute entries to two blocks (by size) 789 // Compute the half 788 /* Distribute entries to two blocks (by size) 789 * - compute the half 790 */ 790 791 uint32_t new_hash = 0; 791 792 uint32_t current_size = 0; … … 801 802 } 802 803 803 / / Check hash collision804 /* Check hash collision */ 804 805 uint32_t continued = 0; 805 806 if (new_hash == sort_array[mid-1].hash) { … … 810 811 void *ptr; 811 812 812 / / First part - to the old block813 /* First part - to the old block */ 813 814 for (uint32_t i = 0; i < mid; ++i) { 814 815 ptr = old_data_block->data + offset; … … 825 826 } 826 827 827 / / Second part - to the new block828 /* Second part - to the new block */ 828 829 offset = 0; 829 830 for (uint32_t i = mid; i < idx; ++i) { … … 841 842 } 842 843 843 / / Do some steps to finish operation844 /* Do some steps to finish operation */ 844 845 old_data_block->dirty = true; 845 846 new_data_block_tmp->dirty = true; … … 879 880 uint16_t leaf_count = ext4_directory_dx_countlimit_get_count(countlimit); 880 881 881 / / Check if is necessary to split index block882 /* Check if is necessary to split index block */ 882 883 if (leaf_limit == leaf_count) { 883 884 … … 894 895 ext4_directory_dx_countlimit_get_count(root_countlimit); 895 896 896 / / Linux limitation897 /* Linux limitation */ 897 898 if ((levels > 0) && (root_limit == root_count)) { 898 899 EXT4FS_DBG("Directory index is full"); … … 900 901 } 901 902 902 / / Add new block to directory903 /* Add new block to directory */ 903 904 uint32_t new_fblock; 904 905 uint32_t new_iblock; … … 909 910 } 910 911 911 / / load new block912 /* load new block */ 912 913 block_t * new_block; 913 914 rc = block_get(&new_block, inode_ref->fs->device, … … 923 924 inode_ref->fs->superblock); 924 925 925 / / Split leaf node926 /* Split leaf node */ 926 927 if (levels > 0) { 927 928 … … 931 932 ext4_directory_dx_entry_get_hash(entries + count_left); 932 933 933 / / Copy data to new node934 /* Copy data to new node */ 934 935 memcpy((void *) new_entries, (void *) (entries + count_left), 935 936 count_right * sizeof(ext4_directory_dx_entry_t)); 936 937 937 / / Initialize new node938 /* Initialize new node */ 938 939 ext4_directory_dx_countlimit_t *left_countlimit = 939 940 (ext4_directory_dx_countlimit_t *)entries; … … 948 949 ext4_directory_dx_countlimit_set_limit(right_countlimit, node_limit); 949 950 950 / / Which index block is target for new entry951 /* Which index block is target for new entry */ 951 952 uint32_t position_index = (dx_block->position - dx_block->entries); 952 953 if (position_index >= count_left) { … … 963 964 } 964 965 965 / / Finally insert new entry966 /* Finally insert new entry */ 966 967 ext4_directory_dx_insert_entry(dx_blocks, hash_right, new_iblock); 967 968 … … 970 971 } else { 971 972 972 / / Create second level index973 974 / / Copy data from root to child block973 /* Create second level index */ 974 975 /* Copy data from root to child block */ 975 976 memcpy((void *) new_entries, (void *) entries, 976 977 leaf_count * sizeof(ext4_directory_dx_entry_t)); … … 983 984 ext4_directory_dx_countlimit_set_limit(new_countlimit, node_limit); 984 985 985 / / Set values in root node986 /* Set values in root node */ 986 987 ext4_directory_dx_countlimit_t *new_root_countlimit = 987 988 (ext4_directory_dx_countlimit_t *)entries; … … 992 993 ((ext4_directory_dx_root_t *)dx_blocks[0].block->data)->info.indirect_levels = 1; 993 994 994 / / Add new entry to the path995 /* Add new entry to the path */ 995 996 dx_block = dx_blocks + 1; 996 997 dx_block->position = dx_block->position - entries + new_entries; … … 1017 1018 int rc2 = EOK; 1018 1019 1019 / / get direct block 0 (index root)1020 /* get direct block 0 (index root) */ 1020 1021 uint32_t root_block_addr; 1021 1022 rc = ext4_filesystem_get_inode_data_block_index(parent, 0, &root_block_addr); … … 1032 1033 } 1033 1034 1034 / / Initialize hinfo structure (mainly compute hash)1035 /* Initialize hinfo structure (mainly compute hash) */ 1035 1036 uint32_t name_len = strlen(name); 1036 1037 ext4_hash_info_t hinfo; … … 1042 1043 } 1043 1044 1044 / / Hardcoded number 2 means maximum height of index tree defined in linux1045 /* Hardcoded number 2 means maximum height of index tree defined in linux */ 1045 1046 ext4_directory_dx_block_t dx_blocks[2]; 1046 1047 ext4_directory_dx_block_t *dx_block, *dx_it; … … 1053 1054 1054 1055 1055 / / Try to insert to existing data block1056 /* Try to insert to existing data block */ 1056 1057 uint32_t leaf_block_idx = ext4_directory_dx_entry_get_block(dx_block->position); 1057 1058 uint32_t leaf_block_addr; … … 1068 1069 } 1069 1070 1070 / / Check if insert operation passed1071 /* Check if insert operation passed */ 1071 1072 rc = ext4_directory_try_insert_entry(fs->superblock, target_block, child, name, name_len); 1072 1073 if (rc == EOK) { … … 1074 1075 } 1075 1076 1076 // Check if there is needed to split index node 1077 // (and recursively also parent nodes) 1077 /* Check if there is needed to split index node 1078 * (and recursively also parent nodes) 1079 */ 1078 1080 rc = ext4_directory_dx_split_index(parent, dx_blocks, dx_block); 1079 1081 if (rc != EOK) { … … 1081 1083 } 1082 1084 1083 / / Split entries to two blocks (includes sorting by hash value)1085 /* Split entries to two blocks (includes sorting by hash value) */ 1084 1086 block_t *new_block = NULL; 1085 1087 rc = ext4_directory_dx_split_data(parent, &hinfo, target_block, dx_block, &new_block); … … 1089 1091 } 1090 1092 1091 / / Where to save new entry1093 /* Where to save new entry */ 1092 1094 uint32_t new_block_hash = ext4_directory_dx_entry_get_hash(dx_block->position + 1); 1093 1095 if (hinfo.hash >= new_block_hash) { … … 1097 1099 } 1098 1100 1099 / / Cleanup1101 /* Cleanup */ 1100 1102 rc = block_put(new_block); 1101 1103 if (rc != EOK) { … … 1104 1106 } 1105 1107 1106 / / Cleanup operations1108 /* Cleanup operations */ 1107 1109 1108 1110 release_target_index: -
uspace/lib/ext4/libext4_extent.c
r9a487cc r06d85e5 262 262 uint16_t entries_count = ext4_extent_header_get_entries_count(header); 263 263 264 / / Initialize bounds264 /* Initialize bounds */ 265 265 l = EXT4_EXTENT_FIRST_INDEX(header) + 1; 266 266 r = EXT4_EXTENT_FIRST_INDEX(header) + entries_count - 1; 267 267 268 / / Do binary search268 /* Do binary search */ 269 269 while (l <= r) { 270 270 m = l + (r - l) / 2; … … 277 277 } 278 278 279 / / Set output value279 /* Set output value */ 280 280 *index = l - 1; 281 281 } … … 296 296 297 297 if (entries_count == 0) { 298 / / this leaf is empty298 /* this leaf is empty */ 299 299 *extent = NULL; 300 300 return; 301 301 } 302 302 303 / / Initialize bounds303 /* Initialize bounds */ 304 304 l = EXT4_EXTENT_FIRST(header) + 1; 305 305 r = EXT4_EXTENT_FIRST(header) + entries_count - 1; 306 306 307 / / Do binary search307 /* Do binary search */ 308 308 while (l <= r) { 309 309 m = l + (r - l) / 2; … … 316 316 } 317 317 318 / / Set output value318 /* Set output value */ 319 319 *extent = l - 1; 320 320 } … … 334 334 int rc; 335 335 336 / / Compute bound defined by i-node size336 /* Compute bound defined by i-node size */ 337 337 uint64_t inode_size = ext4_inode_get_size( 338 338 inode_ref->fs->superblock, inode_ref->inode); … … 343 343 uint32_t last_idx = (inode_size - 1) / block_size; 344 344 345 / / Check if requested iblock is not over size of i-node345 /* Check if requested iblock is not over size of i-node */ 346 346 if (iblock > last_idx) { 347 347 *fblock = 0; … … 351 351 block_t* block = NULL; 352 352 353 / / Walk through extent tree353 /* Walk through extent tree */ 354 354 ext4_extent_header_t *header = ext4_inode_get_extent_header(inode_ref->inode); 355 355 356 // EXT4FS_DBG("inode = \%u", inode_ref->index);357 // EXT4FS_DBG("count = \%u", ext4_extent_header_get_entries_count(header));358 359 356 while (ext4_extent_header_get_depth(header) != 0) { 360 357 361 / / Search index in node358 /* Search index in node */ 362 359 ext4_extent_index_t *index; 363 360 ext4_extent_binsearch_idx(header, &index, iblock); 364 361 365 / / Load child node and set values for the next iteration362 /* Load child node and set values for the next iteration */ 366 363 uint64_t child = ext4_extent_index_get_leaf(index); 367 364 … … 378 375 } 379 376 380 / / Search extent in the leaf block377 /* Search extent in the leaf block */ 381 378 ext4_extent_t* extent = NULL; 382 379 ext4_extent_binsearch(header, &extent, iblock); 383 380 384 / / Prevent empty leaf381 /* Prevent empty leaf */ 385 382 if (extent == NULL) { 386 383 *fblock = 0; 387 384 } else { 388 385 389 // EXT4FS_DBG("required = \%u, first = \%u, start = \%u, count = \%u", iblock, ext4_extent_get_first_block(extent), (uint32_t)ext4_extent_get_start(extent), ext4_extent_get_block_count(extent)); 390 391 // Compute requested physical block address 386 /* Compute requested physical block address */ 392 387 uint32_t phys_block; 393 388 uint32_t first = ext4_extent_get_first_block(extent); 394 389 phys_block = ext4_extent_get_start(extent) + iblock - first; 395 390 396 // phys_block = ext4_extent_get_start(extent) + iblock;397 // phys_block -= ext4_extent_get_first_block(extent);398 399 391 *fblock = phys_block; 400 392 } 401 393 402 / / Cleanup394 /* Cleanup */ 403 395 if (block != NULL) { 404 396 block_put(block); … … 431 423 ext4_extent_path_t *tmp_path; 432 424 433 / / Added 2 for possible tree growing425 /* Added 2 for possible tree growing */ 434 426 tmp_path = malloc(sizeof(ext4_extent_path_t) * (depth + 2)); 435 427 if (tmp_path == NULL) { … … 437 429 } 438 430 439 / / Initialize structure for algorithm start431 /* Initialize structure for algorithm start */ 440 432 tmp_path[0].block = inode_ref->block; 441 433 tmp_path[0].header = eh; 442 434 443 / / Walk through the extent tree435 /* Walk through the extent tree */ 444 436 uint16_t pos = 0; 445 437 while (ext4_extent_header_get_depth(eh) != 0) { 446 438 447 / / Search index in index node by iblock439 /* Search index in index node by iblock */ 448 440 ext4_extent_binsearch_idx(tmp_path[pos].header, &tmp_path[pos].index, iblock); 449 441 … … 453 445 assert(tmp_path[pos].index != NULL); 454 446 455 / / Load information for the next iteration447 /* Load information for the next iteration */ 456 448 uint64_t fblock = ext4_extent_index_get_leaf(tmp_path[pos].index); 457 449 … … 474 466 tmp_path[pos].index = NULL; 475 467 476 / / Find extent in the leaf node468 /* Find extent in the leaf node */ 477 469 ext4_extent_binsearch(tmp_path[pos].header, &tmp_path[pos].extent, iblock); 478 470 … … 482 474 483 475 cleanup: 484 // Put loaded blocks 485 // From 1 -> 0 is a block with inode data 476 /* Put loaded blocks 477 * From 1: 0 is a block with inode data 478 */ 486 479 for (uint16_t i = 1; i < tmp_path->depth; ++i) { 487 480 if (tmp_path[i].block) { … … 490 483 } 491 484 492 / / Destroy temporary data structure485 /* Destroy temporary data structure */ 493 486 free(tmp_path); 494 487 … … 507 500 int rc; 508 501 509 / / Compute number of the first physical block to release502 /* Compute number of the first physical block to release */ 510 503 uint64_t start = ext4_extent_get_start(extent); 511 504 uint16_t block_count = ext4_extent_get_block_count(extent); … … 549 542 if (ext4_extent_header_get_depth(header)) { 550 543 551 / / The node is non-leaf, do recursion544 /* The node is non-leaf, do recursion */ 552 545 553 546 ext4_extent_index_t *idx = EXT4_EXTENT_FIRST_INDEX(header); 554 547 555 / / Release all subbranches548 /* Release all subbranches */ 556 549 for (uint32_t i = 0; i < ext4_extent_header_get_entries_count(header); ++i, ++idx) { 557 550 rc = ext4_extent_release_branch(inode_ref, idx); … … 563 556 } else { 564 557 565 / / Leaf node reached558 /* Leaf node reached */ 566 559 ext4_extent_t *ext = EXT4_EXTENT_FIRST(header); 567 560 568 / / Release all extents and stop recursion561 /* Release all extents and stop recursion */ 569 562 570 563 for (uint32_t i = 0; i < ext4_extent_header_get_entries_count(header); ++i, ++ext) { … … 577 570 } 578 571 579 / / Release data block where the node was stored572 /* Release data block where the node was stored */ 580 573 581 574 rc = block_put(block); … … 600 593 int rc = EOK; 601 594 602 / / Find the first extent to modify595 /* Find the first extent to modify */ 603 596 ext4_extent_path_t *path; 604 597 rc = ext4_extent_find_extent(inode_ref, iblock_from, &path); … … 607 600 } 608 601 609 / / Jump to last item of the path (extent)602 /* Jump to last item of the path (extent) */ 610 603 ext4_extent_path_t *path_ptr = path; 611 604 while (path_ptr->depth != 0) { … … 615 608 assert(path_ptr->extent != NULL); 616 609 617 / / First extent maybe released partially610 /* First extent maybe released partially */ 618 611 uint32_t first_iblock = ext4_extent_get_first_block(path_ptr->extent); 619 612 uint32_t first_fblock = ext4_extent_get_start(path_ptr->extent) + iblock_from - first_iblock; … … 625 618 ext4_extent_get_start(path_ptr->extent) - first_fblock); 626 619 627 / / Release all blocks620 /* Release all blocks */ 628 621 rc = ext4_balloc_free_blocks(inode_ref, first_fblock, delete_count); 629 622 if (rc != EOK) { … … 631 624 } 632 625 633 / / Correct counter626 /* Correct counter */ 634 627 block_count -= delete_count; 635 628 ext4_extent_set_block_count(path_ptr->extent, block_count); 636 629 637 / / Initialize the following loop630 /* Initialize the following loop */ 638 631 uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header); 639 632 ext4_extent_t *tmp_ext = path_ptr->extent + 1; 640 633 ext4_extent_t *stop_ext = EXT4_EXTENT_FIRST(path_ptr->header) + entries; 641 634 642 / / If first extent empty, release it635 /* If first extent empty, release it */ 643 636 if (block_count == 0) { 644 637 entries--; 645 638 } 646 639 647 / / Release all successors of the first extent in the same node640 /* Release all successors of the first extent in the same node */ 648 641 while (tmp_ext < stop_ext) { 649 642 first_fblock = ext4_extent_get_start(tmp_ext); … … 662 655 path_ptr->block->dirty = true; 663 656 664 / / If leaf node is empty, parent entry must be modified657 /* If leaf node is empty, parent entry must be modified */ 665 658 bool remove_parent_record = false; 666 659 667 / / Don't release root block (including inode data) !!!660 /* Don't release root block (including inode data) !!! */ 668 661 if ((path_ptr != path) && (entries == 0)) { 669 662 rc = ext4_balloc_free_block(inode_ref, path_ptr->block->lba); … … 674 667 } 675 668 676 / / Jump to the parent669 /* Jump to the parent */ 677 670 --path_ptr; 678 671 679 / / release all successors in all tree levels672 /* Release all successors in all tree levels */ 680 673 while (path_ptr >= path) { 681 674 entries = ext4_extent_header_get_entries_count(path_ptr->header); … … 684 677 EXT4_EXTENT_FIRST_INDEX(path_ptr->header) + entries; 685 678 686 / / Correct entries count because of changes in the previous iteration679 /* Correct entries count because of changes in the previous iteration */ 687 680 if (remove_parent_record) { 688 681 entries--; 689 682 } 690 683 691 / / Iterate over all entries and release the whole subtrees684 /* Iterate over all entries and release the whole subtrees */ 692 685 while (index < stop) { 693 686 rc = ext4_extent_release_branch(inode_ref, index); … … 702 695 path_ptr->block->dirty = true; 703 696 704 / / Free the node if it is empty697 /* Free the node if it is empty */ 705 698 if ((entries == 0) && (path_ptr != path)) { 706 699 rc = ext4_balloc_free_block(inode_ref, path_ptr->block->lba); … … 709 702 } 710 703 711 / / Mark parent to be checked704 /* Mark parent to be checked */ 712 705 remove_parent_record = true; 713 706 } else { … … 720 713 721 714 cleanup: 722 // Put loaded blocks 723 // From 1 -> 0 is a block with inode data 715 /* Put loaded blocks 716 * starting from 1: 0 is a block with inode data 717 */ 724 718 for (uint16_t i = 1; i <= path->depth; ++i) { 725 719 if (path[i].block) { … … 728 722 } 729 723 730 / / Destroy temporary data structure724 /* Destroy temporary data structure */ 731 725 free(path); 732 726 … … 748 742 uint32_t iblock) 749 743 { 750 EXT4FS_DBG("");751 744 int rc; 752 745 … … 756 749 uint16_t limit = ext4_extent_header_get_max_entries_count(path_ptr->header); 757 750 758 / / Trivial way - no splitting751 /* Trivial way - no splitting */ 759 752 if (entries < limit) { 760 EXT4FS_DBG("adding extent entry");761 753 762 754 ext4_extent_header_set_entries_count(path_ptr->header, entries + 1); … … 773 765 ext4_superblock_get_block_size(inode_ref->fs->superblock); 774 766 775 / / Trivial tree - grow (extents were in root node)767 /* Trivial tree - grow (extents were in root node) */ 776 768 if (path_ptr == path) { 777 769 … … 793 785 memset(block->data, 0, block_size); 794 786 795 / / Move data from root to the new block787 /* Move data from root to the new block */ 796 788 memcpy(block->data, inode_ref->inode->blocks, 797 789 EXT4_INODE_BLOCKS * sizeof(uint32_t)); … … 810 802 ext4_extent_header_set_max_entries_count(path_ptr->header, limit); 811 803 812 / / Modify root (in inode)804 /* Modify root (in inode) */ 813 805 path->depth = 1; 814 806 path->extent = NULL; … … 829 821 } 830 822 831 assert(false); 832 833 // start splitting 823 // TODO !!! 824 // assert(false); 825 826 /* Start splitting */ 834 827 uint32_t fblock = 0; 835 828 while (path_ptr > path) { … … 849 842 } 850 843 851 / / Init block844 /* Init block */ 852 845 memset(block->data, 0, block_size); 853 846 854 / / Not modified847 /* Not modified */ 855 848 block_put(path_ptr->block); 856 849 path_ptr->block = block; … … 867 860 } 868 861 869 / / If splitting reached root node862 /* If splitting reached root node */ 870 863 if (path_ptr == path) { 871 864 … … 887 880 memset(block->data, 0, block_size); 888 881 889 / / Move data from root to the new block882 /* Move data from root to the new block */ 890 883 memcpy(block->data, inode_ref->inode->blocks, 891 884 EXT4_INODE_BLOCKS * sizeof(uint32_t)); … … 904 897 ext4_extent_header_set_max_entries_count(path_ptr->header, limit); 905 898 906 / / Modify root (in inode)899 /* Modify root (in inode) */ 907 900 path->depth = 1; 908 901 path->extent = NULL; … … 940 933 uint32_t *iblock, uint32_t *fblock) 941 934 { 942 EXT4FS_DBG("");943 935 int rc = EOK; 944 936 … … 947 939 uint32_t block_size = ext4_superblock_get_block_size(sb); 948 940 949 / / Calculate number of new logical block941 /* Calculate number of new logical block */ 950 942 uint32_t new_block_idx = 0; 951 943 if (inode_size > 0) { … … 956 948 } 957 949 958 / / Load the nearest leaf (with extent)950 /* Load the nearest leaf (with extent) */ 959 951 ext4_extent_path_t *path; 960 952 rc = ext4_extent_find_extent(inode_ref, new_block_idx, &path); … … 963 955 } 964 956 965 / / Jump to last item of the path (extent)957 /* Jump to last item of the path (extent) */ 966 958 ext4_extent_path_t *path_ptr = path; 967 959 while (path_ptr->depth != 0) { … … 969 961 } 970 962 971 / / Add new extent to the node if not present963 /* Add new extent to the node if not present */ 972 964 if (path_ptr->extent == NULL) { 973 965 goto append_extent; … … 980 972 if (block_count < block_limit) { 981 973 982 / / There is space for new block in the extent974 /* There is space for new block in the extent */ 983 975 984 976 if (block_count == 0) { 985 977 986 / / Existing extent is empty978 /* Existing extent is empty */ 987 979 988 980 rc = ext4_balloc_alloc_block(inode_ref, &phys_block); … … 991 983 } 992 984 993 / / Initialize extent985 /* Initialize extent */ 994 986 ext4_extent_set_first_block(path_ptr->extent, new_block_idx); 995 987 ext4_extent_set_start(path_ptr->extent, phys_block); 996 988 ext4_extent_set_block_count(path_ptr->extent, 1); 997 989 998 / / Update i-node990 /* Update i-node */ 999 991 ext4_inode_set_size(inode_ref->inode, inode_size + block_size); 1000 992 inode_ref->dirty = true; … … 1005 997 } else { 1006 998 1007 / / Existing extent contains some blocks999 /* Existing extent contains some blocks */ 1008 1000 1009 1001 phys_block = ext4_extent_get_start(path_ptr->extent); 1010 1002 phys_block += ext4_extent_get_block_count(path_ptr->extent); 1011 1003 1012 / / Check if the following block is free for allocation1004 /* Check if the following block is free for allocation */ 1013 1005 bool free; 1014 1006 rc = ext4_balloc_try_alloc_block(inode_ref, phys_block, &free); … … 1018 1010 1019 1011 if (! free) { 1020 / / target is not free, new block must be appended to new extent1012 /* target is not free, new block must be appended to new extent */ 1021 1013 goto append_extent; 1022 1014 } 1023 1015 1024 1016 1025 / / Update extent1017 /* Update extent */ 1026 1018 ext4_extent_set_block_count(path_ptr->extent, block_count + 1); 1027 1019 1028 / / Update i-node1020 /* Update i-node */ 1029 1021 ext4_inode_set_size(inode_ref->inode, inode_size + block_size); 1030 1022 inode_ref->dirty = true; … … 1036 1028 } 1037 1029 1038 / / Append new extent to the tree1030 /* Append new extent to the tree */ 1039 1031 append_extent: 1040 1032 1041 1033 phys_block = 0; 1042 1034 1043 / / Allocate new data block1035 /* Allocate new data block */ 1044 1036 rc = ext4_balloc_alloc_block(inode_ref, &phys_block); 1045 1037 if (rc != EOK) { … … 1048 1040 } 1049 1041 1050 / / Append extent for new block (includes tree splitting if needed)1042 /* Append extent for new block (includes tree splitting if needed) */ 1051 1043 rc = ext4_extent_append_extent(inode_ref, path, &path_ptr, new_block_idx); 1052 1044 if (rc != EOK) { … … 1055 1047 } 1056 1048 1057 / / Initialize newly created extent1049 /* Initialize newly created extent */ 1058 1050 ext4_extent_set_block_count(path_ptr->extent, 1); 1059 1051 ext4_extent_set_first_block(path_ptr->extent, new_block_idx); 1060 1052 ext4_extent_set_start(path_ptr->extent, phys_block); 1061 1053 1062 / / Update i-node1054 /* Update i-node */ 1063 1055 ext4_inode_set_size(inode_ref->inode, inode_size + block_size); 1064 1056 inode_ref->dirty = true; … … 1068 1060 1069 1061 finish: 1070 / / Set return values1062 /* Set return values */ 1071 1063 *iblock = new_block_idx; 1072 1064 *fblock = phys_block; 1073 1065 1074 // Put loaded blocks 1075 // From 1 -> 0 is a block with inode data 1066 /* Put loaded blocks 1067 * starting from 1: 0 is a block with inode data 1068 */ 1076 1069 for (uint16_t i = 1; i <= path->depth; ++i) { 1077 1070 if (path[i].block) { … … 1080 1073 } 1081 1074 1082 / / Destroy temporary data structure1075 /* Destroy temporary data structure */ 1083 1076 free(path); 1084 1077 -
uspace/lib/ext4/libext4_filesystem.c
r9a487cc r06d85e5 53 53 fs->device = service_id; 54 54 55 / / Initialize block library (4096 is size of communication channel)55 /* Initialize block library (4096 is size of communication channel) */ 56 56 rc = block_init(EXCHANGE_SERIALIZE, fs->device, 4096); 57 57 if (rc != EOK) { … … 60 60 } 61 61 62 / / Read superblock from device to memory62 /* Read superblock from device to memory */ 63 63 ext4_superblock_t *temp_superblock; 64 64 rc = ext4_superblock_read_direct(fs->device, &temp_superblock); … … 69 69 } 70 70 71 / / Read block size from superblock and check71 /* Read block size from superblock and check */ 72 72 uint32_t block_size = ext4_superblock_get_block_size(temp_superblock); 73 73 if (block_size > EXT4_MAX_BLOCK_SIZE) { … … 77 77 } 78 78 79 / / Initialize block caching by libblock79 /* Initialize block caching by libblock */ 80 80 rc = block_cache_init(service_id, block_size, 0, CACHE_MODE_WT); 81 81 if (rc != EOK) { … … 85 85 } 86 86 87 / / Compute limits for indirect block levels87 /* Compute limits for indirect block levels */ 88 88 uint32_t block_ids_per_block = block_size / sizeof(uint32_t); 89 89 fs->inode_block_limits[0] = EXT4_INODE_DIRECT_BLOCK_COUNT; … … 96 96 } 97 97 98 / / Return loaded superblock98 /* Return loaded superblock */ 99 99 fs->superblock = temp_superblock; 100 100 … … 108 108 } 109 109 110 / / Mark system as mounted110 /* Mark system as mounted */ 111 111 ext4_superblock_set_state(fs->superblock, EXT4_SUPERBLOCK_STATE_ERROR_FS); 112 112 rc = ext4_superblock_write_direct(fs->device, fs->superblock); … … 131 131 int rc = EOK; 132 132 133 / / Write the superblock to the device133 /* Write the superblock to the device */ 134 134 ext4_superblock_set_state(fs->superblock, EXT4_SUPERBLOCK_STATE_VALID_FS); 135 135 rc = ext4_superblock_write_direct(fs->device, fs->superblock); 136 136 137 / / Release memory space for superblock137 /* Release memory space for superblock */ 138 138 free(fs->superblock); 139 139 140 / / Finish work with block library140 /* Finish work with block library */ 141 141 block_fini(fs->device); 142 142 … … 155 155 int rc; 156 156 157 / / Check superblock157 /* Check superblock */ 158 158 rc = ext4_superblock_check_sanity(fs->superblock); 159 159 if (rc != EOK) { … … 176 176 int ext4_filesystem_check_features(ext4_filesystem_t *fs, bool *read_only) 177 177 { 178 / / Feature flags are present only in higher revisions178 /* Feature flags are present only in higher revisions */ 179 179 if (ext4_superblock_get_rev_level(fs->superblock) == 0) { 180 180 *read_only = false; … … 182 182 } 183 183 184 // Check incompatible features - if filesystem has some, 185 // volume can't be mounted 184 /* Check incompatible features - if filesystem has some, 185 * volume can't be mounted 186 */ 186 187 uint32_t incompatible_features; 187 188 incompatible_features = ext4_superblock_get_features_incompatible(fs->superblock); … … 191 192 } 192 193 193 // Check read-only features, if filesystem has some, 194 // volume can be mount only in read-only mode 194 /* Check read-only features, if filesystem has some, 195 * volume can be mount only in read-only mode 196 */ 195 197 uint32_t compatible_read_only; 196 198 compatible_read_only = ext4_superblock_get_features_read_only(fs->superblock); … … 216 218 int rc; 217 219 218 / / Allocate memory for new structure220 /* Allocate memory for new structure */ 219 221 ext4_block_group_ref_t *newref = malloc(sizeof(ext4_block_group_ref_t)); 220 222 if (newref == NULL) { … … 222 224 } 223 225 224 / / Compute number of descriptors, that fits in one data block226 /* Compute number of descriptors, that fits in one data block */ 225 227 uint32_t descriptors_per_block = ext4_superblock_get_block_size(fs->superblock) 226 228 / ext4_superblock_get_desc_size(fs->superblock); 227 229 228 / / Block group descriptor table starts at the next block after superblock230 /* Block group descriptor table starts at the next block after superblock */ 229 231 aoff64_t block_id = ext4_superblock_get_first_data_block(fs->superblock) + 1; 230 232 231 / / Find the block containing the descriptor we are looking for233 /* Find the block containing the descriptor we are looking for */ 232 234 block_id += bgid / descriptors_per_block; 233 235 uint32_t offset = (bgid % descriptors_per_block) * ext4_superblock_get_desc_size(fs->superblock); 234 236 235 / / Load block with descriptors237 /* Load block with descriptors */ 236 238 rc = block_get(&newref->block, fs->device, block_id, 0); 237 239 if (rc != EOK) { … … 240 242 } 241 243 242 / / Inititialize in-memory representation244 /* Inititialize in-memory representation */ 243 245 newref->block_group = newref->block->data + offset; 244 246 newref->fs = fs; … … 263 265 ext4_block_group_t *bg) 264 266 { 265 / / If checksum not supported, 0 will be returned267 /* If checksum not supported, 0 will be returned */ 266 268 uint16_t crc = 0; 267 269 268 / / Compute the checksum only if the filesystem supports it270 /* Compute the checksum only if the filesystem supports it */ 269 271 if (ext4_superblock_has_feature_read_only(sb, EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { 270 272 … … 274 276 uint32_t offset = (uint32_t)(checksum - base); 275 277 276 / / Convert block group index to little endian278 /* Convert block group index to little endian */ 277 279 uint32_t le_group = host2uint32_t_le(bgid); 278 280 279 / / Initialization281 /* Initialization */ 280 282 crc = crc16(~0, sb->uuid, sizeof(sb->uuid)); 281 283 282 / / Include index of block group284 /* Include index of block group */ 283 285 crc = crc16(crc, (uint8_t *)&le_group, sizeof(le_group)); 284 286 285 / / Compute crc from the first part (stop before checksum field)287 /* Compute crc from the first part (stop before checksum field) */ 286 288 crc = crc16(crc, (uint8_t *)bg, offset); 287 289 288 / / Skip checksum290 /* Skip checksum */ 289 291 offset += sizeof(bg->checksum); 290 292 291 / / Checksum of the rest of block group descriptor293 /* Checksum of the rest of block group descriptor */ 292 294 if ((ext4_superblock_has_feature_incompatible(sb, EXT4_FEATURE_INCOMPAT_64BIT)) && 293 295 offset < ext4_superblock_get_desc_size(sb)) { … … 310 312 int rc; 311 313 312 / / Check if reference modified314 /* Check if reference modified */ 313 315 if (ref->dirty) { 314 316 315 / / Compute new checksum of block group317 /* Compute new checksum of block group */ 316 318 uint16_t checksum = ext4_filesystem_bg_checksum( 317 319 ref->fs->superblock, ref->index, ref->block_group); 318 320 ext4_block_group_set_checksum(ref->block_group, checksum); 319 321 320 / / Mark block dirty for writing changes to physical device322 /* Mark block dirty for writing changes to physical device */ 321 323 ref->block->dirty = true; 322 324 } 323 325 324 / / Put back block, that contains block group descriptor326 /* Put back block, that contains block group descriptor */ 325 327 rc = block_put(ref->block); 326 328 free(ref); … … 341 343 int rc; 342 344 343 / / Allocate memory for new structure345 /* Allocate memory for new structure */ 344 346 ext4_inode_ref_t *newref = malloc(sizeof(ext4_inode_ref_t)); 345 347 if (newref == NULL) { … … 347 349 } 348 350 349 / / Compute number of i-nodes, that fits in one data block351 /* Compute number of i-nodes, that fits in one data block */ 350 352 uint32_t inodes_per_group = 351 353 ext4_superblock_get_inodes_per_group(fs->superblock); 352 354 353 /* 354 * inode numbers are 1-based, but it is simpler to work with 0-based 355 /* Inode numbers are 1-based, but it is simpler to work with 0-based 355 356 * when computing indices 356 357 */ … … 359 360 uint32_t offset_in_group = index % inodes_per_group; 360 361 361 / / Load block group, where i-node is located362 /* Load block group, where i-node is located */ 362 363 ext4_block_group_ref_t *bg_ref; 363 364 rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref); … … 367 368 } 368 369 369 / / Load block address, where i-node table is located370 /* Load block address, where i-node table is located */ 370 371 uint32_t inode_table_start = ext4_block_group_get_inode_table_first_block( 371 372 bg_ref->block_group, fs->superblock); 372 373 373 / / Put back block group reference (not needed more)374 /* Put back block group reference (not needed more) */ 374 375 rc = ext4_filesystem_put_block_group_ref(bg_ref); 375 376 if (rc != EOK) { … … 378 379 } 379 380 380 / / Compute position of i-node in the block group381 /* Compute position of i-node in the block group */ 381 382 uint16_t inode_size = ext4_superblock_get_inode_size(fs->superblock); 382 383 uint32_t block_size = ext4_superblock_get_block_size(fs->superblock); 383 384 uint32_t byte_offset_in_group = offset_in_group * inode_size; 384 385 385 / / Compute block address386 /* Compute block address */ 386 387 aoff64_t block_id = inode_table_start + (byte_offset_in_group / block_size); 387 388 rc = block_get(&newref->block, fs->device, block_id, 0); … … 391 392 } 392 393 393 / / Compute position of i-node in the data block394 /* Compute position of i-node in the data block */ 394 395 uint32_t offset_in_block = byte_offset_in_group % block_size; 395 396 newref->inode = newref->block->data + offset_in_block; 396 397 397 / / We need to store the original value of index in the reference398 /* We need to store the original value of index in the reference */ 398 399 newref->index = index + 1; 399 400 newref->fs = fs; … … 414 415 int rc; 415 416 416 / / Check if reference modified417 /* Check if reference modified */ 417 418 if (ref->dirty) { 418 419 419 / / Mark block dirty for writing changes to physical device420 /* Mark block dirty for writing changes to physical device */ 420 421 ref->block->dirty = true; 421 422 } 422 423 423 / / Put back block, that contains i-node424 /* Put back block, that contains i-node */ 424 425 rc = block_put(ref->block); 425 426 free(ref); … … 440 441 int rc; 441 442 442 / / Check if newly allocated i-node will be a directory443 /* Check if newly allocated i-node will be a directory */ 443 444 bool is_dir = false; 444 445 if (flags & L_DIRECTORY) { … … 446 447 } 447 448 448 / / Allocate inode by allocation algorithm449 /* Allocate inode by allocation algorithm */ 449 450 uint32_t index; 450 451 rc = ext4_ialloc_alloc_inode(fs, &index, is_dir); … … 453 454 } 454 455 455 / / Load i-node from on-disk i-node table456 /* Load i-node from on-disk i-node table */ 456 457 rc = ext4_filesystem_get_inode_ref(fs, index, inode_ref); 457 458 if (rc != EOK) { … … 460 461 } 461 462 462 / / Initialize i-node463 /* Initialize i-node */ 463 464 ext4_inode_t *inode = (*inode_ref)->inode; 464 465 465 466 if (is_dir) { 466 467 ext4_inode_set_mode(fs->superblock, inode, EXT4_INODE_MODE_DIRECTORY); 467 ext4_inode_set_links_count(inode, 1); / / '.' entry468 ext4_inode_set_links_count(inode, 1); /* '.' entry */ 468 469 } else { 469 470 ext4_inode_set_mode(fs->superblock, inode, EXT4_INODE_MODE_FILE); … … 482 483 ext4_inode_set_generation(inode, 0); 483 484 484 / / Reset blocks array485 /* Reset blocks array */ 485 486 for (uint32_t i = 0; i < EXT4_INODE_BLOCKS; i++) { 486 487 inode->blocks[i] = 0; 487 488 } 488 489 489 / / Initialize extents if needed490 /* Initialize extents if needed */ 490 491 if (ext4_superblock_has_feature_incompatible( 491 492 fs->superblock, EXT4_FEATURE_INCOMPAT_EXTENTS)) { … … 493 494 ext4_inode_set_flag(inode, EXT4_INODE_FLAG_EXTENTS); 494 495 495 / / Initialize extent root header496 /* Initialize extent root header */ 496 497 ext4_extent_header_t *header = ext4_inode_get_extent_header(inode); 497 498 ext4_extent_header_set_depth(header, 0); … … 522 523 ext4_filesystem_t *fs = inode_ref->fs; 523 524 524 / / For extents must be data block destroyed by other way525 /* For extents must be data block destroyed by other way */ 525 526 if (ext4_superblock_has_feature_incompatible( 526 527 fs->superblock, EXT4_FEATURE_INCOMPAT_EXTENTS) && 527 528 ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS)) { 528 529 529 / / Data structures are released during truncate operation...530 /* Data structures are released during truncate operation... */ 530 531 goto finish; 531 532 } 532 533 533 / / Release all indirect (no data) blocks534 535 / / 1) Single indirect534 /* Release all indirect (no data) blocks */ 535 536 /* 1) Single indirect */ 536 537 uint32_t fblock = ext4_inode_get_indirect_block(inode_ref->inode, 0); 537 538 if (fblock != 0) { … … 548 549 uint32_t count = block_size / sizeof(uint32_t); 549 550 550 / / 2) Double indirect551 /* 2) Double indirect */ 551 552 fblock = ext4_inode_get_indirect_block(inode_ref->inode, 1); 552 553 if (fblock != 0) { … … 579 580 580 581 581 / / 3) Tripple indirect582 /* 3) Tripple indirect */ 582 583 block_t *subblock; 583 584 fblock = ext4_inode_get_indirect_block(inode_ref->inode, 2); … … 637 638 finish: 638 639 639 / / Mark inode dirty for writing to the physical device640 /* Mark inode dirty for writing to the physical device */ 640 641 inode_ref->dirty = true; 641 642 642 / / Free inode by allocator643 /* Free inode by allocator */ 643 644 if (ext4_inode_is_type(fs->superblock, inode_ref->inode, 644 645 EXT4_INODE_MODE_DIRECTORY)) { … … 667 668 ext4_superblock_t *sb = inode_ref->fs->superblock; 668 669 669 / / Check flags, if i-node can be truncated670 /* Check flags, if i-node can be truncated */ 670 671 if (! ext4_inode_can_truncate(sb, inode_ref->inode)) { 671 672 return EINVAL; 672 673 } 673 674 674 / / If sizes are equal, nothing has to be done.675 /* If sizes are equal, nothing has to be done. */ 675 676 aoff64_t old_size = ext4_inode_get_size(sb, inode_ref->inode); 676 677 if (old_size == new_size) { … … 678 679 } 679 680 680 / / It's not suppported to make the larger file by truncate operation681 /* It's not suppported to make the larger file by truncate operation */ 681 682 if (old_size < new_size) { 682 683 return EINVAL; 683 684 } 684 685 685 / / Compute how many blocks will be released686 /* Compute how many blocks will be released */ 686 687 aoff64_t size_diff = old_size - new_size; 687 688 uint32_t block_size = ext4_superblock_get_block_size(sb); … … 700 701 ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS)) { 701 702 702 / / Extents require special operation703 /* Extents require special operation */ 703 704 704 705 rc = ext4_extent_release_blocks_from(inode_ref, … … 709 710 } else { 710 711 711 / / Release data blocks from the end of file712 713 / / Starting from 1 because of logical blocks are numbered from 0712 /* Release data blocks from the end of file */ 713 714 /* Starting from 1 because of logical blocks are numbered from 0 */ 714 715 for (uint32_t i = 1; i <= diff_blocks_count; ++i) { 715 716 rc = ext4_filesystem_release_inode_block(inode_ref, old_blocks_count - i); … … 720 721 } 721 722 722 / / Update i-node723 /* Update i-node */ 723 724 ext4_inode_set_size(inode_ref->inode, new_size); 724 725 inode_ref->dirty = true; … … 741 742 ext4_filesystem_t *fs = inode_ref->fs; 742 743 743 / / For empty file is situation simple744 /* For empty file is situation simple */ 744 745 if (ext4_inode_get_size(fs->superblock, inode_ref->inode) == 0) { 745 746 *fblock = 0; … … 749 750 uint32_t current_block; 750 751 751 / / Handle i-node using extents752 /* Handle i-node using extents */ 752 753 if (ext4_superblock_has_feature_incompatible(fs->superblock, EXT4_FEATURE_INCOMPAT_EXTENTS) && 753 754 ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS)) { … … 766 767 ext4_inode_t *inode = inode_ref->inode; 767 768 768 / / Direct block are read directly from array in i-node structure769 /* Direct block are read directly from array in i-node structure */ 769 770 if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) { 770 771 current_block = ext4_inode_get_direct_block(inode, (uint32_t)iblock); … … 773 774 } 774 775 775 / / Determine indirection level of the target block776 /* Determine indirection level of the target block */ 776 777 int level = -1; 777 778 for (int i = 1; i < 4; i++) { … … 786 787 } 787 788 788 / / Compute offsets for the topmost level789 /* Compute offsets for the topmost level */ 789 790 aoff64_t block_offset_in_level = iblock - fs->inode_block_limits[level-1]; 790 791 current_block = ext4_inode_get_indirect_block(inode, level-1); 791 792 uint32_t offset_in_block = block_offset_in_level / fs->inode_blocks_per_level[level-1]; 792 793 793 / / Sparse file794 /* Sparse file */ 794 795 if (current_block == 0) { 795 796 *fblock = 0; … … 804 805 while (level > 0) { 805 806 806 / / Load indirect block807 /* Load indirect block */ 807 808 rc = block_get(&block, fs->device, current_block, 0); 808 809 if (rc != EOK) { … … 810 811 } 811 812 812 / / Read block address from indirect block813 /* Read block address from indirect block */ 813 814 current_block = uint32_t_le2host(((uint32_t*)block->data)[offset_in_block]); 814 815 815 / / Put back indirect block untouched816 /* Put back indirect block untouched */ 816 817 rc = block_put(block); 817 818 if (rc != EOK) { … … 819 820 } 820 821 821 / / Check for sparse file822 /* Check for sparse file */ 822 823 if (current_block == 0) { 823 824 *fblock = 0; … … 825 826 } 826 827 827 / / Jump to the next level828 /* Jump to the next level */ 828 829 level -= 1; 829 830 830 / / Termination condition - we have address of data block loaded831 /* Termination condition - we have address of data block loaded */ 831 832 if (level == 0) { 832 833 break; 833 834 } 834 835 835 / / Visit the next level836 /* Visit the next level */ 836 837 block_offset_in_level %= fs->inode_blocks_per_level[level]; 837 838 offset_in_block = block_offset_in_level / fs->inode_blocks_per_level[level-1]; … … 857 858 ext4_filesystem_t *fs = inode_ref->fs; 858 859 859 / / Handle inode using extents860 /* Handle inode using extents */ 860 861 if (ext4_superblock_has_feature_compatible(fs->superblock, EXT4_FEATURE_INCOMPAT_EXTENTS) && 861 862 ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_EXTENTS)) { 862 / / not reachable !!!863 /* not reachable !!! */ 863 864 return ENOTSUP; 864 865 } 865 866 866 / / Handle simple case when we are dealing with direct reference867 /* Handle simple case when we are dealing with direct reference */ 867 868 if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) { 868 869 ext4_inode_set_direct_block(inode_ref->inode, (uint32_t)iblock, fblock); … … 871 872 } 872 873 873 / / Determine the indirection level needed to get the desired block874 /* Determine the indirection level needed to get the desired block */ 874 875 int level = -1; 875 876 for (int i = 1; i < 4; i++) { … … 886 887 uint32_t block_size = ext4_superblock_get_block_size(fs->superblock); 887 888 888 / / Compute offsets for the topmost level889 /* Compute offsets for the topmost level */ 889 890 aoff64_t block_offset_in_level = iblock - fs->inode_block_limits[level-1]; 890 891 uint32_t current_block = ext4_inode_get_indirect_block(inode_ref->inode, level-1); … … 894 895 block_t *block, *new_block; 895 896 896 / / Is needed to allocate indirect block on the i-node level897 /* Is needed to allocate indirect block on the i-node level */ 897 898 if (current_block == 0) { 898 899 899 / / Allocate new indirect block900 /* Allocate new indirect block */ 900 901 rc = ext4_balloc_alloc_block(inode_ref, &new_block_addr); 901 902 if (rc != EOK) { … … 903 904 } 904 905 905 / / Update i-node906 /* Update i-node */ 906 907 ext4_inode_set_indirect_block(inode_ref->inode, level - 1, new_block_addr); 907 908 inode_ref->dirty = true; 908 909 909 / / Load newly allocated block910 /* Load newly allocated block */ 910 911 rc = block_get(&new_block, fs->device, new_block_addr, BLOCK_FLAGS_NOREAD); 911 912 if (rc != EOK) { … … 914 915 } 915 916 916 / / Initialize new block917 /* Initialize new block */ 917 918 memset(new_block->data, 0, block_size); 918 919 new_block->dirty = true; 919 920 920 / / Put back the allocated block921 /* Put back the allocated block */ 921 922 rc = block_put(new_block); 922 923 if (rc != EOK) { … … 941 942 if ((level > 1) && (current_block == 0)) { 942 943 943 / / Allocate new block944 /* Allocate new block */ 944 945 rc = ext4_balloc_alloc_block(inode_ref, &new_block_addr); 945 946 if (rc != EOK) { … … 948 949 } 949 950 950 / / Load newly allocated block951 /* Load newly allocated block */ 951 952 rc = block_get(&new_block, fs->device, new_block_addr, BLOCK_FLAGS_NOREAD); 952 953 if (rc != EOK) { … … 955 956 } 956 957 957 / / Initialize allocated block958 /* Initialize allocated block */ 958 959 memset(new_block->data, 0, block_size); 959 960 new_block->dirty = true; … … 965 966 } 966 967 967 / / Write block address to the parent968 /* Write block address to the parent */ 968 969 ((uint32_t*)block->data)[offset_in_block] = host2uint32_t_le(new_block_addr); 969 970 block->dirty = true; … … 971 972 } 972 973 973 / / Will be finished, write the fblock address974 /* Will be finished, write the fblock address */ 974 975 if (level == 1) { 975 976 ((uint32_t*)block->data)[offset_in_block] = host2uint32_t_le(fblock); … … 1014 1015 ext4_filesystem_t *fs = inode_ref->fs; 1015 1016 1016 / / EXTENTS are handled otherwise = there is not support in this function1017 /* EXTENTS are handled otherwise = there is not support in this function */ 1017 1018 assert(! (ext4_superblock_has_feature_incompatible(fs->superblock, 1018 1019 EXT4_FEATURE_INCOMPAT_EXTENTS) && … … 1021 1022 ext4_inode_t *inode = inode_ref->inode; 1022 1023 1023 / / Handle simple case when we are dealing with direct reference1024 /* Handle simple case when we are dealing with direct reference */ 1024 1025 if (iblock < EXT4_INODE_DIRECT_BLOCK_COUNT) { 1025 1026 fblock = ext4_inode_get_direct_block(inode, iblock); 1026 / / Sparse file1027 /* Sparse file */ 1027 1028 if (fblock == 0) { 1028 1029 return EOK; … … 1034 1035 1035 1036 1036 / / Determine the indirection level needed to get the desired block1037 /* Determine the indirection level needed to get the desired block */ 1037 1038 int level = -1; 1038 1039 for (int i = 1; i < 4; i++) { … … 1047 1048 } 1048 1049 1049 / / Compute offsets for the topmost level1050 /* Compute offsets for the topmost level */ 1050 1051 aoff64_t block_offset_in_level = iblock - fs->inode_block_limits[level-1]; 1051 1052 uint32_t current_block = ext4_inode_get_indirect_block(inode, level-1); … … 1064 1065 current_block = uint32_t_le2host(((uint32_t*)block->data)[offset_in_block]); 1065 1066 1066 / / Set zero if physical data block address found1067 /* Set zero if physical data block address found */ 1067 1068 if (level == 1) { 1068 1069 ((uint32_t*)block->data)[offset_in_block] = host2uint32_t_le(0); … … 1095 1096 } 1096 1097 1097 / / Physical block is not referenced, it can be released1098 /* Physical block is not referenced, it can be released */ 1098 1099 1099 1100 return ext4_balloc_free_block(inode_ref, fblock); … … 1113 1114 int rc; 1114 1115 1115 / / Handle extents separately1116 /* Handle extents separately */ 1116 1117 if (ext4_superblock_has_feature_incompatible( 1117 1118 inode_ref->fs->superblock, EXT4_FEATURE_INCOMPAT_EXTENTS) && … … 1124 1125 ext4_superblock_t *sb = inode_ref->fs->superblock; 1125 1126 1126 / / Compute next block index and allocate data block1127 /* Compute next block index and allocate data block */ 1127 1128 uint64_t inode_size = ext4_inode_get_size(sb, inode_ref->inode); 1128 1129 uint32_t block_size = ext4_superblock_get_block_size(sb); 1129 1130 1130 / / Align size i-node size1131 /* Align size i-node size */ 1131 1132 if ((inode_size % block_size) != 0) { 1132 1133 inode_size += block_size - (inode_size % block_size); 1133 1134 } 1134 1135 1135 / / Logical blocks are numbered from 01136 /* Logical blocks are numbered from 0 */ 1136 1137 uint32_t new_block_idx = inode_size / block_size; 1137 1138 1138 / / Allocate new physical block1139 /* Allocate new physical block */ 1139 1140 uint32_t phys_block; 1140 1141 rc = ext4_balloc_alloc_block(inode_ref, &phys_block); … … 1143 1144 } 1144 1145 1145 / / Add physical block address to the i-node1146 /* Add physical block address to the i-node */ 1146 1147 rc = ext4_filesystem_set_inode_data_block_index(inode_ref, new_block_idx, phys_block); 1147 1148 if (rc != EOK) { … … 1150 1151 } 1151 1152 1152 / / Update i-node1153 /* Update i-node */ 1153 1154 ext4_inode_set_size(inode_ref->inode, inode_size + block_size); 1154 1155 inode_ref->dirty = true; … … 1173 1174 inode_ref->fs->superblock); 1174 1175 1175 / / Deletion time is used for holding next item of the list1176 /* Deletion time is used for holding next item of the list */ 1176 1177 ext4_inode_set_deletion_time(inode_ref->inode, next_orphan); 1177 1178 1178 / / Head of the list is in the superblock1179 /* Head of the list is in the superblock */ 1179 1180 ext4_superblock_set_last_orphan( 1180 1181 inode_ref->fs->superblock, inode_ref->index); … … 1196 1197 int rc; 1197 1198 1198 / / Get head of the linked list1199 /* Get head of the linked list */ 1199 1200 uint32_t last_orphan = ext4_superblock_get_last_orphan( 1200 1201 inode_ref->fs->superblock); … … 1210 1211 uint32_t next_orphan = ext4_inode_get_deletion_time(current->inode); 1211 1212 1212 / / Check if the head is the target1213 /* Check if the head is the target */ 1213 1214 if (last_orphan == inode_ref->index) { 1214 1215 ext4_superblock_set_last_orphan(inode_ref->fs->superblock, next_orphan); 1215 // ext4_inode_set_deletion_time(inode_ref->inode, 0);1216 // inode_ref->dirty = true;1217 1216 return EOK; 1218 1217 } … … 1220 1219 bool found = false; 1221 1220 1222 / / Walk thourgh the linked list1221 /* Walk thourgh the linked list */ 1223 1222 while (next_orphan != 0) { 1224 1223 1225 / / Found?1224 /* Found? */ 1226 1225 if (next_orphan == inode_ref->index) { 1227 1226 next_orphan = ext4_inode_get_deletion_time(inode_ref->inode); 1228 1227 ext4_inode_set_deletion_time(current->inode, next_orphan); 1229 // ext4_inode_set_deletion_time(inode_ref->inode, 0);1230 // inode_ref->dirty = true;1231 1228 current->dirty = true; 1232 1229 found = true; -
uspace/lib/ext4/libext4_ialloc.c
r9a487cc r06d85e5 94 94 ext4_superblock_t *sb = fs->superblock; 95 95 96 / / Compute index of block group and load it96 /* Compute index of block group and load it */ 97 97 uint32_t block_group = ext4_ialloc_get_bgid_of_inode(sb, index); 98 98 … … 103 103 } 104 104 105 / / Load i-node bitmap105 /* Load i-node bitmap */ 106 106 uint32_t bitmap_block_addr = ext4_block_group_get_inode_bitmap( 107 107 bg_ref->block_group, sb); … … 112 112 } 113 113 114 / / Free i-node in the bitmap114 /* Free i-node in the bitmap */ 115 115 uint32_t index_in_group = ext4_ialloc_inode2index_in_group(sb, index); 116 116 ext4_bitmap_free_bit(bitmap_block->data, index_in_group); 117 117 bitmap_block->dirty = true; 118 118 119 / / Put back the block with bitmap119 /* Put back the block with bitmap */ 120 120 rc = block_put(bitmap_block); 121 121 if (rc != EOK) { 122 / / Error in saving bitmap122 /* Error in saving bitmap */ 123 123 ext4_filesystem_put_block_group_ref(bg_ref); 124 124 return rc; 125 125 } 126 126 127 / / If released i-node is a directory, decrement used directories count127 /* If released i-node is a directory, decrement used directories count */ 128 128 if (is_dir) { 129 129 uint32_t bg_used_dirs = ext4_block_group_get_used_dirs_count( … … 134 134 } 135 135 136 / / Update block group free inodes count136 /* Update block group free inodes count */ 137 137 uint32_t free_inodes = ext4_block_group_get_free_inodes_count( 138 138 bg_ref->block_group, sb); … … 141 141 sb, free_inodes); 142 142 143 / / Set unused i-nodes count if supported143 /* Set unused i-nodes count if supported */ 144 144 if (ext4_block_group_has_flag(bg_ref->block_group, EXT4_BLOCK_GROUP_INODE_UNINIT)) { 145 145 uint32_t unused_inodes = ext4_block_group_get_itable_unused( … … 151 151 bg_ref->dirty = true; 152 152 153 / / Put back the modified block group153 /* Put back the modified block group */ 154 154 rc = ext4_filesystem_put_block_group_ref(bg_ref); 155 155 if (rc != EOK) { … … 157 157 } 158 158 159 / / Update superblock free inodes count159 /* Update superblock free inodes count */ 160 160 uint32_t sb_free_inodes = ext4_superblock_get_free_inodes_count(sb); 161 161 sb_free_inodes++; … … 185 185 uint32_t avg_free_inodes = sb_free_inodes / bg_count; 186 186 187 / / Try to find free i-node in all block groups187 /* Try to find free i-node in all block groups */ 188 188 while (bgid < bg_count) { 189 189 190 / / Load block group to check190 /* Load block group to check */ 191 191 ext4_block_group_ref_t *bg_ref; 192 192 rc = ext4_filesystem_get_block_group_ref(fs, bgid, &bg_ref); … … 197 197 ext4_block_group_t *bg = bg_ref->block_group; 198 198 199 / / Read necessary values for algorithm199 /* Read necessary values for algorithm */ 200 200 uint32_t free_blocks = ext4_block_group_get_free_blocks_count(bg, sb); 201 201 uint32_t free_inodes = ext4_block_group_get_free_inodes_count(bg, sb); 202 202 uint32_t used_dirs = ext4_block_group_get_used_dirs_count(bg, sb); 203 203 204 / / Check if this block group is good candidate for allocation204 /* Check if this block group is good candidate for allocation */ 205 205 if ((free_inodes >= avg_free_inodes) && (free_blocks > 0)) { 206 206 207 / / Load block with bitmap207 /* Load block with bitmap */ 208 208 uint32_t bitmap_block_addr = ext4_block_group_get_inode_bitmap( 209 209 bg_ref->block_group, sb); … … 216 216 } 217 217 218 / / Try to allocate i-node in the bitmap218 /* Try to allocate i-node in the bitmap */ 219 219 uint32_t inodes_in_group = ext4_superblock_get_inodes_in_group(sb, bgid); 220 220 uint32_t index_in_group; … … 222 222 bitmap_block->data, 0, &index_in_group, inodes_in_group); 223 223 224 / / Block group has not any free i-node224 /* Block group has not any free i-node */ 225 225 if (rc == ENOSPC) { 226 226 block_put(bitmap_block); … … 229 229 } 230 230 231 / / Free i-node found, save the bitmap231 /* Free i-node found, save the bitmap */ 232 232 bitmap_block->dirty = true; 233 233 … … 237 237 } 238 238 239 / / Modify filesystem counters239 /* Modify filesystem counters */ 240 240 free_inodes--; 241 241 ext4_block_group_set_free_inodes_count(bg, sb, free_inodes); 242 242 243 / / Decrement unused i-nodes counter if supported243 /* Decrement unused i-nodes counter if supported */ 244 244 if (ext4_block_group_has_flag(bg, EXT4_BLOCK_GROUP_INODE_UNINIT)) { 245 245 uint16_t unused_inodes = ext4_block_group_get_itable_unused(bg, sb); … … 248 248 } 249 249 250 / / Increment used directories counter250 /* Increment used directories counter */ 251 251 if (is_dir) { 252 252 used_dirs++; … … 254 254 } 255 255 256 / / Save modified block group256 /* Save modified block group */ 257 257 bg_ref->dirty = true; 258 258 … … 263 263 } 264 264 265 / / Update superblock265 /* Update superblock */ 266 266 sb_free_inodes--; 267 267 ext4_superblock_set_free_inodes_count(sb, sb_free_inodes); 268 268 269 / / Compute the absolute i-nodex number269 /* Compute the absolute i-nodex number */ 270 270 *index = ext4_ialloc_index_in_group2inode(sb, index_in_group, bgid); 271 271 … … 274 274 } 275 275 276 / / Block group not modified, put it and jump to the next block group276 /* Block group not modified, put it and jump to the next block group */ 277 277 ext4_filesystem_put_block_group_ref(bg_ref); 278 278 ++bgid; -
uspace/lib/ext4/libext4_inode.c
r9a487cc r06d85e5 266 266 if (ext4_superblock_has_feature_read_only(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) { 267 267 268 / / 48-bit field268 /* 48-bit field */ 269 269 uint64_t count = ((uint64_t)uint16_t_le2host(inode->osd2.linux2.blocks_high)) << 32 | 270 270 uint32_t_le2host(inode->blocks_count_lo); … … 292 292 uint64_t count) 293 293 { 294 / / 32-bit maximum294 /* 32-bit maximum */ 295 295 uint64_t max = 0; 296 296 max = ~max >> 32; … … 303 303 } 304 304 305 / / Check if there can be used huge files (many blocks)305 /* Check if there can be used huge files (many blocks) */ 306 306 if (!ext4_superblock_has_feature_read_only(sb, EXT4_FEATURE_RO_COMPAT_HUGE_FILE)) { 307 307 return EINVAL; 308 308 } 309 309 310 / / 48-bit maximum310 /* 48-bit maximum */ 311 311 max = 0; 312 312 max = ~max >> 16; -
uspace/lib/ext4/libext4_superblock.c
r9a487cc r06d85e5 981 981 int rc; 982 982 983 / / Allocated memory for superblock structure983 /* Allocated memory for superblock structure */ 984 984 void *data = malloc(EXT4_SUPERBLOCK_SIZE); 985 985 if (data == NULL) { … … 987 987 } 988 988 989 / / Read data from block device989 /* Read data from block device */ 990 990 rc = block_read_bytes_direct(service_id, EXT4_SUPERBLOCK_OFFSET, 991 991 EXT4_SUPERBLOCK_SIZE, data); … … 996 996 } 997 997 998 / / Set output value998 /* Set output value */ 999 999 (*sb) = data; 1000 1000 … … 1014 1014 uint32_t phys_block_size; 1015 1015 1016 / / Load physical block size from block device1016 /* Load physical block size from block device */ 1017 1017 rc = block_get_bsize(service_id, &phys_block_size); 1018 1018 if (rc != EOK) { … … 1020 1020 } 1021 1021 1022 / / Compute address of the first block1022 /* Compute address of the first block */ 1023 1023 uint64_t first_block = EXT4_SUPERBLOCK_OFFSET / phys_block_size; 1024 / / Compute number of block to write1024 /* Compute number of block to write */ 1025 1025 uint32_t block_count = EXT4_SUPERBLOCK_SIZE / phys_block_size; 1026 1026 1027 / / Check alignment1027 /* Check alignment */ 1028 1028 if (EXT4_SUPERBLOCK_SIZE % phys_block_size) { 1029 1029 block_count++; 1030 1030 } 1031 1031 1032 / / Write data1032 /* Write data */ 1033 1033 return block_write_direct(service_id, first_block, block_count, sb); 1034 1034 -
uspace/srv/fs/ext4fs/ext4fs_ops.c
r9a487cc r06d85e5 76 76 } ext4fs_node_t; 77 77 78 / / Forward declarations of auxiliary functions78 /* Forward declarations of auxiliary functions */ 79 79 80 80 static int ext4fs_read_directory(ipc_callid_t, aoff64_t, size_t, … … 87 87 static int ext4fs_node_put_core(ext4fs_node_t *); 88 88 89 / / Forward declarations of EXT4 libfs operations.89 /* Forward declarations of EXT4 libfs operations. */ 90 90 91 91 static int ext4fs_root_get(fs_node_t **, service_id_t); … … 106 106 static service_id_t ext4fs_service_get(fs_node_t *node); 107 107 108 / / Static variables108 /* Static variables */ 109 109 110 110 static LIST_INITIALIZE(instance_list); … … 250 250 } 251 251 252 / / Try to find entry252 /* Try to find entry */ 253 253 ext4_directory_search_result_t result; 254 254 rc = ext4_directory_find_entry(&result, eparent->inode_ref, component); … … 261 261 } 262 262 263 / / Load node from search result263 /* Load node from search result */ 264 264 uint32_t inode = ext4_directory_entry_ll_get_inode(result.dentry); 265 265 rc = ext4fs_node_get_core(rfn, eparent->instance, inode); … … 268 268 } 269 269 270 / / Destroy search result structure270 /* Destroy search result structure */ 271 271 rc = ext4_directory_destroy_result(&result); 272 272 if (rc != EOK) { … … 330 330 } 331 331 332 / / Prepare new enode332 /* Prepare new enode */ 333 333 enode = malloc(sizeof(ext4fs_node_t)); 334 334 if (enode == NULL) { … … 337 337 } 338 338 339 / / Prepare new fs_node and initialize339 /* Prepare new fs_node and initialize */ 340 340 fs_node_t *fs_node = malloc(sizeof(fs_node_t)); 341 341 if (fs_node == NULL) { … … 346 346 fs_node_initialize(fs_node); 347 347 348 / / Load i-node from filesystem348 /* Load i-node from filesystem */ 349 349 ext4_inode_ref_t *inode_ref; 350 350 rc = ext4_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref); … … 356 356 } 357 357 358 / / Initialize enode358 /* Initialize enode */ 359 359 enode->inode_ref = inode_ref; 360 360 enode->instance = inst; … … 391 391 enode->instance->open_nodes_count--; 392 392 393 / / Put inode back in filesystem393 /* Put inode back in filesystem */ 394 394 rc = ext4_filesystem_put_inode_ref(enode->inode_ref); 395 395 if (rc != EOK) { … … 397 397 } 398 398 399 / / Destroy data structure399 /* Destroy data structure */ 400 400 free(enode->fs_node); 401 401 free(enode); … … 414 414 int ext4fs_node_open(fs_node_t *fn) 415 415 { 416 / / Stateless operation416 /* Stateless operation */ 417 417 return EOK; 418 418 } … … 460 460 int rc; 461 461 462 / / Allocate enode462 /* Allocate enode */ 463 463 ext4fs_node_t *enode; 464 464 enode = malloc(sizeof(ext4fs_node_t)); … … 467 467 } 468 468 469 / / Allocate fs_node469 /* Allocate fs_node */ 470 470 fs_node_t *fs_node; 471 471 fs_node = malloc(sizeof(fs_node_t)); … … 475 475 } 476 476 477 / / Load instance477 /* Load instance */ 478 478 ext4fs_instance_t *inst; 479 479 rc = ext4fs_instance_get(service_id, &inst); … … 484 484 } 485 485 486 / / Allocate new i-node in filesystem486 /* Allocate new i-node in filesystem */ 487 487 ext4_inode_ref_t *inode_ref; 488 488 rc = ext4_filesystem_alloc_inode(inst->filesystem, &inode_ref, flags); … … 493 493 } 494 494 495 / / Do some interconnections in references495 /* Do some interconnections in references */ 496 496 enode->inode_ref = inode_ref; 497 497 enode->instance = inst; … … 530 530 int rc; 531 531 532 / / If directory, check for children532 /* If directory, check for children */ 533 533 bool has_children; 534 534 rc = ext4fs_has_children(&has_children, fn); … … 546 546 ext4_inode_ref_t *inode_ref = enode->inode_ref; 547 547 548 / / Release data blocks548 /* Release data blocks */ 549 549 rc = ext4_filesystem_truncate_inode(inode_ref, 0); 550 550 if (rc != EOK) { … … 553 553 } 554 554 555 // Handle orphans 555 /* Handle orphans */ 556 // TODO this code should be deleted 556 557 // ext4_filesystem_t *fs = enode->instance->filesystem; 557 558 // uint32_t rev_level = ext4_superblock_get_rev_level(fs->superblock); … … 564 565 // } 565 566 566 // TODO set real deletion time when it will be supported, 567 // temporary set fake time 567 // TODO set real deletion time when it will be supported, temporary set fake time 568 568 // time_t now = time(NULL); 569 569 ext4_inode_set_deletion_time(inode_ref->inode, 0xdeadbeef); 570 570 inode_ref->dirty = true; 571 571 572 / / Free inode572 /* Free inode */ 573 573 rc = ext4_filesystem_free_inode(inode_ref); 574 574 if (rc != EOK) { … … 592 592 int rc; 593 593 594 / / Check maximum name length594 /* Check maximum name length */ 595 595 if (strlen(name) > EXT4_DIRECTORY_FILENAME_LEN) { 596 596 return ENAMETOOLONG; … … 600 600 ext4_filesystem_t *fs = parent->instance->filesystem; 601 601 602 / / Add entry to parent directory602 /* Add entry to parent directory */ 603 603 rc = ext4_directory_add_entry(parent->inode_ref, name, child->inode_ref); 604 604 if (rc != EOK) { … … 606 606 } 607 607 608 / / Fill new dir -> add '.' and '..' entries608 /* Fill new dir -> add '.' and '..' entries */ 609 609 if (ext4_inode_is_type(fs->superblock, child->inode_ref->inode, EXT4_INODE_MODE_DIRECTORY)) { 610 610 … … 622 622 } 623 623 624 / / Initialize directory index if supported624 /* Initialize directory index if supported */ 625 625 if (ext4_superblock_has_feature_compatible( 626 626 fs->superblock, EXT4_FEATURE_COMPAT_DIR_INDEX)) { … … 670 670 } 671 671 672 / / Cannot unlink non-empty node672 /* Cannot unlink non-empty node */ 673 673 if (has_children) { 674 674 return ENOTEMPTY; 675 675 } 676 676 677 / / Remove entry from parent directory677 /* Remove entry from parent directory */ 678 678 ext4_inode_ref_t *parent = EXT4FS_NODE(pfn)->inode_ref; 679 679 rc = ext4_directory_remove_entry(parent, name); … … 682 682 } 683 683 684 / / Decrement links count684 /* Decrement links count */ 685 685 ext4_inode_ref_t * child_inode_ref = EXT4FS_NODE(cfn)->inode_ref; 686 686 … … 688 688 lnk_count--; 689 689 690 / / If directory - handle links from parent690 /* If directory - handle links from parent */ 691 691 if (lnk_count <= 1 && ext4fs_is_directory(cfn)) { 692 692 … … 744 744 ext4_filesystem_t *fs = enode->instance->filesystem; 745 745 746 / / Check if node is directory746 /* Check if node is directory */ 747 747 if (!ext4_inode_is_type(fs->superblock, enode->inode_ref->inode, 748 748 EXT4_INODE_MODE_DIRECTORY)) { … … 830 830 } 831 831 832 / / For regular files return real links count832 /* For regular files return real links count */ 833 833 return lnkcnt; 834 834 } … … 1055 1055 } 1056 1056 1057 / / Load i-node1057 /* Load i-node */ 1058 1058 ext4_inode_ref_t *inode_ref; 1059 1059 rc = ext4_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref); … … 1063 1063 } 1064 1064 1065 / / Read from i-node by type1065 /* Read from i-node by type */ 1066 1066 if (ext4_inode_is_type(inst->filesystem->superblock, inode_ref->inode, 1067 1067 EXT4_INODE_MODE_FILE)) { … … 1183 1183 } 1184 1184 1185 / / Prepare return values1185 /* Prepare return values */ 1186 1186 if (found) { 1187 1187 *rbytes = next - pos; … … 1317 1317 uint32_t block_size = ext4_superblock_get_block_size(fs->superblock); 1318 1318 1319 / / Prevent writing to more than one block1319 /* Prevent writing to more than one block */ 1320 1320 uint32_t bytes = min(len, block_size - (pos % block_size)); 1321 1321 … … 1328 1328 uint32_t fblock; 1329 1329 1330 / / Load inode1330 /* Load inode */ 1331 1331 ext4_inode_ref_t *inode_ref = enode->inode_ref; 1332 1332 rc = ext4_filesystem_get_inode_data_block_index(inode_ref, iblock, &fblock); … … 1337 1337 } 1338 1338 1339 / / Check for sparse file1339 /* Check for sparse file */ 1340 1340 if (fblock == 0) { 1341 1341 … … 1375 1375 } 1376 1376 1377 / / Load target block1377 /* Load target block */ 1378 1378 block_t *write_block; 1379 1379 rc = block_get(&write_block, service_id, fblock, flags); … … 1402 1402 } 1403 1403 1404 / / Do some counting1404 /* Do some counting */ 1405 1405 uint32_t old_inode_size = ext4_inode_get_size(fs->superblock, inode_ref->inode); 1406 1406 if (pos + bytes > old_inode_size) {
Note:
See TracChangeset
for help on using the changeset viewer.