aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-02-21 17:04:57 -0500
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-02-21 17:04:57 -0500
commitcfaa72952fa7b44aa5d967cbc266110900552aef (patch)
tree7ca429e7417d168faa57dab4bc069c23fefb5cc4 /fs
parent06ed4b316e8e24b6899ece7186c6a7a0129326ba (diff)
Btrfs: extent fixes
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.c69
-rw-r--r--fs/btrfs/ctree.h5
-rw-r--r--fs/btrfs/disk-io.c79
-rw-r--r--fs/btrfs/disk-io.h4
-rw-r--r--fs/btrfs/mkfs.c7
5 files changed, 103 insertions, 61 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
925int alloc_extent(struct ctree_root *root, u64 num_blocks, u64 search_start, 934int 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
980insert: 989insert:
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 */
1082int next_key(int i, int max_key) { 1099int 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
1087int main() { 1104int 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;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index b737925be314..78407d32db78 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -57,6 +57,11 @@ struct ctree_root_info {
57 u64 snapuuid[2]; /* root specific uuid */ 57 u64 snapuuid[2]; /* root specific uuid */
58} __attribute__ ((__packed__)); 58} __attribute__ ((__packed__));
59 59
60struct ctree_super_block {
61 struct ctree_root_info root_info;
62 struct ctree_root_info extent_info;
63} __attribute__ ((__packed__));
64
60struct item { 65struct item {
61 struct key key; 66 struct key key;
62 u16 offset; 67 u16 offset;
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 653f18aab330..2f71ccf1c3cb 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -15,7 +15,7 @@ static int allocated_blocks = 0;
15static int get_free_block(struct ctree_root *root, u64 *block) 15static int get_free_block(struct ctree_root *root, u64 *block)
16{ 16{
17 struct stat st; 17 struct stat st;
18 int ret; 18 int ret = 0;
19 19
20 if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks) 20 if (root->alloc_extent->num_used >= root->alloc_extent->num_blocks)
21 return -1; 21 return -1;
@@ -30,9 +30,14 @@ static int get_free_block(struct ctree_root *root, u64 *block)
30 } 30 }
31 st.st_size = 0; 31 st.st_size = 0;
32 ret = fstat(root->fp, &st); 32 ret = fstat(root->fp, &st);
33 if (st.st_size < (*block + 1) * CTREE_BLOCKSIZE) 33 if (st.st_size < (*block + 1) * CTREE_BLOCKSIZE) {
34 ret = ftruncate(root->fp, 34 ret = ftruncate(root->fp,
35 (*block + 1) * CTREE_BLOCKSIZE); 35 (*block + 1) * CTREE_BLOCKSIZE);
36 if (ret) {
37 perror("ftruncate");
38 exit(1);
39 }
40 }
36 return ret; 41 return ret;
37} 42}
38 43
@@ -81,11 +86,7 @@ struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr)
81 buf = radix_tree_lookup(&root->cache_radix, blocknr); 86 buf = radix_tree_lookup(&root->cache_radix, blocknr);
82 if (buf) { 87 if (buf) {
83 buf->count++; 88 buf->count++;
84 if (buf->blocknr != blocknr) 89 goto test;
85 BUG();
86 if (buf->blocknr != buf->node.header.blocknr)
87 BUG();
88 return buf;
89 } 90 }
90 buf = alloc_tree_block(root, blocknr); 91 buf = alloc_tree_block(root, blocknr);
91 if (!buf) 92 if (!buf)
@@ -95,8 +96,11 @@ struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr)
95 free(buf); 96 free(buf);
96 return NULL; 97 return NULL;
97 } 98 }
99test:
98 if (buf->blocknr != buf->node.header.blocknr) 100 if (buf->blocknr != buf->node.header.blocknr)
99 BUG(); 101 BUG();
102 if (root->node && buf->node.header.parentid != root->node->node.header.parentid)
103 BUG();
100 return buf; 104 return buf;
101} 105}
102 106
@@ -111,36 +115,30 @@ int write_tree_block(struct ctree_root *root, struct tree_buffer *buf)
111 ret = pwrite(root->fp, &buf->node, CTREE_BLOCKSIZE, offset); 115 ret = pwrite(root->fp, &buf->node, CTREE_BLOCKSIZE, offset);
112 if (ret != CTREE_BLOCKSIZE) 116 if (ret != CTREE_BLOCKSIZE)
113 return ret; 117 return ret;
114 if (buf == root->node)
115 return update_root_block(root);
116 return 0; 118 return 0;
117} 119}
118 120
119struct ctree_super_block {
120 struct ctree_root_info root_info;
121 struct ctree_root_info extent_info;
122} __attribute__ ((__packed__));
123
124static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root, 121static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root,
125 struct ctree_root_info *info, int fp) 122 struct ctree_root_info *info, int fp)
126{ 123{
124 INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL);
127 root->fp = fp; 125 root->fp = fp;
126 root->node = NULL;
128 root->node = read_tree_block(root, info->tree_root); 127 root->node = read_tree_block(root, info->tree_root);
129 root->extent_root = extent_root; 128 root->extent_root = extent_root;
130 memcpy(&root->ai1, &info->alloc_extent, sizeof(info->alloc_extent)); 129 memcpy(&root->ai1, &info->alloc_extent, sizeof(info->alloc_extent));
131 memcpy(&root->ai2, &info->reserve_extent, sizeof(info->reserve_extent)); 130 memcpy(&root->ai2, &info->reserve_extent, sizeof(info->reserve_extent));
132 root->alloc_extent = &root->ai1; 131 root->alloc_extent = &root->ai1;
133 root->reserve_extent = &root->ai2; 132 root->reserve_extent = &root->ai2;
134 INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); 133 printf("setup done reading root %p, used %lu available %lu\n", root, root->alloc_extent->num_used, root->alloc_extent->num_blocks);
135 printf("setup done reading root %p, used %lu\n", root, root->alloc_extent->num_used); 134 printf("setup done reading root %p, reserve used %lu available %lu\n", root, root->reserve_extent->num_used, root->reserve_extent->num_blocks);
136 return 0; 135 return 0;
137} 136}
138 137
139struct ctree_root *open_ctree(char *filename) 138struct ctree_root *open_ctree(char *filename, struct ctree_super_block *super)
140{ 139{
141 struct ctree_root *root = malloc(sizeof(struct ctree_root)); 140 struct ctree_root *root = malloc(sizeof(struct ctree_root));
142 struct ctree_root *extent_root = malloc(sizeof(struct ctree_root)); 141 struct ctree_root *extent_root = malloc(sizeof(struct ctree_root));
143 struct ctree_super_block super;
144 int fp; 142 int fp;
145 int ret; 143 int ret;
146 144
@@ -149,48 +147,61 @@ struct ctree_root *open_ctree(char *filename)
149 free(root); 147 free(root);
150 return NULL; 148 return NULL;
151 } 149 }
152 ret = pread(fp, &super, sizeof(struct ctree_super_block), 150 ret = pread(fp, super, sizeof(struct ctree_super_block),
153 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); 151 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
154 if (ret == 0) { 152 if (ret == 0) {
155 ret = mkfs(fp); 153 ret = mkfs(fp);
156 if (ret) 154 if (ret)
157 return NULL; 155 return NULL;
158 ret = pread(fp, &super, sizeof(struct ctree_super_block), 156 ret = pread(fp, super, sizeof(struct ctree_super_block),
159 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); 157 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
160 if (ret != sizeof(struct ctree_super_block)) 158 if (ret != sizeof(struct ctree_super_block))
161 return NULL; 159 return NULL;
162 } 160 }
163 BUG_ON(ret < 0); 161 BUG_ON(ret < 0);
164 __setup_root(root, extent_root, &super.root_info, fp); 162 __setup_root(root, extent_root, &super->root_info, fp);
165 __setup_root(extent_root, extent_root, &super.extent_info, fp); 163 __setup_root(extent_root, extent_root, &super->extent_info, fp);
166 return root; 164 return root;
167} 165}
168 166
169int close_ctree(struct ctree_root *root) 167static int __update_root(struct ctree_root *root, struct ctree_root_info *info)
170{ 168{
171 close(root->fp); 169 info->tree_root = root->node->blocknr;
172 if (root->node) 170 memcpy(&info->alloc_extent, root->alloc_extent, sizeof(struct alloc_extent));
173 tree_block_release(root, root->node); 171 memcpy(&info->reserve_extent, root->reserve_extent, sizeof(struct alloc_extent));
174 free(root);
175 printf("on close %d blocks are allocated\n", allocated_blocks);
176 return 0; 172 return 0;
177} 173}
178 174
179int update_root_block(struct ctree_root *root) 175int write_ctree_super(struct ctree_root *root, struct ctree_super_block *s)
180{ 176{
181 int ret; 177 int ret;
182 u64 root_block = root->node->blocknr; 178 __update_root(root, &s->root_info);
183 179 __update_root(root->extent_root, &s->extent_info);
184 ret = pwrite(root->fp, &root_block, sizeof(u64), 0); 180 ret = pwrite(root->fp, s, sizeof(*s), CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
185 if (ret != sizeof(u64)) 181 if (ret != sizeof(*s)) {
182 fprintf(stderr, "failed to write new super block err %d\n", ret);
186 return ret; 183 return ret;
184 }
185 return 0;
186}
187
188int close_ctree(struct ctree_root *root)
189{
190 close(root->fp);
191 if (root->node)
192 tree_block_release(root, root->node);
193 if (root->extent_root->node)
194 tree_block_release(root->extent_root, root->extent_root->node);
195 free(root);
196 printf("on close %d blocks are allocated\n", allocated_blocks);
187 return 0; 197 return 0;
188} 198}
189 199
190void tree_block_release(struct ctree_root *root, struct tree_buffer *buf) 200void tree_block_release(struct ctree_root *root, struct tree_buffer *buf)
191{ 201{
192 return;
193 buf->count--; 202 buf->count--;
203 if (buf->count < 0)
204 BUG();
194 if (buf->count == 0) { 205 if (buf->count == 0) {
195 if (!radix_tree_lookup(&root->cache_radix, buf->blocknr)) 206 if (!radix_tree_lookup(&root->cache_radix, buf->blocknr))
196 BUG(); 207 BUG();
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 41acb65eee19..e288fe883b9a 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -12,11 +12,11 @@ struct tree_buffer {
12 12
13struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr); 13struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr);
14int write_tree_block(struct ctree_root *root, struct tree_buffer *buf); 14int write_tree_block(struct ctree_root *root, struct tree_buffer *buf);
15struct ctree_root *open_ctree(char *filename); 15struct ctree_root *open_ctree(char *filename, struct ctree_super_block *s);
16int close_ctree(struct ctree_root *root); 16int close_ctree(struct ctree_root *root);
17void tree_block_release(struct ctree_root *root, struct tree_buffer *buf); 17void tree_block_release(struct ctree_root *root, struct tree_buffer *buf);
18struct tree_buffer *alloc_free_block(struct ctree_root *root); 18struct tree_buffer *alloc_free_block(struct ctree_root *root);
19int update_root_block(struct ctree_root *root); 19int write_ctree_super(struct ctree_root *root, struct ctree_super_block *s);
20int mkfs(int fd); 20int mkfs(int fd);
21 21
22#define CTREE_SUPER_INFO_OFFSET(bs) (16 * (bs)) 22#define CTREE_SUPER_INFO_OFFSET(bs) (16 * (bs))
diff --git a/fs/btrfs/mkfs.c b/fs/btrfs/mkfs.c
index bab98c6d6fa7..584aba44e801 100644
--- a/fs/btrfs/mkfs.c
+++ b/fs/btrfs/mkfs.c
@@ -18,12 +18,13 @@ int mkfs(int fd)
18 struct extent_item extent_item; 18 struct extent_item extent_item;
19 int ret; 19 int ret;
20 20
21 /* setup the super block area */
21 memset(info, 0, sizeof(info)); 22 memset(info, 0, sizeof(info));
22 info[0].blocknr = 16; 23 info[0].blocknr = 16;
23 info[0].objectid = 1; 24 info[0].objectid = 1;
24 info[0].tree_root = 17; 25 info[0].tree_root = 17;
25 info[0].alloc_extent.blocknr = 0; 26 info[0].alloc_extent.blocknr = 0;
26 info[0].alloc_extent.num_blocks = 20; 27 info[0].alloc_extent.num_blocks = 64;
27 /* 0-17 are used (inclusive) */ 28 /* 0-17 are used (inclusive) */
28 info[0].alloc_extent.num_used = 18; 29 info[0].alloc_extent.num_used = 18;
29 30
@@ -31,12 +32,14 @@ int mkfs(int fd)
31 info[1].objectid = 2; 32 info[1].objectid = 2;
32 info[1].tree_root = 64; 33 info[1].tree_root = 64;
33 info[1].alloc_extent.blocknr = 64; 34 info[1].alloc_extent.blocknr = 64;
34 info[1].alloc_extent.num_blocks = 8; 35 info[1].alloc_extent.num_blocks = 64;
35 info[1].alloc_extent.num_used = 1; 36 info[1].alloc_extent.num_used = 1;
36 ret = pwrite(fd, info, sizeof(info), 37 ret = pwrite(fd, info, sizeof(info),
37 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE)); 38 CTREE_SUPER_INFO_OFFSET(CTREE_BLOCKSIZE));
38 if (ret != sizeof(info)) 39 if (ret != sizeof(info))
39 return -1; 40 return -1;
41
42 /* create leaves for the tree root and extent root */
40 memset(&empty_leaf, 0, sizeof(empty_leaf)); 43 memset(&empty_leaf, 0, sizeof(empty_leaf));
41 empty_leaf.header.parentid = 1; 44 empty_leaf.header.parentid = 1;
42 empty_leaf.header.blocknr = 17; 45 empty_leaf.header.blocknr = 17;