Changeset bae2a79e in mainline
- Timestamp:
- 2012-04-20T09:51:44Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d37d500e
- Parents:
- dfac604
- Location:
- uspace
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/libext4_directory.c
rdfac604 rbae2a79e 42 42 #include "libext4.h" 43 43 44 static int ext4_directory_iterator_set(ext4_directory_iterator_t *, 45 uint32_t); 46 47 44 45 /** Get i-node number from directory entry. 46 * 47 * @param de directory entry 48 * @return i-node number 49 */ 48 50 uint32_t ext4_directory_entry_ll_get_inode(ext4_directory_entry_ll_t *de) 49 51 { … … 51 53 } 52 54 55 /** Set i-node number to directory entry. 56 * 57 * @param de directory entry 58 * @param inode i-node number 59 */ 53 60 void ext4_directory_entry_ll_set_inode(ext4_directory_entry_ll_t *de, 54 61 uint32_t inode) … … 57 64 } 58 65 66 /** Get directory entry length. 67 * 68 * @param de directory entry 69 * @return entry length 70 */ 59 71 uint16_t ext4_directory_entry_ll_get_entry_length( 60 72 ext4_directory_entry_ll_t *de) … … 63 75 } 64 76 77 /** Set directory entry length. 78 * 79 * @param de directory entry 80 * @param length entry length 81 */ 82 65 83 void ext4_directory_entry_ll_set_entry_length(ext4_directory_entry_ll_t *de, 66 84 uint16_t length) … … 69 87 } 70 88 89 /** Get directory entry name length. 90 * 91 * @param sb superblock 92 * @param de directory entry 93 * @return entry name length 94 */ 71 95 uint16_t ext4_directory_entry_ll_get_name_length( 72 96 ext4_superblock_t *sb, ext4_directory_entry_ll_t *de) … … 83 107 } 84 108 109 /** Set directory entry name length. 110 * 111 * @param sb superblock 112 * @param de directory entry 113 * @param length entry name length 114 */ 85 115 void ext4_directory_entry_ll_set_name_length(ext4_superblock_t *sb, 86 116 ext4_directory_entry_ll_t *de, uint16_t length) … … 95 125 } 96 126 127 /** Get i-node type of directory entry. 128 * 129 * @param sb superblock 130 * @param de directory entry 131 * @return i-node type (file, dir, etc.) 132 */ 97 133 uint8_t ext4_directory_entry_ll_get_inode_type( 98 134 ext4_superblock_t *sb, ext4_directory_entry_ll_t *de) … … 108 144 } 109 145 146 /** Set i-node type of directory entry. 147 * 148 * @param sb superblock 149 * @param de directory entry 150 * @param type i-node type (file, dir, etc.) 151 */ 110 152 void ext4_directory_entry_ll_set_inode_type( 111 153 ext4_superblock_t *sb, ext4_directory_entry_ll_t *de, uint8_t type) … … 121 163 } 122 164 165 static int ext4_directory_iterator_seek( 166 ext4_directory_iterator_t *, aoff64_t); 167 static int ext4_directory_iterator_set( 168 ext4_directory_iterator_t *, uint32_t); 169 170 171 /** Initialize directory iterator. 172 * 173 * Set position to the first valid entry from the required position. 174 * 175 * @param it pointer to iterator to be initialized 176 * @param inode_ref directory i-node 177 * @param pos position to start reading entries from 178 * @return error code 179 */ 123 180 int ext4_directory_iterator_init(ext4_directory_iterator_t *it, 124 ext4_filesystem_t *fs,ext4_inode_ref_t *inode_ref, aoff64_t pos)181 ext4_inode_ref_t *inode_ref, aoff64_t pos) 125 182 { 126 183 it->inode_ref = inode_ref; 127 it->fs = fs;128 184 it->current = NULL; 129 185 it->current_offset = 0; … … 133 189 } 134 190 135 191 /** Jump to the next valid entry 192 * 193 * @param it initialized iterator 194 * @return error code 195 */ 136 196 int ext4_directory_iterator_next(ext4_directory_iterator_t *it) 137 197 { … … 145 205 } 146 206 147 207 /** Seek to next valid directory entry. 208 * 209 * Here can be jumped to the next data block. 210 * 211 * @param it initialized iterator 212 * @param pos position of the next entry 213 * @return error code 214 */ 148 215 int ext4_directory_iterator_seek(ext4_directory_iterator_t *it, aoff64_t pos) 149 216 { 150 217 int rc; 151 218 152 uint64_t size = ext4_inode_get_size(it->fs->superblock, it->inode_ref->inode); 219 uint64_t size = ext4_inode_get_size( 220 it->inode_ref->fs->superblock, it->inode_ref->inode); 153 221 154 222 /* The iterator is not valid until we seek to the desired position */ … … 169 237 } 170 238 171 uint32_t block_size = ext4_superblock_get_block_size(it->fs->superblock); 239 // Compute next block address 240 uint32_t block_size = ext4_superblock_get_block_size( 241 it->inode_ref->fs->superblock); 172 242 aoff64_t current_block_idx = it->current_offset / block_size; 173 243 aoff64_t next_block_idx = pos / block_size; … … 192 262 } 193 263 194 rc = block_get(&it->current_block, it-> fs->device, next_block_phys_idx,195 264 rc = block_get(&it->current_block, it->inode_ref->fs->device, 265 next_block_phys_idx, BLOCK_FLAGS_NONE); 196 266 if (rc != EOK) { 197 267 it->current_block = NULL; … … 205 275 } 206 276 277 /** Do some checks before returning iterator. 278 * 279 * @param it iterator to be checked 280 * @param block_size size of data block 281 * @return error code 282 */ 207 283 static int ext4_directory_iterator_set(ext4_directory_iterator_t *it, 208 284 uint32_t block_size) … … 232 308 233 309 /* Ensure the name length is not too large */ 234 if (ext4_directory_entry_ll_get_name_length(it-> fs->superblock,310 if (ext4_directory_entry_ll_get_name_length(it->inode_ref->fs->superblock, 235 311 entry) > length-8) { 236 312 return EIO; 237 313 } 238 314 315 // Everything OK - "publish" the entry 239 316 it->current = entry; 240 317 return EOK; … … 242 319 243 320 321 /** Uninitialize directory iterator. 322 * 323 * Release all allocated structures. 324 * 325 * @param it iterator to be finished 326 * @return error code 327 */ 244 328 int ext4_directory_iterator_fini(ext4_directory_iterator_t *it) 245 329 { 246 330 int rc; 247 331 248 it->fs = NULL;249 332 it->inode_ref = NULL; 250 333 it->current = NULL; … … 260 343 } 261 344 345 /** Write directory entry to concrete data block. 346 * 347 * @param sb superblock 348 * @param entry pointer to entry to be written 349 * @param entry_len lenght of new entry 350 * @param child child i-node to be written to new entry 351 * @param name name of the new entry 352 * @param name_len length of entry name 353 */ 262 354 void ext4_directory_write_entry(ext4_superblock_t *sb, 263 355 ext4_directory_entry_ll_t *entry, uint16_t entry_len, … … 265 357 { 266 358 267 EXT4FS_DBG("writing entry \%s, len \%u, addr = \%u", name, entry_len, (uint32_t)entry); 268 359 // Check maximum entry length 360 uint32_t block_size = ext4_superblock_get_block_size(sb); 361 assert(entry_len <= block_size); 362 363 // Set basic attributes 269 364 ext4_directory_entry_ll_set_inode(entry, child->index); 270 365 ext4_directory_entry_ll_set_entry_length(entry, entry_len); 271 366 ext4_directory_entry_ll_set_name_length(sb, entry, name_len); 272 367 368 // Write name 369 memcpy(entry->name, name, name_len); 370 371 // Set type of entry 273 372 if (ext4_inode_is_type(sb, child->inode, EXT4_INODE_MODE_DIRECTORY)) { 274 373 ext4_directory_entry_ll_set_inode_type( … … 278 377 sb, entry, EXT4_DIRECTORY_FILETYPE_REG_FILE); 279 378 } 280 memcpy(entry->name, name, name_len); 281 } 282 379 380 } 381 382 /** Add new entry to the directory. 383 * 384 * @param parent directory i-node 385 * @param name name of new entry 386 * @param child i-node to be referenced from new entry 387 * @return error code 388 */ 283 389 int ext4_directory_add_entry(ext4_inode_ref_t * parent, 284 390 const char *name, ext4_inode_ref_t *child) 285 391 { 286 392 int rc; 287 288 EXT4FS_DBG("adding entry to directory \%u [ino = \%u, name = \%s]", parent->index, child->index, name);289 393 290 394 ext4_filesystem_t *fs = parent->fs; … … 294 398 ext4_inode_has_flag(parent->inode, EXT4_INODE_FLAG_INDEX)) { 295 399 296 EXT4FS_DBG("index");297 298 400 rc = ext4_directory_dx_add_entry(parent, child, name); 299 401 … … 308 410 } 309 411 310 // Needed to clear dir index flag 412 // Needed to clear dir index flag if corrupted 311 413 ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX); 312 414 parent->dirty = true; … … 324 426 uint32_t name_len = strlen(name); 325 427 326 // Find block, where is space for new entry 428 // Find block, where is space for new entry and try to add 327 429 bool success = false; 328 430 for (iblock = 0; iblock < total_blocks; ++iblock) { … … 339 441 } 340 442 443 // If adding is successful, function can finish 341 444 rc = ext4_directory_try_insert_entry(fs->superblock, block, child, name, name_len); 342 445 if (rc == EOK) { … … 354 457 } 355 458 356 // No free block found - needed to allocate next block459 // No free block found - needed to allocate next data block 357 460 358 461 iblock = 0; … … 363 466 } 364 467 365 EXT4FS_DBG("using iblock \%u fblock \%u", iblock, fblock);366 367 468 // Load new block 368 469 block_t *new_block; … … 387 488 } 388 489 490 /** Find directory entry with passed name. 491 * 492 * @param result result structure to be returned if entry found 493 * @param parent directory i-node 494 * @param name name of entry to be found 495 * @return error code 496 */ 389 497 int ext4_directory_find_entry(ext4_directory_search_result_t *result, 390 498 ext4_inode_ref_t *parent, const char *name) … … 410 518 } 411 519 520 // Needed to clear dir index flag if corrupted 521 ext4_inode_clear_flag(parent->inode, EXT4_INODE_FLAG_INDEX); 522 parent->dirty = true; 523 412 524 EXT4FS_DBG("index is corrupted - doing linear search"); 413 525 } 526 527 // Linear algorithm 414 528 415 529 uint32_t iblock, fblock; … … 418 532 uint32_t total_blocks = inode_size / block_size; 419 533 534 // Walk through all data blocks 420 535 for (iblock = 0; iblock < total_blocks; ++iblock) { 421 536 537 // Load block address 422 538 rc = ext4_filesystem_get_inode_data_block_index(parent, iblock, &fblock); 423 539 if (rc != EOK) { … … 425 541 } 426 542 543 // Load data block 427 544 block_t *block; 428 545 rc = block_get(&block, parent->fs->device, fblock, BLOCK_FLAGS_NONE); … … 431 548 } 432 549 433 // find block entry550 // Try to find entry in block 434 551 ext4_directory_entry_ll_t *res_entry; 435 552 rc = ext4_directory_find_in_block(block, sb, name_len, name, &res_entry); … … 440 557 } 441 558 559 // Entry not found - put block and continue to the next block 560 442 561 rc = block_put(block); 443 562 if (rc != EOK) { … … 445 564 } 446 565 } 566 567 // Entry was not found 447 568 448 569 result->block = NULL; … … 453 574 454 575 576 /** Remove directory entry. 577 * 578 * @param parent directory i-node 579 * @param name name of the entry to be removed 580 * @return error code 581 */ 455 582 int ext4_directory_remove_entry(ext4_inode_ref_t *parent, const char *name) 456 583 { 457 584 int rc; 458 585 586 // Check if removing from directory 459 587 if (!ext4_inode_is_type(parent->fs->superblock, parent->inode, 460 588 EXT4_INODE_MODE_DIRECTORY)) { … … 462 590 } 463 591 592 // Try to find entry 464 593 ext4_directory_search_result_t result; 465 594 rc = ext4_directory_find_entry(&result, parent, name); … … 468 597 } 469 598 599 // Invalidate entry 470 600 ext4_directory_entry_ll_set_inode(result.dentry, 0); 471 601 602 // Store entry position in block 472 603 uint32_t pos = (void *)result.dentry - result.block->data; 473 604 474 uint32_t offset = 0; 605 // If entry is not the first in block, it must be merged 606 // with previous entry 475 607 if (pos != 0) { 476 608 609 uint32_t offset = 0; 610 611 // Start from the first entry in block 477 612 ext4_directory_entry_ll_t *tmp_dentry = result.block->data; 478 613 uint16_t tmp_dentry_length = 479 614 ext4_directory_entry_ll_get_entry_length(tmp_dentry); 480 615 616 // Find direct predecessor of removed entry 481 617 while ((offset + tmp_dentry_length) < pos) { 482 618 offset += ext4_directory_entry_ll_get_entry_length(tmp_dentry); … … 488 624 assert(tmp_dentry_length + offset == pos); 489 625 626 // Add to removed entry length to predecessor's length 490 627 uint16_t del_entry_length = 491 628 ext4_directory_entry_ll_get_entry_length(result.dentry); … … 500 637 } 501 638 502 639 /** Try to insert entry to concrete data block. 640 * 641 * @param sb superblock 642 * @param target_block block to try to insert entry to 643 * @param child child i-node to be inserted by new entry 644 * @param name name of the new entry 645 * @param name_len length of the new entry name 646 * @return error code 647 */ 503 648 int ext4_directory_try_insert_entry(ext4_superblock_t *sb, 504 649 block_t *target_block, ext4_inode_ref_t *child, 505 650 const char *name, uint32_t name_len) 506 651 { 652 // Compute required length entry and align it to 4 bytes 507 653 uint32_t block_size = ext4_superblock_get_block_size(sb); 508 654 uint16_t required_len = sizeof(ext4_fake_directory_entry_t) + name_len; … … 511 657 } 512 658 659 // Initialize pointers, stop means to upper bound 513 660 ext4_directory_entry_ll_t *dentry = target_block->data; 514 661 ext4_directory_entry_ll_t *stop = target_block->data + block_size; 515 662 663 // Walk through the block and check for invalid entries 664 // or entries with free space for new entry 516 665 while (dentry < stop) { 517 666 … … 519 668 uint16_t rec_len = ext4_directory_entry_ll_get_entry_length(dentry); 520 669 670 // If invalid and large enough entry, use it 521 671 if ((inode == 0) && (rec_len >= required_len)) { 522 672 ext4_directory_write_entry(sb, dentry, rec_len, child, name, name_len); … … 525 675 } 526 676 677 // Valid entry, try to split it 527 678 if (inode != 0) { 528 679 uint16_t used_name_len = … … 536 687 uint16_t free_space = rec_len - used_space; 537 688 689 // There is free space for new entry 538 690 if (free_space >= required_len) { 539 691 … … 550 702 } 551 703 704 // Jump to the next entry 552 705 dentry = (void *)dentry + rec_len; 553 706 } 554 707 708 // No free space found for new entry 709 555 710 return ENOSPC; 556 711 } 557 712 713 /** Try to find entry in block by name. 714 * 715 * @param block block containing entries 716 * @param sb superblock 717 * @param name_len length of entry name 718 * @param name name of entry to be found 719 * @param res_entry output pointer to found entry, NULL if not found 720 * @return error code 721 */ 558 722 int ext4_directory_find_in_block(block_t *block, 559 723 ext4_superblock_t *sb, size_t name_len, const char *name, 560 724 ext4_directory_entry_ll_t **res_entry) 561 725 { 562 726 // Start from the first entry in block 563 727 ext4_directory_entry_ll_t *dentry = (ext4_directory_entry_ll_t *)block->data; 728 //Set upper bound for cycling 564 729 uint8_t *addr_limit = block->data + ext4_superblock_get_block_size(sb); 565 730 731 // Walk through the block and check entries 566 732 while ((uint8_t *)dentry < addr_limit) { 567 733 734 // Termination condition 568 735 if ((uint8_t*) dentry + name_len > addr_limit) { 569 736 break; 570 737 } 571 738 739 // Valid entry - check it 572 740 if (dentry->inode != 0) { 741 742 // For more effectivity compare firstly only lengths 573 743 if (name_len == ext4_directory_entry_ll_get_name_length(sb, dentry)) { 574 744 // Compare names … … 580 750 } 581 751 582 // Goto next entry583 752 uint16_t dentry_len = ext4_directory_entry_ll_get_entry_length(dentry); 584 753 754 // Corrupted entry 585 755 if (dentry_len == 0) { 586 756 return EINVAL; 587 757 } 588 758 759 // Jump to next entry 589 760 dentry = (ext4_directory_entry_ll_t *)((uint8_t *)dentry + dentry_len); 590 761 } 591 762 763 // Entry not found 592 764 return ENOENT; 593 765 } 594 766 767 /** Simple function to release allocated data from result. 768 * 769 * @param result search result to destroy 770 * @return error code 771 */ 595 772 int ext4_directory_destroy_result(ext4_directory_search_result_t *result) 596 773 { -
uspace/lib/ext4/libext4_directory.h
rdfac604 rbae2a79e 53 53 54 54 extern int ext4_directory_iterator_init(ext4_directory_iterator_t *, 55 ext4_ filesystem_t *, ext4_inode_ref_t *, aoff64_t);55 ext4_inode_ref_t *, aoff64_t); 56 56 extern int ext4_directory_iterator_next(ext4_directory_iterator_t *); 57 extern int ext4_directory_iterator_seek(ext4_directory_iterator_t *, aoff64_t);58 57 extern int ext4_directory_iterator_fini(ext4_directory_iterator_t *); 59 58 -
uspace/lib/ext4/libext4_types.h
rdfac604 rbae2a79e 386 386 387 387 typedef struct ext4_directory_iterator { 388 ext4_filesystem_t *fs;389 388 ext4_inode_ref_t *inode_ref; 390 389 block_t *current_block; -
uspace/srv/fs/ext4fs/ext4fs_ops.c
rdfac604 rbae2a79e 746 746 747 747 ext4_directory_iterator_t it; 748 rc = ext4_directory_iterator_init(&it, fs,enode->inode_ref, 0);748 rc = ext4_directory_iterator_init(&it, enode->inode_ref, 0); 749 749 if (rc != EOK) { 750 750 return rc; … … 1112 1112 1113 1113 ext4_directory_iterator_t it; 1114 rc = ext4_directory_iterator_init(&it, in st->filesystem, inode_ref, pos);1114 rc = ext4_directory_iterator_init(&it, inode_ref, pos); 1115 1115 if (rc != EOK) { 1116 1116 async_answer_0(callid, rc);
Note:
See TracChangeset
for help on using the changeset viewer.