Changeset 06d85e5 in mainline for uspace/lib/ext4/libext4_extent.c
- Timestamp:
- 2012-06-18T11:09:34Z (13 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_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
Note:
See TracChangeset
for help on using the changeset viewer.