Commit 5276aeda authored by Chris Mason's avatar Chris Mason Committed by David Woodhouse

Btrfs: fix oops after block group lookup

Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent 0cf6c620
...@@ -16,6 +16,5 @@ ...@@ -16,6 +16,5 @@
* Use relocation to try and fix write errors * Use relocation to try and fix write errors
* Make allocator much smarter * Make allocator much smarter
* xattrs (directory streams for regular files) * xattrs (directory streams for regular files)
* fsck
* Scrub & defrag * Scrub & defrag
...@@ -998,6 +998,9 @@ static inline void btrfs_mark_buffer_dirty(struct buffer_head *bh) ...@@ -998,6 +998,9 @@ static inline void btrfs_mark_buffer_dirty(struct buffer_head *bh)
btrfs_item_offset((leaf)->items + (slot)))) btrfs_item_offset((leaf)->items + (slot))))
/* extent-tree.c */ /* extent-tree.c */
struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
btrfs_fs_info *info,
u64 blocknr);
struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
struct btrfs_block_group_cache struct btrfs_block_group_cache
*hint, u64 search_start, *hint, u64 search_start,
......
...@@ -135,9 +135,9 @@ printk("cache block group %Lu\n", block_group->key.objectid); ...@@ -135,9 +135,9 @@ printk("cache block group %Lu\n", block_group->key.objectid);
return 0; return 0;
} }
static struct btrfs_block_group_cache *lookup_block_group(struct struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
btrfs_fs_info *info, btrfs_fs_info *info,
u64 blocknr) u64 blocknr)
{ {
struct btrfs_block_group_cache *block_group; struct btrfs_block_group_cache *block_group;
int ret; int ret;
...@@ -208,7 +208,8 @@ static u64 find_search_start(struct btrfs_root *root, ...@@ -208,7 +208,8 @@ static u64 find_search_start(struct btrfs_root *root,
return max(cache->last_alloc, search_start); return max(cache->last_alloc, search_start);
new_group: new_group:
cache = lookup_block_group(root->fs_info, last + cache->key.offset - 1); cache = btrfs_lookup_block_group(root->fs_info,
last + cache->key.offset - 1);
if (!cache) { if (!cache) {
return max((*cache_ret)->last_alloc, search_start); return max((*cache_ret)->last_alloc, search_start);
} }
...@@ -250,7 +251,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, ...@@ -250,7 +251,7 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root,
if (search_start) { if (search_start) {
struct btrfs_block_group_cache *shint; struct btrfs_block_group_cache *shint;
shint = lookup_block_group(info, search_start); shint = btrfs_lookup_block_group(info, search_start);
if (shint->data == data) { if (shint->data == data) {
used = btrfs_block_group_used(&shint->item); used = btrfs_block_group_used(&shint->item);
if (used + shint->pinned < if (used + shint->pinned <
...@@ -576,7 +577,7 @@ static int update_block_group(struct btrfs_trans_handle *trans, ...@@ -576,7 +577,7 @@ static int update_block_group(struct btrfs_trans_handle *trans,
int ret; int ret;
while(total) { while(total) {
cache = lookup_block_group(info, blocknr); cache = btrfs_lookup_block_group(info, blocknr);
if (!cache) { if (!cache) {
printk(KERN_CRIT "blocknr %Lu lookup failed\n", printk(KERN_CRIT "blocknr %Lu lookup failed\n",
blocknr); blocknr);
...@@ -677,8 +678,8 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct ...@@ -677,8 +678,8 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, struct
first = gang[0]; first = gang[0];
for (i = 0; i < ret; i++) { for (i = 0; i < ret; i++) {
clear_radix_bit(pinned_radix, gang[i]); clear_radix_bit(pinned_radix, gang[i]);
block_group = lookup_block_group(root->fs_info, block_group = btrfs_lookup_block_group(root->fs_info,
gang[i]); gang[i]);
if (block_group) { if (block_group) {
WARN_ON(block_group->pinned == 0); WARN_ON(block_group->pinned == 0);
block_group->pinned--; block_group->pinned--;
...@@ -751,7 +752,8 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending) ...@@ -751,7 +752,8 @@ static int pin_down_block(struct btrfs_root *root, u64 blocknr, int pending)
err = set_radix_bit(&root->fs_info->pinned_radix, blocknr); err = set_radix_bit(&root->fs_info->pinned_radix, blocknr);
if (!err) { if (!err) {
struct btrfs_block_group_cache *cache; struct btrfs_block_group_cache *cache;
cache = lookup_block_group(root->fs_info, blocknr); cache = btrfs_lookup_block_group(root->fs_info,
blocknr);
if (cache) if (cache)
cache->pinned++; cache->pinned++;
} }
...@@ -851,7 +853,8 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct ...@@ -851,7 +853,8 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct
for (i = 0; i < ret; i++) { for (i = 0; i < ret; i++) {
wret = set_radix_bit(pinned_radix, gang[i]); wret = set_radix_bit(pinned_radix, gang[i]);
if (wret == 0) { if (wret == 0) {
cache = lookup_block_group(extent_root->fs_info, cache =
btrfs_lookup_block_group(extent_root->fs_info,
gang[i]); gang[i]);
if (cache) if (cache)
cache->pinned++; cache->pinned++;
...@@ -938,7 +941,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -938,7 +941,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
if (search_end == (u64)-1) if (search_end == (u64)-1)
search_end = btrfs_super_total_blocks(info->disk_super); search_end = btrfs_super_total_blocks(info->disk_super);
if (hint_block) { if (hint_block) {
block_group = lookup_block_group(info, hint_block); block_group = btrfs_lookup_block_group(info, hint_block);
block_group = btrfs_find_block_group(root, block_group, block_group = btrfs_find_block_group(root, block_group,
hint_block, data, 1); hint_block, data, 1);
} else { } else {
...@@ -1118,7 +1121,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1118,7 +1121,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
info->extent_tree_prealloc_nr = total_found; info->extent_tree_prealloc_nr = total_found;
} }
if (!data) { if (!data) {
block_group = lookup_block_group(info, ins->objectid); block_group = btrfs_lookup_block_group(info, ins->objectid);
if (block_group) { if (block_group) {
if (fill_prealloc) if (fill_prealloc)
block_group->last_prealloc = block_group->last_prealloc =
...@@ -1143,7 +1146,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root ...@@ -1143,7 +1146,7 @@ static int find_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root
else else
wrapped = 1; wrapped = 1;
} }
block_group = lookup_block_group(info, search_start); block_group = btrfs_lookup_block_group(info, search_start);
cond_resched(); cond_resched();
if (!full_scan) if (!full_scan)
block_group = btrfs_find_block_group(root, block_group, block_group = btrfs_find_block_group(root, block_group,
......
...@@ -62,7 +62,6 @@ static void btrfs_read_locked_inode(struct inode *inode) ...@@ -62,7 +62,6 @@ static void btrfs_read_locked_inode(struct inode *inode)
struct btrfs_inode_item *inode_item; struct btrfs_inode_item *inode_item;
struct btrfs_root *root = BTRFS_I(inode)->root; struct btrfs_root *root = BTRFS_I(inode)->root;
struct btrfs_key location; struct btrfs_key location;
struct btrfs_block_group_cache *alloc_group;
u64 alloc_group_block; u64 alloc_group_block;
int ret; int ret;
...@@ -95,11 +94,8 @@ static void btrfs_read_locked_inode(struct inode *inode) ...@@ -95,11 +94,8 @@ static void btrfs_read_locked_inode(struct inode *inode)
inode->i_blocks = btrfs_inode_nblocks(inode_item); inode->i_blocks = btrfs_inode_nblocks(inode_item);
inode->i_generation = btrfs_inode_generation(inode_item); inode->i_generation = btrfs_inode_generation(inode_item);
alloc_group_block = btrfs_inode_block_group(inode_item); alloc_group_block = btrfs_inode_block_group(inode_item);
ret = radix_tree_gang_lookup(&root->fs_info->block_group_radix, BTRFS_I(inode)->block_group = btrfs_lookup_block_group(root->fs_info,
(void **)&alloc_group, alloc_group_block);
alloc_group_block, 1);
BUG_ON(!ret);
BTRFS_I(inode)->block_group = alloc_group;
btrfs_free_path(path); btrfs_free_path(path);
inode_item = NULL; inode_item = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment