diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-06-11 21:33:38 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-06-11 21:33:38 -0400 |
commit | 5276aedab0baacfb3c5483208b8be85a8416bd5f (patch) | |
tree | d9370bef282b75e0e2b81ab1f74c146fd308cfd6 /fs | |
parent | 0cf6c620176a294bdf1bedddc492f6ae857e0019 (diff) |
Btrfs: fix oops after block group lookup
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/TODO | 1 | ||||
-rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 29 | ||||
-rw-r--r-- | fs/btrfs/super.c | 8 |
4 files changed, 21 insertions, 20 deletions
diff --git a/fs/btrfs/TODO b/fs/btrfs/TODO index 61d25b5de287..d9b6d38c603a 100644 --- a/fs/btrfs/TODO +++ b/fs/btrfs/TODO | |||
@@ -16,6 +16,5 @@ | |||
16 | * Use relocation to try and fix write errors | 16 | * Use relocation to try and fix write errors |
17 | * Make allocator much smarter | 17 | * Make allocator much smarter |
18 | * xattrs (directory streams for regular files) | 18 | * xattrs (directory streams for regular files) |
19 | * fsck | ||
20 | * Scrub & defrag | 19 | * Scrub & defrag |
21 | 20 | ||
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 5ab25a0cb16a..4e136b7b03ae 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
@@ -998,6 +998,9 @@ static inline void btrfs_mark_buffer_dirty(struct buffer_head *bh) | |||
998 | btrfs_item_offset((leaf)->items + (slot)))) | 998 | btrfs_item_offset((leaf)->items + (slot)))) |
999 | 999 | ||
1000 | /* extent-tree.c */ | 1000 | /* extent-tree.c */ |
1001 | struct btrfs_block_group_cache *btrfs_lookup_block_group(struct | ||
1002 | btrfs_fs_info *info, | ||
1003 | u64 blocknr); | ||
1001 | struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | 1004 | struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, |
1002 | struct btrfs_block_group_cache | 1005 | struct btrfs_block_group_cache |
1003 | *hint, u64 search_start, | 1006 | *hint, u64 search_start, |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 645a4228bfe2..f509ffa38d03 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -135,9 +135,9 @@ printk("cache block group %Lu\n", block_group->key.objectid); | |||
135 | return 0; | 135 | return 0; |
136 | } | 136 | } |
137 | 137 | ||
138 | static struct btrfs_block_group_cache *lookup_block_group(struct | 138 | struct btrfs_block_group_cache *btrfs_lookup_block_group(struct |
139 | btrfs_fs_info *info, | 139 | btrfs_fs_info *info, |
140 | u64 blocknr) | 140 | u64 blocknr) |
141 | { | 141 | { |
142 | struct btrfs_block_group_cache *block_group; | 142 | struct btrfs_block_group_cache *block_group; |
143 | int ret; | 143 | int ret; |
@@ -208,7 +208,8 @@ out: | |||
208 | return max(cache->last_alloc, search_start); | 208 | return max(cache->last_alloc, search_start); |
209 | 209 | ||
210 | new_group: | 210 | new_group: |
211 | cache = lookup_block_group(root->fs_info, last + cache->key.offset - 1); | 211 | cache = btrfs_lookup_block_group(root->fs_info, |
212 | last + cache->key.offset - 1); | ||
212 | if (!cache) { | 213 | if (!cache) { |
213 | return max((*cache_ret)->last_alloc, search_start); | 214 | return max((*cache_ret)->last_alloc, search_start); |
214 | } | 215 | } |
@@ -250,7 +251,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
250 | 251 | ||
251 | if (search_start) { | 252 | if (search_start) { |
252 | struct btrfs_block_group_cache *shint; | 253 | struct btrfs_block_group_cache *shint; |
253 | shint = lookup_block_group(info, search_start); | 254 | shint = btrfs_lookup_block_group(info, search_start); |
254 | if (shint->data == data) { | 255 | if (shint->data == data) { |
255 | used = btrfs_block_group_used(&shint->item); | 256 | used = btrfs_block_group_used(&shint->item); |
256 | if (used + shint->pinned < | 257 | if (used + shint->pinned < |
@@ -576,7 +577,7 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
576 | int ret; | 577 | int ret; |
577 | 578 | ||
578 | while(total) { | 579 | while(total) { |
579 | cache = lookup_block_group(info, blocknr); | 580 | cache = btrfs_lookup_block_group(info, blocknr); |
580 | if (!cache) { | 581 | if (!cache) { |
581 | printk(KERN_CRIT "blocknr %Lu lookup failed\n", | 582 | printk(KERN_CRIT "blocknr %Lu lookup failed\n", |
582 | blocknr); | 583 | blocknr); |
@@ -677,8 +678,8 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct | |||
677 | first = gang[0]; | 678 | first = gang[0]; |
678 | for (i = 0; i < ret; i++) { | 679 | for (i = 0; i < ret; i++) { |
679 | clear_radix_bit(pinned_radix, gang[i]); | 680 | clear_radix_bit(pinned_radix, gang[i]); |
680 | block_group = lookup_block_group(root->fs_info, | 681 | block_group = btrfs_lookup_block_group(root->fs_info, |
681 | gang[i]); | 682 | gang[i]); |
682 | if (block_group) { | 683 | if (block_group) { |
683 | WARN_ON(block_group->pinned == 0); | 684 | WARN_ON(block_group->pinned == 0); |
684 | block_group->pinned--; | 685 | block_group->pinned--; |
@@ -751,7 +752,8 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending) | |||
751 | err = set_radix_bit(&root->fs_info->pinned_radix, blocknr); | 752 | err = set_radix_bit(&root->fs_info->pinned_radix, blocknr); |
752 | if (!err) { | 753 | if (!err) { |
753 | struct btrfs_block_group_cache *cache; | 754 | struct btrfs_block_group_cache *cache; |
754 | cache = lookup_block_group(root->fs_info, blocknr); | 755 | cache = btrfs_lookup_block_group(root->fs_info, |
756 | blocknr); | ||
755 | if (cache) | 757 | if (cache) |
756 | cache->pinned++; | 758 | cache->pinned++; |
757 | } | 759 | } |
@@ -851,7 +853,8 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
851 | for (i = 0; i < ret; i++) { | 853 | for (i = 0; i < ret; i++) { |
852 | wret = set_radix_bit(pinned_radix, gang[i]); | 854 | wret = set_radix_bit(pinned_radix, gang[i]); |
853 | if (wret == 0) { | 855 | if (wret == 0) { |
854 | cache = lookup_block_group(extent_root->fs_info, | 856 | cache = |
857 | btrfs_lookup_block_group(extent_root->fs_info, | ||
855 | gang[i]); | 858 | gang[i]); |
856 | if (cache) | 859 | if (cache) |
857 | cache->pinned++; | 860 | cache->pinned++; |
@@ -938,7 +941,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
938 | if (search_end == (u64)-1) | 941 | if (search_end == (u64)-1) |
939 | search_end = btrfs_super_total_blocks(info->disk_super); | 942 | search_end = btrfs_super_total_blocks(info->disk_super); |
940 | if (hint_block) { | 943 | if (hint_block) { |
941 | block_group = lookup_block_group(info, hint_block); | 944 | block_group = btrfs_lookup_block_group(info, hint_block); |
942 | block_group = btrfs_find_block_group(root, block_group, | 945 | block_group = btrfs_find_block_group(root, block_group, |
943 | hint_block, data, 1); | 946 | hint_block, data, 1); |
944 | } else { | 947 | } else { |
@@ -1118,7 +1121,7 @@ check_pending: | |||
1118 | info->extent_tree_prealloc_nr = total_found; | 1121 | info->extent_tree_prealloc_nr = total_found; |
1119 | } | 1122 | } |
1120 | if (!data) { | 1123 | if (!data) { |
1121 | block_group = lookup_block_group(info, ins->objectid); | 1124 | block_group = btrfs_lookup_block_group(info, ins->objectid); |
1122 | if (block_group) { | 1125 | if (block_group) { |
1123 | if (fill_prealloc) | 1126 | if (fill_prealloc) |
1124 | block_group->last_prealloc = | 1127 | block_group->last_prealloc = |
@@ -1143,7 +1146,7 @@ new_group: | |||
1143 | else | 1146 | else |
1144 | wrapped = 1; | 1147 | wrapped = 1; |
1145 | } | 1148 | } |
1146 | block_group = lookup_block_group(info, search_start); | 1149 | block_group = btrfs_lookup_block_group(info, search_start); |
1147 | cond_resched(); | 1150 | cond_resched(); |
1148 | if (!full_scan) | 1151 | if (!full_scan) |
1149 | block_group = btrfs_find_block_group(root, block_group, | 1152 | block_group = btrfs_find_block_group(root, block_group, |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 2b24a5a2be63..9749090cfbb8 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -62,7 +62,6 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
62 | struct btrfs_inode_item *inode_item; | 62 | struct btrfs_inode_item *inode_item; |
63 | struct btrfs_root *root = BTRFS_I(inode)->root; | 63 | struct btrfs_root *root = BTRFS_I(inode)->root; |
64 | struct btrfs_key location; | 64 | struct btrfs_key location; |
65 | struct btrfs_block_group_cache *alloc_group; | ||
66 | u64 alloc_group_block; | 65 | u64 alloc_group_block; |
67 | int ret; | 66 | int ret; |
68 | 67 | ||
@@ -95,11 +94,8 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
95 | inode->i_blocks = btrfs_inode_nblocks(inode_item); | 94 | inode->i_blocks = btrfs_inode_nblocks(inode_item); |
96 | inode->i_generation = btrfs_inode_generation(inode_item); | 95 | inode->i_generation = btrfs_inode_generation(inode_item); |
97 | alloc_group_block = btrfs_inode_block_group(inode_item); | 96 | alloc_group_block = btrfs_inode_block_group(inode_item); |
98 | ret = radix_tree_gang_lookup(&root->fs_info->block_group_radix, | 97 | BTRFS_I(inode)->block_group = btrfs_lookup_block_group(root->fs_info, |
99 | (void **)&alloc_group, | 98 | alloc_group_block); |
100 | alloc_group_block, 1); | ||
101 | BUG_ON(!ret); | ||
102 | BTRFS_I(inode)->block_group = alloc_group; | ||
103 | 99 | ||
104 | btrfs_free_path(path); | 100 | btrfs_free_path(path); |
105 | inode_item = NULL; | 101 | inode_item = NULL; |