Browse Source

Merge branch 'alloc_path' of git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/btrfs-error-handling into for-linus

Chris Mason 14 years ago
parent
commit
b43b31bdf2
6 changed files with 78 additions and 29 deletions
  1. 19 5
      fs/btrfs/extent-tree.c
  2. 5 2
      fs/btrfs/file-item.c
  3. 2 1
      fs/btrfs/file.c
  4. 35 14
      fs/btrfs/inode.c
  5. 9 3
      fs/btrfs/tree-log.c
  6. 8 4
      fs/btrfs/volumes.c

+ 19 - 5
fs/btrfs/extent-tree.c

@@ -663,7 +663,9 @@ int btrfs_lookup_extent(struct btrfs_root *root, u64 start, u64 len)
 	struct btrfs_path *path;
 	struct btrfs_path *path;
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return -ENOMEM;
+
 	key.objectid = start;
 	key.objectid = start;
 	key.offset = len;
 	key.offset = len;
 	btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
 	btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY);
@@ -3272,6 +3274,9 @@ again:
 	}
 	}
 
 
 	ret = btrfs_alloc_chunk(trans, extent_root, flags);
 	ret = btrfs_alloc_chunk(trans, extent_root, flags);
+	if (ret < 0 && ret != -ENOSPC)
+		goto out;
+
 	spin_lock(&space_info->lock);
 	spin_lock(&space_info->lock);
 	if (ret)
 	if (ret)
 		space_info->full = 1;
 		space_info->full = 1;
@@ -3281,6 +3286,7 @@ again:
 	space_info->force_alloc = CHUNK_ALLOC_NO_FORCE;
 	space_info->force_alloc = CHUNK_ALLOC_NO_FORCE;
 	space_info->chunk_alloc = 0;
 	space_info->chunk_alloc = 0;
 	spin_unlock(&space_info->lock);
 	spin_unlock(&space_info->lock);
+out:
 	mutex_unlock(&extent_root->fs_info->chunk_mutex);
 	mutex_unlock(&extent_root->fs_info->chunk_mutex);
 	return ret;
 	return ret;
 }
 }
