diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-03-20 14:38:32 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-03-20 14:38:32 -0400 |
commit | 9f5fae2fe6dc35b46bf56183f11398451851cb3f (patch) | |
tree | e72b03149662b8e5d4fe491c36f3cf66c5df5437 /fs/btrfs | |
parent | 631d7d950a2f2706f5c86858402c1ec50b9801f1 (diff) |
Btrfs: Add inode map, and the start of file extent items
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/Makefile | 3 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 129 | ||||
-rw-r--r-- | fs/btrfs/debug-tree.c | 9 | ||||
-rw-r--r-- | fs/btrfs/dir-test.c | 91 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 176 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 105 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 6 | ||||
-rw-r--r-- | fs/btrfs/inode-map.c | 136 | ||||
-rw-r--r-- | fs/btrfs/mkfs.c | 44 | ||||
-rw-r--r-- | fs/btrfs/print-tree.c | 13 | ||||
-rw-r--r-- | fs/btrfs/quick-test.c | 3 |
11 files changed, 542 insertions, 173 deletions
diff --git a/fs/btrfs/Makefile b/fs/btrfs/Makefile index 7953b41848c1..636c63efde6f 100644 --- a/fs/btrfs/Makefile +++ b/fs/btrfs/Makefile | |||
@@ -3,7 +3,8 @@ CFLAGS = -g -Wall -Werror | |||
3 | headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h \ | 3 | headers = radix-tree.h ctree.h disk-io.h kerncompat.h print-tree.h list.h \ |
4 | transaction.h | 4 | transaction.h |
5 | objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o \ | 5 | objects = ctree.o disk-io.o radix-tree.o mkfs.o extent-tree.o print-tree.o \ |
6 | root-tree.o dir-item.o hash.o file-item.o inode-item.o | 6 | root-tree.o dir-item.o hash.o file-item.o inode-item.o \ |
7 | inode-map.o \ | ||
7 | 8 | ||
8 | # if you don't have sparse installed, use ls instead | 9 | # if you don't have sparse installed, use ls instead |
9 | CHECKFLAGS=-D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \ | 10 | CHECKFLAGS=-D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ -Wbitwise \ |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 68f0af39777f..68e3da274f17 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -10,7 +10,8 @@ struct btrfs_trans_handle; | |||
10 | 10 | ||
11 | #define BTRFS_ROOT_TREE_OBJECTID 1 | 11 | #define BTRFS_ROOT_TREE_OBJECTID 1 |
12 | #define BTRFS_EXTENT_TREE_OBJECTID 2 | 12 | #define BTRFS_EXTENT_TREE_OBJECTID 2 |
13 | #define BTRFS_FS_TREE_OBJECTID 3 | 13 | #define BTRFS_INODE_MAP_OBJECTID 3 |
14 | #define BTRFS_FS_TREE_OBJECTID 4 | ||
14 | 15 | ||
15 | /* | 16 | /* |
16 | * the key defines the order in the tree, and so it also defines (optimal) | 17 | * the key defines the order in the tree, and so it also defines (optimal) |
@@ -178,31 +179,65 @@ struct btrfs_root_item { | |||
178 | __le64 block_limit; | 179 | __le64 block_limit; |
179 | __le64 blocks_used; | 180 | __le64 blocks_used; |
180 | __le32 refs; | 181 | __le32 refs; |
181 | }; | 182 | } __attribute__ ((__packed__)); |
182 | 183 | ||
183 | /* | 184 | struct btrfs_file_extent_item { |
184 | * in ram representation of the tree. extent_root is used for all allocations | 185 | /* |
185 | * and for the extent tree extent_root root. current_insert is used | 186 | * disk space consumed by the extent, checksum blocks are included |
186 | * only for the extent tree. | 187 | * in these numbers |
187 | */ | 188 | */ |
188 | struct btrfs_root { | 189 | __le64 disk_blocknr; |
189 | struct btrfs_buffer *node; | 190 | __le64 disk_num_blocks; |
190 | struct btrfs_buffer *commit_root; | 191 | /* |
192 | * the logical offset in file bytes (no csums) | ||
193 | * this extent record is for. This allows a file extent to point | ||
194 | * into the middle of an existing extent on disk, sharing it | ||
195 | * between two snapshots (useful if some bytes in the middle of the | ||
196 | * extent have changed | ||
197 | */ | ||
198 | __le64 offset; | ||
199 | /* | ||
200 | * the logical number of file blocks (no csums included) | ||
201 | */ | ||
202 | __le64 num_blocks; | ||
203 | } __attribute__ ((__packed__)); | ||
204 | |||
205 | struct btrfs_inode_map_item { | ||
206 | struct btrfs_disk_key key; | ||
207 | } __attribute__ ((__packed__)); | ||
208 | |||
209 | struct btrfs_fs_info { | ||
210 | struct btrfs_root *fs_root; | ||
191 | struct btrfs_root *extent_root; | 211 | struct btrfs_root *extent_root; |
192 | struct btrfs_root *tree_root; | 212 | struct btrfs_root *tree_root; |
213 | struct btrfs_root *inode_root; | ||
193 | struct btrfs_key current_insert; | 214 | struct btrfs_key current_insert; |
194 | struct btrfs_key last_insert; | 215 | struct btrfs_key last_insert; |
195 | int fp; | ||
196 | struct radix_tree_root cache_radix; | 216 | struct radix_tree_root cache_radix; |
197 | struct radix_tree_root pinned_radix; | 217 | struct radix_tree_root pinned_radix; |
198 | struct list_head trans; | 218 | struct list_head trans; |
199 | struct list_head cache; | 219 | struct list_head cache; |
220 | u64 last_inode_alloc; | ||
221 | u64 last_inode_alloc_dirid; | ||
200 | int cache_size; | 222 | int cache_size; |
201 | int ref_cows; | 223 | int fp; |
224 | struct btrfs_trans_handle *running_transaction; | ||
225 | }; | ||
226 | |||
227 | /* | ||
228 | * in ram representation of the tree. extent_root is used for all allocations | ||
229 | * and for the extent tree extent_root root. current_insert is used | ||
230 | * only for the extent tree. | ||
231 | */ | ||
232 | struct btrfs_root { | ||
233 | struct btrfs_buffer *node; | ||
234 | struct btrfs_buffer *commit_root; | ||
202 | struct btrfs_root_item root_item; | 235 | struct btrfs_root_item root_item; |
203 | struct btrfs_key root_key; | 236 | struct btrfs_key root_key; |
237 | struct btrfs_fs_info *fs_info; | ||
204 | u32 blocksize; | 238 | u32 blocksize; |
205 | struct btrfs_trans_handle *running_transaction; | 239 | int ref_cows; |
240 | u32 type; | ||
206 | }; | 241 | }; |
207 | 242 | ||
208 | /* the lower bits in the key flags defines the item type */ | 243 | /* the lower bits in the key flags defines the item type */ |
@@ -240,11 +275,17 @@ struct btrfs_root { | |||
240 | * are used, and how many references there are to each block | 275 | * are used, and how many references there are to each block |
241 | */ | 276 | */ |
242 | #define BTRFS_EXTENT_ITEM_KEY 6 | 277 | #define BTRFS_EXTENT_ITEM_KEY 6 |
278 | |||
279 | /* | ||
280 | * the inode map records which inode numbers are in use and where | ||
281 | * they actually live on disk | ||
282 | */ | ||
283 | #define BTRFS_INODE_MAP_ITEM_KEY 7 | ||
243 | /* | 284 | /* |
244 | * string items are for debugging. They just store a short string of | 285 | * string items are for debugging. They just store a short string of |
245 | * data in the FS | 286 | * data in the FS |
246 | */ | 287 | */ |
247 | #define BTRFS_STRING_ITEM_KEY 7 | 288 | #define BTRFS_STRING_ITEM_KEY 8 |
248 | 289 | ||
249 | static inline u64 btrfs_inode_generation(struct btrfs_inode_item *i) | 290 | static inline u64 btrfs_inode_generation(struct btrfs_inode_item *i) |
250 | { | 291 | { |
@@ -654,6 +695,57 @@ static inline u8 *btrfs_leaf_data(struct btrfs_leaf *l) | |||
654 | { | 695 | { |
655 | return (u8 *)l->items; | 696 | return (u8 *)l->items; |
656 | } | 697 | } |
698 | |||
699 | static inline u64 btrfs_file_extent_disk_blocknr(struct btrfs_file_extent_item | ||
700 | *e) | ||
701 | { | ||
702 | return le64_to_cpu(e->disk_blocknr); | ||
703 | } | ||
704 | |||
705 | static inline void btrfs_set_file_extent_disk_blocknr(struct | ||
706 | btrfs_file_extent_item | ||
707 | *e, u64 val) | ||
708 | { | ||
709 | e->disk_blocknr = cpu_to_le64(val); | ||
710 | } | ||
711 | |||
712 | static inline u64 btrfs_file_extent_disk_num_blocks(struct | ||
713 | btrfs_file_extent_item *e) | ||
714 | { | ||
715 | return le64_to_cpu(e->disk_num_blocks); | ||
716 | } | ||
717 | |||
718 | static inline void btrfs_set_file_extent_disk_num_blocks(struct | ||
719 | btrfs_file_extent_item | ||
720 | *e, u64 val) | ||
721 | { | ||
722 | e->disk_num_blocks = cpu_to_le64(val); | ||
723 | } | ||
724 | |||
725 | static inline u64 btrfs_file_extent_offset(struct btrfs_file_extent_item *e) | ||
726 | { | ||
727 | return le64_to_cpu(e->offset); | ||
728 | } | ||
729 | |||
730 | static inline void btrfs_set_file_extent_offset(struct btrfs_file_extent_item | ||
731 | *e, u64 val) | ||
732 | { | ||
733 | e->offset = cpu_to_le64(val); | ||
734 | } | ||
735 | |||
736 | static inline u64 btrfs_file_extent_num_blocks(struct btrfs_file_extent_item | ||
737 | *e) | ||
738 | { | ||
739 | return le64_to_cpu(e->num_blocks); | ||
740 | } | ||
741 | |||
742 | static inline void btrfs_set_file_extent_num_blocks(struct | ||
743 | btrfs_file_extent_item *e, | ||
744 | u64 val) | ||
745 | { | ||
746 | e->num_blocks = cpu_to_le64(val); | ||
747 | } | ||
748 | |||
657 | /* helper function to cast into the data area of the leaf. */ | 749 | /* helper function to cast into the data area of the leaf. */ |
658 | #define btrfs_item_ptr(leaf, slot, type) \ | 750 | #define btrfs_item_ptr(leaf, slot, type) \ |
659 | ((type *)(btrfs_leaf_data(leaf) + \ | 751 | ((type *)(btrfs_leaf_data(leaf) + \ |
@@ -701,4 +793,13 @@ int btrfs_lookup_dir_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
701 | int name_len, int mod); | 793 | int name_len, int mod); |
702 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, | 794 | int btrfs_match_dir_item_name(struct btrfs_root *root, struct btrfs_path *path, |
703 | char *name, int name_len); | 795 | char *name, int name_len); |
796 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | ||
797 | struct btrfs_root *fs_root, | ||
798 | u64 dirid, u64 *objectid); | ||
799 | int btrfs_insert_inode_map(struct btrfs_trans_handle *trans, | ||
800 | struct btrfs_root *root, | ||
801 | u64 objectid, struct btrfs_key *location); | ||
802 | int btrfs_lookup_inode_map(struct btrfs_trans_handle *trans, | ||
803 | struct btrfs_root *root, struct btrfs_path *path, | ||
804 | u64 objectid, int mod); | ||
704 | #endif | 805 | #endif |
diff --git a/fs/btrfs/debug-tree.c b/fs/btrfs/debug-tree.c index 91dea7a0a476..d9f36efc3dd1 100644 --- a/fs/btrfs/debug-tree.c +++ b/fs/btrfs/debug-tree.c | |||
@@ -15,8 +15,13 @@ int main(int ac, char **av) { | |||
15 | printf("fs tree\n"); | 15 | printf("fs tree\n"); |
16 | btrfs_print_tree(root, root->node); | 16 | btrfs_print_tree(root, root->node); |
17 | printf("map tree\n"); | 17 | printf("map tree\n"); |
18 | btrfs_print_tree(root->extent_root, root->extent_root->node); | 18 | btrfs_print_tree(root->fs_info->extent_root, |
19 | root->fs_info->extent_root->node); | ||
20 | printf("inode tree\n"); | ||
21 | btrfs_print_tree(root->fs_info->inode_root, | ||
22 | root->fs_info->inode_root->node); | ||
19 | printf("root tree\n"); | 23 | printf("root tree\n"); |
20 | btrfs_print_tree(root->tree_root, root->tree_root->node); | 24 | btrfs_print_tree(root->fs_info->tree_root, |
25 | root->fs_info->tree_root->node); | ||
21 | return 0; | 26 | return 0; |
22 | } | 27 | } |
diff --git a/fs/btrfs/dir-test.c b/fs/btrfs/dir-test.c index e908c0c588cc..56f06c3ba573 100644 --- a/fs/btrfs/dir-test.c +++ b/fs/btrfs/dir-test.c | |||
@@ -45,13 +45,26 @@ static int ins_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
45 | int ret; | 45 | int ret; |
46 | char buf[128]; | 46 | char buf[128]; |
47 | unsigned long oid; | 47 | unsigned long oid; |
48 | u64 objectid; | ||
48 | struct btrfs_path path; | 49 | struct btrfs_path path; |
50 | struct btrfs_key inode_map; | ||
49 | 51 | ||
50 | find_num(radix, &oid, 0); | 52 | find_num(radix, &oid, 0); |
51 | sprintf(buf, "str-%lu", oid); | 53 | sprintf(buf, "str-%lu", oid); |
52 | 54 | ||
55 | ret = btrfs_find_free_objectid(trans, root, dir_oid + 1, &objectid); | ||
56 | if (ret) | ||
57 | goto error; | ||
58 | |||
59 | inode_map.objectid = objectid; | ||
60 | inode_map.flags = 0; | ||
61 | inode_map.offset = 0; | ||
62 | |||
63 | ret = btrfs_insert_inode_map(trans, root, objectid, &inode_map); | ||
64 | if (ret) | ||
65 | goto error; | ||
53 | ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf), dir_oid, | 66 | ret = btrfs_insert_dir_item(trans, root, buf, strlen(buf), dir_oid, |
54 | file_oid, 1); | 67 | objectid, 1); |
55 | if (ret) | 68 | if (ret) |
56 | goto error; | 69 | goto error; |
57 | 70 | ||
@@ -120,6 +133,53 @@ static int insert_dup(struct btrfs_trans_handle *trans, struct btrfs_root | |||
120 | return 0; | 133 | return 0; |
121 | } | 134 | } |
122 | 135 | ||
136 | static int del_dir_item(struct btrfs_trans_handle *trans, | ||
137 | struct btrfs_root *root, | ||
138 | struct radix_tree_root *radix, | ||
139 | unsigned long radix_index, | ||
140 | struct btrfs_path *path) | ||
141 | { | ||
142 | int ret; | ||
143 | unsigned long *ptr; | ||
144 | u64 file_objectid; | ||
145 | struct btrfs_dir_item *di; | ||
146 | struct btrfs_path map_path; | ||
147 | |||
148 | /* find the inode number of the file */ | ||
149 | di = btrfs_item_ptr(&path->nodes[0]->leaf, path->slots[0], | ||
150 | struct btrfs_dir_item); | ||
151 | file_objectid = btrfs_dir_objectid(di); | ||
152 | |||
153 | /* delete the directory item */ | ||
154 | ret = btrfs_del_item(trans, root, path); | ||
155 | if (ret) | ||
156 | goto out; | ||
157 | |||
158 | /* delete the inode mapping */ | ||
159 | btrfs_init_path(&map_path); | ||
160 | ret = btrfs_lookup_inode_map(trans, root, &map_path, file_objectid, -1); | ||
161 | if (ret) | ||
162 | goto out_release; | ||
163 | ret = btrfs_del_item(trans, root->fs_info->inode_root, &map_path); | ||
164 | if (ret) | ||
165 | goto out_release; | ||
166 | |||
167 | if (root->fs_info->last_inode_alloc > file_objectid) | ||
168 | root->fs_info->last_inode_alloc = file_objectid; | ||
169 | btrfs_release_path(root, &map_path); | ||
170 | ptr = radix_tree_delete(radix, radix_index); | ||
171 | if (!ptr) { | ||
172 | ret = -5555; | ||
173 | goto out; | ||
174 | } | ||
175 | return 0; | ||
176 | out_release: | ||
177 | btrfs_release_path(root, &map_path); | ||
178 | out: | ||
179 | printf("failed to delete %lu %d\n", radix_index, ret); | ||
180 | return -1; | ||
181 | } | ||
182 | |||
123 | static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 183 | static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
124 | struct radix_tree_root *radix) | 184 | struct radix_tree_root *radix) |
125 | { | 185 | { |
@@ -127,7 +187,6 @@ static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
127 | char buf[128]; | 187 | char buf[128]; |
128 | unsigned long oid; | 188 | unsigned long oid; |
129 | struct btrfs_path path; | 189 | struct btrfs_path path; |
130 | unsigned long *ptr; | ||
131 | 190 | ||
132 | ret = find_num(radix, &oid, 1); | 191 | ret = find_num(radix, &oid, 1); |
133 | if (ret < 0) | 192 | if (ret < 0) |
@@ -138,19 +197,14 @@ static int del_one(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
138 | strlen(buf), -1); | 197 | strlen(buf), -1); |
139 | if (ret) | 198 | if (ret) |
140 | goto out_release; | 199 | goto out_release; |
141 | ret = btrfs_del_item(trans, root, &path); | 200 | |
201 | ret = del_dir_item(trans, root, radix, oid, &path); | ||
142 | if (ret) | 202 | if (ret) |
143 | goto out_release; | 203 | goto out_release; |
144 | btrfs_release_path(root, &path); | 204 | btrfs_release_path(root, &path); |
145 | ptr = radix_tree_delete(radix, oid); | 205 | return ret; |
146 | if (!ptr) { | ||
147 | ret = -5555; | ||
148 | goto out; | ||
149 | } | ||
150 | return 0; | ||
151 | out_release: | 206 | out_release: |
152 | btrfs_release_path(root, &path); | 207 | btrfs_release_path(root, &path); |
153 | out: | ||
154 | printf("failed to delete %lu %d\n", oid, ret); | 208 | printf("failed to delete %lu %d\n", oid, ret); |
155 | return -1; | 209 | return -1; |
156 | } | 210 | } |
@@ -162,6 +216,8 @@ static int lookup_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
162 | char buf[128]; | 216 | char buf[128]; |
163 | int ret; | 217 | int ret; |
164 | unsigned long oid; | 218 | unsigned long oid; |
219 | u64 objectid; | ||
220 | struct btrfs_dir_item *di; | ||
165 | 221 | ||
166 | ret = find_num(radix, &oid, 1); | 222 | ret = find_num(radix, &oid, 1); |
167 | if (ret < 0) | 223 | if (ret < 0) |
@@ -170,6 +226,14 @@ static int lookup_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
170 | btrfs_init_path(&path); | 226 | btrfs_init_path(&path); |
171 | ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf, | 227 | ret = btrfs_lookup_dir_item(trans, root, &path, dir_oid, buf, |
172 | strlen(buf), 0); | 228 | strlen(buf), 0); |
229 | if (!ret) { | ||
230 | di = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], | ||
231 | struct btrfs_dir_item); | ||
232 | objectid = btrfs_dir_objectid(di); | ||
233 | btrfs_release_path(root, &path); | ||
234 | btrfs_init_path(&path); | ||
235 | ret = btrfs_lookup_inode_map(trans, root, &path, objectid, 0); | ||
236 | } | ||
173 | btrfs_release_path(root, &path); | 237 | btrfs_release_path(root, &path); |
174 | if (ret) { | 238 | if (ret) { |
175 | printf("unable to find key %lu\n", oid); | 239 | printf("unable to find key %lu\n", oid); |
@@ -210,7 +274,6 @@ static int empty_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
210 | u32 found_len; | 274 | u32 found_len; |
211 | int ret; | 275 | int ret; |
212 | int slot; | 276 | int slot; |
213 | int *ptr; | ||
214 | int count = 0; | 277 | int count = 0; |
215 | char buf[128]; | 278 | char buf[128]; |
216 | struct btrfs_dir_item *di; | 279 | struct btrfs_dir_item *di; |
@@ -241,7 +304,7 @@ static int empty_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
241 | BUG_ON(found_len > 128); | 304 | BUG_ON(found_len > 128); |
242 | buf[found_len] = '\0'; | 305 | buf[found_len] = '\0'; |
243 | found = atoi(buf + 4); | 306 | found = atoi(buf + 4); |
244 | ret = btrfs_del_item(trans, root, &path); | 307 | ret = del_dir_item(trans, root, radix, found, &path); |
245 | count++; | 308 | count++; |
246 | if (ret) { | 309 | if (ret) { |
247 | fprintf(stderr, | 310 | fprintf(stderr, |
@@ -250,14 +313,10 @@ static int empty_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
250 | return -1; | 313 | return -1; |
251 | } | 314 | } |
252 | btrfs_release_path(root, &path); | 315 | btrfs_release_path(root, &path); |
253 | ptr = radix_tree_delete(radix, found); | ||
254 | if (!ptr) | ||
255 | goto error; | ||
256 | if (!keep_running) | 316 | if (!keep_running) |
257 | break; | 317 | break; |
258 | } | 318 | } |
259 | return 0; | 319 | return 0; |
260 | error: | ||
261 | fprintf(stderr, "failed to delete from the radix %lu\n", found); | 320 | fprintf(stderr, "failed to delete from the radix %lu\n", found); |
262 | return -1; | 321 | return -1; |
263 | } | 322 | } |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 25ce07908ee3..1849a99690c8 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -28,15 +28,15 @@ static int free_some_buffers(struct btrfs_root *root) | |||
28 | { | 28 | { |
29 | struct list_head *node, *next; | 29 | struct list_head *node, *next; |
30 | struct btrfs_buffer *b; | 30 | struct btrfs_buffer *b; |
31 | if (root->cache_size < cache_max) | 31 | if (root->fs_info->cache_size < cache_max) |
32 | return 0; | 32 | return 0; |
33 | list_for_each_safe(node, next, &root->cache) { | 33 | list_for_each_safe(node, next, &root->fs_info->cache) { |
34 | b = list_entry(node, struct btrfs_buffer, cache); | 34 | b = list_entry(node, struct btrfs_buffer, cache); |
35 | if (b->count == 1) { | 35 | if (b->count == 1) { |
36 | BUG_ON(!list_empty(&b->dirty)); | 36 | BUG_ON(!list_empty(&b->dirty)); |
37 | list_del_init(&b->cache); | 37 | list_del_init(&b->cache); |
38 | btrfs_block_release(root, b); | 38 | btrfs_block_release(root, b); |
39 | if (root->cache_size < cache_max) | 39 | if (root->fs_info->cache_size < cache_max) |
40 | break; | 40 | break; |
41 | } | 41 | } |
42 | } | 42 | } |
@@ -57,10 +57,10 @@ struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 blocknr) | |||
57 | INIT_LIST_HEAD(&buf->dirty); | 57 | INIT_LIST_HEAD(&buf->dirty); |
58 | free_some_buffers(root); | 58 | free_some_buffers(root); |
59 | radix_tree_preload(GFP_KERNEL); | 59 | radix_tree_preload(GFP_KERNEL); |
60 | ret = radix_tree_insert(&root->cache_radix, blocknr, buf); | 60 | ret = radix_tree_insert(&root->fs_info->cache_radix, blocknr, buf); |
61 | radix_tree_preload_end(); | 61 | radix_tree_preload_end(); |
62 | list_add_tail(&buf->cache, &root->cache); | 62 | list_add_tail(&buf->cache, &root->fs_info->cache); |
63 | root->cache_size++; | 63 | root->fs_info->cache_size++; |
64 | if (ret) { | 64 | if (ret) { |
65 | free(buf); | 65 | free(buf); |
66 | return NULL; | 66 | return NULL; |
@@ -71,7 +71,7 @@ struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 blocknr) | |||
71 | struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr) | 71 | struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr) |
72 | { | 72 | { |
73 | struct btrfs_buffer *buf; | 73 | struct btrfs_buffer *buf; |
74 | buf = radix_tree_lookup(&root->cache_radix, blocknr); | 74 | buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr); |
75 | if (buf) { | 75 | if (buf) { |
76 | buf->count++; | 76 | buf->count++; |
77 | } else { | 77 | } else { |
@@ -90,14 +90,15 @@ struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr) | |||
90 | struct btrfs_buffer *buf; | 90 | struct btrfs_buffer *buf; |
91 | int ret; | 91 | int ret; |
92 | 92 | ||
93 | buf = radix_tree_lookup(&root->cache_radix, blocknr); | 93 | buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr); |
94 | if (buf) { | 94 | if (buf) { |
95 | buf->count++; | 95 | buf->count++; |
96 | } else { | 96 | } else { |
97 | buf = alloc_tree_block(root, blocknr); | 97 | buf = alloc_tree_block(root, blocknr); |
98 | if (!buf) | 98 | if (!buf) |
99 | return NULL; | 99 | return NULL; |
100 | ret = pread(root->fp, &buf->node, root->blocksize, offset); | 100 | ret = pread(root->fs_info->fp, &buf->node, root->blocksize, |
101 | offset); | ||
101 | if (ret != root->blocksize) { | 102 | if (ret != root->blocksize) { |
102 | free(buf); | 103 | free(buf); |
103 | return NULL; | 104 | return NULL; |
@@ -113,7 +114,7 @@ int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
113 | { | 114 | { |
114 | if (!list_empty(&buf->dirty)) | 115 | if (!list_empty(&buf->dirty)) |
115 | return 0; | 116 | return 0; |
116 | list_add_tail(&buf->dirty, &root->trans); | 117 | list_add_tail(&buf->dirty, &root->fs_info->trans); |
117 | buf->count++; | 118 | buf->count++; |
118 | return 0; | 119 | return 0; |
119 | } | 120 | } |
@@ -137,7 +138,7 @@ int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
137 | 138 | ||
138 | if (buf->blocknr != btrfs_header_blocknr(&buf->node.header)) | 139 | if (buf->blocknr != btrfs_header_blocknr(&buf->node.header)) |
139 | BUG(); | 140 | BUG(); |
140 | ret = pwrite(root->fp, &buf->node, root->blocksize, offset); | 141 | ret = pwrite(root->fs_info->fp, &buf->node, root->blocksize, offset); |
141 | if (ret != root->blocksize) | 142 | if (ret != root->blocksize) |
142 | return ret; | 143 | return ret; |
143 | return 0; | 144 | return 0; |
@@ -149,8 +150,9 @@ static int __commit_transaction(struct btrfs_trans_handle *trans, struct | |||
149 | struct btrfs_buffer *b; | 150 | struct btrfs_buffer *b; |
150 | int ret = 0; | 151 | int ret = 0; |
151 | int wret; | 152 | int wret; |
152 | while(!list_empty(&root->trans)) { | 153 | while(!list_empty(&root->fs_info->trans)) { |
153 | b = list_entry(root->trans.next, struct btrfs_buffer, dirty); | 154 | b = list_entry(root->fs_info->trans.next, struct btrfs_buffer, |
155 | dirty); | ||
154 | list_del_init(&b->dirty); | 156 | list_del_init(&b->dirty); |
155 | wret = write_tree_block(trans, root, b); | 157 | wret = write_tree_block(trans, root, b); |
156 | if (wret) | 158 | if (wret) |
@@ -160,13 +162,21 @@ static int __commit_transaction(struct btrfs_trans_handle *trans, struct | |||
160 | return ret; | 162 | return ret; |
161 | } | 163 | } |
162 | 164 | ||
163 | static int commit_extent_and_tree_roots(struct btrfs_trans_handle *trans, | 165 | static int commit_tree_roots(struct btrfs_trans_handle *trans, |
164 | struct btrfs_root *tree_root, struct | 166 | struct btrfs_fs_info *fs_info) |
165 | btrfs_root *extent_root) | ||
166 | { | 167 | { |
167 | int ret; | 168 | int ret; |
168 | u64 old_extent_block; | 169 | u64 old_extent_block; |
169 | 170 | struct btrfs_root *tree_root = fs_info->tree_root; | |
171 | struct btrfs_root *extent_root = fs_info->extent_root; | ||
172 | struct btrfs_root *inode_root = fs_info->inode_root; | ||
173 | |||
174 | btrfs_set_root_blocknr(&inode_root->root_item, | ||
175 | inode_root->node->blocknr); | ||
176 | ret = btrfs_update_root(trans, tree_root, | ||
177 | &inode_root->root_key, | ||
178 | &inode_root->root_item); | ||
179 | BUG_ON(ret); | ||
170 | while(1) { | 180 | while(1) { |
171 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); | 181 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); |
172 | if (old_extent_block == extent_root->node->blocknr) | 182 | if (old_extent_block == extent_root->node->blocknr) |
@@ -178,8 +188,6 @@ static int commit_extent_and_tree_roots(struct btrfs_trans_handle *trans, | |||
178 | &extent_root->root_item); | 188 | &extent_root->root_item); |
179 | BUG_ON(ret); | 189 | BUG_ON(ret); |
180 | } | 190 | } |
181 | __commit_transaction(trans, extent_root); | ||
182 | __commit_transaction(trans, tree_root); | ||
183 | return 0; | 191 | return 0; |
184 | } | 192 | } |
185 | 193 | ||
@@ -190,9 +198,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct | |||
190 | struct btrfs_buffer *snap = root->commit_root; | 198 | struct btrfs_buffer *snap = root->commit_root; |
191 | struct btrfs_key snap_key; | 199 | struct btrfs_key snap_key; |
192 | 200 | ||
193 | ret = __commit_transaction(trans, root); | ||
194 | BUG_ON(ret); | ||
195 | |||
196 | if (root->commit_root == root->node) | 201 | if (root->commit_root == root->node) |
197 | return 0; | 202 | return 0; |
198 | 203 | ||
@@ -200,54 +205,55 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct | |||
200 | root->root_key.offset++; | 205 | root->root_key.offset++; |
201 | 206 | ||
202 | btrfs_set_root_blocknr(&root->root_item, root->node->blocknr); | 207 | btrfs_set_root_blocknr(&root->root_item, root->node->blocknr); |
203 | ret = btrfs_insert_root(trans, root->tree_root, &root->root_key, | 208 | ret = btrfs_insert_root(trans, root->fs_info->tree_root, |
204 | &root->root_item); | 209 | &root->root_key, &root->root_item); |
210 | BUG_ON(ret); | ||
211 | |||
212 | ret = commit_tree_roots(trans, root->fs_info); | ||
205 | BUG_ON(ret); | 213 | BUG_ON(ret); |
206 | 214 | ||
207 | ret = commit_extent_and_tree_roots(trans, root->tree_root, | 215 | ret = __commit_transaction(trans, root); |
208 | root->extent_root); | ||
209 | BUG_ON(ret); | 216 | BUG_ON(ret); |
210 | 217 | ||
211 | write_ctree_super(trans, root, s); | 218 | write_ctree_super(trans, root, s); |
212 | btrfs_finish_extent_commit(trans, root->extent_root); | 219 | btrfs_finish_extent_commit(trans, root->fs_info->extent_root); |
213 | btrfs_finish_extent_commit(trans, root->tree_root); | 220 | btrfs_finish_extent_commit(trans, root->fs_info->tree_root); |
214 | 221 | ||
215 | root->commit_root = root->node; | 222 | root->commit_root = root->node; |
216 | root->node->count++; | 223 | root->node->count++; |
217 | ret = btrfs_drop_snapshot(trans, root, snap); | 224 | ret = btrfs_drop_snapshot(trans, root, snap); |
218 | BUG_ON(ret); | 225 | BUG_ON(ret); |
219 | 226 | ||
220 | ret = btrfs_del_root(trans, root->tree_root, &snap_key); | 227 | ret = btrfs_del_root(trans, root->fs_info->tree_root, &snap_key); |
221 | BUG_ON(ret); | 228 | BUG_ON(ret); |
222 | 229 | ||
223 | return ret; | 230 | return ret; |
224 | } | 231 | } |
225 | 232 | ||
226 | static int __setup_root(struct btrfs_super_block *super, | 233 | static int __setup_root(struct btrfs_super_block *super, |
227 | struct btrfs_root *root, u64 objectid, int fp) | 234 | struct btrfs_root *root, |
235 | struct btrfs_fs_info *fs_info, | ||
236 | u64 objectid, int fp) | ||
228 | { | 237 | { |
229 | INIT_LIST_HEAD(&root->trans); | ||
230 | INIT_LIST_HEAD(&root->cache); | ||
231 | root->cache_size = 0; | ||
232 | root->fp = fp; | ||
233 | root->node = NULL; | 238 | root->node = NULL; |
234 | root->commit_root = NULL; | 239 | root->commit_root = NULL; |
235 | root->blocksize = btrfs_super_blocksize(super); | 240 | root->blocksize = btrfs_super_blocksize(super); |
236 | root->ref_cows = 0; | 241 | root->ref_cows = 0; |
237 | memset(&root->current_insert, 0, sizeof(root->current_insert)); | 242 | root->fs_info = fs_info; |
238 | memset(&root->last_insert, 0, sizeof(root->last_insert)); | ||
239 | memset(&root->root_key, 0, sizeof(root->root_key)); | 243 | memset(&root->root_key, 0, sizeof(root->root_key)); |
240 | memset(&root->root_item, 0, sizeof(root->root_item)); | 244 | memset(&root->root_item, 0, sizeof(root->root_item)); |
241 | return 0; | 245 | return 0; |
242 | } | 246 | } |
243 | 247 | ||
244 | static int find_and_setup_root(struct btrfs_super_block *super, | 248 | static int find_and_setup_root(struct btrfs_super_block *super, |
245 | struct btrfs_root *tree_root, u64 objectid, | 249 | struct btrfs_root *tree_root, |
250 | struct btrfs_fs_info *fs_info, | ||
251 | u64 objectid, | ||
246 | struct btrfs_root *root, int fp) | 252 | struct btrfs_root *root, int fp) |
247 | { | 253 | { |
248 | int ret; | 254 | int ret; |
249 | 255 | ||
250 | __setup_root(super, root, objectid, fp); | 256 | __setup_root(super, root, fs_info, objectid, fp); |
251 | ret = btrfs_find_last_root(tree_root, objectid, | 257 | ret = btrfs_find_last_root(tree_root, objectid, |
252 | &root->root_item, &root->root_key); | 258 | &root->root_item, &root->root_key); |
253 | BUG_ON(ret); | 259 | BUG_ON(ret); |
@@ -263,29 +269,31 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) | |||
263 | struct btrfs_root *root = malloc(sizeof(struct btrfs_root)); | 269 | struct btrfs_root *root = malloc(sizeof(struct btrfs_root)); |
264 | struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root)); | 270 | struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root)); |
265 | struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root)); | 271 | struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root)); |
272 | struct btrfs_root *inode_root = malloc(sizeof(struct btrfs_root)); | ||
273 | struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info)); | ||
266 | int fp; | 274 | int fp; |
267 | int ret; | 275 | int ret; |
268 | 276 | ||
269 | root->extent_root = extent_root; | ||
270 | root->tree_root = tree_root; | ||
271 | |||
272 | extent_root->extent_root = extent_root; | ||
273 | extent_root->tree_root = tree_root; | ||
274 | |||
275 | tree_root->extent_root = extent_root; | ||
276 | tree_root->tree_root = tree_root; | ||
277 | |||
278 | fp = open(filename, O_CREAT | O_RDWR, 0600); | 277 | fp = open(filename, O_CREAT | O_RDWR, 0600); |
279 | if (fp < 0) { | 278 | if (fp < 0) { |
280 | free(root); | 279 | free(root); |
281 | return NULL; | 280 | return NULL; |
282 | } | 281 | } |
283 | INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL); | 282 | INIT_RADIX_TREE(&fs_info->cache_radix, GFP_KERNEL); |
284 | INIT_RADIX_TREE(&root->pinned_radix, GFP_KERNEL); | 283 | INIT_RADIX_TREE(&fs_info->pinned_radix, GFP_KERNEL); |
285 | INIT_RADIX_TREE(&extent_root->pinned_radix, GFP_KERNEL); | 284 | INIT_LIST_HEAD(&fs_info->trans); |
286 | INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL); | 285 | INIT_LIST_HEAD(&fs_info->cache); |
287 | INIT_RADIX_TREE(&tree_root->pinned_radix, GFP_KERNEL); | 286 | fs_info->cache_size = 0; |
288 | INIT_RADIX_TREE(&tree_root->cache_radix, GFP_KERNEL); | 287 | fs_info->fp = fp; |
288 | fs_info->running_transaction = NULL; | ||
289 | fs_info->fs_root = root; | ||
290 | fs_info->tree_root = tree_root; | ||
291 | fs_info->extent_root = extent_root; | ||
292 | fs_info->inode_root = inode_root; | ||
293 | fs_info->last_inode_alloc = 0; | ||
294 | fs_info->last_inode_alloc_dirid = 0; | ||
295 | memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert)); | ||
296 | memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); | ||
289 | 297 | ||
290 | ret = pread(fp, super, sizeof(struct btrfs_super_block), | 298 | ret = pread(fp, super, sizeof(struct btrfs_super_block), |
291 | BTRFS_SUPER_INFO_OFFSET); | 299 | BTRFS_SUPER_INFO_OFFSET); |
@@ -301,16 +309,20 @@ struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) | |||
301 | } | 309 | } |
302 | BUG_ON(ret < 0); | 310 | BUG_ON(ret < 0); |
303 | 311 | ||
304 | __setup_root(super, tree_root, BTRFS_ROOT_TREE_OBJECTID, fp); | 312 | __setup_root(super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID, fp); |
305 | tree_root->node = read_tree_block(tree_root, btrfs_super_root(super)); | 313 | tree_root->node = read_tree_block(tree_root, btrfs_super_root(super)); |
306 | BUG_ON(!tree_root->node); | 314 | BUG_ON(!tree_root->node); |
307 | 315 | ||
308 | ret = find_and_setup_root(super, tree_root, BTRFS_EXTENT_TREE_OBJECTID, | 316 | ret = find_and_setup_root(super, tree_root, fs_info, |
309 | extent_root, fp); | 317 | BTRFS_EXTENT_TREE_OBJECTID, extent_root, fp); |
310 | BUG_ON(ret); | 318 | BUG_ON(ret); |
311 | 319 | ||
312 | ret = find_and_setup_root(super, tree_root, BTRFS_FS_TREE_OBJECTID, | 320 | ret = find_and_setup_root(super, tree_root, fs_info, |
313 | root, fp); | 321 | BTRFS_INODE_MAP_OBJECTID, inode_root, fp); |
322 | BUG_ON(ret); | ||
323 | |||
324 | ret = find_and_setup_root(super, tree_root, fs_info, | ||
325 | BTRFS_FS_TREE_OBJECTID, root, fp); | ||
314 | BUG_ON(ret); | 326 | BUG_ON(ret); |
315 | 327 | ||
316 | root->commit_root = root->node; | 328 | root->commit_root = root->node; |
@@ -323,8 +335,8 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | |||
323 | *root, struct btrfs_super_block *s) | 335 | *root, struct btrfs_super_block *s) |
324 | { | 336 | { |
325 | int ret; | 337 | int ret; |
326 | btrfs_set_super_root(s, root->tree_root->node->blocknr); | 338 | btrfs_set_super_root(s, root->fs_info->tree_root->node->blocknr); |
327 | ret = pwrite(root->fp, s, sizeof(*s), | 339 | ret = pwrite(root->fs_info->fp, s, sizeof(*s), |
328 | BTRFS_SUPER_INFO_OFFSET); | 340 | BTRFS_SUPER_INFO_OFFSET); |
329 | if (ret != sizeof(*s)) { | 341 | if (ret != sizeof(*s)) { |
330 | fprintf(stderr, "failed to write new super block err %d\n", ret); | 342 | fprintf(stderr, "failed to write new super block err %d\n", ret); |
@@ -335,9 +347,10 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | |||
335 | 347 | ||
336 | static int drop_cache(struct btrfs_root *root) | 348 | static int drop_cache(struct btrfs_root *root) |
337 | { | 349 | { |
338 | while(!list_empty(&root->cache)) { | 350 | while(!list_empty(&root->fs_info->cache)) { |
339 | struct btrfs_buffer *b = list_entry(root->cache.next, | 351 | struct btrfs_buffer *b = list_entry(root->fs_info->cache.next, |
340 | struct btrfs_buffer, cache); | 352 | struct btrfs_buffer, |
353 | cache); | ||
341 | list_del_init(&b->cache); | 354 | list_del_init(&b->cache); |
342 | btrfs_block_release(root, b); | 355 | btrfs_block_release(root, b); |
343 | } | 356 | } |
@@ -348,26 +361,28 @@ int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s) | |||
348 | int ret; | 361 | int ret; |
349 | struct btrfs_trans_handle *trans; | 362 | struct btrfs_trans_handle *trans; |
350 | 363 | ||
351 | trans = root->running_transaction; | 364 | trans = root->fs_info->running_transaction; |
352 | btrfs_commit_transaction(trans, root, s); | 365 | btrfs_commit_transaction(trans, root, s); |
353 | ret = commit_extent_and_tree_roots(trans, root->tree_root, | 366 | ret = commit_tree_roots(trans, root->fs_info); |
354 | root->extent_root); | 367 | BUG_ON(ret); |
368 | ret = __commit_transaction(trans, root); | ||
355 | BUG_ON(ret); | 369 | BUG_ON(ret); |
356 | write_ctree_super(trans, root, s); | 370 | write_ctree_super(trans, root, s); |
357 | drop_cache(root->extent_root); | ||
358 | drop_cache(root->tree_root); | ||
359 | drop_cache(root); | 371 | drop_cache(root); |
360 | BUG_ON(!list_empty(&root->trans)); | 372 | BUG_ON(!list_empty(&root->fs_info->trans)); |
361 | BUG_ON(!list_empty(&root->extent_root->trans)); | ||
362 | BUG_ON(!list_empty(&root->tree_root->trans)); | ||
363 | 373 | ||
364 | close(root->fp); | 374 | close(root->fs_info->fp); |
365 | if (root->node) | 375 | if (root->node) |
366 | btrfs_block_release(root, root->node); | 376 | btrfs_block_release(root, root->node); |
367 | if (root->extent_root->node) | 377 | if (root->fs_info->extent_root->node) |
368 | btrfs_block_release(root->extent_root, root->extent_root->node); | 378 | btrfs_block_release(root->fs_info->extent_root, |
369 | if (root->tree_root->node) | 379 | root->fs_info->extent_root->node); |
370 | btrfs_block_release(root->tree_root, root->tree_root->node); | 380 | if (root->fs_info->inode_root->node) |
381 | btrfs_block_release(root->fs_info->inode_root, | ||
382 | root->fs_info->inode_root->node); | ||
383 | if (root->fs_info->tree_root->node) | ||
384 | btrfs_block_release(root->fs_info->tree_root, | ||
385 | root->fs_info->tree_root->node); | ||
371 | btrfs_block_release(root, root->commit_root); | 386 | btrfs_block_release(root, root->commit_root); |
372 | free(root); | 387 | free(root); |
373 | printf("on close %d blocks are allocated\n", allocated_blocks); | 388 | printf("on close %d blocks are allocated\n", allocated_blocks); |
@@ -382,15 +397,16 @@ void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf) | |||
382 | if (buf->count == 0) { | 397 | if (buf->count == 0) { |
383 | BUG_ON(!list_empty(&buf->cache)); | 398 | BUG_ON(!list_empty(&buf->cache)); |
384 | BUG_ON(!list_empty(&buf->dirty)); | 399 | BUG_ON(!list_empty(&buf->dirty)); |
385 | if (!radix_tree_lookup(&root->cache_radix, buf->blocknr)) | 400 | if (!radix_tree_lookup(&root->fs_info->cache_radix, |
401 | buf->blocknr)) | ||
386 | BUG(); | 402 | BUG(); |
387 | radix_tree_delete(&root->cache_radix, buf->blocknr); | 403 | radix_tree_delete(&root->fs_info->cache_radix, buf->blocknr); |
388 | memset(buf, 0, sizeof(*buf)); | 404 | memset(buf, 0, sizeof(*buf)); |
389 | free(buf); | 405 | free(buf); |
390 | BUG_ON(allocated_blocks == 0); | 406 | BUG_ON(allocated_blocks == 0); |
391 | allocated_blocks--; | 407 | allocated_blocks--; |
392 | BUG_ON(root->cache_size == 0); | 408 | BUG_ON(root->fs_info->cache_size == 0); |
393 | root->cache_size--; | 409 | root->fs_info->cache_size--; |
394 | } | 410 | } |
395 | } | 411 | } |
396 | 412 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c29b92d440e0..09eeeb4d9d28 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -35,13 +35,15 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
35 | struct btrfs_key ins; | 35 | struct btrfs_key ins; |
36 | u32 refs; | 36 | u32 refs; |
37 | 37 | ||
38 | find_free_extent(trans, root->extent_root, 0, 0, (u64)-1, &ins); | 38 | find_free_extent(trans, root->fs_info->extent_root, 0, 0, (u64)-1, |
39 | &ins); | ||
39 | btrfs_init_path(&path); | 40 | btrfs_init_path(&path); |
40 | key.objectid = blocknr; | 41 | key.objectid = blocknr; |
41 | key.flags = 0; | 42 | key.flags = 0; |
42 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 43 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
43 | key.offset = 1; | 44 | key.offset = 1; |
44 | ret = btrfs_search_slot(trans, root->extent_root, &key, &path, 0, 1); | 45 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, &path, |
46 | 0, 1); | ||
45 | if (ret != 0) | 47 | if (ret != 0) |
46 | BUG(); | 48 | BUG(); |
47 | BUG_ON(ret != 0); | 49 | BUG_ON(ret != 0); |
@@ -51,9 +53,9 @@ static int inc_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
51 | btrfs_set_extent_refs(item, refs + 1); | 53 | btrfs_set_extent_refs(item, refs + 1); |
52 | 54 | ||
53 | BUG_ON(list_empty(&path.nodes[0]->dirty)); | 55 | BUG_ON(list_empty(&path.nodes[0]->dirty)); |
54 | btrfs_release_path(root->extent_root, &path); | 56 | btrfs_release_path(root->fs_info->extent_root, &path); |
55 | finish_current_insert(trans, root->extent_root); | 57 | finish_current_insert(trans, root->fs_info->extent_root); |
56 | run_pending(trans, root->extent_root); | 58 | run_pending(trans, root->fs_info->extent_root); |
57 | return 0; | 59 | return 0; |
58 | } | 60 | } |
59 | 61 | ||
@@ -70,13 +72,14 @@ static int lookup_block_ref(struct btrfs_trans_handle *trans, struct btrfs_root | |||
70 | key.offset = 1; | 72 | key.offset = 1; |
71 | key.flags = 0; | 73 | key.flags = 0; |
72 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 74 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
73 | ret = btrfs_search_slot(trans, root->extent_root, &key, &path, 0, 0); | 75 | ret = btrfs_search_slot(trans, root->fs_info->extent_root, &key, &path, |
76 | 0, 0); | ||
74 | if (ret != 0) | 77 | if (ret != 0) |
75 | BUG(); | 78 | BUG(); |
76 | l = &path.nodes[0]->leaf; | 79 | l = &path.nodes[0]->leaf; |
77 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); | 80 | item = btrfs_item_ptr(l, path.slots[0], struct btrfs_extent_item); |
78 | *refs = btrfs_extent_refs(item); | 81 | *refs = btrfs_extent_refs(item); |
79 | btrfs_release_path(root->extent_root, &path); | 82 | btrfs_release_path(root->fs_info->extent_root, &path); |
80 | return 0; | 83 | return 0; |
81 | } | 84 | } |
82 | 85 | ||
@@ -107,19 +110,20 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | |||
107 | int i; | 110 | int i; |
108 | 111 | ||
109 | while(1) { | 112 | while(1) { |
110 | ret = radix_tree_gang_lookup(&root->pinned_radix, | 113 | ret = radix_tree_gang_lookup(&root->fs_info->pinned_radix, |
111 | (void **)gang, 0, | 114 | (void **)gang, 0, |
112 | ARRAY_SIZE(gang)); | 115 | ARRAY_SIZE(gang)); |
113 | if (!ret) | 116 | if (!ret) |
114 | break; | 117 | break; |
115 | if (!first) | 118 | if (!first) |
116 | first = gang[0]; | 119 | first = gang[0]; |
117 | for (i = 0; i < ret; i++) { | 120 | for (i = 0; i < ret; i++) { |
118 | radix_tree_delete(&root->pinned_radix, gang[i]); | 121 | radix_tree_delete(&root->fs_info->pinned_radix, |
122 | gang[i]); | ||
119 | } | 123 | } |
120 | } | 124 | } |
121 | root->last_insert.objectid = first; | 125 | root->fs_info->last_insert.objectid = first; |
122 | root->last_insert.offset = 0; | 126 | root->fs_info->last_insert.offset = 0; |
123 | return 0; | 127 | return 0; |
124 | } | 128 | } |
125 | 129 | ||
@@ -138,13 +142,14 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
138 | ins.flags = 0; | 142 | ins.flags = 0; |
139 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); | 143 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); |
140 | 144 | ||
141 | for (i = 0; i < extent_root->current_insert.flags; i++) { | 145 | for (i = 0; i < extent_root->fs_info->current_insert.flags; i++) { |
142 | ins.objectid = extent_root->current_insert.objectid + i; | 146 | ins.objectid = extent_root->fs_info->current_insert.objectid + |
147 | i; | ||
143 | ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item, | 148 | ret = btrfs_insert_item(trans, extent_root, &ins, &extent_item, |
144 | sizeof(extent_item)); | 149 | sizeof(extent_item)); |
145 | BUG_ON(ret); | 150 | BUG_ON(ret); |
146 | } | 151 | } |
147 | extent_root->current_insert.offset = 0; | 152 | extent_root->fs_info->current_insert.offset = 0; |
148 | return 0; | 153 | return 0; |
149 | } | 154 | } |
150 | 155 | ||
@@ -156,7 +161,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
156 | { | 161 | { |
157 | struct btrfs_path path; | 162 | struct btrfs_path path; |
158 | struct btrfs_key key; | 163 | struct btrfs_key key; |
159 | struct btrfs_root *extent_root = root->extent_root; | 164 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
160 | int ret; | 165 | int ret; |
161 | struct btrfs_extent_item *ei; | 166 | struct btrfs_extent_item *ei; |
162 | struct btrfs_key ins; | 167 | struct btrfs_key ins; |
@@ -186,14 +191,16 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
186 | if (pin) { | 191 | if (pin) { |
187 | int err; | 192 | int err; |
188 | radix_tree_preload(GFP_KERNEL); | 193 | radix_tree_preload(GFP_KERNEL); |
189 | err = radix_tree_insert(&extent_root->pinned_radix, | 194 | err = radix_tree_insert( |
190 | blocknr, (void *)blocknr); | 195 | &extent_root->fs_info->pinned_radix, |
196 | blocknr, (void *)blocknr); | ||
191 | BUG_ON(err); | 197 | BUG_ON(err); |
192 | radix_tree_preload_end(); | 198 | radix_tree_preload_end(); |
193 | } | 199 | } |
194 | ret = btrfs_del_item(trans, extent_root, &path); | 200 | ret = btrfs_del_item(trans, extent_root, &path); |
195 | if (!pin && extent_root->last_insert.objectid > blocknr) | 201 | if (!pin && extent_root->fs_info->last_insert.objectid > |
196 | extent_root->last_insert.objectid = blocknr; | 202 | blocknr) |
203 | extent_root->fs_info->last_insert.objectid = blocknr; | ||
197 | if (ret) | 204 | if (ret) |
198 | BUG(); | 205 | BUG(); |
199 | } | 206 | } |
@@ -214,18 +221,19 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
214 | int i; | 221 | int i; |
215 | 222 | ||
216 | while(1) { | 223 | while(1) { |
217 | ret = radix_tree_gang_lookup_tag(&extent_root->cache_radix, | 224 | ret = radix_tree_gang_lookup_tag( |
218 | (void **)gang, 0, | 225 | &extent_root->fs_info->cache_radix, |
219 | ARRAY_SIZE(gang), | 226 | (void **)gang, 0, |
220 | CTREE_EXTENT_PENDING_DEL); | 227 | ARRAY_SIZE(gang), |
228 | CTREE_EXTENT_PENDING_DEL); | ||
221 | if (!ret) | 229 | if (!ret) |
222 | break; | 230 | break; |
223 | for (i = 0; i < ret; i++) { | 231 | for (i = 0; i < ret; i++) { |
224 | ret = __free_extent(trans, extent_root, | 232 | ret = __free_extent(trans, extent_root, |
225 | gang[i]->blocknr, 1, 1); | 233 | gang[i]->blocknr, 1, 1); |
226 | radix_tree_tag_clear(&extent_root->cache_radix, | 234 | radix_tree_tag_clear(&extent_root->fs_info->cache_radix, |
227 | gang[i]->blocknr, | 235 | gang[i]->blocknr, |
228 | CTREE_EXTENT_PENDING_DEL); | 236 | CTREE_EXTENT_PENDING_DEL); |
229 | btrfs_block_release(extent_root, gang[i]); | 237 | btrfs_block_release(extent_root, gang[i]); |
230 | } | 238 | } |
231 | } | 239 | } |
@@ -235,8 +243,8 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
235 | static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root | 243 | static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root |
236 | *extent_root) | 244 | *extent_root) |
237 | { | 245 | { |
238 | while(radix_tree_tagged(&extent_root->cache_radix, | 246 | while(radix_tree_tagged(&extent_root->fs_info->cache_radix, |
239 | CTREE_EXTENT_PENDING_DEL)) | 247 | CTREE_EXTENT_PENDING_DEL)) |
240 | del_pending_extents(trans, extent_root); | 248 | del_pending_extents(trans, extent_root); |
241 | return 0; | 249 | return 0; |
242 | } | 250 | } |
@@ -248,19 +256,19 @@ static int run_pending(struct btrfs_trans_handle *trans, struct btrfs_root | |||
248 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 256 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
249 | *root, u64 blocknr, u64 num_blocks, int pin) | 257 | *root, u64 blocknr, u64 num_blocks, int pin) |
250 | { | 258 | { |
251 | struct btrfs_root *extent_root = root->extent_root; | 259 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
252 | struct btrfs_buffer *t; | 260 | struct btrfs_buffer *t; |
253 | int pending_ret; | 261 | int pending_ret; |
254 | int ret; | 262 | int ret; |
255 | 263 | ||
256 | if (root == extent_root) { | 264 | if (root == extent_root) { |
257 | t = find_tree_block(root, blocknr); | 265 | t = find_tree_block(root, blocknr); |
258 | radix_tree_tag_set(&root->cache_radix, blocknr, | 266 | radix_tree_tag_set(&root->fs_info->cache_radix, blocknr, |
259 | CTREE_EXTENT_PENDING_DEL); | 267 | CTREE_EXTENT_PENDING_DEL); |
260 | return 0; | 268 | return 0; |
261 | } | 269 | } |
262 | ret = __free_extent(trans, root, blocknr, num_blocks, pin); | 270 | ret = __free_extent(trans, root, blocknr, num_blocks, pin); |
263 | pending_ret = run_pending(trans, root->extent_root); | 271 | pending_ret = run_pending(trans, root->fs_info->extent_root); |
264 | return ret ? ret : pending_ret; | 272 | return ret ? ret : pending_ret; |
265 | } | 273 | } |
266 | 274 | ||
@@ -285,12 +293,12 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
285 | u64 test_block; | 293 | u64 test_block; |
286 | int start_found; | 294 | int start_found; |
287 | struct btrfs_leaf *l; | 295 | struct btrfs_leaf *l; |
288 | struct btrfs_root * root = orig_root->extent_root; | 296 | struct btrfs_root * root = orig_root->fs_info->extent_root; |
289 | int total_needed = num_blocks; | 297 | int total_needed = num_blocks; |
290 | 298 | ||
291 | total_needed += (btrfs_header_level(&root->node->node.header) + 1) * 3; | 299 | total_needed += (btrfs_header_level(&root->node->node.header) + 1) * 3; |
292 | if (root->last_insert.objectid > search_start) | 300 | if (root->fs_info->last_insert.objectid > search_start) |
293 | search_start = root->last_insert.objectid; | 301 | search_start = root->fs_info->last_insert.objectid; |
294 | 302 | ||
295 | ins->flags = 0; | 303 | ins->flags = 0; |
296 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); | 304 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); |
@@ -353,16 +361,17 @@ check_pending: | |||
353 | BUG_ON(ins->objectid < search_start); | 361 | BUG_ON(ins->objectid < search_start); |
354 | for (test_block = ins->objectid; | 362 | for (test_block = ins->objectid; |
355 | test_block < ins->objectid + total_needed; test_block++) { | 363 | test_block < ins->objectid + total_needed; test_block++) { |
356 | if (radix_tree_lookup(&root->pinned_radix, test_block)) { | 364 | if (radix_tree_lookup(&root->fs_info->pinned_radix, |
365 | test_block)) { | ||
357 | search_start = test_block + 1; | 366 | search_start = test_block + 1; |
358 | goto check_failed; | 367 | goto check_failed; |
359 | } | 368 | } |
360 | } | 369 | } |
361 | BUG_ON(root->current_insert.offset); | 370 | BUG_ON(root->fs_info->current_insert.offset); |
362 | root->current_insert.offset = total_needed - num_blocks; | 371 | root->fs_info->current_insert.offset = total_needed - num_blocks; |
363 | root->current_insert.objectid = ins->objectid + num_blocks; | 372 | root->fs_info->current_insert.objectid = ins->objectid + num_blocks; |
364 | root->current_insert.flags = 0; | 373 | root->fs_info->current_insert.flags = 0; |
365 | root->last_insert.objectid = ins->objectid; | 374 | root->fs_info->last_insert.objectid = ins->objectid; |
366 | ins->offset = num_blocks; | 375 | ins->offset = num_blocks; |
367 | return 0; | 376 | return 0; |
368 | error: | 377 | error: |
@@ -383,20 +392,20 @@ static int alloc_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
383 | { | 392 | { |
384 | int ret; | 393 | int ret; |
385 | int pending_ret; | 394 | int pending_ret; |
386 | struct btrfs_root *extent_root = root->extent_root; | 395 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
387 | struct btrfs_extent_item extent_item; | 396 | struct btrfs_extent_item extent_item; |
388 | 397 | ||
389 | btrfs_set_extent_refs(&extent_item, 1); | 398 | btrfs_set_extent_refs(&extent_item, 1); |
390 | btrfs_set_extent_owner(&extent_item, owner); | 399 | btrfs_set_extent_owner(&extent_item, owner); |
391 | 400 | ||
392 | if (root == extent_root) { | 401 | if (root == extent_root) { |
393 | BUG_ON(extent_root->current_insert.offset == 0); | 402 | BUG_ON(extent_root->fs_info->current_insert.offset == 0); |
394 | BUG_ON(num_blocks != 1); | 403 | BUG_ON(num_blocks != 1); |
395 | BUG_ON(extent_root->current_insert.flags == | 404 | BUG_ON(extent_root->fs_info->current_insert.flags == |
396 | extent_root->current_insert.offset); | 405 | extent_root->fs_info->current_insert.offset); |
397 | ins->offset = 1; | 406 | ins->offset = 1; |
398 | ins->objectid = extent_root->current_insert.objectid + | 407 | ins->objectid = extent_root->fs_info->current_insert.objectid + |
399 | extent_root->current_insert.flags++; | 408 | extent_root->fs_info->current_insert.flags++; |
400 | return 0; | 409 | return 0; |
401 | } | 410 | } |
402 | ret = find_free_extent(trans, root, num_blocks, search_start, | 411 | ret = find_free_extent(trans, root, num_blocks, search_start, |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index f5b36c732c5e..24cfd6d85240 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -4,4 +4,10 @@ | |||
4 | #include "radix-tree.h" | 4 | #include "radix-tree.h" |
5 | #include "ctree.h" | 5 | #include "ctree.h" |
6 | #include "disk-io.h" | 6 | #include "disk-io.h" |
7 | #include "transaction.h" | ||
7 | 8 | ||
9 | int btrfs_create_file(struct btrfs_trans_handle *trans, | ||
10 | struct btrfs_root *root, u64 dirid, u64 *objectid) | ||
11 | { | ||
12 | return 0; | ||
13 | } | ||
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c new file mode 100644 index 000000000000..f412b3392135 --- /dev/null +++ b/fs/btrfs/inode-map.c | |||
@@ -0,0 +1,136 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include "kerncompat.h" | ||
4 | #include "radix-tree.h" | ||
5 | #include "ctree.h" | ||
6 | #include "disk-io.h" | ||
7 | #include "transaction.h" | ||
8 | |||
9 | /* | ||
10 | * walks the btree of allocated inodes and find a hole. | ||
11 | */ | ||
12 | int btrfs_find_free_objectid(struct btrfs_trans_handle *trans, | ||
13 | struct btrfs_root *fs_root, | ||
14 | u64 dirid, u64 *objectid) | ||
15 | { | ||
16 | struct btrfs_path path; | ||
17 | struct btrfs_key key; | ||
18 | int ret; | ||
19 | u64 hole_size = 0; | ||
20 | int slot = 0; | ||
21 | u64 last_ino; | ||
22 | int start_found; | ||
23 | struct btrfs_leaf *l; | ||
24 | struct btrfs_root *root = fs_root->fs_info->inode_root; | ||
25 | struct btrfs_key search_key; | ||
26 | u64 search_start = dirid; | ||
27 | |||
28 | if (fs_root->fs_info->last_inode_alloc_dirid == dirid) | ||
29 | search_start = fs_root->fs_info->last_inode_alloc; | ||
30 | |||
31 | search_key.objectid = search_start; | ||
32 | search_key.flags = 0; | ||
33 | btrfs_set_key_type(&search_key, BTRFS_INODE_MAP_ITEM_KEY); | ||
34 | search_key.offset = 0; | ||
35 | |||
36 | btrfs_init_path(&path); | ||
37 | start_found = 0; | ||
38 | ret = btrfs_search_slot(trans, root, &search_key, &path, 0, 0); | ||
39 | if (ret < 0) | ||
40 | goto error; | ||
41 | |||
42 | if (path.slots[0] > 0) | ||
43 | path.slots[0]--; | ||
44 | |||
45 | while (1) { | ||
46 | l = &path.nodes[0]->leaf; | ||
47 | slot = path.slots[0]; | ||
48 | if (slot >= btrfs_header_nritems(&l->header)) { | ||
49 | ret = btrfs_next_leaf(root, &path); | ||
50 | if (ret == 0) | ||
51 | continue; | ||
52 | if (ret < 0) | ||
53 | goto error; | ||
54 | if (!start_found) { | ||
55 | *objectid = search_start; | ||
56 | start_found = 1; | ||
57 | goto found; | ||
58 | } | ||
59 | *objectid = last_ino > search_start ? | ||
60 | last_ino : search_start; | ||
61 | goto found; | ||
62 | } | ||
63 | btrfs_disk_key_to_cpu(&key, &l->items[slot].key); | ||
64 | if (key.objectid >= search_start) { | ||
65 | if (start_found) { | ||
66 | if (last_ino < search_start) | ||
67 | last_ino = search_start; | ||
68 | hole_size = key.objectid - last_ino; | ||
69 | if (hole_size > 0) { | ||
70 | *objectid = last_ino; | ||
71 | goto found; | ||
72 | } | ||
73 | } | ||
74 | } | ||
75 | start_found = 1; | ||
76 | last_ino = key.objectid + 1; | ||
77 | path.slots[0]++; | ||
78 | } | ||
79 | // FIXME -ENOSPC | ||
80 | found: | ||
81 | root->fs_info->last_inode_alloc = *objectid; | ||
82 | root->fs_info->last_inode_alloc_dirid = dirid; | ||
83 | btrfs_release_path(root, &path); | ||
84 | BUG_ON(*objectid < search_start); | ||
85 | return 0; | ||
86 | error: | ||
87 | btrfs_release_path(root, &path); | ||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | int btrfs_insert_inode_map(struct btrfs_trans_handle *trans, | ||
92 | struct btrfs_root *fs_root, | ||
93 | u64 objectid, struct btrfs_key *location) | ||
94 | { | ||
95 | int ret = 0; | ||
96 | struct btrfs_path path; | ||
97 | struct btrfs_inode_map_item *inode_item; | ||
98 | struct btrfs_key key; | ||
99 | struct btrfs_root *inode_root = fs_root->fs_info->inode_root; | ||
100 | |||
101 | key.objectid = objectid; | ||
102 | key.flags = 0; | ||
103 | btrfs_set_key_type(&key, BTRFS_INODE_MAP_ITEM_KEY); | ||
104 | key.offset = 0; | ||
105 | btrfs_init_path(&path); | ||
106 | ret = btrfs_insert_empty_item(trans, inode_root, &path, &key, | ||
107 | sizeof(struct btrfs_inode_map_item)); | ||
108 | if (ret) | ||
109 | goto out; | ||
110 | |||
111 | inode_item = btrfs_item_ptr(&path.nodes[0]->leaf, path.slots[0], | ||
112 | struct btrfs_inode_map_item); | ||
113 | btrfs_cpu_key_to_disk(&inode_item->key, location); | ||
114 | out: | ||
115 | btrfs_release_path(inode_root, &path); | ||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | int btrfs_lookup_inode_map(struct btrfs_trans_handle *trans, | ||
120 | struct btrfs_root *fs_root, struct btrfs_path *path, | ||
121 | u64 objectid, int mod) | ||
122 | { | ||
123 | int ret; | ||
124 | struct btrfs_key key; | ||
125 | int ins_len = mod < 0 ? -1 : 0; | ||
126 | int cow = mod != 0; | ||
127 | struct btrfs_root *inode_root = fs_root->fs_info->inode_root; | ||
128 | |||
129 | key.objectid = objectid; | ||
130 | key.flags = 0; | ||
131 | key.offset = 0; | ||
132 | btrfs_set_key_type(&key, BTRFS_INODE_MAP_ITEM_KEY); | ||
133 | ret = btrfs_search_slot(trans, inode_root, &key, path, ins_len, cow); | ||
134 | return ret; | ||
135 | } | ||
136 | |||
diff --git a/fs/btrfs/mkfs.c b/fs/btrfs/mkfs.c index 9aa900811c33..1cac5ab114dd 100644 --- a/fs/btrfs/mkfs.c +++ b/fs/btrfs/mkfs.c | |||
@@ -42,7 +42,7 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) | |||
42 | btrfs_set_header_parentid(&empty_leaf->header, | 42 | btrfs_set_header_parentid(&empty_leaf->header, |
43 | BTRFS_ROOT_TREE_OBJECTID); | 43 | BTRFS_ROOT_TREE_OBJECTID); |
44 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 1); | 44 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 1); |
45 | btrfs_set_header_nritems(&empty_leaf->header, 2); | 45 | btrfs_set_header_nritems(&empty_leaf->header, 3); |
46 | 46 | ||
47 | /* create the items for the root tree */ | 47 | /* create the items for the root tree */ |
48 | btrfs_set_root_blocknr(&root_item, start_block + 2); | 48 | btrfs_set_root_blocknr(&root_item, start_block + 2); |
@@ -61,17 +61,25 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) | |||
61 | btrfs_set_root_blocknr(&root_item, start_block + 3); | 61 | btrfs_set_root_blocknr(&root_item, start_block + 3); |
62 | itemoff = itemoff - sizeof(root_item); | 62 | itemoff = itemoff - sizeof(root_item); |
63 | btrfs_set_item_offset(&item, itemoff); | 63 | btrfs_set_item_offset(&item, itemoff); |
64 | btrfs_set_disk_key_objectid(&item.key, BTRFS_FS_TREE_OBJECTID); | 64 | btrfs_set_disk_key_objectid(&item.key, BTRFS_INODE_MAP_OBJECTID); |
65 | memcpy(empty_leaf->items + 1, &item, sizeof(item)); | 65 | memcpy(empty_leaf->items + 1, &item, sizeof(item)); |
66 | memcpy(btrfs_leaf_data(empty_leaf) + itemoff, | 66 | memcpy(btrfs_leaf_data(empty_leaf) + itemoff, |
67 | &root_item, sizeof(root_item)); | 67 | &root_item, sizeof(root_item)); |
68 | |||
69 | btrfs_set_root_blocknr(&root_item, start_block + 4); | ||
70 | itemoff = itemoff - sizeof(root_item); | ||
71 | btrfs_set_item_offset(&item, itemoff); | ||
72 | btrfs_set_disk_key_objectid(&item.key, BTRFS_FS_TREE_OBJECTID); | ||
73 | memcpy(empty_leaf->items + 2, &item, sizeof(item)); | ||
74 | memcpy(btrfs_leaf_data(empty_leaf) + itemoff, | ||
75 | &root_item, sizeof(root_item)); | ||
68 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 1) * blocksize); | 76 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 1) * blocksize); |
69 | 77 | ||
70 | /* create the items for the extent tree */ | 78 | /* create the items for the extent tree */ |
71 | btrfs_set_header_parentid(&empty_leaf->header, | 79 | btrfs_set_header_parentid(&empty_leaf->header, |
72 | BTRFS_EXTENT_TREE_OBJECTID); | 80 | BTRFS_EXTENT_TREE_OBJECTID); |
73 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 2); | 81 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 2); |
74 | btrfs_set_header_nritems(&empty_leaf->header, 4); | 82 | btrfs_set_header_nritems(&empty_leaf->header, 5); |
75 | 83 | ||
76 | /* item1, reserve blocks 0-16 */ | 84 | /* item1, reserve blocks 0-16 */ |
77 | btrfs_set_disk_key_objectid(&item.key, 0); | 85 | btrfs_set_disk_key_objectid(&item.key, 0); |
@@ -108,12 +116,12 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) | |||
108 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), | 116 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), |
109 | &extent_item, btrfs_item_size(&item)); | 117 | &extent_item, btrfs_item_size(&item)); |
110 | 118 | ||
111 | /* item4, give block 19 to the FS root */ | 119 | /* item4, give block 19 to the inode map */ |
112 | btrfs_set_disk_key_objectid(&item.key, start_block + 3); | 120 | btrfs_set_disk_key_objectid(&item.key, start_block + 3); |
113 | btrfs_set_disk_key_offset(&item.key, 1); | 121 | btrfs_set_disk_key_offset(&item.key, 1); |
114 | itemoff = itemoff - sizeof(struct btrfs_extent_item); | 122 | itemoff = itemoff - sizeof(struct btrfs_extent_item); |
115 | btrfs_set_item_offset(&item, itemoff); | 123 | btrfs_set_item_offset(&item, itemoff); |
116 | btrfs_set_extent_owner(&extent_item, BTRFS_FS_TREE_OBJECTID); | 124 | btrfs_set_extent_owner(&extent_item, BTRFS_INODE_MAP_OBJECTID); |
117 | memcpy(empty_leaf->items + 3, &item, sizeof(item)); | 125 | memcpy(empty_leaf->items + 3, &item, sizeof(item)); |
118 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), | 126 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), |
119 | &extent_item, btrfs_item_size(&item)); | 127 | &extent_item, btrfs_item_size(&item)); |
@@ -121,12 +129,34 @@ int mkfs(int fd, u64 num_blocks, u32 blocksize) | |||
121 | if (ret != blocksize) | 129 | if (ret != blocksize) |
122 | return -1; | 130 | return -1; |
123 | 131 | ||
124 | /* finally create the FS root */ | 132 | /* item5, give block 20 to the FS root */ |
125 | btrfs_set_header_parentid(&empty_leaf->header, BTRFS_FS_TREE_OBJECTID); | 133 | btrfs_set_disk_key_objectid(&item.key, start_block + 4); |
134 | btrfs_set_disk_key_offset(&item.key, 1); | ||
135 | itemoff = itemoff - sizeof(struct btrfs_extent_item); | ||
136 | btrfs_set_item_offset(&item, itemoff); | ||
137 | btrfs_set_extent_owner(&extent_item, BTRFS_FS_TREE_OBJECTID); | ||
138 | memcpy(empty_leaf->items + 4, &item, sizeof(item)); | ||
139 | memcpy(btrfs_leaf_data(empty_leaf) + btrfs_item_offset(&item), | ||
140 | &extent_item, btrfs_item_size(&item)); | ||
141 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 2) * blocksize); | ||
142 | if (ret != blocksize) | ||
143 | return -1; | ||
144 | |||
145 | /* create the inode map */ | ||
146 | btrfs_set_header_parentid(&empty_leaf->header, | ||
147 | BTRFS_INODE_MAP_OBJECTID); | ||
126 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 3); | 148 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 3); |
127 | btrfs_set_header_nritems(&empty_leaf->header, 0); | 149 | btrfs_set_header_nritems(&empty_leaf->header, 0); |
128 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 3) * blocksize); | 150 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 3) * blocksize); |
129 | if (ret != blocksize) | 151 | if (ret != blocksize) |
130 | return -1; | 152 | return -1; |
153 | |||
154 | /* finally create the FS root */ | ||
155 | btrfs_set_header_parentid(&empty_leaf->header, BTRFS_FS_TREE_OBJECTID); | ||
156 | btrfs_set_header_blocknr(&empty_leaf->header, start_block + 4); | ||
157 | btrfs_set_header_nritems(&empty_leaf->header, 0); | ||
158 | ret = pwrite(fd, empty_leaf, blocksize, (start_block + 4) * blocksize); | ||
159 | if (ret != blocksize) | ||
160 | return -1; | ||
131 | return 0; | 161 | return 0; |
132 | } | 162 | } |
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index 0bb5c38427c9..f250e5fad773 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c | |||
@@ -13,8 +13,8 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | |||
13 | struct btrfs_extent_item *ei; | 13 | struct btrfs_extent_item *ei; |
14 | struct btrfs_root_item *ri; | 14 | struct btrfs_root_item *ri; |
15 | struct btrfs_dir_item *di; | 15 | struct btrfs_dir_item *di; |
16 | struct btrfs_inode_map_item *mi; | ||
16 | u32 type; | 17 | u32 type; |
17 | u32 namelen; | ||
18 | 18 | ||
19 | printf("leaf %Lu total ptrs %d free space %d\n", | 19 | printf("leaf %Lu total ptrs %d free space %d\n", |
20 | btrfs_header_blocknr(&l->header), nr, | 20 | btrfs_header_blocknr(&l->header), nr, |
@@ -34,15 +34,13 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | |||
34 | case BTRFS_INODE_ITEM_KEY: | 34 | case BTRFS_INODE_ITEM_KEY: |
35 | break; | 35 | break; |
36 | case BTRFS_DIR_ITEM_KEY: | 36 | case BTRFS_DIR_ITEM_KEY: |
37 | namelen = btrfs_item_size(l->items + i) - sizeof(*di); | ||
38 | di = btrfs_item_ptr(l, i, struct btrfs_dir_item); | 37 | di = btrfs_item_ptr(l, i, struct btrfs_dir_item); |
39 | printf("\t\tdir oid %Lu flags %u type %u\n", | 38 | printf("\t\tdir oid %Lu flags %u type %u\n", |
40 | btrfs_dir_objectid(di), | 39 | btrfs_dir_objectid(di), |
41 | btrfs_dir_flags(di), | 40 | btrfs_dir_flags(di), |
42 | btrfs_dir_type(di)); | 41 | btrfs_dir_type(di)); |
43 | printf("\t\tname %.*s\n", | 42 | printf("\t\tname %.*s\n", |
44 | namelen, (char *)(di + 1)); | 43 | btrfs_dir_name_len(di),(char *)(di + 1)); |
45 | |||
46 | break; | 44 | break; |
47 | case BTRFS_ROOT_ITEM_KEY: | 45 | case BTRFS_ROOT_ITEM_KEY: |
48 | ri = btrfs_item_ptr(l, i, struct btrfs_root_item); | 46 | ri = btrfs_item_ptr(l, i, struct btrfs_root_item); |
@@ -54,6 +52,13 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | |||
54 | printf("\t\textent data refs %u owner %Lu\n", | 52 | printf("\t\textent data refs %u owner %Lu\n", |
55 | btrfs_extent_refs(ei), btrfs_extent_owner(ei)); | 53 | btrfs_extent_refs(ei), btrfs_extent_owner(ei)); |
56 | break; | 54 | break; |
55 | case BTRFS_INODE_MAP_ITEM_KEY: | ||
56 | mi = btrfs_item_ptr(l, i, struct btrfs_inode_map_item); | ||
57 | printf("\t\tinode map key %Lu %u %Lu\n", | ||
58 | btrfs_disk_key_objectid(&mi->key), | ||
59 | btrfs_disk_key_flags(&mi->key), | ||
60 | btrfs_disk_key_offset(&mi->key)); | ||
61 | break; | ||
57 | case BTRFS_STRING_ITEM_KEY: | 62 | case BTRFS_STRING_ITEM_KEY: |
58 | printf("\t\titem data %.*s\n", btrfs_item_size(item), | 63 | printf("\t\titem data %.*s\n", btrfs_item_size(item), |
59 | btrfs_leaf_data(l) + btrfs_item_offset(item)); | 64 | btrfs_leaf_data(l) + btrfs_item_offset(item)); |
diff --git a/fs/btrfs/quick-test.c b/fs/btrfs/quick-test.c index d676577185d5..ef12cf888783 100644 --- a/fs/btrfs/quick-test.c +++ b/fs/btrfs/quick-test.c | |||
@@ -172,7 +172,8 @@ int main(int ac, char **av) { | |||
172 | printf("tree size is now %d\n", tree_size); | 172 | printf("tree size is now %d\n", tree_size); |
173 | printf("root %p commit root %p\n", root->node, root->commit_root); | 173 | printf("root %p commit root %p\n", root->node, root->commit_root); |
174 | printf("map tree\n"); | 174 | printf("map tree\n"); |
175 | btrfs_print_tree(root->extent_root, root->extent_root->node); | 175 | btrfs_print_tree(root->fs_info->extent_root, |
176 | root->fs_info->extent_root->node); | ||
176 | close_ctree(root, &super); | 177 | close_ctree(root, &super); |
177 | return 0; | 178 | return 0; |
178 | } | 179 | } |