diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-05-07 20:03:49 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-05-07 20:03:49 -0400 |
commit | 3e1ad54fe2839319c1aa66b954da0753f5b1f906 (patch) | |
tree | 1e9d98508e9d4d569e73c51617b5167ef0910541 /fs/btrfs/extent-tree.c | |
parent | be74417553f4b2ee46be2088007a674ef2f02330 (diff) |
Btrfs: allocator and tuning
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 75 |
1 files changed, 33 insertions, 42 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 2937fd9aba74..3edfc300289f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -23,7 +23,7 @@ static struct btrfs_block_group_cache *lookup_block_group(struct | |||
23 | (void **)&block_group, | 23 | (void **)&block_group, |
24 | blocknr, 1); | 24 | blocknr, 1); |
25 | if (ret) { | 25 | if (ret) { |
26 | if (block_group->key.objectid <= blocknr && blocknr < | 26 | if (block_group->key.objectid <= blocknr && blocknr <= |
27 | block_group->key.objectid + block_group->key.offset) | 27 | block_group->key.objectid + block_group->key.offset) |
28 | return block_group; | 28 | return block_group; |
29 | } | 29 | } |
@@ -31,11 +31,16 @@ static struct btrfs_block_group_cache *lookup_block_group(struct | |||
31 | (void **)&block_group, | 31 | (void **)&block_group, |
32 | blocknr, 1); | 32 | blocknr, 1); |
33 | if (ret) { | 33 | if (ret) { |
34 | if (block_group->key.objectid <= blocknr && blocknr < | 34 | if (block_group->key.objectid <= blocknr && blocknr <= |
35 | block_group->key.objectid + block_group->key.offset) | 35 | block_group->key.objectid + block_group->key.offset) |
36 | return block_group; | 36 | return block_group; |
37 | } | 37 | } |
38 | printk("lookup_block_group fails for blocknr %Lu\n", blocknr); | 38 | WARN_ON(1); |
39 | printk("lookup_block_group fails for blocknr %Lu\n", blocknr); | ||
40 | printk("last ret was %d\n", ret); | ||
41 | if (ret) { | ||
42 | printk("last block group was %Lu %Lu\n", block_group->key.objectid, block_group->key.offset); | ||
43 | } | ||
39 | return NULL; | 44 | return NULL; |
40 | } | 45 | } |
41 | 46 | ||
@@ -356,45 +361,20 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
356 | { | 361 | { |
357 | struct btrfs_block_group_cache *cache; | 362 | struct btrfs_block_group_cache *cache; |
358 | struct btrfs_fs_info *info = root->fs_info; | 363 | struct btrfs_fs_info *info = root->fs_info; |
359 | struct radix_tree_root *radix; | ||
360 | u64 total = num; | 364 | u64 total = num; |
361 | u64 old_val; | 365 | u64 old_val; |
362 | u64 block_in_group; | 366 | u64 block_in_group; |
363 | int ret; | 367 | |
364 | if (num != 1) | ||
365 | radix = &info->block_group_data_radix; | ||
366 | else | ||
367 | radix = &info->block_group_radix; | ||
368 | while(total) { | 368 | while(total) { |
369 | ret = radix_tree_gang_lookup(radix, (void **)&cache, | 369 | cache = lookup_block_group(info, blocknr); |
370 | blocknr, 1); | 370 | if (!cache) { |
371 | if (!ret) { | ||
372 | printk(KERN_CRIT "blocknr %Lu lookup failed\n", | 371 | printk(KERN_CRIT "blocknr %Lu lookup failed\n", |
373 | blocknr); | 372 | blocknr); |
374 | return -1; | 373 | return -1; |
375 | } | 374 | } |
376 | block_in_group = blocknr - cache->key.objectid; | 375 | block_in_group = blocknr - cache->key.objectid; |
377 | if (block_in_group > cache->key.offset || cache->key.objectid > | ||
378 | blocknr) { | ||
379 | if (radix == &info->block_group_data_radix) | ||
380 | radix = &info->block_group_radix; | ||
381 | else | ||
382 | radix = &info->block_group_data_radix; | ||
383 | ret = radix_tree_gang_lookup(radix, (void **)&cache, | ||
384 | blocknr, 1); | ||
385 | if (!ret) { | ||
386 | printk(KERN_CRIT "blocknr %Lu lookup failed\n", | ||
387 | blocknr); | ||
388 | return -1; | ||
389 | } | ||
390 | block_in_group = blocknr - cache->key.objectid; | ||
391 | if (block_in_group > cache->key.offset || | ||
392 | cache->key.objectid > blocknr) { | ||
393 | BUG(); | ||
394 | } | ||
395 | } | ||
396 | WARN_ON(block_in_group > cache->key.offset); | 376 | WARN_ON(block_in_group > cache->key.offset); |
397 | radix_tree_tag_set(radix, cache->key.objectid + | 377 | radix_tree_tag_set(cache->radix, cache->key.objectid + |
398 | cache->key.offset - 1, | 378 | cache->key.offset - 1, |
399 | BTRFS_BLOCK_GROUP_DIRTY); | 379 | BTRFS_BLOCK_GROUP_DIRTY); |
400 | 380 | ||
@@ -693,6 +673,8 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
693 | num_blocks = 1; | 673 | num_blocks = 1; |
694 | total_needed = (min(level + 1, BTRFS_MAX_LEVEL) + 2) * 3; | 674 | total_needed = (min(level + 1, BTRFS_MAX_LEVEL) + 2) * 3; |
695 | } | 675 | } |
676 | if (search_end == (u64)-1) | ||
677 | search_end = btrfs_super_total_blocks(info->disk_super); | ||
696 | if (search_start) { | 678 | if (search_start) { |
697 | block_group = lookup_block_group(info, search_start); | 679 | block_group = lookup_block_group(info, search_start); |
698 | block_group = btrfs_find_block_group(root, block_group, | 680 | block_group = btrfs_find_block_group(root, block_group, |
@@ -704,7 +686,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
704 | } | 686 | } |
705 | 687 | ||
706 | check_failed: | 688 | check_failed: |
707 | if (block_group->data != data) | 689 | if (!full_scan && block_group->data != data) |
708 | WARN_ON(1); | 690 | WARN_ON(1); |
709 | if (block_group->last_alloc > search_start) | 691 | if (block_group->last_alloc > search_start) |
710 | search_start = block_group->last_alloc; | 692 | search_start = block_group->last_alloc; |
@@ -734,13 +716,13 @@ check_failed: | |||
734 | goto error; | 716 | goto error; |
735 | if (!start_found) { | 717 | if (!start_found) { |
736 | ins->objectid = search_start; | 718 | ins->objectid = search_start; |
737 | ins->offset = (u64)-1 - search_start; | 719 | ins->offset = search_end - search_start; |
738 | start_found = 1; | 720 | start_found = 1; |
739 | goto check_pending; | 721 | goto check_pending; |
740 | } | 722 | } |
741 | ins->objectid = last_block > search_start ? | 723 | ins->objectid = last_block > search_start ? |
742 | last_block : search_start; | 724 | last_block : search_start; |
743 | ins->offset = (u64)-1 - ins->objectid; | 725 | ins->offset = search_end - ins->objectid; |
744 | goto check_pending; | 726 | goto check_pending; |
745 | } | 727 | } |
746 | btrfs_disk_key_to_cpu(&key, &l->items[slot].key); | 728 | btrfs_disk_key_to_cpu(&key, &l->items[slot].key); |
@@ -777,7 +759,7 @@ check_pending: | |||
777 | */ | 759 | */ |
778 | btrfs_release_path(root, path); | 760 | btrfs_release_path(root, path); |
779 | BUG_ON(ins->objectid < search_start); | 761 | BUG_ON(ins->objectid < search_start); |
780 | if (ins->objectid >= btrfs_super_total_blocks(info->disk_super)) { | 762 | if (ins->objectid + num_blocks >= search_end) { |
781 | if (full_scan) | 763 | if (full_scan) |
782 | return -ENOSPC; | 764 | return -ENOSPC; |
783 | search_start = orig_search_start; | 765 | search_start = orig_search_start; |
@@ -840,7 +822,7 @@ check_pending: | |||
840 | return 0; | 822 | return 0; |
841 | 823 | ||
842 | new_group: | 824 | new_group: |
843 | if (search_start >= btrfs_super_total_blocks(info->disk_super)) { | 825 | if (search_start + num_blocks >= search_end) { |
844 | search_start = orig_search_start; | 826 | search_start = orig_search_start; |
845 | full_scan = 1; | 827 | full_scan = 1; |
846 | } | 828 | } |
@@ -900,7 +882,12 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
900 | return ret; | 882 | return ret; |
901 | 883 | ||
902 | /* then do prealloc for the extent tree */ | 884 | /* then do prealloc for the extent tree */ |
903 | ret = find_free_extent(trans, root, 0, ins->objectid + ins->offset, | 885 | if (ins->objectid + ins->offset >= search_end) |
886 | search_end = ins->objectid - 1; | ||
887 | else | ||
888 | search_start = ins->objectid + ins->offset; | ||
889 | |||
890 | ret = find_free_extent(trans, root, 0, search_start, | ||
904 | search_end, &prealloc_key, 0); | 891 | search_end, &prealloc_key, 0); |
905 | if (ret) | 892 | if (ret) |
906 | return ret; | 893 | return ret; |
@@ -1198,6 +1185,12 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
1198 | err = -1; | 1185 | err = -1; |
1199 | break; | 1186 | break; |
1200 | } | 1187 | } |
1188 | |||
1189 | if (nr & 1) | ||
1190 | radix = &info->block_group_data_radix; | ||
1191 | else | ||
1192 | radix = &info->block_group_radix; | ||
1193 | |||
1201 | bi = btrfs_item_ptr(leaf, path->slots[0], | 1194 | bi = btrfs_item_ptr(leaf, path->slots[0], |
1202 | struct btrfs_block_group_item); | 1195 | struct btrfs_block_group_item); |
1203 | memcpy(&cache->item, bi, sizeof(*bi)); | 1196 | memcpy(&cache->item, bi, sizeof(*bi)); |
@@ -1206,12 +1199,10 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
1206 | cache->first_free = cache->key.objectid; | 1199 | cache->first_free = cache->key.objectid; |
1207 | cache->pinned = 0; | 1200 | cache->pinned = 0; |
1208 | cache->data = (nr & 1); | 1201 | cache->data = (nr & 1); |
1202 | cache->radix = radix; | ||
1203 | |||
1209 | key.objectid = found_key.objectid + found_key.offset; | 1204 | key.objectid = found_key.objectid + found_key.offset; |
1210 | btrfs_release_path(root, path); | 1205 | btrfs_release_path(root, path); |
1211 | if (nr & 1) | ||
1212 | radix = &info->block_group_data_radix; | ||
1213 | else | ||
1214 | radix = &info->block_group_radix; | ||
1215 | ret = radix_tree_insert(radix, found_key.objectid + | 1206 | ret = radix_tree_insert(radix, found_key.objectid + |
1216 | found_key.offset - 1, | 1207 | found_key.offset - 1, |
1217 | (void *)cache); | 1208 | (void *)cache); |