diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-02-21 17:04:57 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-02-21 17:04:57 -0500 |
commit | cfaa72952fa7b44aa5d967cbc266110900552aef (patch) | |
tree | 7ca429e7417d168faa57dab4bc069c23fefb5cc4 /fs/btrfs/ctree.c | |
parent | 06ed4b316e8e24b6899ece7186c6a7a0129326ba (diff) |
Btrfs: extent fixes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 69 |
1 files changed, 46 insertions, 23 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 2177744dedd3..2891b582e26f 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -354,6 +354,7 @@ int __insert_ptr(struct ctree_root *root, | |||
354 | c->header.nritems = 2; | 354 | c->header.nritems = 2; |
355 | c->header.flags = node_level(level); | 355 | c->header.flags = node_level(level); |
356 | c->header.blocknr = t->blocknr; | 356 | c->header.blocknr = t->blocknr; |
357 | c->header.parentid = root->node->node.header.parentid; | ||
357 | lower = &path->nodes[level-1]->node; | 358 | lower = &path->nodes[level-1]->node; |
358 | if (is_leaf(lower->header.flags)) | 359 | if (is_leaf(lower->header.flags)) |
359 | lower_key = &((struct leaf *)lower)->items[0].key; | 360 | lower_key = &((struct leaf *)lower)->items[0].key; |
@@ -363,7 +364,7 @@ int __insert_ptr(struct ctree_root *root, | |||
363 | memcpy(c->keys + 1, key, sizeof(struct key)); | 364 | memcpy(c->keys + 1, key, sizeof(struct key)); |
364 | c->blockptrs[0] = path->nodes[level-1]->blocknr; | 365 | c->blockptrs[0] = path->nodes[level-1]->blocknr; |
365 | c->blockptrs[1] = blocknr; | 366 | c->blockptrs[1] = blocknr; |
366 | /* the path has an extra ref to root->node */ | 367 | /* the super has an extra ref to root->node */ |
367 | tree_block_release(root, root->node); | 368 | tree_block_release(root, root->node); |
368 | root->node = t; | 369 | root->node = t; |
369 | t->count++; | 370 | t->count++; |
@@ -439,6 +440,7 @@ int insert_ptr(struct ctree_root *root, | |||
439 | b = &b_buffer->node; | 440 | b = &b_buffer->node; |
440 | b->header.flags = c->header.flags; | 441 | b->header.flags = c->header.flags; |
441 | b->header.blocknr = b_buffer->blocknr; | 442 | b->header.blocknr = b_buffer->blocknr; |
443 | b->header.parentid = root->node->node.header.parentid; | ||
442 | mid = (c->header.nritems + 1) / 2; | 444 | mid = (c->header.nritems + 1) / 2; |
443 | memcpy(b->keys, c->keys + mid, | 445 | memcpy(b->keys, c->keys + mid, |
444 | (c->header.nritems - mid) * sizeof(struct key)); | 446 | (c->header.nritems - mid) * sizeof(struct key)); |
@@ -642,6 +644,7 @@ int split_leaf(struct ctree_root *root, struct ctree_path *path, int data_size) | |||
642 | right->header.nritems = nritems - mid; | 644 | right->header.nritems = nritems - mid; |
643 | right->header.blocknr = right_buffer->blocknr; | 645 | right->header.blocknr = right_buffer->blocknr; |
644 | right->header.flags = node_level(0); | 646 | right->header.flags = node_level(0); |
647 | right->header.parentid = root->node->node.header.parentid; | ||
645 | data_copy_size = l->items[mid].offset + l->items[mid].size - | 648 | data_copy_size = l->items[mid].offset + l->items[mid].size - |
646 | leaf_data_end(l); | 649 | leaf_data_end(l); |
647 | memcpy(right->items, l->items + mid, | 650 | memcpy(right->items, l->items + mid, |
@@ -689,8 +692,12 @@ int insert_item(struct ctree_root *root, struct key *key, | |||
689 | unsigned int data_end; | 692 | unsigned int data_end; |
690 | struct ctree_path path; | 693 | struct ctree_path path; |
691 | 694 | ||
695 | refill_alloc_extent(root); | ||
696 | |||
692 | /* create a root if there isn't one */ | 697 | /* create a root if there isn't one */ |
693 | if (!root->node) { | 698 | if (!root->node) { |
699 | BUG(); | ||
700 | #if 0 | ||
694 | struct tree_buffer *t; | 701 | struct tree_buffer *t; |
695 | t = alloc_free_block(root); | 702 | t = alloc_free_block(root); |
696 | BUG_ON(!t); | 703 | BUG_ON(!t); |
@@ -699,6 +706,7 @@ int insert_item(struct ctree_root *root, struct key *key, | |||
699 | t->node.header.blocknr = t->blocknr; | 706 | t->node.header.blocknr = t->blocknr; |
700 | root->node = t; | 707 | root->node = t; |
701 | write_tree_block(root, t); | 708 | write_tree_block(root, t); |
709 | #endif | ||
702 | } | 710 | } |
703 | init_path(&path); | 711 | init_path(&path); |
704 | ret = search_slot(root, key, &path); | 712 | ret = search_slot(root, key, &path); |
@@ -758,7 +766,6 @@ int insert_item(struct ctree_root *root, struct key *key, | |||
758 | if (leaf_free_space(leaf) < 0) | 766 | if (leaf_free_space(leaf) < 0) |
759 | BUG(); | 767 | BUG(); |
760 | release_path(root, &path); | 768 | release_path(root, &path); |
761 | refill_alloc_extent(root); | ||
762 | return 0; | 769 | return 0; |
763 | } | 770 | } |
764 | 771 | ||
@@ -893,7 +900,7 @@ int next_leaf(struct ctree_root *root, struct ctree_path *path) | |||
893 | int level = 1; | 900 | int level = 1; |
894 | u64 blocknr; | 901 | u64 blocknr; |
895 | struct tree_buffer *c; | 902 | struct tree_buffer *c; |
896 | struct tree_buffer *next; | 903 | struct tree_buffer *next = NULL; |
897 | 904 | ||
898 | while(level < MAX_LEVEL) { | 905 | while(level < MAX_LEVEL) { |
899 | if (!path->nodes[level]) | 906 | if (!path->nodes[level]) |
@@ -905,6 +912,8 @@ int next_leaf(struct ctree_root *root, struct ctree_path *path) | |||
905 | continue; | 912 | continue; |
906 | } | 913 | } |
907 | blocknr = c->node.blockptrs[slot]; | 914 | blocknr = c->node.blockptrs[slot]; |
915 | if (next) | ||
916 | tree_block_release(root, next); | ||
908 | next = read_tree_block(root, blocknr); | 917 | next = read_tree_block(root, blocknr); |
909 | break; | 918 | break; |
910 | } | 919 | } |
@@ -922,7 +931,7 @@ int next_leaf(struct ctree_root *root, struct ctree_path *path) | |||
922 | return 0; | 931 | return 0; |
923 | } | 932 | } |
924 | 933 | ||
925 | int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start, | 934 | int alloc_extent(struct ctree_root *orig_root, u64 num_blocks, u64 search_start, |
926 | u64 search_end, u64 owner, struct key *ins) | 935 | u64 search_end, u64 owner, struct key *ins) |
927 | { | 936 | { |
928 | struct ctree_path path; | 937 | struct ctree_path path; |
@@ -934,6 +943,7 @@ int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start, | |||
934 | int start_found = 0; | 943 | int start_found = 0; |
935 | struct leaf *l; | 944 | struct leaf *l; |
936 | struct extent_item extent_item; | 945 | struct extent_item extent_item; |
946 | struct ctree_root * root = orig_root->extent_root; | ||
937 | 947 | ||
938 | init_path(&path); | 948 | init_path(&path); |
939 | ins->objectid = search_start; | 949 | ins->objectid = search_start; |
@@ -974,13 +984,18 @@ int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start, | |||
974 | start_found = 1; | 984 | start_found = 1; |
975 | last_block = key->objectid + key->offset; | 985 | last_block = key->objectid + key->offset; |
976 | path.slots[0]++; | 986 | path.slots[0]++; |
977 | printf("last block is not %lu\n", last_block); | ||
978 | } | 987 | } |
979 | // FIXME -ENOSPC | 988 | // FIXME -ENOSPC |
980 | insert: | 989 | insert: |
990 | release_path(root, &path); | ||
981 | extent_item.refs = 1; | 991 | extent_item.refs = 1; |
982 | extent_item.owner = owner; | 992 | extent_item.owner = owner; |
983 | ret = insert_item(root, ins, &extent_item, sizeof(extent_item)); | 993 | if (root == orig_root && root->reserve_extent->num_blocks == 0) { |
994 | root->reserve_extent->blocknr = ins->objectid; | ||
995 | root->reserve_extent->num_blocks = ins->offset; | ||
996 | root->reserve_extent->num_used = 0; | ||
997 | } | ||
998 | ret = insert_item(root->extent_root, ins, &extent_item, sizeof(extent_item)); | ||
984 | return ret; | 999 | return ret; |
985 | } | 1000 | } |
986 | 1001 | ||
@@ -991,7 +1006,6 @@ static int refill_alloc_extent(struct ctree_root *root) | |||
991 | int ret; | 1006 | int ret; |
992 | int min_blocks = MAX_LEVEL * 2; | 1007 | int min_blocks = MAX_LEVEL * 2; |
993 | 1008 | ||
994 | printf("refill alloc root %p, numused %lu total %lu\n", root, ae->num_used, ae->num_blocks); | ||
995 | if (ae->num_blocks > ae->num_used && ae->num_blocks - ae->num_used > | 1009 | if (ae->num_blocks > ae->num_used && ae->num_blocks - ae->num_used > |
996 | min_blocks) | 1010 | min_blocks) |
997 | return 0; | 1011 | return 0; |
@@ -1007,9 +1021,9 @@ static int refill_alloc_extent(struct ctree_root *root) | |||
1007 | BUG(); | 1021 | BUG(); |
1008 | return 0; | 1022 | return 0; |
1009 | } | 1023 | } |
1010 | // FIXME, this recurses | 1024 | ret = alloc_extent(root, |
1011 | ret = alloc_extent(root->extent_root, | 1025 | min_blocks * 2, 0, (unsigned long)-1, |
1012 | min_blocks * 2, 0, (unsigned long)-1, 0, &key); | 1026 | root->node->node.header.parentid, &key); |
1013 | ae->blocknr = key.objectid; | 1027 | ae->blocknr = key.objectid; |
1014 | ae->num_blocks = key.offset; | 1028 | ae->num_blocks = key.offset; |
1015 | ae->num_used = 0; | 1029 | ae->num_used = 0; |
@@ -1021,6 +1035,7 @@ void print_leaf(struct leaf *l) | |||
1021 | int i; | 1035 | int i; |
1022 | int nr = l->header.nritems; | 1036 | int nr = l->header.nritems; |
1023 | struct item *item; | 1037 | struct item *item; |
1038 | struct extent_item *ei; | ||
1024 | printf("leaf %lu total ptrs %d free space %d\n", l->header.blocknr, nr, | 1039 | printf("leaf %lu total ptrs %d free space %d\n", l->header.blocknr, nr, |
1025 | leaf_free_space(l)); | 1040 | leaf_free_space(l)); |
1026 | fflush(stdout); | 1041 | fflush(stdout); |
@@ -1032,6 +1047,8 @@ void print_leaf(struct leaf *l) | |||
1032 | item->offset, item->size); | 1047 | item->offset, item->size); |
1033 | fflush(stdout); | 1048 | fflush(stdout); |
1034 | printf("\t\titem data %.*s\n", item->size, l->data+item->offset); | 1049 | printf("\t\titem data %.*s\n", item->size, l->data+item->offset); |
1050 | ei = (struct extent_item *)(l->data + item->offset); | ||
1051 | printf("\t\textent data %u %lu\n", ei->refs, ei->owner); | ||
1035 | fflush(stdout); | 1052 | fflush(stdout); |
1036 | } | 1053 | } |
1037 | } | 1054 | } |
@@ -1080,8 +1097,8 @@ void print_tree(struct ctree_root *root, struct tree_buffer *t) | |||
1080 | 1097 | ||
1081 | /* for testing only */ | 1098 | /* for testing only */ |
1082 | int next_key(int i, int max_key) { | 1099 | int next_key(int i, int max_key) { |
1083 | // return rand() % max_key; | 1100 | return rand() % max_key; |
1084 | return i; | 1101 | // return i; |
1085 | } | 1102 | } |
1086 | 1103 | ||
1087 | int main() { | 1104 | int main() { |
@@ -1092,15 +1109,20 @@ int main() { | |||
1092 | int i; | 1109 | int i; |
1093 | int num; | 1110 | int num; |
1094 | int ret; | 1111 | int ret; |
1095 | int run_size = 256; | 1112 | int run_size = 10000; |
1096 | int max_key = 100000000; | 1113 | int max_key = 100000000; |
1097 | int tree_size = 0; | 1114 | int tree_size = 0; |
1098 | struct ctree_path path; | 1115 | struct ctree_path path; |
1116 | struct ctree_super_block super; | ||
1099 | 1117 | ||
1100 | radix_tree_init(); | 1118 | radix_tree_init(); |
1101 | 1119 | ||
1102 | 1120 | ||
1103 | root = open_ctree("dbfile"); | 1121 | root = open_ctree("dbfile", &super); |
1122 | printf("root tree\n"); | ||
1123 | print_tree(root, root->node); | ||
1124 | printf("map tree\n"); | ||
1125 | print_tree(root->extent_root, root->extent_root->node); | ||
1104 | 1126 | ||
1105 | srand(55); | 1127 | srand(55); |
1106 | for (i = 0; i < run_size; i++) { | 1128 | for (i = 0; i < run_size; i++) { |
@@ -1112,22 +1134,20 @@ int main() { | |||
1112 | ins.objectid = num; | 1134 | ins.objectid = num; |
1113 | ins.offset = 0; | 1135 | ins.offset = 0; |
1114 | ins.flags = 0; | 1136 | ins.flags = 0; |
1115 | printf("insert %d\n", i); | ||
1116 | ret = insert_item(root, &ins, buf, strlen(buf)); | 1137 | ret = insert_item(root, &ins, buf, strlen(buf)); |
1117 | if (!ret) | 1138 | if (!ret) |
1118 | tree_size++; | 1139 | tree_size++; |
1119 | printf("done insert %d\n", i); | ||
1120 | } | 1140 | } |
1121 | printf("root used: %lu\n", root->alloc_extent->num_used); | 1141 | printf("root used: %lu\n", root->alloc_extent->num_used); |
1122 | printf("root tree\n"); | 1142 | printf("root tree\n"); |
1123 | print_tree(root, root->node); | 1143 | // print_tree(root, root->node); |
1124 | printf("map tree\n"); | 1144 | printf("map tree\n"); |
1125 | printf("map used: %lu\n", root->extent_root->alloc_extent->num_used); | 1145 | printf("map used: %lu\n", root->extent_root->alloc_extent->num_used); |
1126 | print_tree(root->extent_root, root->extent_root->node); | 1146 | // print_tree(root->extent_root, root->extent_root->node); |
1127 | exit(1); | 1147 | write_ctree_super(root, &super); |
1128 | |||
1129 | close_ctree(root); | 1148 | close_ctree(root); |
1130 | root = open_ctree("dbfile"); | 1149 | |
1150 | root = open_ctree("dbfile", &super); | ||
1131 | printf("starting search\n"); | 1151 | printf("starting search\n"); |
1132 | srand(55); | 1152 | srand(55); |
1133 | for (i = 0; i < run_size; i++) { | 1153 | for (i = 0; i < run_size; i++) { |
@@ -1142,8 +1162,9 @@ int main() { | |||
1142 | } | 1162 | } |
1143 | release_path(root, &path); | 1163 | release_path(root, &path); |
1144 | } | 1164 | } |
1165 | write_ctree_super(root, &super); | ||
1145 | close_ctree(root); | 1166 | close_ctree(root); |
1146 | root = open_ctree("dbfile"); | 1167 | root = open_ctree("dbfile", &super); |
1147 | printf("node %p level %d total ptrs %d free spc %lu\n", root->node, | 1168 | printf("node %p level %d total ptrs %d free spc %lu\n", root->node, |
1148 | node_level(root->node->node.header.flags), | 1169 | node_level(root->node->node.header.flags), |
1149 | root->node->node.header.nritems, | 1170 | root->node->node.header.nritems, |
@@ -1174,8 +1195,9 @@ int main() { | |||
1174 | if (!ret) | 1195 | if (!ret) |
1175 | tree_size++; | 1196 | tree_size++; |
1176 | } | 1197 | } |
1198 | write_ctree_super(root, &super); | ||
1177 | close_ctree(root); | 1199 | close_ctree(root); |
1178 | root = open_ctree("dbfile"); | 1200 | root = open_ctree("dbfile", &super); |
1179 | printf("starting search2\n"); | 1201 | printf("starting search2\n"); |
1180 | srand(128); | 1202 | srand(128); |
1181 | for (i = 0; i < run_size; i++) { | 1203 | for (i = 0; i < run_size; i++) { |
@@ -1221,6 +1243,7 @@ int main() { | |||
1221 | } | 1243 | } |
1222 | release_path(root, &path); | 1244 | release_path(root, &path); |
1223 | } | 1245 | } |
1246 | write_ctree_super(root, &super); | ||
1224 | close_ctree(root); | 1247 | close_ctree(root); |
1225 | printf("tree size is now %d\n", tree_size); | 1248 | printf("tree size is now %d\n", tree_size); |
1226 | return 0; | 1249 | return 0; |