Btrfs: fix oops after block group lookup
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
committed by
David Woodhouse
parent
0cf6c62017
commit
5276aedab0
@@ -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)
|
|||||||
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,7 +135,7 @@ 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)
|
||||||
{
|
{
|
||||||
@@ -208,7 +208,8 @@ out:
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,7 +678,7 @@ 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);
|
||||||
@@ -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
|
|||||||
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
|
|||||||
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 @@ check_pending:
|
|||||||
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 @@ new_group:
|
|||||||
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)
|
|||||||
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)
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user