diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-26 16:46:15 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-26 16:46:15 -0400 |
commit | 9078a3e1e4e489dddc636c7bb8780349d4298743 (patch) | |
tree | 98597a438d60fc8722c7562b79cecaa303b4721d | |
parent | f2458e1d8c90958ed3631654cb7fd5ab01478505 (diff) |
Btrfs: start of block group code
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/ctree.h | 66 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 4 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 204 | ||||
-rw-r--r-- | fs/btrfs/print-tree.c | 7 | ||||
-rw-r--r-- | fs/btrfs/super.c | 1 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 2 |
6 files changed, 252 insertions, 32 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 26d0cdd46f49..419917279e65 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -239,6 +239,19 @@ struct btrfs_device_item { | |||
239 | __le64 device_id; | 239 | __le64 device_id; |
240 | } __attribute__ ((__packed__)); | 240 | } __attribute__ ((__packed__)); |
241 | 241 | ||
242 | /* tag for the radix tree of block groups in ram */ | ||
243 | #define BTRFS_BLOCK_GROUP_DIRTY 0 | ||
244 | #define BTRFS_BLOCK_GROUP_HINTS 8 | ||
245 | #define BTRFS_BLOCK_GROUP_SIZE (256 * 1024 * 1024) | ||
246 | struct btrfs_block_group_item { | ||
247 | __le64 used; | ||
248 | } __attribute__ ((__packed__)); | ||
249 | |||
250 | struct btrfs_block_group_cache { | ||
251 | struct btrfs_key key; | ||
252 | struct btrfs_block_group_item item; | ||
253 | }; | ||
254 | |||
242 | struct crypto_hash; | 255 | struct crypto_hash; |
243 | struct btrfs_fs_info { | 256 | struct btrfs_fs_info { |
244 | struct btrfs_root *extent_root; | 257 | struct btrfs_root *extent_root; |
@@ -249,6 +262,7 @@ struct btrfs_fs_info { | |||
249 | struct radix_tree_root pending_del_radix; | 262 | struct radix_tree_root pending_del_radix; |
250 | struct radix_tree_root pinned_radix; | 263 | struct radix_tree_root pinned_radix; |
251 | struct radix_tree_root dev_radix; | 264 | struct radix_tree_root dev_radix; |
265 | struct radix_tree_root block_group_radix; | ||
252 | 266 | ||
253 | u64 extent_tree_insert[BTRFS_MAX_LEVEL * 3]; | 267 | u64 extent_tree_insert[BTRFS_MAX_LEVEL * 3]; |
254 | int extent_tree_insert_nr; | 268 | int extent_tree_insert_nr; |
@@ -301,49 +315,67 @@ struct btrfs_root { | |||
301 | * info about object characteristics. There is one for every file and dir in | 315 | * info about object characteristics. There is one for every file and dir in |
302 | * the FS | 316 | * the FS |
303 | */ | 317 | */ |
304 | #define BTRFS_INODE_ITEM_KEY 1 | 318 | #define BTRFS_INODE_ITEM_KEY 1 |
319 | |||
320 | /* reserve 2-15 close to the inode for later flexibility */ | ||
305 | 321 | ||
306 | /* | 322 | /* |
307 | * dir items are the name -> inode pointers in a directory. There is one | 323 | * dir items are the name -> inode pointers in a directory. There is one |
308 | * for every name in a directory. | 324 | * for every name in a directory. |
309 | */ | 325 | */ |
310 | #define BTRFS_DIR_ITEM_KEY 2 | 326 | #define BTRFS_DIR_ITEM_KEY 16 |
311 | #define BTRFS_DIR_INDEX_KEY 3 | 327 | #define BTRFS_DIR_INDEX_KEY 17 |
312 | /* | 328 | /* |
313 | * inline data is file data that fits in the btree. | 329 | * extent data is for file data |
314 | */ | 330 | */ |
315 | #define BTRFS_INLINE_DATA_KEY 4 | 331 | #define BTRFS_EXTENT_DATA_KEY 18 |
316 | /* | ||
317 | * extent data is for data that can't fit in the btree. It points to | ||
318 | * a (hopefully) huge chunk of disk | ||
319 | */ | ||
320 | #define BTRFS_EXTENT_DATA_KEY 5 | ||
321 | /* | 332 | /* |
322 | * csum items have the checksums for data in the extents | 333 | * csum items have the checksums for data in the extents |
323 | */ | 334 | */ |
324 | #define BTRFS_CSUM_ITEM_KEY 6 | 335 | #define BTRFS_CSUM_ITEM_KEY 19 |
336 | |||
337 | /* reserve 20-31 for other file stuff */ | ||
325 | 338 | ||
326 | /* | 339 | /* |
327 | * root items point to tree roots. There are typically in the root | 340 | * root items point to tree roots. There are typically in the root |
328 | * tree used by the super block to find all the other trees | 341 | * tree used by the super block to find all the other trees |
329 | */ | 342 | */ |
330 | #define BTRFS_ROOT_ITEM_KEY 7 | 343 | #define BTRFS_ROOT_ITEM_KEY 32 |
331 | /* | 344 | /* |
332 | * extent items are in the extent map tree. These record which blocks | 345 | * extent items are in the extent map tree. These record which blocks |
333 | * are used, and how many references there are to each block | 346 | * are used, and how many references there are to each block |
334 | */ | 347 | */ |
335 | #define BTRFS_EXTENT_ITEM_KEY 8 | 348 | #define BTRFS_EXTENT_ITEM_KEY 33 |
349 | |||
350 | /* | ||
351 | * block groups give us hints into the extent allocation trees. Which | ||
352 | * blocks are free etc etc | ||
353 | */ | ||
354 | #define BTRFS_BLOCK_GROUP_ITEM_KEY 34 | ||
336 | 355 | ||
337 | /* | 356 | /* |
338 | * dev items list the devices that make up the FS | 357 | * dev items list the devices that make up the FS |
339 | */ | 358 | */ |
340 | #define BTRFS_DEV_ITEM_KEY 9 | 359 | #define BTRFS_DEV_ITEM_KEY 35 |
341 | 360 | ||
342 | /* | 361 | /* |
343 | * string items are for debugging. They just store a short string of | 362 | * string items are for debugging. They just store a short string of |
344 | * data in the FS | 363 | * data in the FS |
345 | */ | 364 | */ |
346 | #define BTRFS_STRING_ITEM_KEY 10 | 365 | #define BTRFS_STRING_ITEM_KEY 253 |
366 | |||
367 | |||
368 | static inline u64 btrfs_block_group_used(struct btrfs_block_group_item *bi) | ||
369 | { | ||
370 | return le64_to_cpu(bi->used); | ||
371 | } | ||
372 | |||
373 | static inline void btrfs_set_block_group_used(struct | ||
374 | btrfs_block_group_item *bi, | ||
375 | u64 val) | ||
376 | { | ||
377 | bi->used = cpu_to_le64(val); | ||
378 | } | ||
347 | 379 | ||
348 | static inline u64 btrfs_inode_generation(struct btrfs_inode_item *i) | 380 | static inline u64 btrfs_inode_generation(struct btrfs_inode_item *i) |
349 | { | 381 | { |
@@ -1037,6 +1069,10 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | |||
1037 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | 1069 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, |
1038 | struct btrfs_root *root, | 1070 | struct btrfs_root *root, |
1039 | u64 blocknr, u64 num_blocks); | 1071 | u64 blocknr, u64 num_blocks); |
1072 | int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | ||
1073 | struct btrfs_root *root); | ||
1074 | int btrfs_free_block_groups(struct btrfs_fs_info *info); | ||
1075 | int btrfs_read_block_groups(struct btrfs_root *root); | ||
1040 | /* ctree.c */ | 1076 | /* ctree.c */ |
1041 | int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root | 1077 | int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root |
1042 | *root, struct btrfs_path *path, u32 data_size); | 1078 | *root, struct btrfs_path *path, u32 data_size); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 956727f015a5..1c27eb645510 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -529,6 +529,7 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
529 | init_bit_radix(&fs_info->pending_del_radix); | 529 | init_bit_radix(&fs_info->pending_del_radix); |
530 | INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); | 530 | INIT_RADIX_TREE(&fs_info->fs_roots_radix, GFP_NOFS); |
531 | INIT_RADIX_TREE(&fs_info->dev_radix, GFP_NOFS); | 531 | INIT_RADIX_TREE(&fs_info->dev_radix, GFP_NOFS); |
532 | INIT_RADIX_TREE(&fs_info->block_group_radix, GFP_KERNEL); | ||
532 | INIT_LIST_HEAD(&fs_info->trans_list); | 533 | INIT_LIST_HEAD(&fs_info->trans_list); |
533 | sb_set_blocksize(sb, 4096); | 534 | sb_set_blocksize(sb, 4096); |
534 | fs_info->running_transaction = NULL; | 535 | fs_info->running_transaction = NULL; |
@@ -613,6 +614,8 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
613 | BTRFS_EXTENT_TREE_OBJECTID, extent_root); | 614 | BTRFS_EXTENT_TREE_OBJECTID, extent_root); |
614 | BUG_ON(ret); | 615 | BUG_ON(ret); |
615 | 616 | ||
617 | btrfs_read_block_groups(extent_root); | ||
618 | |||
616 | fs_info->generation = btrfs_super_generation(disk_super) + 1; | 619 | fs_info->generation = btrfs_super_generation(disk_super) + 1; |
617 | memset(&fs_info->kobj, 0, sizeof(fs_info->kobj)); | 620 | memset(&fs_info->kobj, 0, sizeof(fs_info->kobj)); |
618 | kobj_set_kset_s(fs_info, btrfs_subsys); | 621 | kobj_set_kset_s(fs_info, btrfs_subsys); |
@@ -741,6 +744,7 @@ int close_ctree(struct btrfs_root *root) | |||
741 | iput(fs_info->btree_inode); | 744 | iput(fs_info->btree_inode); |
742 | 745 | ||
743 | free_dev_radix(fs_info); | 746 | free_dev_radix(fs_info); |
747 | btrfs_free_block_groups(root->fs_info); | ||
744 | del_fs_roots(fs_info); | 748 | del_fs_roots(fs_info); |
745 | kfree(fs_info->extent_root); | 749 | kfree(fs_info->extent_root); |
746 | kfree(fs_info->tree_root); | 750 | kfree(fs_info->tree_root); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index e6fe3fd38819..0bb4fc83cfd6 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -127,6 +127,105 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
127 | return 0; | 127 | return 0; |
128 | } | 128 | } |
129 | 129 | ||
130 | static int write_one_cache_group(struct btrfs_trans_handle *trans, | ||
131 | struct btrfs_root *root, | ||
132 | struct btrfs_path *path, | ||
133 | struct btrfs_block_group_cache *cache) | ||
134 | { | ||
135 | int ret; | ||
136 | int pending_ret; | ||
137 | struct btrfs_root *extent_root = root->fs_info->extent_root; | ||
138 | struct btrfs_block_group_item *bi; | ||
139 | struct btrfs_key ins; | ||
140 | |||
141 | find_free_extent(trans, extent_root, 0, 0, (u64)-1, &ins); | ||
142 | ret = btrfs_search_slot(trans, extent_root, &cache->key, path, 0, 1); | ||
143 | BUG_ON(ret); | ||
144 | bi = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), path->slots[0], | ||
145 | struct btrfs_block_group_item); | ||
146 | memcpy(bi, &cache->item, sizeof(*bi)); | ||
147 | mark_buffer_dirty(path->nodes[0]); | ||
148 | btrfs_release_path(extent_root, path); | ||
149 | |||
150 | finish_current_insert(trans, extent_root); | ||
151 | pending_ret = del_pending_extents(trans, extent_root); | ||
152 | if (ret) | ||
153 | return ret; | ||
154 | if (pending_ret) | ||
155 | return pending_ret; | ||
156 | return 0; | ||
157 | |||
158 | } | ||
159 | |||
160 | int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | ||
161 | struct btrfs_root *root) | ||
162 | { | ||
163 | struct btrfs_block_group_cache *cache[8]; | ||
164 | int ret; | ||
165 | int err = 0; | ||
166 | int werr = 0; | ||
167 | struct radix_tree_root *radix = &root->fs_info->block_group_radix; | ||
168 | int i; | ||
169 | struct btrfs_path *path; | ||
170 | |||
171 | path = btrfs_alloc_path(); | ||
172 | if (!path) | ||
173 | return -ENOMEM; | ||
174 | |||
175 | while(1) { | ||
176 | ret = radix_tree_gang_lookup_tag(radix, (void **)cache, | ||
177 | 0, ARRAY_SIZE(cache), | ||
178 | BTRFS_BLOCK_GROUP_DIRTY); | ||
179 | if (!ret) | ||
180 | break; | ||
181 | for (i = 0; i < ret; i++) { | ||
182 | radix_tree_tag_clear(radix, cache[i]->key.objectid + | ||
183 | cache[i]->key.offset - 1, | ||
184 | BTRFS_BLOCK_GROUP_DIRTY); | ||
185 | err = write_one_cache_group(trans, root, | ||
186 | path, cache[i]); | ||
187 | if (err) | ||
188 | werr = err; | ||
189 | } | ||
190 | } | ||
191 | btrfs_free_path(path); | ||
192 | return werr; | ||
193 | } | ||
194 | |||
195 | static int update_block_group(struct btrfs_trans_handle *trans, | ||
196 | struct btrfs_root *root, | ||
197 | u64 blocknr, u64 num, int alloc) | ||
198 | { | ||
199 | struct btrfs_block_group_cache *cache; | ||
200 | struct btrfs_fs_info *info = root->fs_info; | ||
201 | u64 total = num; | ||
202 | u64 old_val; | ||
203 | u64 block_in_group; | ||
204 | int ret; | ||
205 | while(total) { | ||
206 | ret = radix_tree_gang_lookup(&info->block_group_radix, | ||
207 | (void **)&cache, blocknr, 1); | ||
208 | if (!ret) | ||
209 | return -1; | ||
210 | block_in_group = blocknr - cache->key.objectid; | ||
211 | WARN_ON(block_in_group > cache->key.offset); | ||
212 | radix_tree_tag_set(&info->block_group_radix, | ||
213 | cache->key.objectid + cache->key.offset - 1, | ||
214 | BTRFS_BLOCK_GROUP_DIRTY); | ||
215 | |||
216 | old_val = btrfs_block_group_used(&cache->item); | ||
217 | num = min(total, cache->key.offset - block_in_group); | ||
218 | total -= num; | ||
219 | blocknr += num; | ||
220 | if (alloc) | ||
221 | old_val += num; | ||
222 | else | ||
223 | old_val -= num; | ||
224 | btrfs_set_block_group_used(&cache->item, old_val); | ||
225 | } | ||
226 | return 0; | ||
227 | } | ||
228 | |||
130 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | 229 | int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct |
131 | btrfs_root *root) | 230 | btrfs_root *root) |
132 | { | 231 | { |
@@ -264,6 +363,8 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
264 | ret = btrfs_del_item(trans, extent_root, path); | 363 | ret = btrfs_del_item(trans, extent_root, path); |
265 | if (ret) | 364 | if (ret) |
266 | BUG(); | 365 | BUG(); |
366 | ret = update_block_group(trans, root, blocknr, num_blocks, 0); | ||
367 | BUG_ON(ret); | ||
267 | } | 368 | } |
268 | btrfs_release_path(extent_root, path); | 369 | btrfs_release_path(extent_root, path); |
269 | btrfs_free_path(path); | 370 | btrfs_free_path(path); |
@@ -365,21 +466,6 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
365 | num_blocks = 1; | 466 | num_blocks = 1; |
366 | total_needed = min(level + 2, BTRFS_MAX_LEVEL) * 3; | 467 | total_needed = min(level + 2, BTRFS_MAX_LEVEL) * 3; |
367 | } | 468 | } |
368 | if (info->last_insert.objectid == 0 && search_end == (u64)-1) { | ||
369 | struct btrfs_disk_key *last_key; | ||
370 | btrfs_init_path(path); | ||
371 | ins->objectid = (u64)-1; | ||
372 | ins->offset = (u64)-1; | ||
373 | ret = btrfs_search_slot(trans, root, ins, path, 0, 0); | ||
374 | if (ret < 0) | ||
375 | goto error; | ||
376 | BUG_ON(ret == 0); | ||
377 | if (path->slots[0] > 0) | ||
378 | path->slots[0]--; | ||
379 | l = btrfs_buffer_leaf(path->nodes[0]); | ||
380 | last_key = &l->items[path->slots[0]].key; | ||
381 | search_start = btrfs_disk_key_objectid(last_key); | ||
382 | } | ||
383 | if (info->last_insert.objectid > search_start) | 469 | if (info->last_insert.objectid > search_start) |
384 | search_start = info->last_insert.objectid; | 470 | search_start = info->last_insert.objectid; |
385 | 471 | ||
@@ -420,6 +506,8 @@ check_failed: | |||
420 | goto check_pending; | 506 | goto check_pending; |
421 | } | 507 | } |
422 | btrfs_disk_key_to_cpu(&key, &l->items[slot].key); | 508 | btrfs_disk_key_to_cpu(&key, &l->items[slot].key); |
509 | if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY) | ||
510 | goto next; | ||
423 | if (key.objectid >= search_start) { | 511 | if (key.objectid >= search_start) { |
424 | if (start_found) { | 512 | if (start_found) { |
425 | if (last_block < search_start) | 513 | if (last_block < search_start) |
@@ -434,6 +522,7 @@ check_failed: | |||
434 | } | 522 | } |
435 | start_found = 1; | 523 | start_found = 1; |
436 | last_block = key.objectid + key.offset; | 524 | last_block = key.objectid + key.offset; |
525 | next: | ||
437 | path->slots[0]++; | 526 | path->slots[0]++; |
438 | } | 527 | } |
439 | // FIXME -ENOSPC | 528 | // FIXME -ENOSPC |
@@ -498,7 +587,6 @@ error: | |||
498 | btrfs_free_path(path); | 587 | btrfs_free_path(path); |
499 | return ret; | 588 | return ret; |
500 | } | 589 | } |
501 | |||
502 | /* | 590 | /* |
503 | * finds a free extent and does all the dirty work required for allocation | 591 | * finds a free extent and does all the dirty work required for allocation |
504 | * returns the key for the extent through ins, and a tree buffer for | 592 | * returns the key for the extent through ins, and a tree buffer for |
@@ -532,6 +620,9 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
532 | ins->objectid = info->extent_tree_prealloc[nr]; | 620 | ins->objectid = info->extent_tree_prealloc[nr]; |
533 | info->extent_tree_insert[info->extent_tree_insert_nr++] = | 621 | info->extent_tree_insert[info->extent_tree_insert_nr++] = |
534 | ins->objectid; | 622 | ins->objectid; |
623 | ret = update_block_group(trans, root, | ||
624 | ins->objectid, ins->offset, 1); | ||
625 | BUG_ON(ret); | ||
535 | return 0; | 626 | return 0; |
536 | } | 627 | } |
537 | /* do the real allocation */ | 628 | /* do the real allocation */ |
@@ -558,6 +649,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
558 | return ret; | 649 | return ret; |
559 | if (pending_ret) | 650 | if (pending_ret) |
560 | return pending_ret; | 651 | return pending_ret; |
652 | ret = update_block_group(trans, root, ins->objectid, ins->offset, 1); | ||
561 | return 0; | 653 | return 0; |
562 | } | 654 | } |
563 | 655 | ||
@@ -578,6 +670,7 @@ struct buffer_head *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
578 | BUG(); | 670 | BUG(); |
579 | return NULL; | 671 | return NULL; |
580 | } | 672 | } |
673 | BUG_ON(ret); | ||
581 | buf = btrfs_find_create_tree_block(root, ins.objectid); | 674 | buf = btrfs_find_create_tree_block(root, ins.objectid); |
582 | set_buffer_uptodate(buf); | 675 | set_buffer_uptodate(buf); |
583 | return buf; | 676 | return buf; |
@@ -758,3 +851,82 @@ int btrfs_drop_snapshot(struct btrfs_trans_handle *trans, struct btrfs_root | |||
758 | btrfs_free_path(path); | 851 | btrfs_free_path(path); |
759 | return ret; | 852 | return ret; |
760 | } | 853 | } |
854 | |||
855 | int btrfs_free_block_groups(struct btrfs_fs_info *info) | ||
856 | { | ||
857 | int ret; | ||
858 | struct btrfs_block_group_cache *cache[8]; | ||
859 | int i; | ||
860 | |||
861 | while(1) { | ||
862 | ret = radix_tree_gang_lookup(&info->block_group_radix, | ||
863 | (void **)cache, 0, | ||
864 | ARRAY_SIZE(cache)); | ||
865 | if (!ret) | ||
866 | break; | ||
867 | for (i = 0; i < ret; i++) { | ||
868 | radix_tree_delete(&info->block_group_radix, | ||
869 | cache[i]->key.objectid + | ||
870 | cache[i]->key.offset - 1); | ||
871 | kfree(cache[i]); | ||
872 | } | ||
873 | } | ||
874 | return 0; | ||
875 | } | ||
876 | |||
877 | int btrfs_read_block_groups(struct btrfs_root *root) | ||
878 | { | ||
879 | struct btrfs_path *path; | ||
880 | int ret; | ||
881 | int err = 0; | ||
882 | struct btrfs_block_group_item *bi; | ||
883 | struct btrfs_block_group_cache *cache; | ||
884 | struct btrfs_key key; | ||
885 | struct btrfs_key found_key; | ||
886 | struct btrfs_leaf *leaf; | ||
887 | u64 group_size_blocks = BTRFS_BLOCK_GROUP_SIZE / root->blocksize; | ||
888 | |||
889 | root = root->fs_info->extent_root; | ||
890 | key.objectid = 0; | ||
891 | key.offset = group_size_blocks; | ||
892 | key.flags = 0; | ||
893 | btrfs_set_key_type(&key, BTRFS_BLOCK_GROUP_ITEM_KEY); | ||
894 | |||
895 | path = btrfs_alloc_path(); | ||
896 | if (!path) | ||
897 | return -ENOMEM; | ||
898 | |||
899 | while(1) { | ||
900 | ret = btrfs_search_slot(NULL, root->fs_info->extent_root, | ||
901 | &key, path, 0, 0); | ||
902 | if (ret != 0) { | ||
903 | err = ret; | ||
904 | break; | ||
905 | } | ||
906 | leaf = btrfs_buffer_leaf(path->nodes[0]); | ||
907 | btrfs_disk_key_to_cpu(&found_key, | ||
908 | &leaf->items[path->slots[0]].key); | ||
909 | cache = kmalloc(sizeof(*cache), GFP_NOFS); | ||
910 | if (!cache) { | ||
911 | err = -1; | ||
912 | break; | ||
913 | } | ||
914 | bi = btrfs_item_ptr(leaf, path->slots[0], | ||
915 | struct btrfs_block_group_item); | ||
916 | memcpy(&cache->item, bi, sizeof(*bi)); | ||
917 | memcpy(&cache->key, &found_key, sizeof(found_key)); | ||
918 | key.objectid = found_key.objectid + found_key.offset; | ||
919 | btrfs_release_path(root, path); | ||
920 | ret = radix_tree_insert(&root->fs_info->block_group_radix, | ||
921 | found_key.objectid + | ||
922 | found_key.offset - 1, | ||
923 | (void *)cache); | ||
924 | BUG_ON(ret); | ||
925 | if (key.objectid >= | ||
926 | btrfs_super_total_blocks(root->fs_info->disk_super)) | ||
927 | break; | ||
928 | } | ||
929 | |||
930 | btrfs_free_path(path); | ||
931 | return 0; | ||
932 | } | ||
diff --git a/fs/btrfs/print-tree.c b/fs/btrfs/print-tree.c index 1e7038b070ae..2f95fc67a036 100644 --- a/fs/btrfs/print-tree.c +++ b/fs/btrfs/print-tree.c | |||
@@ -11,6 +11,7 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | |||
11 | struct btrfs_root_item *ri; | 11 | struct btrfs_root_item *ri; |
12 | struct btrfs_dir_item *di; | 12 | struct btrfs_dir_item *di; |
13 | struct btrfs_inode_item *ii; | 13 | struct btrfs_inode_item *ii; |
14 | struct btrfs_block_group_item *bi; | ||
14 | u32 type; | 15 | u32 type; |
15 | 16 | ||
16 | printk("leaf %Lu total ptrs %d free space %d\n", | 17 | printk("leaf %Lu total ptrs %d free space %d\n", |
@@ -53,6 +54,12 @@ void btrfs_print_leaf(struct btrfs_root *root, struct btrfs_leaf *l) | |||
53 | printk("\t\textent data refs %u\n", | 54 | printk("\t\textent data refs %u\n", |
54 | btrfs_extent_refs(ei)); | 55 | btrfs_extent_refs(ei)); |
55 | break; | 56 | break; |
57 | case BTRFS_BLOCK_GROUP_ITEM_KEY: | ||
58 | bi = btrfs_item_ptr(l, i, | ||
59 | struct btrfs_block_group_item); | ||
60 | printk("\t\tblock group used %Lu\n", | ||
61 | btrfs_block_group_used(bi)); | ||
62 | break; | ||
56 | case BTRFS_STRING_ITEM_KEY: | 63 | case BTRFS_STRING_ITEM_KEY: |
57 | printk("\t\titem data %.*s\n", btrfs_item_size(item), | 64 | printk("\t\titem data %.*s\n", btrfs_item_size(item), |
58 | btrfs_leaf_data(l) + btrfs_item_offset(item)); | 65 | btrfs_leaf_data(l) + btrfs_item_offset(item)); |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 5bbccbc7e3cc..edcebf79b04a 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -377,7 +377,6 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
377 | if (btrfs_disk_key_objectid(found_key) != inode->i_ino) | 377 | if (btrfs_disk_key_objectid(found_key) != inode->i_ino) |
378 | break; | 378 | break; |
379 | if (btrfs_disk_key_type(found_key) != BTRFS_CSUM_ITEM_KEY && | 379 | if (btrfs_disk_key_type(found_key) != BTRFS_CSUM_ITEM_KEY && |
380 | btrfs_disk_key_type(found_key) != BTRFS_INLINE_DATA_KEY && | ||
381 | btrfs_disk_key_type(found_key) != BTRFS_EXTENT_DATA_KEY) | 380 | btrfs_disk_key_type(found_key) != BTRFS_EXTENT_DATA_KEY) |
382 | break; | 381 | break; |
383 | if (btrfs_disk_key_offset(found_key) < inode->i_size) | 382 | if (btrfs_disk_key_offset(found_key) < inode->i_size) |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 078cb9cbf9dd..8a2545f6a5b6 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -125,6 +125,7 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, | |||
125 | btrfs_set_super_device_root(fs_info->disk_super, | 125 | btrfs_set_super_device_root(fs_info->disk_super, |
126 | bh_blocknr(dev_root->node)); | 126 | bh_blocknr(dev_root->node)); |
127 | } | 127 | } |
128 | btrfs_write_dirty_block_groups(trans, extent_root); | ||
128 | while(1) { | 129 | while(1) { |
129 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); | 130 | old_extent_block = btrfs_root_blocknr(&extent_root->root_item); |
130 | if (old_extent_block == bh_blocknr(extent_root->node)) | 131 | if (old_extent_block == bh_blocknr(extent_root->node)) |
@@ -135,6 +136,7 @@ int btrfs_commit_tree_roots(struct btrfs_trans_handle *trans, | |||
135 | &extent_root->root_key, | 136 | &extent_root->root_key, |
136 | &extent_root->root_item); | 137 | &extent_root->root_item); |
137 | BUG_ON(ret); | 138 | BUG_ON(ret); |
139 | btrfs_write_dirty_block_groups(trans, extent_root); | ||
138 | } | 140 | } |
139 | return 0; | 141 | return 0; |
140 | } | 142 | } |