Changeset 96606fe in mainline for uspace/lib/ext4/libext4_extent.c
- Timestamp:
- 2012-07-06T14:50:43Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- cc51c27
- Parents:
- d802671d
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/libext4_extent.c
rd802671d r96606fe 751 751 752 752 /* Trivial way - no splitting */ 753 if (entries < limit) { 754 755 ext4_extent_header_set_entries_count(path_ptr->header, entries + 1); 756 path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries; 757 ext4_extent_set_block_count(path_ptr->extent, 0); 758 ext4_extent_set_first_block(path_ptr->extent, iblock); 759 ext4_extent_set_start(path_ptr->extent, 0); 760 path_ptr->block->dirty = true; 761 762 return EOK; 763 } 753 // if ((entries < limit) && (path == path_ptr)) { 754 // 755 // ext4_extent_header_set_entries_count(path_ptr->header, entries + 1); 756 // path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries; 757 // path_ptr->block->dirty = true; 758 // 759 // return EOK; 760 // } 764 761 765 762 uint32_t block_size = 766 763 ext4_superblock_get_block_size(inode_ref->fs->superblock); 767 764 768 /* Trivial tree - grow (extents were in root node) */ 769 if (path_ptr == path) { 770 771 EXT4FS_DBG("splitting root with extents"); 772 773 uint32_t new_fblock; 774 rc = ext4_balloc_alloc_block(inode_ref, &new_fblock); 775 if (rc != EOK) { 776 EXT4FS_DBG("error in block allocation"); 777 return rc; 778 } 779 780 EXT4FS_DBG("alllocated block \%u for new leaf", new_fblock); 781 782 block_t *block; 783 rc = block_get(&block, inode_ref->fs->device, 784 new_fblock, BLOCK_FLAGS_NOREAD); 785 if (rc != EOK) { 786 EXT4FS_DBG("error in block_get"); 787 return rc; 788 } 789 790 memset(block->data, 0, block_size); 791 792 /* Move data from root to the new block */ 793 memcpy(block->data, inode_ref->inode->blocks, 794 EXT4_INODE_BLOCKS * sizeof(uint32_t)); 795 796 path_ptr++; 797 path_ptr->block = block; 798 path_ptr->header = (ext4_extent_header_t *)block->data; 799 path_ptr->depth = 0; 800 path_ptr->index = NULL; 801 802 uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header); 803 path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries; 804 ext4_extent_header_set_entries_count(path_ptr->header, entries + 1); 805 uint16_t limit = (block_size - sizeof(ext4_extent_header_t)) / 806 sizeof(ext4_extent_t); 807 ext4_extent_header_set_max_entries_count(path_ptr->header, limit); 808 809 /* Initialize new extent */ 810 ext4_extent_set_block_count(path_ptr->extent, 0); 811 ext4_extent_set_first_block(path_ptr->extent, iblock); 812 ext4_extent_set_start(path_ptr->extent, 0); 813 814 /* Modify root (in inode) */ 815 path->depth = 1; 816 path->extent = NULL; 817 path->index = EXT4_EXTENT_FIRST_INDEX(path->header); 818 819 ext4_extent_header_set_depth(path->header, 1); 820 ext4_extent_header_set_entries_count(path->header, 1); 821 822 ext4_extent_index_set_first_block(path->index, 0); 823 ext4_extent_index_set_leaf(path->index, new_fblock); 824 825 path_ptr->block->dirty = true; 826 path->block->dirty = true; 827 828 *last_path_item = path_ptr; 829 830 831 ext4_extent_header_t *tmp_root = path->header; 832 EXT4FS_DBG("new root: items = \%u, maximum = \%u, depth = \%u", ext4_extent_header_get_entries_count(tmp_root), 833 ext4_extent_header_get_max_entries_count(tmp_root), ext4_extent_header_get_depth(tmp_root)); 834 835 ext4_extent_index_t *root_idx = EXT4_EXTENT_FIRST_INDEX(path->header); 836 EXT4FS_DBG("first iblock = \%u, fblock = \%u", ext4_extent_index_get_first_block(root_idx), 837 (uint32_t)ext4_extent_index_get_leaf(root_idx)); 838 839 ext4_extent_header_t *new_leaf = path_ptr->header; 840 EXT4FS_DBG("new leaf: items = \%u, maximum = \%u, depth = \%u", ext4_extent_header_get_entries_count(new_leaf), 841 ext4_extent_header_get_max_entries_count(new_leaf), ext4_extent_header_get_depth(new_leaf)); 842 843 for (uint32_t j = 0; j < ext4_extent_header_get_entries_count(new_leaf); ++j) { 844 ext4_extent_t *tmp_ext = EXT4_EXTENT_FIRST(path_ptr->header) + j; 845 846 EXT4FS_DBG("item \%u, first iblock = \%u", j, ext4_extent_get_first_block(tmp_ext)); 847 } 848 849 850 EXT4FS_DBG("Root block containing extents was split"); 851 return EOK; 852 } 765 // /* Trivial tree - grow (extents were in root node) */ 766 // if ((path_ptr == path) && ((entries == limit))){ 767 // 768 // EXT4FS_DBG("splitting root with extents"); 769 // 770 // uint32_t new_fblock; 771 // rc = ext4_balloc_alloc_block(inode_ref, &new_fblock); 772 // if (rc != EOK) { 773 // EXT4FS_DBG("error in block allocation"); 774 // return rc; 775 // } 776 // 777 //// EXT4FS_DBG("alllocated block \%u for new leaf", new_fblock); 778 // 779 // block_t *block; 780 // rc = block_get(&block, inode_ref->fs->device, 781 // new_fblock, BLOCK_FLAGS_NOREAD); 782 // if (rc != EOK) { 783 // EXT4FS_DBG("error in block_get"); 784 // return rc; 785 // } 786 // 787 // memset(block->data, 0, block_size); 788 // 789 // /* Move data from root to the new block */ 790 // memcpy(block->data, inode_ref->inode->blocks, 791 // EXT4_INODE_BLOCKS * sizeof(uint32_t)); 792 // 793 // path_ptr++; 794 // path_ptr->block = block; 795 // path_ptr->header = (ext4_extent_header_t *)block->data; 796 // path_ptr->depth = 0; 797 // path_ptr->index = NULL; 798 // 799 // uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header); 800 // path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries; 801 // ext4_extent_header_set_entries_count(path_ptr->header, entries + 1); 802 // uint16_t limit = (block_size - sizeof(ext4_extent_header_t)) / 803 // sizeof(ext4_extent_t); 804 // ext4_extent_header_set_max_entries_count(path_ptr->header, limit); 805 // 806 // /* Modify root (in inode) */ 807 // path->depth = 1; 808 // path->extent = NULL; 809 // path->index = EXT4_EXTENT_FIRST_INDEX(path->header); 810 // 811 // ext4_extent_header_set_depth(path->header, 1); 812 // ext4_extent_header_set_entries_count(path->header, 1); 813 // 814 // ext4_extent_index_set_first_block(path->index, 0); 815 // ext4_extent_index_set_leaf(path->index, new_fblock); 816 // 817 // path_ptr->block->dirty = true; 818 // path->block->dirty = true; 819 // 820 // *last_path_item = path_ptr; 821 // 822 //// ext4_extent_header_t *tmp_root = path->header; 823 //// EXT4FS_DBG("new root: items = \%u, maximum = \%u, depth = \%u", ext4_extent_header_get_entries_count(tmp_root), 824 //// ext4_extent_header_get_max_entries_count(tmp_root), ext4_extent_header_get_depth(tmp_root)); 825 //// 826 //// ext4_extent_index_t *root_idx = EXT4_EXTENT_FIRST_INDEX(path->header); 827 //// EXT4FS_DBG("first iblock = \%u, fblock = \%u", ext4_extent_index_get_first_block(root_idx), 828 //// (uint32_t)ext4_extent_index_get_leaf(root_idx)); 829 //// 830 //// ext4_extent_header_t *new_leaf = path_ptr->header; 831 //// EXT4FS_DBG("new leaf: items = \%u, maximum = \%u, depth = \%u", ext4_extent_header_get_entries_count(new_leaf), 832 //// ext4_extent_header_get_max_entries_count(new_leaf), ext4_extent_header_get_depth(new_leaf)); 833 //// 834 //// for (uint32_t j = 0; j < ext4_extent_header_get_entries_count(new_leaf); ++j) { 835 //// ext4_extent_t *tmp_ext = EXT4_EXTENT_FIRST(path_ptr->header) + j; 836 //// 837 //// EXT4FS_DBG("item \%u, first iblock = \%u", j, ext4_extent_get_first_block(tmp_ext)); 838 //// } 839 // 840 // EXT4FS_DBG("Root block containing extents was split"); 841 // return EOK; 842 // } 853 843 854 844 // TODO !!! 855 845 // assert(false); 856 846 857 EXT4FS_DBG("More complex splitting");847 // EXT4FS_DBG("More complex splitting"); 858 848 859 849 /* Start splitting */ 860 uint32_t fblock = 0;861 850 while (path_ptr > path) { 862 863 // TODO 864 865 rc = ext4_balloc_alloc_block(inode_ref, &fblock); 866 if (rc != EOK) { 867 return rc; 868 } 869 870 block_t *block; 871 rc = block_get(&block, inode_ref->fs->device, fblock, BLOCK_FLAGS_NOREAD); 872 if (rc != EOK) { 873 ext4_balloc_free_block(inode_ref, fblock); 874 return rc; 875 } 876 877 /* Init block */ 878 memset(block->data, 0, block_size); 879 880 /* Not modified */ 881 block_put(path_ptr->block); 882 path_ptr->block = block; 883 884 path_ptr->header = block->data; 885 886 if (path_ptr->depth) { 887 path_ptr->index = EXT4_EXTENT_FIRST_INDEX(path_ptr->header); 851 uint32_t fblock; 852 853 entries = ext4_extent_header_get_entries_count(path_ptr->header); 854 limit = ext4_extent_header_get_max_entries_count(path_ptr->header); 855 856 if (entries == limit) { 857 858 EXT4FS_DBG("Full non-root node (\%s)", path_ptr->depth ? "index" : "extent"); 859 860 /* Full node */ 861 rc = ext4_balloc_alloc_block(inode_ref, &fblock); 862 if (rc != EOK) { 863 return rc; 864 } 865 866 block_t *block; 867 rc = block_get(&block, inode_ref->fs->device, fblock, BLOCK_FLAGS_NOREAD); 868 if (rc != EOK) { 869 ext4_balloc_free_block(inode_ref, fblock); 870 return rc; 871 } 872 873 /* Init block */ 874 memset(block->data, 0, block_size); 875 876 /* Not modified old block */ 877 block_put(path_ptr->block); 878 path_ptr->block = block; 879 path_ptr->header = block->data; 880 881 if (path_ptr->depth) { 882 path_ptr->index = EXT4_EXTENT_FIRST_INDEX(path_ptr->header); 883 ext4_extent_index_set_first_block(path_ptr->index, iblock); 884 ext4_extent_index_set_leaf(path_ptr->index, (path_ptr + 1)->block->lba); 885 limit = (block_size - sizeof(ext4_extent_header_t)) / 886 sizeof(ext4_extent_index_t); 887 } else { 888 path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header); 889 ext4_extent_set_first_block(path_ptr->extent, iblock); 890 limit = (block_size - sizeof(ext4_extent_header_t)) / 891 sizeof(ext4_extent_t); 892 } 893 894 ext4_extent_header_set_entries_count(path_ptr->header, 1); 895 ext4_extent_header_set_max_entries_count(path_ptr->header, limit); 896 897 path_ptr->block->dirty = true; 898 899 path_ptr--; 900 888 901 } else { 889 path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header); 890 } 891 892 path_ptr--; 893 } 894 895 /* If splitting reached root node */ 902 903 // EXT4FS_DBG("Adding entry non-root node (\%s)", path_ptr->depth ? "index" : "extent"); 904 905 /* Node with free space */ 906 if (path_ptr->depth) { 907 path_ptr->index = EXT4_EXTENT_FIRST_INDEX(path_ptr->header) + entries; 908 ext4_extent_index_set_first_block(path_ptr->index, iblock); 909 ext4_extent_index_set_leaf(path_ptr->index, (path_ptr + 1)->block->lba); 910 } else { 911 path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries; 912 ext4_extent_set_first_block(path_ptr->extent, iblock); 913 } 914 915 ext4_extent_header_set_entries_count(path_ptr->header, entries + 1); 916 path_ptr->block->dirty = true; 917 *last_path_item = path_ptr; 918 919 return EOK; 920 } 921 922 } 923 924 /* Should be the root split too? */ 896 925 if (path_ptr == path) { 897 926 898 EXT4FS_DBG("Splitting root"); 899 900 uint32_t new_fblock; 901 rc = ext4_balloc_alloc_block(inode_ref, &new_fblock); 902 if (rc != EOK) { 903 EXT4FS_DBG("error in block allocation"); 904 return rc; 905 } 906 907 block_t *block; 908 rc = block_get(&block, inode_ref->fs->device, 909 new_fblock, BLOCK_FLAGS_NOREAD); 910 if (rc != EOK) { 911 EXT4FS_DBG("error in block_get"); 912 return rc; 913 } 914 915 memset(block->data, 0, block_size); 916 917 /* Move data from root to the new block */ 918 memcpy(block->data, inode_ref->inode->blocks, 919 EXT4_INODE_BLOCKS * sizeof(uint32_t)); 920 921 path_ptr++; 922 path_ptr->block = block; 923 path_ptr->header = (ext4_extent_header_t *)block->data; 924 path_ptr->depth = ext4_extent_header_get_depth(path_ptr->header); 925 path_ptr->index = NULL; 926 927 uint16_t entries = ext4_extent_header_get_entries_count(path_ptr->header); 928 path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries; 929 ext4_extent_header_set_entries_count(path_ptr->header, entries + 1); 930 uint16_t limit = (block_size - sizeof(ext4_extent_header_t)) / 931 sizeof(ext4_extent_t); 932 ext4_extent_header_set_max_entries_count(path_ptr->header, limit); 933 934 /* Modify root (in inode) */ 935 path->depth = 1; 936 path->extent = NULL; 937 path->index = EXT4_EXTENT_FIRST_INDEX(path->header); 938 939 ext4_extent_header_set_depth(path->header, path_ptr->depth + 1); 940 ext4_extent_header_set_entries_count(path->header, 1); 941 942 ext4_extent_index_set_first_block(path->index, 0); 943 ext4_extent_index_set_leaf(path->index, new_fblock); 944 945 path_ptr->block->dirty = true; 946 path->block->dirty = true; 947 948 *last_path_item = path_ptr; 949 950 } 951 952 EXT4FS_DBG("Finishing"); 927 entries = ext4_extent_header_get_entries_count(path->header); 928 limit = ext4_extent_header_get_max_entries_count(path->header); 929 930 if (entries == limit) { 931 932 EXT4FS_DBG("Splitting root"); 933 934 uint32_t new_fblock; 935 rc = ext4_balloc_alloc_block(inode_ref, &new_fblock); 936 if (rc != EOK) { 937 EXT4FS_DBG("error in block allocation"); 938 return rc; 939 } 940 941 block_t *block; 942 rc = block_get(&block, inode_ref->fs->device, 943 new_fblock, BLOCK_FLAGS_NOREAD); 944 if (rc != EOK) { 945 EXT4FS_DBG("error in block_get"); 946 return rc; 947 } 948 949 memset(block->data, 0, block_size); 950 951 /* Move data from root to the new block */ 952 memcpy(block->data, inode_ref->inode->blocks, 953 EXT4_INODE_BLOCKS * sizeof(uint32_t)); 954 955 EXT4FS_DBG("New block prepared"); 956 957 /* Make space for tree growing */ 958 memmove(path + 1, path, path->depth + 1); 959 960 EXT4FS_DBG("Place for new root ready"); 961 962 path_ptr = path + 1; 963 path_ptr->block = block; 964 path_ptr->header = (ext4_extent_header_t *)block->data; 965 966 if (path_ptr->depth) { 967 limit = (block_size - sizeof(ext4_extent_header_t)) / 968 sizeof(ext4_extent_index_t); 969 path_ptr->index = EXT4_EXTENT_FIRST_INDEX(path_ptr->header) + entries; 970 ext4_extent_index_set_first_block(path_ptr->index, iblock); 971 ext4_extent_index_set_leaf(path_ptr->index, (path_ptr + 1)->block->lba); 972 path_ptr->extent = NULL; 973 } else { 974 limit = (block_size - sizeof(ext4_extent_header_t)) / 975 sizeof(ext4_extent_t); 976 path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries; 977 ext4_extent_set_first_block(path_ptr->extent, iblock); 978 path_ptr->index = NULL; 979 } 980 981 ext4_extent_header_set_entries_count(path_ptr->header, entries + 1); 982 ext4_extent_header_set_max_entries_count(path_ptr->header, limit); 983 984 path_ptr->block->dirty = true; 985 986 path->block = inode_ref->block; 987 path->depth = path_ptr->depth + 1; 988 path->header = (ext4_extent_header_t *)inode_ref->inode->blocks; 989 path->extent = NULL; 990 path->index = EXT4_EXTENT_FIRST_INDEX(path->header); 991 992 993 ext4_extent_header_set_entries_count(path->header, 1); 994 ext4_extent_header_set_depth(path->header, path->depth); 995 996 ext4_extent_index_set_first_block(path->index, 0); 997 ext4_extent_index_set_leaf(path->index, new_fblock); 998 999 path->block->dirty = true; 1000 1001 *last_path_item = *last_path_item + 1; 1002 1003 EXT4FS_DBG("Leaving split root"); 1004 1005 } else { 1006 1007 EXT4FS_DBG("Adding entry to root node"); 1008 1009 if (path_ptr->depth) { 1010 path_ptr->index = EXT4_EXTENT_FIRST_INDEX(path_ptr->header) + entries; 1011 ext4_extent_index_set_first_block(path_ptr->index, iblock); 1012 ext4_extent_index_set_leaf(path_ptr->index, (path_ptr + 1)->block->lba); 1013 } else { 1014 path_ptr->extent = EXT4_EXTENT_FIRST(path_ptr->header) + entries; 1015 ext4_extent_set_first_block(path_ptr->extent, iblock); 1016 } 1017 1018 ext4_extent_header_set_entries_count(path_ptr->header, entries + 1); 1019 path->block->dirty = true; 1020 } 1021 } 1022 953 1023 954 1024 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.