aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-04-27 10:08:34 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-04-27 10:08:34 -0400
commitcd1bc4653dc37f6390f4d6df4f987044c64f700b (patch)
treeff259c33e47159758d70a6d8bdc1ff5d47f710bb
parent9078a3e1e4e489dddc636c7bb8780349d4298743 (diff)
Btrfs: more block allocator work
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r--fs/btrfs/ctree.h4
-rw-r--r--fs/btrfs/disk-io.c2
-rw-r--r--fs/btrfs/extent-tree.c95
-rw-r--r--fs/btrfs/super.c3
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 {
250struct btrfs_block_group_cache { 250struct 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
255struct crypto_hash; 257struct 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
12static int del_pending_extents(struct btrfs_trans_handle *trans, struct 12static int del_pending_extents(struct btrfs_trans_handle *trans, struct
13 btrfs_root *extent_root); 13 btrfs_root *extent_root);
14 14
15static 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;
30find_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
15int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, 72int 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
472check_failed: 537check_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,
411error: 412error:
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
939out_fail: 942out_fail:
940 btrfs_end_transaction(trans, root); 943 btrfs_end_transaction(trans, root);