diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/ctree.c | 69 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 5 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 79 | ||||
-rw-r--r-- | fs/btrfs/disk-io.h | 4 | ||||
-rw-r--r-- | fs/btrfs/mkfs.c | 7 |
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 | ||
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; |
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 | ||
60 | struct ctree_super_block { | ||
61 | struct ctree_root_info root_info; | ||
62 | struct ctree_root_info extent_info; | ||
63 | } __attribute__ ((__packed__)); | ||
64 | |||
60 | struct item { | 65 | struct 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; | |||
15 | static int get_free_block(struct ctree_root *root, u64 *block) | 15 | static 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 | } |
99 | test: | ||
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 | ||
119 | struct ctree_super_block { | ||
120 | struct ctree_root_info root_info; | ||
121 | struct ctree_root_info extent_info; | ||
122 | } __attribute__ ((__packed__)); | ||
123 | |||
124 | static int __setup_root(struct ctree_root *root, struct ctree_root *extent_root, | 121 | static 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 | ||
139 | struct ctree_root *open_ctree(char *filename) | 138 | struct 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 | ||
169 | int close_ctree(struct ctree_root *root) | 167 | static 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 | ||
179 | int update_root_block(struct ctree_root *root) | 175 | int 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 | |||
188 | int 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 | ||
190 | void tree_block_release(struct ctree_root *root, struct tree_buffer *buf) | 200 | void 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 | ||
13 | struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr); | 13 | struct tree_buffer *read_tree_block(struct ctree_root *root, u64 blocknr); |
14 | int write_tree_block(struct ctree_root *root, struct tree_buffer *buf); | 14 | int write_tree_block(struct ctree_root *root, struct tree_buffer *buf); |
15 | struct ctree_root *open_ctree(char *filename); | 15 | struct ctree_root *open_ctree(char *filename, struct ctree_super_block *s); |
16 | int close_ctree(struct ctree_root *root); | 16 | int close_ctree(struct ctree_root *root); |
17 | void tree_block_release(struct ctree_root *root, struct tree_buffer *buf); | 17 | void tree_block_release(struct ctree_root *root, struct tree_buffer *buf); |
18 | struct tree_buffer *alloc_free_block(struct ctree_root *root); | 18 | struct tree_buffer *alloc_free_block(struct ctree_root *root); |
19 | int update_root_block(struct ctree_root *root); | 19 | int write_ctree_super(struct ctree_root *root, struct ctree_super_block *s); |
20 | int mkfs(int fd); | 20 | int 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; |