@@ -5501,7 +5507,8 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans,
 	u32 size = sizeof(*extent_item) + sizeof(*block_info) + sizeof(*iref);
 	u32 size = sizeof(*extent_item) + sizeof(*block_info) + sizeof(*iref);
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return -ENOMEM;
 
 
 	path->leave_spinning = 1;
 	path->leave_spinning = 1;
 	ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path,
 	ret = btrfs_insert_empty_item(trans, fs_info->extent_root, path,
@@ -6272,10 +6279,14 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
 	int level;
 	int level;
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return -ENOMEM;
 
 
 	wc = kzalloc(sizeof(*wc), GFP_NOFS);
 	wc = kzalloc(sizeof(*wc), GFP_NOFS);
-	BUG_ON(!wc);
+	if (!wc) {
+		btrfs_free_path(path);
+		return -ENOMEM;
+	}
 
 
 	trans = btrfs_start_transaction(tree_root, 0);
 	trans = btrfs_start_transaction(tree_root, 0);
 	BUG_ON(IS_ERR(trans));
 	BUG_ON(IS_ERR(trans));
@@ -7183,7 +7194,10 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
 	spin_unlock(&cluster->refill_lock);
 	spin_unlock(&cluster->refill_lock);
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
 
 	inode = lookup_free_space_inode(root, block_group, path);
 	inode = lookup_free_space_inode(root, block_group, path);
 	if (!IS_ERR(inode)) {
 	if (!IS_ERR(inode)) {

+ 5 - 2
fs/btrfs/file-item.c

@@ -291,7 +291,8 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
 	u16 csum_size = btrfs_super_csum_size(&root->fs_info->super_copy);
 	u16 csum_size = btrfs_super_csum_size(&root->fs_info->super_copy);
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return -ENOMEM;
 
 
 	if (search_commit) {
 	if (search_commit) {
 		path->skip_locking = 1;
 		path->skip_locking = 1;
@@ -677,7 +678,9 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
 		btrfs_super_csum_size(&root->fs_info->super_copy);
 		btrfs_super_csum_size(&root->fs_info->super_copy);
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return -ENOMEM;
+
 	sector_sum = sums->sums;
 	sector_sum = sums->sums;
 again:
 again:
 	next_offset = (u64)-1;
 	next_offset = (u64)-1;

+ 2 - 1
fs/btrfs/file.c

@@ -855,7 +855,8 @@ int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
 	btrfs_drop_extent_cache(inode, start, end - 1, 0);
 	btrfs_drop_extent_cache(inode, start, end - 1, 0);
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return -ENOMEM;
 again:
 again:
 	recow = 0;
 	recow = 0;
 	split = start;
 	split = start;

+ 35 - 14
fs/btrfs/inode.c

@@ -1061,7 +1061,8 @@ static noinline int run_delalloc_nocow(struct inode *inode,
 	u64 ino = btrfs_ino(inode);
 	u64 ino = btrfs_ino(inode);
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return -ENOMEM;
 
 
 	nolock = btrfs_is_free_space_inode(root, inode);
 	nolock = btrfs_is_free_space_inode(root, inode);
 
 
@@ -1645,7 +1646,8 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
 	int ret;
 	int ret;
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return -ENOMEM;
 
 
 	path->leave_spinning = 1;
 	path->leave_spinning = 1;
 
 
@@ -2517,7 +2519,9 @@ static void btrfs_read_locked_inode(struct inode *inode)
 		filled = true;
 		filled = true;
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		goto make_bad;
+
 	path->leave_spinning = 1;
 	path->leave_spinning = 1;
 	memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
 	memcpy(&location, &BTRFS_I(inode)->location, sizeof(location));
 
 
@@ -3147,6 +3151,11 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
 
 
 	BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
 	BUG_ON(new_size > 0 && min_type != BTRFS_EXTENT_DATA_KEY);
 
 
+	path = btrfs_alloc_path();
+	if (!path)
+		return -ENOMEM;
+	path->reada = -1;
+
 	if (root->ref_cows || root == root->fs_info->tree_root)
 	if (root->ref_cows || root == root->fs_info->tree_root)
 		btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0);
 		btrfs_drop_extent_cache(inode, new_size & (~mask), (u64)-1, 0);
 
 
@@ -3159,10 +3168,6 @@ int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
 	if (min_type == 0 && root == BTRFS_I(inode)->root)
 	if (min_type == 0 && root == BTRFS_I(inode)->root)
 		btrfs_kill_delayed_inode_items(inode);
 		btrfs_kill_delayed_inode_items(inode);
 
 
-	path = btrfs_alloc_path();
-	BUG_ON(!path);
-	path->reada = -1;
-
 	key.objectid = ino;
 	key.objectid = ino;
 	key.offset = (u64)-1;
 	key.offset = (u64)-1;
 	key.type = (u8)-1;
 	key.type = (u8)-1;
@@ -3690,7 +3695,8 @@ static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry,
 	int ret = 0;
 	int ret = 0;
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return -ENOMEM;
 
 
 	di = btrfs_lookup_dir_item(NULL, root, path, btrfs_ino(dir), name,
 	di = btrfs_lookup_dir_item(NULL, root, path, btrfs_ino(dir), name,
 				    namelen, 0);
 				    namelen, 0);
@@ -3946,6 +3952,7 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
 			 struct btrfs_root *root, int *new)
 			 struct btrfs_root *root, int *new)
 {
 {
 	struct inode *inode;
 	struct inode *inode;
+	int bad_inode = 0;
 
 
 	inode = btrfs_iget_locked(s, location->objectid, root);
 	inode = btrfs_iget_locked(s, location->objectid, root);
 	if (!inode)
 	if (!inode)
@@ -3955,10 +3962,19 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
 		BTRFS_I(inode)->root = root;
 		BTRFS_I(inode)->root = root;
 		memcpy(&BTRFS_I(inode)->location, location, sizeof(*location));
 		memcpy(&BTRFS_I(inode)->location, location, sizeof(*location));
 		btrfs_read_locked_inode(inode);
 		btrfs_read_locked_inode(inode);
-		inode_tree_add(inode);
-		unlock_new_inode(inode);
-		if (new)
-			*new = 1;
+		if (!is_bad_inode(inode)) {
+			inode_tree_add(inode);
+			unlock_new_inode(inode);
+			if (new)
+				*new = 1;
+		} else {
+			bad_inode = 1;
+		}
+	}
+
+	if (bad_inode) {
+		iput(inode);
+		inode = ERR_PTR(-ESTALE);
 	}
 	}
 
 
 	return inode;
 	return inode;
@@ -4415,7 +4431,8 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
 	int owner;
 	int owner;
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return ERR_PTR(-ENOMEM);
 
 
 	inode = new_inode(root->fs_info->sb);
 	inode = new_inode(root->fs_info->sb);
 	if (!inode) {
 	if (!inode) {
@@ -7172,7 +7189,11 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
 		goto out_unlock;
 		goto out_unlock;
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path) {
+		err = -ENOMEM;
+		drop_inode = 1;
+		goto out_unlock;
+	}
 	key.objectid = btrfs_ino(inode);
 	key.objectid = btrfs_ino(inode);
 	key.offset = 0;
 	key.offset = 0;
 	btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY);
 	btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY);

+ 9 - 3
fs/btrfs/tree-log.c

@@ -1617,7 +1617,8 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb,
 		return 0;
 		return 0;
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return -ENOMEM;
 
 
 	nritems = btrfs_header_nritems(eb);
 	nritems = btrfs_header_nritems(eb);
 	for (i = 0; i < nritems; i++) {
 	for (i = 0; i < nritems; i++) {
@@ -1723,7 +1724,9 @@ static noinline int walk_down_log_tree(struct btrfs_trans_handle *trans,
 			return -ENOMEM;
 			return -ENOMEM;
 
 
 		if (*level == 1) {
 		if (*level == 1) {
-			wc->process_func(root, next, wc, ptr_gen);
+			ret = wc->process_func(root, next, wc, ptr_gen);
+			if (ret)
+				return ret;
 
 
 			path->slots[*level]++;
 			path->slots[*level]++;
 			if (wc->free) {
 			if (wc->free) {
@@ -1788,8 +1791,11 @@ static noinline int walk_up_log_tree(struct btrfs_trans_handle *trans,
 				parent = path->nodes[*level + 1];
 				parent = path->nodes[*level + 1];
 
 
 			root_owner = btrfs_header_owner(parent);
 			root_owner = btrfs_header_owner(parent);
-			wc->process_func(root, path->nodes[*level], wc,
+			ret = wc->process_func(root, path->nodes[*level], wc,
 				 btrfs_header_generation(path->nodes[*level]));
 				 btrfs_header_generation(path->nodes[*level]));
+			if (ret)
+				return ret;
+
 			if (wc->free) {
 			if (wc->free) {
 				struct extent_buffer *next;
 				struct extent_buffer *next;
 
 

+ 8 - 4
fs/btrfs/volumes.c

@@ -1037,7 +1037,8 @@ static noinline int find_next_chunk(struct btrfs_root *root,
 	struct btrfs_key found_key;
 	struct btrfs_key found_key;
 
 
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return -ENOMEM;
 
 
 	key.objectid = objectid;
 	key.objectid = objectid;
 	key.offset = (u64)-1;
 	key.offset = (u64)-1;
@@ -2061,8 +2062,10 @@ int btrfs_balance(struct btrfs_root *dev_root)
 
 
 	/* step two, relocate all the chunks */
 	/* step two, relocate all the chunks */
 	path = btrfs_alloc_path();
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
-
+	if (!path) {
+		ret = -ENOMEM;
+		goto error;
+	}
 	key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
 	key.objectid = BTRFS_FIRST_CHUNK_TREE_OBJECTID;
 	key.offset = (u64)-1;
 	key.offset = (u64)-1;
 	key.type = BTRFS_CHUNK_ITEM_KEY;
 	key.type = BTRFS_CHUNK_ITEM_KEY;
@@ -2661,7 +2664,8 @@ static noinline int init_first_rw_device(struct btrfs_trans_handle *trans,
 
 
 	ret = find_next_chunk(fs_info->chunk_root,
 	ret = find_next_chunk(fs_info->chunk_root,
 			      BTRFS_FIRST_CHUNK_TREE_OBJECTID, &chunk_offset);
 			      BTRFS_FIRST_CHUNK_TREE_OBJECTID, &chunk_offset);
-	BUG_ON(ret);
+	if (ret)
+		return ret;
 
 
 	alloc_profile = BTRFS_BLOCK_GROUP_METADATA |
 	alloc_profile = BTRFS_BLOCK_GROUP_METADATA |
 			(fs_info->metadata_alloc_profile &
 			(fs_info->metadata_alloc_profile &