aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/ctree.c
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-02-20 16:40:44 -0500
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-02-20 16:40:44 -0500
commitd97e63b69ef21c02b67e20e41d9968b0e503572e (patch)
tree400db046be21c09f2d96f74ff98677464c45507f /fs/btrfs/ctree.c
parent74123bd72a4e34c66e5ad95ce233dd352bebc572 (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.c152
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
8static int refill_alloc_extent(struct ctree_root *root);
9
8static inline void init_path(struct ctree_path *p) 10static 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
890int 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
925int 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
980insert:
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
987static 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
887void print_leaf(struct leaf *l) 1019void 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 */
950int next_key(int i, int max_key) { 1082int 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
955int main() { 1087int 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");