Changeset 06d85e5 in mainline for uspace/lib/ext4/libext4_directory_index.c
- 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
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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:
Note:
See TracChangeset
for help on using the changeset viewer.