diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-27 10:08:34 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-27 10:08:34 -0400 |
commit | cd1bc4653dc37f6390f4d6df4f987044c64f700b (patch) | |
tree | ff259c33e47159758d70a6d8bdc1ff5d47f710bb | |
parent | 9078a3e1e4e489dddc636c7bb8780349d4298743 (diff) |
Btrfs: more block allocator work
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/ctree.h | 4 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 2 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 95 | ||||
-rw-r--r-- | fs/btrfs/super.c | 3 |
4 files changed, 90 insertions, 14 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 419917279e65..c432222d40e3 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -250,6 +250,8 @@ struct btrfs_block_group_item { | |||
250 | struct btrfs_block_group_cache { | 250 | struct btrfs_block_group_cache { |
251 | struct btrfs_key key; | 251 | struct btrfs_key key; |
252 | struct btrfs_block_group_item item; | 252 | struct btrfs_block_group_item item; |
253 | u64 first_free; | ||
254 | u64 last_alloc; | ||
253 | }; | 255 | }; |
254 | 256 | ||
255 | struct crypto_hash; | 257 | struct crypto_hash; |
@@ -257,7 +259,7 @@ struct btrfs_fs_info { | |||
257 | struct btrfs_root *extent_root; | 259 | struct btrfs_root *extent_root; |
258 | struct btrfs_root *tree_root; | 260 | struct btrfs_root *tree_root; |
259 | struct btrfs_root *dev_root; | 261 | struct btrfs_root *dev_root; |
260 | struct btrfs_key last_insert; | 262 | struct btrfs_block_group_cache *block_group_cache; |
261 | struct radix_tree_root fs_roots_radix; | 263 | struct radix_tree_root fs_roots_radix; |
262 | struct radix_tree_root pending_del_radix; | 264 | struct radix_tree_root pending_del_radix; |
263 | struct radix_tree_root pinned_radix; | 265 | struct radix_tree_root pinned_radix; |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 1c27eb645510..2489ffa5fb38 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -558,7 +558,7 @@ struct btrfs_root *open_ctree(struct super_block *sb) | |||
558 | } | 558 | } |
559 | mutex_init(&fs_info->trans_mutex); | 559 | mutex_init(&fs_info->trans_mutex); |
560 | mutex_init(&fs_info->fs_mutex); | 560 | mutex_init(&fs_info->fs_mutex); |
561 | memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); | 561 | fs_info->block_group_cache = NULL; |
562 | 562 | ||
563 | __setup_root(sb->s_blocksize, dev_root, | 563 | __setup_root(sb->s_blocksize, dev_root, |
564 | fs_info, BTRFS_DEV_TREE_OBJECTID); | 564 | fs_info, BTRFS_DEV_TREE_OBJECTID); |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 0bb4fc83cfd6..71e3b311fc42 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -12,6 +12,63 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
12 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct | 12 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct |
13 | btrfs_root *extent_root); | 13 | btrfs_root *extent_root); |
14 | 14 | ||
15 | static int find_search_start(struct btrfs_root *root, int data) | ||
16 | { | ||
17 | struct btrfs_block_group_cache *cache[8]; | ||
18 | struct btrfs_fs_info *info = root->fs_info; | ||
19 | u64 used; | ||
20 | u64 last; | ||
21 | int i; | ||
22 | int ret; | ||
23 | |||
24 | cache[0] = info->block_group_cache; | ||
25 | if (!cache[0]) | ||
26 | goto find_new; | ||
27 | used = btrfs_block_group_used(&cache[0]->item); | ||
28 | if (used < (cache[0]->key.offset * 3 / 2)) | ||
29 | return 0; | ||
30 | find_new: | ||
31 | last = 0; | ||
32 | while(1) { | ||
33 | ret = radix_tree_gang_lookup_tag(&info->block_group_radix, | ||
34 | (void **)cache, | ||
35 | last, ARRAY_SIZE(cache), | ||
36 | BTRFS_BLOCK_GROUP_DIRTY); | ||
37 | if (!ret) | ||
38 | break; | ||
39 | for (i = 0; i < ret; i++) { | ||
40 | used = btrfs_block_group_used(&cache[i]->item); | ||
41 | if (used < (cache[i]->key.offset * 3 / 2)) { | ||
42 | info->block_group_cache = cache[i]; | ||
43 | cache[i]->last_alloc = cache[i]->first_free; | ||
44 | return 0; | ||
45 | } | ||
46 | last = cache[i]->key.objectid + | ||
47 | cache[i]->key.offset - 1; | ||
48 | } | ||
49 | } | ||
50 | last = 0; | ||
51 | while(1) { | ||
52 | ret = radix_tree_gang_lookup(&info->block_group_radix, | ||
53 | (void **)cache, | ||
54 | last, ARRAY_SIZE(cache)); | ||
55 | if (!ret) | ||
56 | break; | ||
57 | for (i = 0; i < ret; i++) { | ||
58 | used = btrfs_block_group_used(&cache[i]->item); | ||
59 | if (used < (cache[i]->key.offset * 3 / 2)) { | ||
60 | info->block_group_cache = cache[i]; | ||
61 | cache[i]->last_alloc = cache[i]->first_free; | ||
62 | return 0; | ||
63 | } | ||
64 | last = cache[i]->key.objectid + | ||
65 | cache[i]->key.offset - 1; | ||
66 | } | ||
67 | } | ||
68 | info->block_group_cache = NULL; | ||
69 | return 0; | ||
70 | } | ||
71 | |||
15 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | 72 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, |
16 | struct btrfs_root *root, | 73 | struct btrfs_root *root, |
17 | u64 blocknr, u64 num_blocks) | 74 | u64 blocknr, u64 num_blocks) |
@@ -205,8 +262,11 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
205 | while(total) { | 262 | while(total) { |
206 | ret = radix_tree_gang_lookup(&info->block_group_radix, | 263 | ret = radix_tree_gang_lookup(&info->block_group_radix, |
207 | (void **)&cache, blocknr, 1); | 264 | (void **)&cache, blocknr, 1); |
208 | if (!ret) | 265 | if (!ret) { |
266 | printk(KERN_CRIT "blocknr %Lu lookup failed\n", | ||
267 | blocknr); | ||
209 | return -1; | 268 | return -1; |
269 | } | ||
210 | block_in_group = blocknr - cache->key.objectid; | 270 | block_in_group = blocknr - cache->key.objectid; |
211 | WARN_ON(block_in_group > cache->key.offset); | 271 | WARN_ON(block_in_group > cache->key.offset); |
212 | radix_tree_tag_set(&info->block_group_radix, | 272 | radix_tree_tag_set(&info->block_group_radix, |
@@ -217,10 +277,15 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
217 | num = min(total, cache->key.offset - block_in_group); | 277 | num = min(total, cache->key.offset - block_in_group); |
218 | total -= num; | 278 | total -= num; |
219 | blocknr += num; | 279 | blocknr += num; |
220 | if (alloc) | 280 | if (alloc) { |
221 | old_val += num; | 281 | old_val += num; |
222 | else | 282 | if (blocknr > cache->last_alloc) |
283 | cache->last_alloc = blocknr; | ||
284 | } else { | ||
223 | old_val -= num; | 285 | old_val -= num; |
286 | if (blocknr < cache->first_free) | ||
287 | cache->first_free = blocknr; | ||
288 | } | ||
224 | btrfs_set_block_group_used(&cache->item, old_val); | 289 | btrfs_set_block_group_used(&cache->item, old_val); |
225 | } | 290 | } |
226 | return 0; | 291 | return 0; |
@@ -246,9 +311,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | |||
246 | clear_radix_bit(pinned_radix, gang[i]); | 311 | clear_radix_bit(pinned_radix, gang[i]); |
247 | } | 312 | } |
248 | } | 313 | } |
249 | if (root->fs_info->last_insert.objectid > first) | 314 | root->fs_info->block_group_cache = NULL; |
250 | root->fs_info->last_insert.objectid = first; | ||
251 | root->fs_info->last_insert.offset = 0; | ||
252 | return 0; | 315 | return 0; |
253 | } | 316 | } |
254 | 317 | ||
@@ -466,8 +529,10 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
466 | num_blocks = 1; | 529 | num_blocks = 1; |
467 | total_needed = min(level + 2, BTRFS_MAX_LEVEL) * 3; | 530 | total_needed = min(level + 2, BTRFS_MAX_LEVEL) * 3; |
468 | } | 531 | } |
469 | if (info->last_insert.objectid > search_start) | 532 | find_search_start(root, 0); |
470 | search_start = info->last_insert.objectid; | 533 | if (info->block_group_cache && |
534 | info->block_group_cache->last_alloc > search_start) | ||
535 | search_start = info->block_group_cache->last_alloc; | ||
471 | 536 | ||
472 | check_failed: | 537 | check_failed: |
473 | btrfs_init_path(path); | 538 | btrfs_init_path(path); |
@@ -567,8 +632,7 @@ check_pending: | |||
567 | total_found < total_needed) { | 632 | total_found < total_needed) { |
568 | nr = total_needed - total_found - 1; | 633 | nr = total_needed - total_found - 1; |
569 | BUG_ON(nr < 0); | 634 | BUG_ON(nr < 0); |
570 | root->fs_info->extent_tree_prealloc[nr] = | 635 | info->extent_tree_prealloc[nr] = test_block; |
571 | test_block; | ||
572 | total_found++; | 636 | total_found++; |
573 | test_block++; | 637 | test_block++; |
574 | } | 638 | } |
@@ -576,9 +640,14 @@ check_pending: | |||
576 | search_start = test_block; | 640 | search_start = test_block; |
577 | goto check_failed; | 641 | goto check_failed; |
578 | } | 642 | } |
579 | root->fs_info->extent_tree_prealloc_nr = total_found; | 643 | info->extent_tree_prealloc_nr = total_found; |
644 | } | ||
645 | ret = radix_tree_gang_lookup(&info->block_group_radix, | ||
646 | (void **)&info->block_group_cache, | ||
647 | ins->objectid, 1); | ||
648 | if (ret) { | ||
649 | info->block_group_cache->last_alloc = ins->objectid; | ||
580 | } | 650 | } |
581 | root->fs_info->last_insert.objectid = ins->objectid; | ||
582 | ins->offset = num_blocks; | 651 | ins->offset = num_blocks; |
583 | btrfs_free_path(path); | 652 | btrfs_free_path(path); |
584 | return 0; | 653 | return 0; |
@@ -915,6 +984,8 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
915 | struct btrfs_block_group_item); | 984 | struct btrfs_block_group_item); |
916 | memcpy(&cache->item, bi, sizeof(*bi)); | 985 | memcpy(&cache->item, bi, sizeof(*bi)); |
917 | memcpy(&cache->key, &found_key, sizeof(found_key)); | 986 | memcpy(&cache->key, &found_key, sizeof(found_key)); |
987 | cache->last_alloc = 0; | ||
988 | cache->first_free = 0; | ||
918 | key.objectid = found_key.objectid + found_key.offset; | 989 | key.objectid = found_key.objectid + found_key.offset; |
919 | btrfs_release_path(root, path); | 990 | btrfs_release_path(root, path); |
920 | ret = radix_tree_insert(&root->fs_info->block_group_radix, | 991 | ret = radix_tree_insert(&root->fs_info->block_group_radix, |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index edcebf79b04a..a10e902d3102 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -223,6 +223,7 @@ err: | |||
223 | btrfs_update_inode(trans, root, dir); | 223 | btrfs_update_inode(trans, root, dir); |
224 | drop_nlink(dentry->d_inode); | 224 | drop_nlink(dentry->d_inode); |
225 | btrfs_update_inode(trans, root, dentry->d_inode); | 225 | btrfs_update_inode(trans, root, dentry->d_inode); |
226 | dir->i_sb->s_dirt = 1; | ||
226 | } | 227 | } |
227 | return ret; | 228 | return ret; |
228 | } | 229 | } |
@@ -411,6 +412,7 @@ static int btrfs_truncate_in_trans(struct btrfs_trans_handle *trans, | |||
411 | error: | 412 | error: |
412 | btrfs_release_path(root, path); | 413 | btrfs_release_path(root, path); |
413 | btrfs_free_path(path); | 414 | btrfs_free_path(path); |
415 | inode->i_sb->s_dirt = 1; | ||
414 | return ret; | 416 | return ret; |
415 | } | 417 | } |
416 | 418 | ||
@@ -935,6 +937,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
935 | goto out_fail; | 937 | goto out_fail; |
936 | d_instantiate(dentry, inode); | 938 | d_instantiate(dentry, inode); |
937 | drop_on_err = 0; | 939 | drop_on_err = 0; |
940 | dir->i_sb->s_dirt = 1; | ||
938 | 941 | ||
939 | out_fail: | 942 | out_fail: |
940 | btrfs_end_transaction(trans, root); | 943 | btrfs_end_transaction(trans, root); |