Browse Source

Btrfs: fix oops after block group lookup

Signed-off-by: Chris Mason <chris.mason@oracle.com>
Chris Mason 18 years ago
parent
commit
5276aedab0
4 changed files with 21 additions and 20 deletions
  1. 0 1
      fs/btrfs/TODO
  2. 3 0
      fs/btrfs/ctree.h
  3. 16 13
      fs/btrfs/extent-tree.c
  4. 2 6
      fs/btrfs/super.c

+ 0 - 1
fs/btrfs/TODO

@@ -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
 
 

+ 3 - 0
fs/btrfs/ctree.h

@@ -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,

+ 16 - 13
fs/btrfs/extent-tree.c

@@ -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
-							  btrfs_fs_info *info,
-							  u64 blocknr)
+struct btrfs_block_group_cache *btrfs_lookup_block_group(struct
+							 btrfs_fs_info *info,
+							 u64 blocknr)
 {
 {
 	struct btrfs_block_group_cache *block_group;
 	struct btrfs_block_group_cache *block_group;
 	int ret;
 	int ret;
@@ -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,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,
-							 gang[i]);
+			block_group = btrfs_lookup_block_group(root->fs_info,
+							       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)
 		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,

+ 2 - 6
fs/btrfs/super.c

@@ -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,
-				     (void **)&alloc_group,
-				     alloc_group_block, 1);
-	BUG_ON(!ret);
-	BTRFS_I(inode)->block_group = alloc_group;
+	BTRFS_I(inode)->block_group = btrfs_lookup_block_group(root->fs_info,
+						       alloc_group_block);
 
 
 	btrfs_free_path(path);
 	btrfs_free_path(path);
 	inode_item = NULL;
 	inode_item = NULL;