diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-02-20 16:40:44 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-02-20 16:40:44 -0500 |
commit | d97e63b69ef21c02b67e20e41d9968b0e503572e (patch) | |
tree | 400db046be21c09f2d96f74ff98677464c45507f /fs/btrfs/ctree.c | |
parent | 74123bd72a4e34c66e5ad95ce233dd352bebc572 (diff) |
Btrfs: early extent mapping support
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 152 |
1 files changed, 147 insertions, 5 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 6b64f49a0279..2177744dedd3 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -5,6 +5,8 @@ | |||
5 | #include "ctree.h" | 5 | #include "ctree.h" |
6 | #include "disk-io.h" | 6 | #include "disk-io.h" |
7 | 7 | ||
8 | static int refill_alloc_extent(struct ctree_root *root); | ||
9 | |||
8 | static inline void init_path(struct ctree_path *p) | 10 | static inline void init_path(struct ctree_path *p) |
9 | { | 11 | { |
10 | memset(p, 0, sizeof(*p)); | 12 | memset(p, 0, sizeof(*p)); |
@@ -29,7 +31,7 @@ static inline unsigned int leaf_data_end(struct leaf *leaf) | |||
29 | { | 31 | { |
30 | unsigned int nr = leaf->header.nritems; | 32 | unsigned int nr = leaf->header.nritems; |
31 | if (nr == 0) | 33 | if (nr == 0) |
32 | return ARRAY_SIZE(leaf->data); | 34 | return sizeof(leaf->data); |
33 | return leaf->items[nr-1].offset; | 35 | return leaf->items[nr-1].offset; |
34 | } | 36 | } |
35 | 37 | ||
@@ -421,7 +423,7 @@ int insert_ptr(struct ctree_root *root, | |||
421 | * due to splitting. Once we've done all the splitting required | 423 | * due to splitting. Once we've done all the splitting required |
422 | * do the inserts based on the data in the bal array. | 424 | * do the inserts based on the data in the bal array. |
423 | */ | 425 | */ |
424 | memset(bal, 0, ARRAY_SIZE(bal)); | 426 | memset(bal, 0, sizeof(bal)); |
425 | while(t && t->node.header.nritems == NODEPTRS_PER_BLOCK) { | 427 | while(t && t->node.header.nritems == NODEPTRS_PER_BLOCK) { |
426 | c = &t->node; | 428 | c = &t->node; |
427 | if (push_node_left(root, path, | 429 | if (push_node_left(root, path, |
@@ -756,6 +758,7 @@ int insert_item(struct ctree_root *root, struct key *key, | |||
756 | if (leaf_free_space(leaf) < 0) | 758 | if (leaf_free_space(leaf) < 0) |
757 | BUG(); | 759 | BUG(); |
758 | release_path(root, &path); | 760 | release_path(root, &path); |
761 | refill_alloc_extent(root); | ||
759 | return 0; | 762 | return 0; |
760 | } | 763 | } |
761 | 764 | ||
@@ -884,6 +887,135 @@ int del_item(struct ctree_root *root, struct ctree_path *path) | |||
884 | return 0; | 887 | return 0; |
885 | } | 888 | } |
886 | 889 | ||
890 | int next_leaf(struct ctree_root *root, struct ctree_path *path) | ||
891 | { | ||
892 | int slot; | ||
893 | int level = 1; | ||
894 | u64 blocknr; | ||
895 | struct tree_buffer *c; | ||
896 | struct tree_buffer *next; | ||
897 | |||
898 | while(level < MAX_LEVEL) { | ||
899 | if (!path->nodes[level]) | ||
900 | return -1; | ||
901 | slot = path->slots[level] + 1; | ||
902 | c = path->nodes[level]; | ||
903 | if (slot >= c->node.header.nritems) { | ||
904 | level++; | ||
905 | continue; | ||
906 | } | ||
907 | blocknr = c->node.blockptrs[slot]; | ||
908 | next = read_tree_block(root, blocknr); | ||
909 | break; | ||
910 | } | ||
911 | path->slots[level] = slot; | ||
912 | while(1) { | ||
913 | level--; | ||
914 | c = path->nodes[level]; | ||
915 | tree_block_release(root, c); | ||
916 | path->nodes[level] = next; | ||
917 | path->slots[level] = 0; | ||
918 | if (!level) | ||
919 | break; | ||
920 | next = read_tree_block(root, next->node.blockptrs[0]); | ||
921 | } | ||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start, | ||
926 | u64 search_end, u64 owner, struct key *ins) | ||
927 | { | ||
928 | struct ctree_path path; | ||
929 | struct key *key; | ||
930 | int ret; | ||
931 | u64 hole_size = 0; | ||
932 | int slot = 0; | ||
933 | u64 last_block; | ||
934 | int start_found = 0; | ||
935 | struct leaf *l; | ||
936 | struct extent_item extent_item; | ||
937 | |||
938 | init_path(&path); | ||
939 | ins->objectid = search_start; | ||
940 | ins->offset = 0; | ||
941 | ins->flags = 0; | ||
942 | |||
943 | ret = search_slot(root, ins, &path); | ||
944 | while (1) { | ||
945 | l = &path.nodes[0]->leaf; | ||
946 | slot = path.slots[0]; | ||
947 | if (!l) { | ||
948 | // FIXME allocate root | ||
949 | } | ||
950 | if (slot >= l->header.nritems) { | ||
951 | ret = next_leaf(root, &path); | ||
952 | if (ret == 0) | ||
953 | continue; | ||
954 | if (!start_found) { | ||
955 | ins->objectid = search_start; | ||
956 | ins->offset = num_blocks; | ||
957 | hole_size = search_end - search_start; | ||
958 | goto insert; | ||
959 | } | ||
960 | ins->objectid = last_block; | ||
961 | ins->offset = num_blocks; | ||
962 | hole_size = search_end - last_block; | ||
963 | goto insert; | ||
964 | } | ||
965 | key = &l->items[slot].key; | ||
966 | if (start_found) { | ||
967 | hole_size = key->objectid - last_block; | ||
968 | if (hole_size > num_blocks) { | ||
969 | ins->objectid = last_block; | ||
970 | ins->offset = num_blocks; | ||
971 | goto insert; | ||
972 | } | ||
973 | } else | ||
974 | start_found = 1; | ||
975 | last_block = key->objectid + key->offset; | ||
976 | path.slots[0]++; | ||
977 | printf("last block is not %lu\n", last_block); | ||
978 | } | ||
979 | // FIXME -ENOSPC | ||
980 | insert: | ||
981 | extent_item.refs = 1; | ||
982 | extent_item.owner = owner; | ||
983 | ret = insert_item(root, ins, &extent_item, sizeof(extent_item)); | ||
984 | return ret; | ||
985 | } | ||
986 | |||
987 | static int refill_alloc_extent(struct ctree_root *root) | ||
988 | { | ||
989 | struct alloc_extent *ae = root->alloc_extent; | ||
990 | struct key key; | ||
991 | int ret; | ||
992 | int min_blocks = MAX_LEVEL * 2; | ||
993 | |||
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 > | ||
996 | min_blocks) | ||
997 | return 0; | ||
998 | ae = root->reserve_extent; | ||
999 | if (ae->num_blocks > ae->num_used) { | ||
1000 | if (root->alloc_extent->num_blocks == 0) { | ||
1001 | /* we should swap reserve/alloc_extent when alloc | ||
1002 | * fills up | ||
1003 | */ | ||
1004 | BUG(); | ||
1005 | } | ||
1006 | if (ae->num_blocks - ae->num_used < min_blocks) | ||
1007 | BUG(); | ||
1008 | return 0; | ||
1009 | } | ||
1010 | // FIXME, this recurses | ||
1011 | ret = alloc_extent(root->extent_root, | ||
1012 | min_blocks * 2, 0, (unsigned long)-1, 0, &key); | ||
1013 | ae->blocknr = key.objectid; | ||
1014 | ae->num_blocks = key.offset; | ||
1015 | ae->num_used = 0; | ||
1016 | return ret; | ||
1017 | } | ||
1018 | |||
887 | void print_leaf(struct leaf *l) | 1019 | void print_leaf(struct leaf *l) |
888 | { | 1020 | { |
889 | int i; | 1021 | int i; |
@@ -948,8 +1080,8 @@ void print_tree(struct ctree_root *root, struct tree_buffer *t) | |||
948 | 1080 | ||
949 | /* for testing only */ | 1081 | /* for testing only */ |
950 | int next_key(int i, int max_key) { | 1082 | int next_key(int i, int max_key) { |
951 | return rand() % max_key; | 1083 | // return rand() % max_key; |
952 | // return i; | 1084 | return i; |
953 | } | 1085 | } |
954 | 1086 | ||
955 | int main() { | 1087 | int main() { |
@@ -960,7 +1092,7 @@ int main() { | |||
960 | int i; | 1092 | int i; |
961 | int num; | 1093 | int num; |
962 | int ret; | 1094 | int ret; |
963 | int run_size = 25000; | 1095 | int run_size = 256; |
964 | int max_key = 100000000; | 1096 | int max_key = 100000000; |
965 | int tree_size = 0; | 1097 | int tree_size = 0; |
966 | struct ctree_path path; | 1098 | struct ctree_path path; |
@@ -980,10 +1112,20 @@ int main() { | |||
980 | ins.objectid = num; | 1112 | ins.objectid = num; |
981 | ins.offset = 0; | 1113 | ins.offset = 0; |
982 | ins.flags = 0; | 1114 | ins.flags = 0; |
1115 | printf("insert %d\n", i); | ||
983 | ret = insert_item(root, &ins, buf, strlen(buf)); | 1116 | ret = insert_item(root, &ins, buf, strlen(buf)); |
984 | if (!ret) | 1117 | if (!ret) |
985 | tree_size++; | 1118 | tree_size++; |
1119 | printf("done insert %d\n", i); | ||
986 | } | 1120 | } |
1121 | printf("root used: %lu\n", root->alloc_extent->num_used); | ||
1122 | printf("root tree\n"); | ||
1123 | print_tree(root, root->node); | ||
1124 | printf("map tree\n"); | ||
1125 | printf("map used: %lu\n", root->extent_root->alloc_extent->num_used); | ||
1126 | print_tree(root->extent_root, root->extent_root->node); | ||
1127 | exit(1); | ||
1128 | |||
987 | close_ctree(root); | 1129 | close_ctree(root); |
988 | root = open_ctree("dbfile"); | 1130 | root = open_ctree("dbfile"); |
989 | printf("starting search\n"); | 1131 | printf("starting search\n"); |