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 | |
| parent | be74417553f4b2ee46be2088007a674ef2f02330 (diff) | |
Btrfs: allocator and tuning
Signed-off-by: Chris Mason <chris.mason@oracle.com>
| -rw-r--r-- | fs/btrfs/ctree.h | 1 | ||||
| -rw-r--r-- | fs/btrfs/extent-tree.c | 75 |
2 files changed, 34 insertions, 42 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 086e7dea3c92..cdb7c23c41f9 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -255,6 +255,7 @@ struct btrfs_block_group_item { | |||
| 255 | struct btrfs_block_group_cache { | 255 | struct btrfs_block_group_cache { |
| 256 | struct btrfs_key key; | 256 | struct btrfs_key key; |
| 257 | struct btrfs_block_group_item item; | 257 | struct btrfs_block_group_item item; |
| 258 | struct radix_tree_root *radix; | ||
| 258 | u64 first_free; | 259 | u64 first_free; |
| 259 | u64 last_alloc; | 260 | u64 last_alloc; |
| 260 | u64 pinned; | 261 | u64 pinned; |
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); |
