Changeset a35b458 in mainline for uspace/lib/ext4/src/directory.c
- Timestamp:
- 2018-03-02T20:10:49Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f1380b7
- Parents:
- 3061bc1
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-02-28 17:38:31)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-02 20:10:49)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/src/directory.c
r3061bc1 ra35b458 110 110 return ((uint16_t)de->name_length_high) << 8 | 111 111 ((uint16_t)de->name_length); 112 112 113 113 return de->name_length; 114 114 … … 126 126 { 127 127 de->name_length = (length << 8) >> 8; 128 128 129 129 if ((ext4_superblock_get_rev_level(sb) == 0) && 130 130 (ext4_superblock_get_minor_rev_level(sb) < 5)) 131 131 de->name_length_high = length >> 8; 132 132 133 133 /* Else do nothing */ 134 134 } … … 148 148 (ext4_superblock_get_minor_rev_level(sb) >= 5)) 149 149 return de->inode_type; 150 150 151 151 return EXT4_DIRECTORY_FILETYPE_UNKNOWN; 152 152 } … … 165 165 (ext4_superblock_get_minor_rev_level(sb) >= 5)) 166 166 de->inode_type = type; 167 167 168 168 /* Else do nothing */ 169 169 } … … 190 190 it->current_offset = 0; 191 191 it->current_block = NULL; 192 192 193 193 return ext4_directory_iterator_seek(it, pos); 194 194 } … … 204 204 { 205 205 assert(it->current != NULL); 206 206 207 207 uint16_t skip = ext4_directory_entry_ll_get_entry_length(it->current); 208 208 209 209 return ext4_directory_iterator_seek(it, it->current_offset + skip); 210 210 } … … 224 224 uint64_t size = ext4_inode_get_size(it->inode_ref->fs->superblock, 225 225 it->inode_ref->inode); 226 226 227 227 /* The iterator is not valid until we seek to the desired position */ 228 228 it->current = NULL; 229 229 230 230 /* Are we at the end? */ 231 231 if (pos >= size) { … … 233 233 errno_t rc = block_put(it->current_block); 234 234 it->current_block = NULL; 235 235 236 236 if (rc != EOK) 237 237 return rc; 238 238 } 239 239 240 240 it->current_offset = pos; 241 241 return EOK; 242 242 } 243 243 244 244 /* Compute next block address */ 245 245 uint32_t block_size = … … 247 247 aoff64_t current_block_idx = it->current_offset / block_size; 248 248 aoff64_t next_block_idx = pos / block_size; 249 249 250 250 /* 251 251 * If we don't have a block or are moving accross block boundary, … … 257 257 errno_t rc = block_put(it->current_block); 258 258 it->current_block = NULL; 259 259 260 260 if (rc != EOK) 261 261 return rc; 262 262 } 263 263 264 264 uint32_t next_block_phys_idx; 265 265 errno_t rc = ext4_filesystem_get_inode_data_block_index(it->inode_ref, … … 267 267 if (rc != EOK) 268 268 return rc; 269 269 270 270 rc = block_get(&it->current_block, it->inode_ref->fs->device, 271 271 next_block_phys_idx, BLOCK_FLAGS_NONE); … … 275 275 } 276 276 } 277 277 278 278 it->current_offset = pos; 279 279 280 280 return ext4_directory_iterator_set(it, block_size); 281 281 } … … 293 293 { 294 294 it->current = NULL; 295 295 296 296 uint32_t offset_in_block = it->current_offset % block_size; 297 297 298 298 /* Ensure proper alignment */ 299 299 if ((offset_in_block % 4) != 0) 300 300 return EIO; 301 301 302 302 /* Ensure that the core of the entry does not overflow the block */ 303 303 if (offset_in_block > block_size - 8) 304 304 return EIO; 305 305 306 306 ext4_directory_entry_ll_t *entry = 307 307 it->current_block->data + offset_in_block; 308 308 309 309 /* Ensure that the whole entry does not overflow the block */ 310 310 uint16_t length = ext4_directory_entry_ll_get_entry_length(entry); 311 311 if (offset_in_block + length > block_size) 312 312 return EIO; 313 313 314 314 /* Ensure the name length is not too large */ 315 315 if (ext4_directory_entry_ll_get_name_length( 316 316 it->inode_ref->fs->superblock, entry) > length-8) 317 317 return EIO; 318 318 319 319 /* Everything OK - "publish" the entry */ 320 320 it->current = entry; … … 335 335 it->inode_ref = NULL; 336 336 it->current = NULL; 337 337 338 338 if (it->current_block) 339 339 return block_put(it->current_block); 340 340 341 341 return EOK; 342 342 } … … 359 359 uint32_t block_size = ext4_superblock_get_block_size(sb); 360 360 assert(entry_len <= block_size); 361 361 362 362 /* Set basic attributes */ 363 363 ext4_directory_entry_ll_set_inode(entry, child->index); 364 364 ext4_directory_entry_ll_set_entry_length(entry, entry_len); 365 365 ext4_directory_entry_ll_set_name_length(sb, entry, name_len); 366 366 367 367 /* Write name */ 368 368 memcpy(entry->name, name, name_len); 369 369 370 370 /* Set type of entry */ 371 371 if (ext4_inode_is_type(sb, child->inode, EXT4_INODE_MODE_DIRECTORY)) … … 390 390 { 391 391 ext4_filesystem_t *fs = parent->fs; 392 392 393 393 /* Index adding (if allowed) */ 394 394 if ((ext4_superblock_has_feature_compatible(fs->superblock, … … 405 405 parent->dirty = true; 406 406 } 407 407 408 408 /* Linear algorithm */ 409 409 410 410 uint32_t iblock = 0; 411 411 uint32_t fblock = 0; … … 413 413 uint32_t inode_size = ext4_inode_get_size(fs->superblock, parent->inode); 414 414 uint32_t total_blocks = inode_size / block_size; 415 415 416 416 uint32_t name_len = str_size(name); 417 417 418 418 /* Find block, where is space for new entry and try to add */ 419 419 bool success = false; … … 423 423 if (rc != EOK) 424 424 return rc; 425 425 426 426 block_t *block; 427 427 rc = block_get(&block, fs->device, fblock, BLOCK_FLAGS_NONE); 428 428 if (rc != EOK) 429 429 return rc; 430 430 431 431 /* If adding is successful, function can finish */ 432 432 rc = ext4_directory_try_insert_entry(fs->superblock, block, … … 434 434 if (rc == EOK) 435 435 success = true; 436 436 437 437 rc = block_put(block); 438 438 if (rc != EOK) 439 439 return rc; 440 440 441 441 if (success) 442 442 return EOK; 443 443 } 444 444 445 445 /* No free block found - needed to allocate next data block */ 446 446 447 447 iblock = 0; 448 448 fblock = 0; … … 450 450 if (rc != EOK) 451 451 return rc; 452 452 453 453 /* Load new block */ 454 454 block_t *new_block; … … 456 456 if (rc != EOK) 457 457 return rc; 458 458 459 459 /* Fill block with zeroes */ 460 460 memset(new_block->data, 0, block_size); … … 462 462 ext4_directory_write_entry(fs->superblock, block_entry, block_size, 463 463 child, name, name_len); 464 464 465 465 /* Save new block */ 466 466 new_block->dirty = true; 467 467 rc = block_put(new_block); 468 468 469 469 return rc; 470 470 } … … 483 483 { 484 484 uint32_t name_len = str_size(name); 485 485 486 486 ext4_superblock_t *sb = parent->fs->superblock; 487 487 488 488 /* Index search */ 489 489 if ((ext4_superblock_has_feature_compatible(sb, … … 492 492 errno_t rc = ext4_directory_dx_find_entry(result, parent, name_len, 493 493 name); 494 494 495 495 /* Check if index is not corrupted */ 496 496 if (rc != EXT4_ERR_BAD_DX_DIR) { 497 497 if (rc != EOK) 498 498 return rc; 499 499 500 500 return EOK; 501 501 } 502 502 503 503 /* Needed to clear dir index flag if corrupted */ 504 504 ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX); 505 505 parent->dirty = true; 506 506 } 507 507 508 508 /* Linear algorithm */ 509 509 510 510 uint32_t iblock; 511 511 uint32_t fblock; … … 513 513 uint32_t inode_size = ext4_inode_get_size(sb, parent->inode); 514 514 uint32_t total_blocks = inode_size / block_size; 515 515 516 516 /* Walk through all data blocks */ 517 517 for (iblock = 0; iblock < total_blocks; ++iblock) { … … 521 521 if (rc != EOK) 522 522 return rc; 523 523 524 524 /* Load data block */ 525 525 block_t *block; … … 527 527 if (rc != EOK) 528 528 return rc; 529 529 530 530 /* Try to find entry in block */ 531 531 ext4_directory_entry_ll_t *res_entry; … … 537 537 return EOK; 538 538 } 539 539 540 540 /* Entry not found - put block and continue to the next block */ 541 541 542 542 rc = block_put(block); 543 543 if (rc != EOK) 544 544 return rc; 545 545 } 546 546 547 547 /* Entry was not found */ 548 548 549 549 result->block = NULL; 550 550 result->dentry = NULL; 551 551 552 552 return ENOENT; 553 553 } … … 567 567 EXT4_INODE_MODE_DIRECTORY)) 568 568 return ENOTDIR; 569 569 570 570 /* Try to find entry */ 571 571 ext4_directory_search_result_t result; … … 573 573 if (rc != EOK) 574 574 return rc; 575 575 576 576 /* Invalidate entry */ 577 577 ext4_directory_entry_ll_set_inode(result.dentry, 0); 578 578 579 579 /* Store entry position in block */ 580 580 uint32_t pos = (void *) result.dentry - result.block->data; 581 581 582 582 /* 583 583 * If entry is not the first in block, it must be merged … … 586 586 if (pos != 0) { 587 587 uint32_t offset = 0; 588 588 589 589 /* Start from the first entry in block */ 590 590 ext4_directory_entry_ll_t *tmp_dentry = result.block->data; 591 591 uint16_t tmp_dentry_length = 592 592 ext4_directory_entry_ll_get_entry_length(tmp_dentry); 593 593 594 594 /* Find direct predecessor of removed entry */ 595 595 while ((offset + tmp_dentry_length) < pos) { … … 600 600 ext4_directory_entry_ll_get_entry_length(tmp_dentry); 601 601 } 602 602 603 603 assert(tmp_dentry_length + offset == pos); 604 604 605 605 /* Add to removed entry length to predecessor's length */ 606 606 uint16_t del_entry_length = … … 609 609 tmp_dentry_length + del_entry_length); 610 610 } 611 611 612 612 result.block->dirty = true; 613 613 614 614 return ext4_directory_destroy_result(&result); 615 615 } … … 633 633 uint32_t block_size = ext4_superblock_get_block_size(sb); 634 634 uint16_t required_len = sizeof(ext4_fake_directory_entry_t) + name_len; 635 635 636 636 if ((required_len % 4) != 0) 637 637 required_len += 4 - (required_len % 4); 638 638 639 639 /* Initialize pointers, stop means to upper bound */ 640 640 ext4_directory_entry_ll_t *dentry = target_block->data; 641 641 ext4_directory_entry_ll_t *stop = target_block->data + block_size; 642 642 643 643 /* 644 644 * Walk through the block and check for invalid entries … … 648 648 uint32_t inode = ext4_directory_entry_ll_get_inode(dentry); 649 649 uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(dentry); 650 650 651 651 /* If invalid and large enough entry, use it */ 652 652 if ((inode == 0) && (rec_len >= required_len)) { … … 654 654 name, name_len); 655 655 target_block->dirty = true; 656 656 657 657 return EOK; 658 658 } 659 659 660 660 /* Valid entry, try to split it */ 661 661 if (inode != 0) { 662 662 uint16_t used_name_len = 663 663 ext4_directory_entry_ll_get_name_length(sb, dentry); 664 664 665 665 uint16_t used_space = 666 666 sizeof(ext4_fake_directory_entry_t) + used_name_len; 667 667 668 668 if ((used_name_len % 4) != 0) 669 669 used_space += 4 - (used_name_len % 4); 670 670 671 671 uint16_t free_space = rec_len - used_space; 672 672 673 673 /* There is free space for new entry */ 674 674 if (free_space >= required_len) { … … 679 679 ext4_directory_write_entry(sb, new_entry, 680 680 free_space, child, name, name_len); 681 681 682 682 target_block->dirty = true; 683 683 684 684 return EOK; 685 685 } 686 686 } 687 687 688 688 /* Jump to the next entry */ 689 689 dentry = (void *) dentry + rec_len; 690 690 } 691 691 692 692 /* No free space found for new entry */ 693 693 return ENOSPC; … … 711 711 ext4_directory_entry_ll_t *dentry = 712 712 (ext4_directory_entry_ll_t *) block->data; 713 713 714 714 /* Set upper bound for cycling */ 715 715 uint8_t *addr_limit = block->data + ext4_superblock_get_block_size(sb); 716 716 717 717 /* Walk through the block and check entries */ 718 718 while ((uint8_t *) dentry < addr_limit) { … … 720 720 if ((uint8_t *) dentry + name_len > addr_limit) 721 721 break; 722 722 723 723 /* Valid entry - check it */ 724 724 if (dentry->inode != 0) { … … 733 733 } 734 734 } 735 735 736 736 uint16_t dentry_len = 737 737 ext4_directory_entry_ll_get_entry_length(dentry); 738 738 739 739 /* Corrupted entry */ 740 740 if (dentry_len == 0) 741 741 return EINVAL; 742 742 743 743 /* Jump to next entry */ 744 744 dentry = (ext4_directory_entry_ll_t *) ((uint8_t *) dentry + dentry_len); 745 745 } 746 746 747 747 /* Entry not found */ 748 748 return ENOENT; … … 760 760 if (result->block) 761 761 return block_put(result->block); 762 762 763 763 return EOK; 764 764 }
Note:
See TracChangeset
for help on using the changeset viewer.