Skip to contentSkip to conversation

Error handling patchset v5

GIT PULL In review Jeff Mahoney 5 participants 77 messages Oct 25, 2011 – Oct 31, 2011 Btrfs file system

lore
Share & tools
lore
#0 lore raw

Hi all -

Here's my current error handling patchset, against David's integration branch. Almost all of this patchset is preparing for actual error handling. Before we start in on that work, I'm trying to reduce the surface we need to worry about. It turns out that there is a ton of code that returns an error code but never actually reports an error.

The patchset has grown to 66 patches. 46 of them change functions that currently return int to return void. Many of them didn't even have the error codes checked in the caller to begin with. 11 of the patches push error codes up into the caller.

The remaining 9 patches do:
- Add a btrfs_panic facility, with a mount option to select BUG or panic
- Catch tree operation failures
- Simplify/add some wrapper functions

The biggest change, which will probably merit some discussion, is the introduction of slab-backed mempools in the delayed ref code. I expect to use this technique in other areas of the code to deal with deep failures that are impossible to recover gracefully from. Rather than returning -ENOMEM, we keep a page's worth of objects around for each node type. That allows the callers to be drastically simplified. There's no reason in particular to start with the delayed ref code, it's just where I happened to do it.

Changes since v3 in order of impact:
- Fixed an issue in ("btrfs: clear_extent_bit error push-up") where a positive error code returned by clear_extent_bit was being passed to callers of btrfs_direct_IO. The callers intepreted it as an error and xfstests reported corruption in test 130.
- Push-up patches have added __must_check to their prototypes so that new callers are forced to properly handle the error conditions, even if it's also with BUG_ON. Some callers weren't checking error codes at all and this will prevent those types of issues from being re-introduced.
- Added error push-up and tree locking check for convert_extent_bit.
- Moved btrfs_drop_snapshot checks into the patch that changed it to return int.

This is also available in my git repository at:
git://git.jeffreymahoney.com/linux/btrfs-unstable for-david-v5

It depends on git://repo.or.cz/linux-2.6/btrfs-unstable.git, starting with commit f2ab07c6 ("Btrfs: fix the amount of space reserved for unlink").

I can rebase if necessary.

-Jeff

#1 lore raw

PATCH 1/66 btrfs: Add btrfs_panic()

As part of the effort to eliminate BUG_ON as an error handling technique, we need to determine which errors are actual logic errors, which are on-disk corruption, and which are normal runtime errors e.g. -ENOMEM.

Annotating these error cases is helpful to understand and report them.

This patch adds a btrfs_panic() routine that will either panic or BUG depending on the new -ofatal_errors={panic,bug} mount option. Since there are still so many BUG_ONs, it defaults to BUG for now but I expect that to change once the error handling effort has made significant progress.

---
 fs/btrfs/ctree.h |   11 +++++++++++
 fs/btrfs/super.c |   50 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 60 insertions(+), 1 deletion(-)
fs/btrfs/ctree.h +11 -0
@@ -1357,6 +1357,7 @@ struct btrfs_ioctl_defrag_range_args {
 #define BTRFS_MOUNT_ENOSPC_DEBUG	 (1 << 15)
 #define BTRFS_MOUNT_AUTO_DEFRAG		(1 << 16)
 #define BTRFS_MOUNT_INODE_MAP_CACHE	(1 << 17)
+#define BTRFS_MOUNT_PANIC_ON_FATAL_ERROR	(1 << 18)
 
 #define btrfs_clear_opt(o, opt)		((o) &= ~BTRFS_MOUNT_##opt)
 #define btrfs_set_opt(o, opt)		((o) |= BTRFS_MOUNT_##opt)
@@ -2644,6 +2645,16 @@ do {								\
 		__btrfs_std_error((fs_info), __func__, __LINE__, (errno));\
 } while (0)
 
+void __btrfs_panic(struct btrfs_fs_info *fs_info, const char *function,
+		   unsigned int line, int errno, const char *fmt, ...);
+
+#define btrfs_panic(fs_info, errno, fmt, args...)			\
+do {									\
+	struct btrfs_fs_info *_i = (fs_info);				\
+	__btrfs_panic(_i, __func__, __LINE__, errno, fmt, ##args);	\
+	BUG_ON(!(_i->mount_opt & BTRFS_MOUNT_PANIC_ON_FATAL_ERROR));	\
+} while (0)
+
 /* acl.c */
 #ifdef CONFIG_BTRFS_FS_POSIX_ACL
 struct posix_acl *btrfs_get_acl(struct inode *inode, int type);
fs/btrfs/super.c +49 -1

86 lines not on this page · raw message

#2 lore raw

PATCH 2/66 btrfs: Catch locking failures in {set,clear,convert}_extent_bit

In reply to Jeff Mahoney

The *_state functions can only return 0 or -EEXIST. This patch addresses the cases where those functions return -EEXIST, representing a locking failure. It handles them by panicking with an appropriate error message.

---
 fs/btrfs/extent_io.c |   58 +++++++++++++++++++++++++++++++++------------------
 1 file changed, 38 insertions(+), 20 deletions(-)
fs/btrfs/extent_io.c +38 -20
@@ -51,6 +51,12 @@ struct extent_page_data {
 	unsigned int sync_io:1;
 };
 
+static inline struct btrfs_fs_info *
+tree_fs_info(struct extent_io_tree *tree)
+{
+	return btrfs_sb(tree->mapping->host->i_sb)->fs_info;
+}
+
 int __init extent_io_init(void)
 {
 	extent_state_cache = kmem_cache_create("extent_state",
@@ -437,6 +443,13 @@ alloc_extent_state_atomic(struct extent_
 	return prealloc;
 }
 
+NORET_TYPE void extent_io_tree_panic(struct extent_io_tree *tree, int err)
+{
+	btrfs_panic(tree_fs_info(tree), err, "Locking error: "
+		    "Extent tree was modified by another "
+		    "thread while locked.");
+}
+
 /*
  * clear some bits on a range in the tree.  This may require splitting
  * or inserting elements in the tree, so the gfp mask is used to
@@ -531,7 +544,9 @@ hit_next:
 		prealloc = alloc_extent_state_atomic(prealloc);
 		BUG_ON(!prealloc);
 		err = split_state(tree, state, prealloc, start);
-		BUG_ON(err == -EEXIST);
+		if (err)
+			extent_io_tree_panic(tree, err);
+
 		prealloc = NULL;
 		if (err)
 			goto out;
@@ -553,7 +568,9 @@ hit_next:
 		prealloc = alloc_extent_state_atomic(prealloc);
 		BUG_ON(!prealloc);
 		err = split_state(tree, state, prealloc, end + 1);
-		BUG_ON(err == -EEXIST);
+		if (err)
+			extent_io_tree_panic(tree, err);
+
 		if (wake)
 			wake_up(&state->wq);
 
@@ -736,8 +753,10 @@ again:
 		prealloc = alloc_extent_state_atomic(prealloc);
 		BUG_ON(!prealloc);
 		err = insert_state(tree, prealloc, start, end, &bits);
+		if (err)
+			extent_io_tree_panic(tree, err);
+
 		prealloc = NULL;
-		BUG_ON(err == -EEXIST);
 		goto out;
 	}
 	state = rb_entry(node, struct extent_state, rb_node);
@@ -803,7 +822,9 @@ hit_next:
 		prealloc = alloc_extent_state_atomic(prealloc);
 		BUG_ON(!prealloc);
 		err = split_state(tree, state, prealloc, start);
-		BUG_ON(err == -EEXIST);
+		if (err)
+			extent_io_tree_panic(tree, err);
+
 		prealloc = NULL;
 		if (err)
 			goto out;
@@ -840,12 +861,9 @@ hit_next:
 		 */
 		err = insert_state(tree, prealloc, start, this_end,
 				   &bits);
-		BUG_ON(err == -EEXIST);
-		if (err) {
-			free_extent_state(prealloc);
-			prealloc = NULL;
-			goto out;
-		}
+		if (err)
+			extent_io_tree_panic(tree, err);
+
 		cache_state(prealloc, cached_state);
 		prealloc = NULL;
 		start = this_end + 1;
@@ -867,7 +885,8 @@ hit_next:
 		prealloc = alloc_extent_state_atomic(prealloc);
 		BUG_ON(!prealloc);
 		err = split_state(tree, state, prealloc, end + 1);
-		BUG_ON(err == -EEXIST);
+		if (err)
+			extent_io_tree_panic(tree, err);
 
 		set_state_bits(tree, prealloc, &bits);
 		cache_state(prealloc, cached_state);
@@ -938,7 +957,8 @@ again:
 			return -ENOMEM;
 		err = insert_state(tree, prealloc, start, end, &bits);
 		prealloc = NULL;
-		BUG_ON(err == -EEXIST);
+		if (err)
+			extent_io_tree_panic(tree, err);
 		goto out;
 	}
 	state = rb_entry(node, struct extent_state, rb_node);
@@ -994,7 +1014,8 @@ hit_next:
 		if (!prealloc)
 			return -ENOMEM;
 		err = split_state(tree, state, prealloc, start);
-		BUG_ON(err == -EEXIST);
+		if (err)
+			extent_io_tree_panic(tree, err);
 		prealloc = NULL;
 		if (err)
 			goto out;
@@ -1032,12 +1053,8 @@ hit_next:
 		 */
 		err = insert_state(tree, prealloc, start, this_end,
 				   &bits);
-		BUG_ON(err == -EEXIST);
-		if (err) {
-			free_extent_state(prealloc);
-			prealloc = NULL;
-			goto out;
-		}
+		if (err)
+			extent_io_tree_panic(tree, err);
 		prealloc = NULL;
 		start = this_end + 1;
 		goto search_again;
@@ -1054,7 +1071,8 @@ hit_next:
 			return -ENOMEM;
 
 		err = split_state(tree, state, prealloc, end + 1);
-		BUG_ON(err == -EEXIST);
+		if (err)
+			extent_io_tree_panic(tree, err);
 
 		set_state_bits(tree, prealloc, &bits);
 		clear_state_bit(tree, prealloc, &clear_bits, 0);
#3 lore raw

PATCH 3/66 btrfs: Panic on bad rbtree operations

In reply to Jeff Mahoney

The ordered data and relocation trees have BUG_ONs to protect against bad tree operations.

This patch replaces them with a panic that will report the problem.

---
 fs/btrfs/ordered-data.c |   12 ++++++++++--
 fs/btrfs/relocation.c   |   36 +++++++++++++++++++++++++++++-------
 2 files changed, 39 insertions(+), 9 deletions(-)
fs/btrfs/ordered-data.c +10 -2
index a1c9404..5a53d94 100644
@@ -59,6 +59,14 @@ static struct rb_node *tree_insert(struct rb_root *root, u64 file_offset,
 	return NULL;
 }
 
+NORET_TYPE static void ordered_data_tree_panic(struct inode *inode, int errno,
+					       u64 offset)
+{
+	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb)->fs_info;
+	btrfs_panic(fs_info, errno, "Inconsistency in ordered tree at offset "
+		    "%llu\n", offset);
+}
+
 /*
  * look for a given offset in the tree, and if it can't be found return the
  * first lesser offset
@@ -207,7 +215,8 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
 	spin_lock(&tree->lock);
 	node = tree_insert(&tree->tree, file_offset,
 			   &entry->rb_node);
-	BUG_ON(node);
+	if (node)
+		ordered_data_tree_panic(inode, -EEXIST, file_offset);
 	spin_unlock(&tree->lock);
 
 	spin_lock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock);
@@ -215,7 +224,6 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
 		      &BTRFS_I(inode)->root->fs_info->ordered_extents);
 	spin_unlock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock);
 
-	BUG_ON(node);
 	return 0;
 }
 
fs/btrfs/relocation.c +29 -7
index 7fa090f..a222957 100644
@@ -326,6 +326,19 @@ static struct rb_node *tree_search(struct rb_root *root, u64 bytenr)
 	return NULL;
 }
 
+NORET_TYPE static void backref_tree_panic(struct rb_node *rb_node, int errno,
+					  u64 bytenr)
+{
+
+	struct btrfs_fs_info *fs_info = NULL;
+	struct backref_node *bnode = rb_entry(rb_node, struct backref_node,
+					      rb_node);
+	if (bnode->root)
+		fs_info = bnode->root->fs_info;
+	btrfs_panic(fs_info, errno, "Inconsistency in backref cache "
+		    "found at offset %llu\n", bytenr);
+}
+
 /*
  * walk up backref nodes until reach node presents tree root
  */
@@ -452,7 +465,8 @@ static void update_backref_node(struct backref_cache *cache,
 	rb_erase(&node->rb_node, &cache->rb_root);
 	node->bytenr = bytenr;
 	rb_node = tree_insert(&cache->rb_root, node->bytenr, &node->rb_node);
-	BUG_ON(rb_node);
+	if (rb_node)
+		backref_tree_panic(rb_node, -EEXIST, bytenr);
 }
 
 /*
@@ -999,7 +1013,8 @@ next:
 	if (!cowonly) {
 		rb_node = tree_insert(&cache->rb_root, node->bytenr,
 				      &node->rb_node);
-		BUG_ON(rb_node);
+		if (rb_node)
+			backref_tree_panic(rb_node, -EEXIST, node->bytenr);
 		list_add_tail(&node->lower, &cache->leaves);
 	}
 
@@ -1034,7 +1049,9 @@ next:
 		if (!cowonly) {
 			rb_node = tree_insert(&cache->rb_root, upper->bytenr,
 					      &upper->rb_node);
-			BUG_ON(rb_node);
+			if (rb_node)
+				backref_tree_panic(rb_node, -EEXIST,
+						   upper->bytenr);
 		}
 
 		list_add_tail(&edge->list[UPPER], &upper->lower);
@@ -1178,7 +1195,8 @@ static int clone_backref_node(struct btrfs_trans_handle *trans,
 
 	rb_node = tree_insert(&cache->rb_root, new_node->bytenr,
 			      &new_node->rb_node);
-	BUG_ON(rb_node);
+	if (rb_node)
+		backref_tree_panic(rb_node, -EEXIST, new_node->bytenr);
 
 	if (!new_node->lowest) {
 		list_for_each_entry(new_edge, &new_node->lower, list[UPPER]) {
@@ -1250,7 +1268,8 @@ static int __update_reloc_root(struct btrfs_root *root, int del)
 		rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
 				      node->bytenr, &node->rb_node);
 		spin_unlock(&rc->reloc_root_tree.lock);
-		BUG_ON(rb_node);
+		if (rb_node)
+			backref_tree_panic(rb_node, -EEXIST, node->bytenr);
 	} else {
 		list_del_init(&root->root_list);
 		kfree(node);
@@ -3151,7 +3170,8 @@ static int add_tree_block(struct reloc_control *rc,
 	block->key_ready = 0;
 
 	rb_node = tree_insert(blocks, block->bytenr, &block->rb_node);
-	BUG_ON(rb_node);
+	if (rb_node)
+		backref_tree_panic(rb_node, -EEXIST, block->bytenr);
 
 	return 0;
 }
@@ -3420,7 +3440,9 @@ static int find_data_references(struct reloc_control *rc,
 			block->key_ready = 1;
 			rb_node = tree_insert(blocks, block->bytenr,
 					      &block->rb_node);
-			BUG_ON(rb_node);
+			if (rb_node)
+				backref_tree_panic(rb_node, -EEXIST,
+						   block->bytenr);
 		}
 		if (counted)
 			added = 1;
#4 lore raw

PATCH 4/66 btrfs: Simplify btrfs_insert_root

In reply to Jeff Mahoney

btrfs_insert_root is just a wrapper for btrfs_insert_item. Just return the error directly.

---
 fs/btrfs/root-tree.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)
fs/btrfs/root-tree.c +3 -6
index f409990..1fd93d6 100644
@@ -116,13 +116,10 @@ out:
 	return ret;
 }
 
-int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
-		      *root, struct btrfs_key *key, struct btrfs_root_item
-		      *item)
+int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+		      struct btrfs_key *key, struct btrfs_root_item *item)
 {
-	int ret;
-	ret = btrfs_insert_item(trans, root, key, item, sizeof(*item));
-	return ret;
+	return btrfs_insert_item(trans, root, key, item, sizeof(*item));
 }
 
 /*
#5 lore raw

PATCH 5/66 btrfs: set_extent_bit error push-up

In reply to Jeff Mahoney

In the locking case, set_extent_bit can return -EEXIST but callers already handle that.

In the non-locking case, it can't fail. Memory allocation failures are handled by BUG_ON.

This patch pushes up the BUG_ONs from set_extent_bit to callers, except where -ENOMEM can't occur (e.g. __GFP_WAIT && __GFP_NOFAIL).

Update v2: Changed cases of BUG_ON(ret) to BUG_ON(ret < 0)

---
 fs/btrfs/ctree.h       |    2 -
 fs/btrfs/extent-tree.c |   48 +++++++++++++++++++++++++++++++--------------
 fs/btrfs/extent_io.c   |   52 ++++++++++++++++++++++++++++++++++++-------------
 fs/btrfs/extent_io.h   |   12 ++++++-----
 fs/btrfs/file-item.c   |    3 +-
 fs/btrfs/inode.c       |   25 ++++++++++++++++-------
 fs/btrfs/ioctl.c       |    5 ++--
 fs/btrfs/relocation.c  |   23 +++++++++++++--------
 8 files changed, 116 insertions(+), 54 deletions(-)
fs/btrfs/ctree.h +1 -1
@@ -2551,7 +2551,7 @@ int btrfs_truncate_inode_items(struct bt
 
 int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput);
 int btrfs_set_extent_delalloc(struct inode *inode, u64 start, u64 end,
-			      struct extent_state **cached_state);
+			      struct extent_state **cached_state) __must_check;
 int btrfs_writepages(struct address_space *mapping,
 		     struct writeback_control *wbc);
 int btrfs_create_subvol_root(struct btrfs_trans_handle *trans,
fs/btrfs/extent-tree.c +33 -15

93 lines not on this page · raw message

fs/btrfs/extent_io.c +39 -13

124 lines not on this page · raw message

fs/btrfs/extent_io.h +7 -5
@@ -203,16 +203,18 @@ int clear_extent_bit(struct extent_io_tr
 		     int bits, int wake, int delete, struct extent_state **cached,
 		     gfp_t mask);
 int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
-		    int bits, gfp_t mask);
+		    int bits, gfp_t mask) __must_check;
 int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
 		   int bits, int exclusive_bits, u64 *failed_start,
-		   struct extent_state **cached_state, gfp_t mask);
+		   struct extent_state **cached_state, gfp_t mask)
+		   __must_check;
 int set_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end,
-			struct extent_state **cached_state, gfp_t mask);
+			struct extent_state **cached_state, gfp_t mask)
+			__must_check;
 int set_extent_new(struct extent_io_tree *tree, u64 start, u64 end,
-		   gfp_t mask);
+		   gfp_t mask) __must_check;
 int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
-		     gfp_t mask);
+		     gfp_t mask) __must_check;
 int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
 		       gfp_t mask);
 int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
fs/btrfs/file-item.c +2 -1
@@ -214,9 +214,10 @@ static int __btrfs_lookup_bio_sums(struc
 				sum = 0;
 				if (BTRFS_I(inode)->root->root_key.objectid ==
 				    BTRFS_DATA_RELOC_TREE_OBJECTID) {
-					set_extent_bits(io_tree, offset,
+					ret = set_extent_bits(io_tree, offset,
 						offset + bvec->bv_len - 1,
 						EXTENT_NODATASUM, GFP_NOFS);
+					BUG_ON(ret < 0);
 				} else {
 					printk(KERN_INFO "btrfs no csum found "
 					       "for inode %llu start %llu\n",
fs/btrfs/inode.c +17 -8
@@ -1548,6 +1548,7 @@ static void btrfs_writepage_fixup_worker
 	struct inode *inode;
 	u64 page_start;
 	u64 page_end;
+	int ret;
 
 	fixup = container_of(work, struct btrfs_writepage_fixup, work);
 	page = fixup->page;
@@ -1579,7 +1580,9 @@ again:
 	}
 
 	BUG();
-	btrfs_set_extent_delalloc(inode, page_start, page_end, &cached_state);
+	ret = btrfs_set_extent_delalloc(inode, page_start, page_end,
+					&cached_state);
+	BUG_ON(ret < 0);
 	ClearPageChecked(page);
 out:
 	unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start, page_end,
@@ -1883,8 +1886,11 @@ static int btrfs_io_failed_hook(struct b
 		}
 		failrec->logical = logical;
 		free_extent_map(em);
-		set_extent_bits(failure_tree, start, end, EXTENT_LOCKED |
-				EXTENT_DIRTY, GFP_NOFS);
+
+		/* Doesn't this ignore locking failures? */
+		ret = set_extent_bits(failure_tree, start, end, EXTENT_LOCKED |
+				      EXTENT_DIRTY, GFP_NOFS);
+		BUG_ON(ret < 0);
 		set_state_private(failure_tree, start,
 				 (u64)(unsigned long)failrec);
 	} else {
@@ -5148,8 +5154,10 @@ again:
 			kunmap(page);
 			btrfs_mark_buffer_dirty(leaf);
 		}
-		set_extent_uptodate(io_tree, em->start,
-				    extent_map_end(em) - 1, NULL, GFP_NOFS);
+		ret = set_extent_uptodate(io_tree, em->start,
+					  extent_map_end(em) - 1,
+					  NULL, GFP_NOFS);
+		BUG_ON(ret < 0);
 		goto insert;
 	} else {
 		printk(KERN_ERR "btrfs unknown found_type %d\n", found_type);
@@ -6211,9 +6219,10 @@ static ssize_t btrfs_direct_IO(int rw, s
 	 */
 	if (writing) {
 		write_bits = EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING;
-		ret = set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend,
-				     EXTENT_DELALLOC, 0, NULL, &cached_state,
-				     GFP_NOFS);
+		ret = set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
+				     lockend, EXTENT_DELALLOC, 0, NULL,
+				     &cached_state, GFP_NOFS);
+		BUG_ON(ret < 0);
 		if (ret) {
 			clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
 					 lockend, EXTENT_LOCKED | write_bits,
fs/btrfs/ioctl.c +3 -2
@@ -944,8 +944,9 @@ again:
 	}
 
 
-	btrfs_set_extent_delalloc(inode, page_start, page_end - 1,
-				  &cached_state);
+	ret = btrfs_set_extent_delalloc(inode, page_start, page_end - 1,
+					&cached_state);
+	BUG_ON(ret < 0);
 
 	unlock_extent_cached(&BTRFS_I(inode)->io_tree,
 			     page_start, page_end - 1, &cached_state,
fs/btrfs/relocation.c +14 -9
@@ -2641,11 +2641,11 @@ static int finish_pending_nodes(struct b
 	return err;
 }
 
-static void mark_block_processed(struct reloc_control *rc,
-				 u64 bytenr, u32 blocksize)
+static int __must_check mark_block_processed(struct reloc_control *rc,
+					     u64 bytenr, u32 blocksize)
 {
-	set_extent_bits(&rc->processed_blocks, bytenr, bytenr + blocksize - 1,
-			EXTENT_DIRTY, GFP_NOFS);
+	return set_extent_bits(&rc->processed_blocks, bytenr,
+			       bytenr + blocksize - 1, EXTENT_DIRTY, GFP_NOFS);
 }
 
 static void __mark_block_processed(struct reloc_control *rc,
@@ -2654,8 +2654,10 @@ static void __mark_block_processed(struc
 	u32 blocksize;
 	if (node->level == 0 ||
 	    in_block_group(node->bytenr, rc->block_group)) {
+		int ret;
 		blocksize = btrfs_level_size(rc->extent_root, node->level);
-		mark_block_processed(rc, node->bytenr, blocksize);
+		ret = mark_block_processed(rc, node->bytenr, blocksize);
+		BUG_ON(ret < 0);
 	}
 	node->processed = 1;
 }
@@ -3013,13 +3015,16 @@ static int relocate_file_extent_cluster(
 
 		if (nr < cluster->nr &&
 		    page_start + offset == cluster->boundary[nr]) {
-			set_extent_bits(&BTRFS_I(inode)->io_tree,
-					page_start, page_end,
-					EXTENT_BOUNDARY, GFP_NOFS);
+			ret = set_extent_bits(&BTRFS_I(inode)->io_tree,
+					      page_start, page_end,
+					      EXTENT_BOUNDARY, GFP_NOFS);
+			BUG_ON(ret < 0);
 			nr++;
 		}
 
-		btrfs_set_extent_delalloc(inode, page_start, page_end, NULL);
+		ret = btrfs_set_extent_delalloc(inode, page_start,
+						page_end, NULL);
+		BUG_ON(ret < 0);
 		set_page_dirty(page);
 
 		unlock_extent(&BTRFS_I(inode)->io_tree,
#6 lore raw

PATCH 6/66 btrfs: lock_extent error push-up

In reply to Jeff Mahoney

lock_extent, try_lock_extent, and lock_extent_bits can't currently fail because errors are caught via BUG_ON.

This patch pushes the error handling up to callers, which currently only handle them via BUG_ON themselves.

---
 fs/btrfs/compression.c      |    3 +-
 fs/btrfs/disk-io.c          |    5 ++-
 fs/btrfs/extent_io.c        |   20 ++++++++-----
 fs/btrfs/extent_io.h        |    8 +++--
 fs/btrfs/file.c             |   17 ++++++-----
 fs/btrfs/free-space-cache.c |    6 ++--
 fs/btrfs/inode.c            |   66 ++++++++++++++++++++++++++------------------
 fs/btrfs/ioctl.c            |   16 ++++++----
 fs/btrfs/relocation.c       |   18 ++++++++----
 9 files changed, 99 insertions(+), 60 deletions(-)
fs/btrfs/compression.c +2 -1
@@ -496,7 +496,8 @@ static noinline int add_ra_bio_pages(str
 		 * sure they map to this compressed extent on disk.
 		 */
 		set_page_extent_mapped(page);
-		lock_extent(tree, last_offset, end, GFP_NOFS);
+		ret = lock_extent(tree, last_offset, end, GFP_NOFS);
+		BUG_ON(ret < 0);
 		read_lock(&em_tree->lock);
 		em = lookup_extent_mapping(em_tree, last_offset,
 					   PAGE_CACHE_SIZE);
fs/btrfs/disk-io.c +3 -2
@@ -331,8 +331,9 @@ static int verify_parent_transid(struct
 	if (!parent_transid || btrfs_header_generation(eb) == parent_transid)
 		return 0;
 
-	lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1,
-			 0, &cached_state, GFP_NOFS);
+	ret = lock_extent_bits(io_tree, eb->start, eb->start + eb->len - 1,
+			       0, &cached_state, GFP_NOFS);
+	BUG_ON(ret < 0);
 	if (extent_buffer_uptodate(io_tree, eb, cached_state) &&
 	    btrfs_header_generation(eb) == parent_transid) {
 		ret = 0;
fs/btrfs/extent_io.c +12 -8
@@ -1200,7 +1200,6 @@ int lock_extent_bits(struct extent_io_tr
 		}
 		WARN_ON(start > end);
 	}
-	BUG_ON(err < 0);
 	return err;
 }
 
@@ -1222,8 +1221,8 @@ int try_lock_extent(struct extent_io_tre
 			clear_extent_bit(tree, start, failed_start - 1,
 					 EXTENT_LOCKED, 1, 0, NULL, mask);
 		return 0;
-	}
-	BUG_ON(err < 0);
+	} else if (err < 0)
+		return err;
 	return 1;
 }
 
@@ -1534,8 +1533,9 @@ again:
 	BUG_ON(ret);
 
 	/* step three, lock the state bits for the whole range */
-	lock_extent_bits(tree, delalloc_start, delalloc_end,
-			 0, &cached_state, GFP_NOFS);
+	ret = lock_extent_bits(tree, delalloc_start, delalloc_end,
+			       0, &cached_state, GFP_NOFS);
+	BUG_ON(ret < 0);
 
 	/* then test to make sure it is all still delalloc */
 	ret = test_range_bit(tree, delalloc_start, delalloc_end,
@@ -2164,7 +2164,8 @@ static int __extent_read_full_page(struc
 
 	end = page_end;
 	while (1) {
-		lock_extent(tree, start, end, GFP_NOFS);
+		ret = lock_extent(tree, start, end, GFP_NOFS);
+		BUG_ON(ret < 0);
 		ordered = btrfs_lookup_ordered_extent(inode, start);
 		if (!ordered)
 			break;
@@ -2854,12 +2855,14 @@ int extent_invalidatepage(struct extent_
 	u64 start = ((u64)page->index << PAGE_CACHE_SHIFT);
 	u64 end = start + PAGE_CACHE_SIZE - 1;
 	size_t blocksize = page->mapping->host->i_sb->s_blocksize;
+	int ret;
 
 	start += (offset + blocksize - 1) & ~(blocksize - 1);
 	if (start > end)
 		return 0;
 
-	lock_extent_bits(tree, start, end, 0, &cached_state, GFP_NOFS);
+	ret = lock_extent_bits(tree, start, end, 0, &cached_state, GFP_NOFS);
+	BUG_ON(ret < 0);
 	wait_on_page_writeback(page);
 	clear_extent_bit(tree, start, end,
 			 EXTENT_LOCKED | EXTENT_DIRTY | EXTENT_DELALLOC |
@@ -3069,8 +3072,9 @@ int extent_fiemap(struct inode *inode, s
 		last_for_get_extent = isize;
 	}
 
-	lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0,
+	ret = lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0,
 			 &cached_state, GFP_NOFS);
+	BUG_ON(ret < 0);
 
 	em = get_extent_skip_holes(inode, off, last_for_get_extent,
 				   get_extent);
fs/btrfs/extent_io.h +5 -3
@@ -177,14 +177,16 @@ int try_release_extent_buffer(struct ext
 int try_release_extent_state(struct extent_map_tree *map,
 			     struct extent_io_tree *tree, struct page *page,
 			     gfp_t mask);
-int lock_extent(struct extent_io_tree *tree, u64 start, u64 end, gfp_t mask);
+int lock_extent(struct extent_io_tree *tree, u64 start, u64 end, gfp_t mask)
+		__must_check;
 int lock_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
-		     int bits, struct extent_state **cached, gfp_t mask);
+		     int bits, struct extent_state **cached, gfp_t mask)
+		     __must_check;
 int unlock_extent(struct extent_io_tree *tree, u64 start, u64 end, gfp_t mask);
 int unlock_extent_cached(struct extent_io_tree *tree, u64 start, u64 end,
 			 struct extent_state **cached, gfp_t mask);
 int try_lock_extent(struct extent_io_tree *tree, u64 start, u64 end,
-		    gfp_t mask);
+		    gfp_t mask) __must_check;
 int extent_read_full_page(struct extent_io_tree *tree, struct page *page,
 			  get_extent_t *get_extent);
 int __init extent_io_init(void);
fs/btrfs/file.c +10 -7
@@ -1104,9 +1104,10 @@ again:
 	err = 0;
 	if (start_pos < inode->i_size) {
 		struct btrfs_ordered_extent *ordered;
-		lock_extent_bits(&BTRFS_I(inode)->io_tree,
-				 start_pos, last_pos - 1, 0, &cached_state,
-				 GFP_NOFS);
+		err = lock_extent_bits(&BTRFS_I(inode)->io_tree,
+				       start_pos, last_pos - 1, 0,
+				       &cached_state, GFP_NOFS);
+		BUG_ON(err < 0);
 		ordered = btrfs_lookup_first_ordered_extent(inode,
 							    last_pos - 1);
 		if (ordered &&
@@ -1623,8 +1624,9 @@ static long btrfs_fallocate(struct file
 		/* the extent lock is ordered inside the running
 		 * transaction
 		 */
-		lock_extent_bits(&BTRFS_I(inode)->io_tree, alloc_start,
-				 locked_end, 0, &cached_state, GFP_NOFS);
+		ret = lock_extent_bits(&BTRFS_I(inode)->io_tree, alloc_start,
+				       locked_end, 0, &cached_state, GFP_NOFS);
+		BUG_ON(ret < 0);
 		ordered = btrfs_lookup_first_ordered_extent(inode,
 							    alloc_end - 1);
 		if (ordered &&
@@ -1735,8 +1737,9 @@ static int find_desired_extent(struct in
 	if (inode->i_size == 0)
 		return -ENXIO;
 
-	lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, 0,
-			 &cached_state, GFP_NOFS);
+	ret = lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend, 0,
+			       &cached_state, GFP_NOFS);
+	BUG_ON(ret < 0);
 
 	/*
 	 * Delalloc is such a pain.  If we have a hole and we have pending
fs/btrfs/free-space-cache.c +4 -2
@@ -850,8 +850,10 @@ int __btrfs_write_out_cache(struct btrfs
 	/* Lock all pages first so we can lock the extent safely. */
 	io_ctl_prepare_pages(&io_ctl, inode, 0);
 
-	lock_extent_bits(&BTRFS_I(inode)->io_tree, 0, i_size_read(inode) - 1,
-			 0, &cached_state, GFP_NOFS);
+	ret = lock_extent_bits(&BTRFS_I(inode)->io_tree, 0,
+			       i_size_read(inode) - 1, 0, &cached_state,
+			       GFP_NOFS);
+	BUG_ON(ret < 0);
 
 	/*
 	 * When searching for pinned extents, we need to start at our start
fs/btrfs/inode.c +40 -26

138 lines not on this page · raw message

fs/btrfs/ioctl.c +10 -6
@@ -762,7 +762,7 @@ static int should_defrag_range(struct in
 	struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
 	struct extent_map *em = NULL;
 	struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
-	int ret = 1;
+	int ret = 1, err;
 
 	/*
 	 * make sure that once we start defragging and extent, we keep on
@@ -783,7 +783,8 @@ static int should_defrag_range(struct in
 
 	if (!em) {
 		/* get the big lock and read metadata off disk */
-		lock_extent(io_tree, start, start + len - 1, GFP_NOFS);
+		err = lock_extent(io_tree, start, start + len - 1, GFP_NOFS);
+		BUG_ON(err < 0);
 		em = btrfs_get_extent(inode, NULL, 0, start, len, 0);
 		unlock_extent(io_tree, start, start + len - 1, GFP_NOFS);
 
@@ -908,9 +909,10 @@ again:
 	page_start = page_offset(pages[0]);
 	page_end = page_offset(pages[i_done - 1]) + PAGE_CACHE_SIZE;
 
-	lock_extent_bits(&BTRFS_I(inode)->io_tree,
-			 page_start, page_end - 1, 0, &cached_state,
-			 GFP_NOFS);
+	ret = lock_extent_bits(&BTRFS_I(inode)->io_tree,
+			       page_start, page_end - 1, 0, &cached_state,
+			       GFP_NOFS);
+	BUG_ON(ret < 0);
 	ordered = btrfs_lookup_first_ordered_extent(inode, page_end - 1);
 	if (ordered &&
 	    ordered->file_offset + ordered->len > page_start &&
@@ -2246,7 +2248,9 @@ static noinline long btrfs_ioctl_clone(s
 	   another, and lock file content */
 	while (1) {
 		struct btrfs_ordered_extent *ordered;
-		lock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS);
+		ret = lock_extent(&BTRFS_I(src)->io_tree, off, off+len,
+				  GFP_NOFS);
+		BUG_ON(ret < 0);
 		ordered = btrfs_lookup_first_ordered_extent(src, off+len);
 		if (!ordered &&
 		    !test_range_bit(&BTRFS_I(src)->io_tree, off, off+len,
fs/btrfs/relocation.c +13 -5
@@ -1596,6 +1596,7 @@ int replace_file_extents(struct btrfs_tr
 				ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
 						      key.offset, end,
 						      GFP_NOFS);
+				BUG_ON(ret < 0);
 				if (!ret)
 					continue;
 
@@ -1918,6 +1919,7 @@ static int invalidate_extent_cache(struc
 	u64 objectid;
 	u64 start, end;
 	u64 ino;
+	int ret;
 
 	objectid = min_key->objectid;
 	while (1) {
@@ -1971,7 +1973,9 @@ static int invalidate_extent_cache(struc
 		}
 
 		/* the lock_extent waits for readpage to complete */
-		lock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+		ret = lock_extent(&BTRFS_I(inode)->io_tree, start, end,
+				  GFP_NOFS);
+		BUG_ON(ret < 0);
 		btrfs_drop_extent_cache(inode, start, end, 1);
 		unlock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
 	}
@@ -2882,7 +2886,9 @@ int prealloc_file_extent_cluster(struct
 		else
 			end = cluster->end - offset;
 
-		lock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+		ret = lock_extent(&BTRFS_I(inode)->io_tree, start,
+				  end, GFP_NOFS);
+		BUG_ON(ret < 0);
 		num_bytes = end + 1 - start;
 		ret = btrfs_prealloc_file_range(inode, 0, start,
 						num_bytes, num_bytes,
@@ -2919,7 +2925,8 @@ int setup_extent_mapping(struct inode *i
 	em->bdev = root->fs_info->fs_devices->latest_bdev;
 	set_bit(EXTENT_FLAG_PINNED, &em->flags);
 
-	lock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+	ret = lock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+	BUG_ON(ret < 0);
 	while (1) {
 		write_lock(&em_tree->lock);
 		ret = add_extent_mapping(em_tree, em);
@@ -3010,8 +3017,9 @@ static int relocate_file_extent_cluster(
 		page_start = (u64)page->index << PAGE_CACHE_SHIFT;
 		page_end = page_start + PAGE_CACHE_SIZE - 1;
 
-		lock_extent(&BTRFS_I(inode)->io_tree,
-			    page_start, page_end, GFP_NOFS);
+		ret = lock_extent(&BTRFS_I(inode)->io_tree,
+				  page_start, page_end, GFP_NOFS);
+		BUG_ON(ret < 0);
 
 		set_page_extent_mapped(page);
 
#7 lore raw

PATCH 7/66 btrfs: clear_extent_bit error push-up

In reply to Jeff Mahoney

clear_extent_bit can fail with -ENOMEM for a specific case but will BUG on other memory allocation failures.

This patch returns -ENOMEM for memory allocation failures and handles them with BUG_ON in callers which don't handle it already.

---
 fs/btrfs/disk-io.c          |    8 ++-
 fs/btrfs/extent-tree.c      |   14 ++++--
 fs/btrfs/extent_io.c        |   61 ++++++++++++++++++++--------
 fs/btrfs/extent_io.h        |    8 +--
 fs/btrfs/file.c             |   10 ++--
 fs/btrfs/free-space-cache.c |    7 ++-
 fs/btrfs/inode.c            |   94 +++++++++++++++++++++++++++-----------------
 fs/btrfs/ioctl.c            |    9 ++--
 fs/btrfs/relocation.c       |    5 +-
 fs/btrfs/transaction.c      |    4 +
 fs/btrfs/tree-log.c         |    5 +-
 11 files changed, 146 insertions(+), 79 deletions(-)
fs/btrfs/disk-io.c +6 -2
@@ -2981,7 +2981,10 @@ static int btrfs_destroy_marked_extents(
 		if (ret)
 			break;
 
-		clear_extent_bits(dirty_pages, start, end, mark, GFP_NOFS);
+		ret = clear_extent_bits(dirty_pages, start, end, mark,
+					GFP_NOFS);
+		BUG_ON(ret < 0);
+		ret = 0;
 		while (start <= end) {
 			index = start >> PAGE_CACHE_SHIFT;
 			start = (u64)(index + 1) << PAGE_CACHE_SHIFT;
@@ -3042,7 +3045,8 @@ static int btrfs_destroy_pinned_extent(s
 							 end + 1 - start,
 							 NULL);
 
-		clear_extent_dirty(unpin, start, end, GFP_NOFS);
+		ret = clear_extent_dirty(unpin, start, end, GFP_NOFS);
+		BUG_ON(ret < 0);
 		btrfs_error_unpin_extent_range(root, start, end);
 		cond_resched();
 	}
fs/btrfs/extent-tree.c +9 -5
@@ -223,14 +223,17 @@ static void free_excluded_extents(struct
 				  struct btrfs_block_group_cache *cache)
 {
 	u64 start, end;
+	int ret;
 
 	start = cache->key.objectid;
 	end = start + cache->key.offset - 1;
 
-	clear_extent_bits(&root->fs_info->freed_extents[0],
-			  start, end, EXTENT_UPTODATE, GFP_NOFS);
-	clear_extent_bits(&root->fs_info->freed_extents[1],
-			  start, end, EXTENT_UPTODATE, GFP_NOFS);
+	ret = clear_extent_bits(&root->fs_info->freed_extents[0],
+				start, end, EXTENT_UPTODATE, GFP_NOFS);
+	BUG_ON(ret < 0);
+	ret = clear_extent_bits(&root->fs_info->freed_extents[1],
+				start, end, EXTENT_UPTODATE, GFP_NOFS);
+	BUG_ON(ret < 0);
 }
 
 static int exclude_super_stripes(struct btrfs_root *root,
@@ -4478,7 +4481,8 @@ int btrfs_finish_extent_commit(struct bt
 			ret = btrfs_discard_extent(root, start,
 						   end + 1 - start, NULL);
 
-		clear_extent_dirty(unpin, start, end, GFP_NOFS);
+		ret = clear_extent_dirty(unpin, start, end, GFP_NOFS);
+		BUG_ON(ret < 0);
 		unpin_extent_range(root, start, end);
 		cond_resched();
 	}
fs/btrfs/extent_io.c +43 -18

119 lines not on this page · raw message

fs/btrfs/extent_io.h +4 -4
@@ -200,10 +200,10 @@ void free_extent_state(struct extent_sta
 int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end,
 		   int bits, int filled, struct extent_state *cached_state);
 int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
-		      int bits, gfp_t mask);
+		      int bits, gfp_t mask) __must_check;
 int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
-		     int bits, int wake, int delete, struct extent_state **cached,
-		     gfp_t mask);
+		     int bits, int wake, int delete,
+		     struct extent_state **cached, gfp_t mask) __must_check;
 int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
 		    int bits, gfp_t mask) __must_check;
 int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
@@ -218,7 +218,7 @@ int set_extent_new(struct extent_io_tree
 int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
 		     gfp_t mask) __must_check;
 int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
-		       gfp_t mask);
+		       gfp_t mask) __must_check;
 int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
 		       int bits, int clear_bits, gfp_t mask);
 int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end,
fs/btrfs/file.c +6 -4
@@ -1128,10 +1128,12 @@ again:
 		if (ordered)
 			btrfs_put_ordered_extent(ordered);
 
-		clear_extent_bit(&BTRFS_I(inode)->io_tree, start_pos,
-				  last_pos - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
-				  EXTENT_DO_ACCOUNTING, 0, 0, &cached_state,
-				  GFP_NOFS);
+		err = clear_extent_bit(&BTRFS_I(inode)->io_tree, start_pos,
+				      last_pos - 1,
+				      EXTENT_DIRTY | EXTENT_DELALLOC |
+				      EXTENT_DO_ACCOUNTING, 0, 0,
+				      &cached_state, GFP_NOFS);
+		BUG_ON(err < 0);
 		unlock_extent_cached(&BTRFS_I(inode)->io_tree,
 				     start_pos, last_pos - 1, &cached_state,
 				     GFP_NOFS);
fs/btrfs/free-space-cache.c +5 -2
@@ -964,9 +964,11 @@ int __btrfs_write_out_cache(struct btrfs
 
 	ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
 	if (ret < 0) {
-		clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, inode->i_size - 1,
+		ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, 0,
+				inode->i_size - 1,
 				 EXTENT_DIRTY | EXTENT_DELALLOC, 0, 0, NULL,
 				 GFP_NOFS);
+		BUG_ON(ret < 0);
 		goto out;
 	}
 	leaf = path->nodes[0];
@@ -977,10 +979,11 @@ int __btrfs_write_out_cache(struct btrfs
 		btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
 		if (found_key.objectid != BTRFS_FREE_SPACE_OBJECTID ||
 		    found_key.offset != offset) {
-			clear_extent_bit(&BTRFS_I(inode)->io_tree, 0,
+			ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, 0,
 					 inode->i_size - 1,
 					 EXTENT_DIRTY | EXTENT_DELALLOC, 0, 0,
 					 NULL, GFP_NOFS);
+			BUG_ON(ret < 0);
 			btrfs_release_path(path);
 			goto out;
 		}
fs/btrfs/inode.c +59 -35

176 lines not on this page · raw message

fs/btrfs/ioctl.c +5 -4
@@ -932,10 +932,11 @@ again:
 	if (ordered)
 		btrfs_put_ordered_extent(ordered);
 
-	clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start,
-			  page_end - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
-			  EXTENT_DO_ACCOUNTING, 0, 0, &cached_state,
-			  GFP_NOFS);
+	ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, page_start,
+			       page_end - 1, EXTENT_DIRTY | EXTENT_DELALLOC |
+			       EXTENT_DO_ACCOUNTING, 0, 0, &cached_state,
+			       GFP_NOFS);
+	BUG_ON(ret < 0);
 
 	if (i_done != num_pages) {
 		spin_lock(&BTRFS_I(inode)->lock);
fs/btrfs/relocation.c +3 -2
@@ -3853,8 +3853,9 @@ restart:
 	}
 
 	btrfs_release_path(path);
-	clear_extent_bits(&rc->processed_blocks, 0, (u64)-1, EXTENT_DIRTY,
-			  GFP_NOFS);
+	ret = clear_extent_bits(&rc->processed_blocks, 0, (u64)-1,
+				EXTENT_DIRTY, GFP_NOFS);
+	BUG_ON(ret < 0);
 
 	if (trans) {
 		nr = trans->blocks_used;
fs/btrfs/transaction.c +3 -1
@@ -610,7 +610,9 @@ int btrfs_wait_marked_extents(struct btr
 
 	while (!find_first_extent_bit(dirty_pages, start, &start, &end,
 				      EXTENT_NEED_WAIT)) {
-		clear_extent_bits(dirty_pages, start, end, EXTENT_NEED_WAIT, GFP_NOFS);
+		err = clear_extent_bits(dirty_pages, start, end,
+				EXTENT_NEED_WAIT, GFP_NOFS);
+		BUG_ON(err < 0);
 		err = filemap_fdatawait_range(mapping, start, end);
 		if (err)
 			werr = err;
fs/btrfs/tree-log.c +3 -2
@@ -2178,8 +2178,9 @@ static void free_log_tree(struct btrfs_t
 		if (ret)
 			break;
 
-		clear_extent_bits(&log->dirty_log_pages, start, end,
-				  EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS);
+		ret = clear_extent_bits(&log->dirty_log_pages, start, end,
+					EXTENT_DIRTY | EXTENT_NEW, GFP_NOFS);
+		BUG_ON(ret < 0);
 	}
 
 	free_extent_buffer(log->node);
#8 lore raw

Re: [patch 07/66] btrfs: clear_extent_bit error push-up

Hi,

I've tested it and still crashes in xfstets/113, but this time I know what to look for :)

fs/btrfs/extent_io.h void free_extent_state(struct extent_sta · line 203

Quoted 8 lines · Jeff Mahoney
fs/btrfs/extent_io.h +1 -1
@@ -200,10 +200,10 @@ void free_extent_state(struct extent_sta
 int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end,
 		   int bits, int filled, struct extent_state *cached_state);
 int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
-		      int bits, gfp_t mask);
+		      int bits, gfp_t mask) __must_check;
                                            ^^^^^^^^^^^^

this

fs/btrfs/extent_io.h void free_extent_state(struct extent_sta · line 206

Quoted 5 lines
fs/btrfs/extent_io.h +2 -2
 int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
-		     int bits, int wake, int delete, struct extent_state **cached,
-		     gfp_t mask);
+		     int bits, int wake, int delete,
+		     struct extent_state **cached, gfp_t mask) __must_check;
                                                               ^^^^^^^^^^^^

this

fs/btrfs/extent_io.h int set_extent_new(struct extent_io_tree · line 221

Quoted 9 lines
fs/btrfs/extent_io.h +1 -1
 int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
 		    int bits, gfp_t mask) __must_check;
 int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
@@ -218,7 +218,7 @@ int set_extent_new(struct extent_io_tree
 int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
 		     gfp_t mask) __must_check;
 int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
-		       gfp_t mask);
+		       gfp_t mask) __must_check;
                                   ^^^^^^^^^^^^

shouldn't this be placed at the beginning of the prototype?

Quoted 4 lines
fs/btrfs/extent_io.h +0 -0
@@ -6250,19 +6265,23 @@ static ssize_t btrfs_direct_IO(int rw, s
 		   btrfs_submit_direct, 0);
 
 	if (ret < 0 && ret != -EIOCBQUEUED) {

fs/btrfs/extent_io.h static ssize_t btrfs_direct_IO(int rw, s · line 6273

Quoted 10 lines
fs/btrfs/extent_io.h +6 -4
-		clear_extent_bit(&BTRFS_I(inode)->io_tree, offset,
-			      offset + iov_length(iov, nr_segs) - 1,
-			      EXTENT_LOCKED | write_bits, 1, 0,
-			      &cached_state, GFP_NOFS);
+		ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, offset,
+				       offset + iov_length(iov, nr_segs) - 1,
+				       EXTENT_LOCKED | write_bits, 1, 0,
+				       &cached_state, GFP_NOFS);
+		BUG_ON(ret < 0);
+		ret = 0;
                ^^^^^^^^

this

Quoted 5 lines
fs/btrfs/extent_io.h +0 -0
 	} else if (ret >= 0 && ret < iov_length(iov, nr_segs)) {
 		/*
 		 * We're falling back to buffered, unlock the section we didn't
 		 * do IO on.
 		 */

fs/btrfs/extent_io.h static ssize_t btrfs_direct_IO(int rw, s · line 6284

Quoted 10 lines
fs/btrfs/extent_io.h +6 -4
-		clear_extent_bit(&BTRFS_I(inode)->io_tree, offset + ret,
-			      offset + iov_length(iov, nr_segs) - 1,
-			      EXTENT_LOCKED | write_bits, 1, 0,
-			      &cached_state, GFP_NOFS);
+		ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, offset + ret,
+				       offset + iov_length(iov, nr_segs) - 1,
+				       EXTENT_LOCKED | write_bits, 1, 0,
+				       &cached_state, GFP_NOFS);
+		BUG_ON(ret < 0);
+		ret = 0;
                ^^^^^^^^

and this clobber the original ret value which is returned a few lines below and used in the caller.

fs/btrfs/extent_io.h static ssize_t btrfs_direct_IO(int rw, s · line 6287

Quoted 3 lines
fs/btrfs/extent_io.h +0 -0
 	}
 out:
 	free_extent_state(cached_state);
        return ret;
}

david

#9 lore raw

Re: [patch 07/66] btrfs: clear_extent_bit error push-up

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 22 lines · David Sterba

Hi,

I've tested it and still crashes in xfstets/113, but this time I know what to look for :)

Quoted 7 lines · Jeff Mahoney

--- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -200,10 +200,10 @@ void free_extent_state(struct extent_sta int test_range_bit(struct extent_io_tree *tree, u64 start, u64 end, int bits, int filled, struct extent_state *cached_state); int clear_extent_bits(struct extent_io_tree *tree, u64 start, u64
end, - int bits, gfp_t mask); + int bits, gfp_t
mask) __must_check;

^^^^^^^^^^^^ this

Quoted 5 lines

int clear_extent_bit(struct extent_io_tree *tree, u64 start, u64
end, - int bits, int wake, int delete, struct extent_state
**cached, - gfp_t mask); + int bits, int wake, int
delete, + struct extent_state **cached, gfp_t mask)
__must_check;

^^^^^^^^^^^^ this

Quoted 10 lines

Review

Quoted 8 lines

int set_extent_bits(struct extent_io_tree *tree, u64 start, u64 end, int bits, gfp_t mask) __must_check; int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,

(quoted diff) +0 -0
@@ -218,7 +218,7 @@ int set_extent_new(struct extent_io_tree int

set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, gfp_t mask) __must_check; int clear_extent_dirty(struct
extent_io_tree *tree, u64 start, u64 end, - gfp_t mask);

(quoted diff) +1 -0
+		       gfp_t mask) __must_check;

^^^^^^^^^^^^ shouldn't this be placed at the beginning of the prototype?

I don't see why that would need to be the case. It needs to be at the beginning of the prototype if it's the actual function definition but not when it's a prototype.

Quoted 24 lines
Quoted 11 lines
fs/btrfs/inode.c +0 -0
@@ -6250,19 +6265,23 @@ static ssize_t btrfs_direct_IO(int rw, s 
 btrfs_submit_direct, 0);
 

if (ret < 0 && ret != -EIOCBQUEUED) { - clear_extent_bit(&BTRFS_I(inode)->io_tree, offset, -
offset + iov_length(iov, nr_segs) - 1, - EXTENT_LOCKED |
write_bits, 1, 0, - &cached_state, GFP_NOFS); + ret =
clear_extent_bit(&BTRFS_I(inode)->io_tree, offset, +
offset + iov_length(iov, nr_segs) - 1, + EXTENT_LOCKED
| write_bits, 1, 0, + &cached_state, GFP_NOFS); +
BUG_ON(ret < 0); + ret = 0;

^^^^^^^^ this

Quoted 9 lines

} else if (ret >= 0 && ret < iov_length(iov, nr_segs)) { /* * We're falling back to buffered, unlock the section we didn't * do
IO on. */ - clear_extent_bit(&BTRFS_I(inode)->io_tree, offset +
ret, - offset + iov_length(iov, nr_segs) - 1, -
EXTENT_LOCKED | write_bits, 1, 0, - &cached_state,
GFP_NOFS); + ret = clear_extent_bit(&BTRFS_I(inode)->io_tree,
offset + ret, + offset + iov_length(iov, nr_segs) - 1,

(quoted diff) +1 -0
+				       EXTENT_LOCKED | write_bits, 1, 0, +

&cached_state, GFP_NOFS); + BUG_ON(ret < 0); + ret = 0;

^^^^^^^^

Quoted 6 lines

and this clobber the original ret value which is returned a few lines below and used in the caller.

Quoted 1 line

} out: free_extent_state(cached_state);

return ret; }

*smack*

Ugh. You're right. It avoids the corruption but signals a short write.

- -Jeff

- --
Jeff Mahoney
SUSE Labs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.18 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQIcBAEBAgAGBQJOqCTSAAoJEB57S2MheeWyV7kP/RvVD7qI4clRtXlmw4MI7WwA xzdc6bykBe6hV3/lhXmsIW0T1ox6x2OazS7d+jp3tGcrBo8NcVuXa9hM40/YtP3y drbF3aP0eNOs35qxFTehjCh5ZZH/U8+S9EWNSklbIYKwko2hBVSV/0q7G7VFJPa/ GwzNRc+QWXTKNwwNMiONXwCMw/wDA0w2i2zsBr+Rf4HCRb4WHzslFFlqQvc9eD1b mdE6qIZBLRAkyoPyXpJeMbPRn41PSpEHuOUcKgiYA5t52+b3QNvkyNiPPHNWzIyI Bf6q8NdEnSPx1idcLTxB8Hh2cV6ITf6SQ6CGZjr1nkF/vJaNX/xip5FaAcDtyhZC UWeQP0ZiYez86Xz7J/lE/vyP47yqrz8fKRDjCQ35ylF3Ctuf8Lpqjrt8UaawAV7z VukuuBJ3IxTiUI2IXacKWwrbMO6bKC7WgMOpR/nzETHqE8H8rVKvKiI50S8v140G dNNOu5BBMw4btqd87edr/J/wXBk5xXJZ29eYkAiaPPt63rpXP+/ppakqCf+AwjyF 3gkyxrj/rYAlRvsLZ6glN3Wowqe3y8Vun9Hq3Occ1+exDtdE7/bh6tVlh1wqaNGo nZIYPXVBzqmr4ltp0FKJY5vb7MNOeh2QcbKSnSu41s7Xs4pcITyhtbVKxkgWSZlJ /YDmGztQOu64yUWWm/PR
=BlwO
-----END PGP SIGNATURE-----

#10 lore raw

Re: [patch 07/66] btrfs: clear_extent_bit error push-up

Quoted 8 lines · Jeff Mahoney
Quoted 4 lines

Review

Quoted 2 lines

extent_io_tree *tree, u64 start, u64 end, - gfp_t mask);

(quoted diff) +1 -0
+		       gfp_t mask) __must_check;

^^^^^^^^^^^^ shouldn't this be placed at the beginning of the prototype?

I don't see why that would need to be the case. It needs to be at the beginning of the prototype if it's the actual function definition but not when it's a prototype.

I'm not aware of a general recommendation, but the __must_check is related to return value and makes sense to place it there. There is no other instance of __must_check placed at the end of declaratin/definition so I'm applying the "be consistent with surrounding code" rule.

david

#11 lore raw

Re: [patch 07/66] btrfs: clear_extent_bit error push-up

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 10 lines · David Sterba
Quoted 8 lines · Jeff Mahoney
Quoted 4 lines
Quoted 2 lines

extent_io_tree *tree, u64 start, u64 end, - gfp_t
mask); + gfp_t mask) __must_check;

^^^^^^^^^^^^ shouldn't this be placed at the beginning of the prototype?

I don't see why that would need to be the case. It needs to be at the beginning of the prototype if it's the actual function definition but not when it's a prototype.

Quoted 5 lines

I'm not aware of a general recommendation, but the __must_check is related to return value and makes sense to place it there. There is no other instance of __must_check placed at the end of declaratin/definition so I'm applying the "be consistent with surrounding code" rule.

Putting it at the beginning means indenting the entire prototype, which I'm not a fan of.

- -Jeff

- --
Jeff Mahoney
SUSE Labs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.18 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQIcBAEBAgAGBQJOqDG6AAoJEB57S2MheeWyv8MP/31fGc7lYFEvmJU9OgJ0cFiU Bz5Tic3cvO/OXyvmzOvDrO3Gre6AeDB+NXkU2VkkMBOwocat9kTTcX3bzZ3pSVJr GtGAqM0x8jF4h2WGIYzuqW+oyM/Bah4a+39tPycrz21piboygJax18rEqU0+dl1x kyTzWbk4AwZJQrL205/BcXQqC+/08jluExhsUz8uTK7VDO5PO5ml11WyGY2uG4OD mLXylADCUdnd7v7azcjQ/Oa/BB5lMJ+1LIu5YsuVDHbWfDfM0PQRKNbQiwN9jqww notpLQmJuIVgU1PtV82bHnn/eRD1pJBWuTFkzWI1eg+mWgB8o03aSOTXQnoN5SR0 rdLcGnUmvZH+lwjskSbaPsiHqReW+6Pf+QhCEplNMGUFwlw+M9U2BhaCviEWMZC9 xYMFrqyvWFaBsz6FCvg/HjvaqSrOgT85yeNNhWTXtNH1J0SuEYA8USjOPoa9+TMD jDlgEogFtkmhaZQd+qPSAdna0jCxB8e/zB5/XfBAwxtfVcWtB362wlMHE/a0M59a tGt9DydF9UN6pQ7Kznx59rHS4IYND5MmBK4R9eqi5OPIFD3f4EMLU0qDemAUnmcV 2Ng9zIT6ka/RnzkecT8qg84Hg6qotQ2NL91zJ5ys8xAdUIq0gq8uhTmGD6qHVVeu pRATEdBa3477yt+ex0Wd
=53Ir
-----END PGP SIGNATURE-----

#12 lore raw

Re: [patch 07/66] btrfs: clear_extent_bit error push-up

Quoted 20 lines · Jeff Mahoney

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 10 lines · David Sterba
Quoted 8 lines · Jeff Mahoney
Quoted 4 lines
Quoted 2 lines

extent_io_tree *tree, u64 start, u64 end, - gfp_t
mask); + gfp_t mask) __must_check;

^^^^^^^^^^^^ shouldn't this be placed at the beginning of the prototype?

I don't see why that would need to be the case. It needs to be at the beginning of the prototype if it's the actual function definition but not when it's a prototype.

Quoted 5 lines

I'm not aware of a general recommendation, but the __must_check is related to return value and makes sense to place it there. There is no other instance of __must_check placed at the end of declaratin/definition so I'm applying the "be consistent with surrounding code" rule.

Quoted 4 lines

Putting it at the beginning means indenting the entire prototype, which I'm not a fan of.

- -Jeff

I think it would be much better to put it at the beginning. For one it's conventional and the rest of the kernel puts it at the beginning. The other, and much more important, thing is that it greatly confuses C indexing tools like cscope. Now you could argue that those tools' regexes should be tweaked but since it's just a matter of taste why don't put it at the beginning ?

Thanks,

Ilya

#13 lore raw

Re: [patch 07/66] btrfs: clear_extent_bit error push-up

Quoted 24 lines · Ilya Dryomov
Quoted 23 lines · Jeff Mahoney

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 10 lines · David Sterba
Quoted 8 lines · Jeff Mahoney
Quoted 4 lines
Quoted 2 lines

extent_io_tree *tree, u64 start, u64 end, - gfp_t
mask); + gfp_t mask) __must_check;

^^^^^^^^^^^^ shouldn't this be placed at the beginning of the prototype?

I don't see why that would need to be the case. It needs to be at the beginning of the prototype if it's the actual function definition but not when it's a prototype.

Quoted 5 lines

I'm not aware of a general recommendation, but the __must_check is related to return value and makes sense to place it there. There is no other instance of __must_check placed at the end of declaratin/definition so I'm applying the "be consistent with surrounding code" rule.

Putting it at the beginning means indenting the entire prototype, which I'm not a fan of.

Quoted 8 lines
Quoted 1 line

- -Jeff

I think it would be much better to put it at the beginning. For one it's conventional and the rest of the kernel puts it at the beginning. The other, and much more important, thing is that it greatly confuses C indexing tools like cscope. Now you could argue that those tools' regexes should be tweaked but since it's just a matter of taste why don't put it at the beginning ?

The rest of the kernel seems to use the beginning. I don't really have a preference, but it's good to use the same standard as the rest of the kernel.

(Sorry Jeff)

-chris

#14 lore raw

Re: [patch 07/66] btrfs: clear_extent_bit error push-up

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 34 lines · Chris Mason
Quoted 24 lines · Ilya Dryomov
Quoted 23 lines · Jeff Mahoney

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1

Quoted 11 lines · David Sterba
Quoted 8 lines · Jeff Mahoney
Quoted 4 lines
Quoted 2 lines

extent_io_tree *tree, u64 start, u64 end, -
gfp_t mask); + gfp_t mask) __must_check;

^^^^^^^^^^^^ shouldn't this be placed at the beginning of the prototype?

I don't see why that would need to be the case. It needs to be at the beginning of the prototype if it's the actual function definition but not when it's a prototype.

Quoted 5 lines

I'm not aware of a general recommendation, but the __must_check is related to return value and makes sense to place it there. There is no other instance of __must_check placed at the end of declaratin/definition so I'm applying the "be consistent with surrounding code" rule.

Putting it at the beginning means indenting the entire prototype, which I'm not a fan of.

Quoted 8 lines
Quoted 1 line

- -Jeff

I think it would be much better to put it at the beginning. For one it's conventional and the rest of the kernel puts it at the beginning. The other, and much more important, thing is that it greatly confuses C indexing tools like cscope. Now you could argue that those tools' regexes should be tweaked but since it's just a matter of taste why don't put it at the beginning ?

Quoted 5 lines

The rest of the kernel seems to use the beginning. I don't really have a preference, but it's good to use the same standard as the rest of the kernel.

(Sorry Jeff)

Ok. I'll adjust. Thanks for weighing in.

- -Jeff

- --
Jeff Mahoney
SUSE Labs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.18 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iQIcBAEBAgAGBQJOrqP5AAoJEB57S2MheeWynmgP/33qFEMZcq6AiXp+1JYBwWNu W725iBRAI1t5cnp7Pgj5Xv+2iccP14lG8dhECBR3g0+xcFI06XetE88jqd3NKPx7 vsKSAt7Txi33NkaihfUPTL07e8HiPgJ9S4MycJ5pZyLCAfmSCbd6NlenZOrsopft 7HVVZKOjDNCSPOjPFGO3NGdaOapfdEkHlImRabpxJQTCNqdrJGCN0+2to30PKQ1Z Ss2o1tmLdFt+RVSQP9jJ9+zdLnlxqjGMXpI0C103SP+T7GmUJD4XkamPfpMfXNKv tCHHepRHsqMTERjVXdyu46+Xu0jHfADYIeea/2fXi2XMy88IIsWT/UC3eyeXHaJP VmykOMnKzcw45r3v1AnAjZ2yqIEwWeGtwz1yXW8vKCALmHrrc+XyI5cRK59jSltf I/+ghDBw8SycN7e/b+82HCc68VJFoa1vBN4nvvOLrkDiraLwcMgvQvUpdS5vuvSP aqwhqMtu7qjdw+DxN7oGHEbFzdpIuiHSfAHvW7W4a/SnuRJXqzLMFgqNQ4gyjLAl 6yv/YZ+FqDC2qupZ5Nu6mZXubWI5oEF9p+E0xCTF4NHbbG1rUnnsVTU/xEmZQhcf 2VTZ8+R7g2i61WYxRj9kRZpDAi3zbhMojtN78C2y9pejHDA07FyyTp2vXnbcX7/e EnsiEPPvcxsUbPH8/osE
=aG23
-----END PGP SIGNATURE-----

#15 lore raw

Re: [patch 07/66] btrfs: clear_extent_bit error push-up

In reply to Jeff Mahoney
Quoted 10 lines · Jeff Mahoney
Quoted 6 lines

and this clobber the original ret value which is returned a few lines below and used in the caller.

Quoted 1 line

} out: free_extent_state(cached_state);

return ret; }

*smack*

Ugh. You're right. It avoids the corruption but signals a short write.

still crashes in xfstests/113 with the following fixup. so there may be more occurences of the ret value clobbering, I closely reviewed only this patch. I'll verify with just that on top.

fs/btrfs/inode.c +5 -7
@@ -6223,6 +6223,7 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
        struct extent_state *cached_state = NULL;
        u64 lockstart, lockend;
        ssize_t ret;
+       int ret2;
        int writing = rw & WRITE;
        int write_bits = 0;
        size_t count = iov_length(iov, nr_segs);
@@ -6273,7 +6274,6 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
                                     &cached_state, GFP_NOFS);
                BUG_ON(ret < 0);
                if (ret) {
-                       int ret2;
                        ret2 = clear_extent_bit(&BTRFS_I(inode)->io_tree,
                                                lockstart, lockend,
                                                EXTENT_LOCKED | write_bits,
@@ -6292,23 +6292,21 @@ static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
                   btrfs_submit_direct, 0);
 
        if (ret < 0 && ret != -EIOCBQUEUED) {
-               ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, offset,
+               ret2 = clear_extent_bit(&BTRFS_I(inode)->io_tree, offset,
                                       offset + iov_length(iov, nr_segs) - 1,
                                       EXTENT_LOCKED | write_bits, 1, 0,
                                       &cached_state, GFP_NOFS);
-               BUG_ON(ret < 0);
-               ret = 0;
+               BUG_ON(ret2 < 0);
        } else if (ret >= 0 && ret < iov_length(iov, nr_segs)) {
                /*
                 * We're falling back to buffered, unlock the section we didn't
                 * do IO on.
                 */
-               ret = clear_extent_bit(&BTRFS_I(inode)->io_tree, offset + ret,
+               ret2 = clear_extent_bit(&BTRFS_I(inode)->io_tree, offset + ret,
                                       offset + iov_length(iov, nr_segs) - 1,
                                       EXTENT_LOCKED | write_bits, 1, 0,
                                       &cached_state, GFP_NOFS);
-               BUG_ON(ret < 0);
-               ret = 0;
+               BUG_ON(ret2 < 0);
        }
 out:
        free_extent_state(cached_state);

---

stacktrace, same as every crash before:

[ 1741.840468] ------------[ cut here ]------------
[ 1741.844015] kernel BUG at drivers/scsi/scsi_lib.c:988!
[ 1741.844015] invalid opcode: 0000 [#1] SMP
[ 1741.844015] CPU 0
[ 1741.844015] Modules linked in: loop btrfs aoe
[ 1741.844015]
[ 1741.844015] Pid: 9220, comm: aio-stress Tainted: G        W   3.1.0-rc9-default+ #63 Intel Corporation Santa Rosa platform/Matanzas
[ 1741.844015] RIP: 0010:[<ffffffff815f25ef>]  [<ffffffff815f25ef>] scsi_init_sgtable+0x5f/0x70
[ 1741.844015] RSP: 0018:ffff880078cd7c18  EFLAGS: 00010006
[ 1741.844015] RAX: 0000000000000004 RBX: ffff88005d9a97d8 RCX: 00000000ffffffff
[ 1741.844015] RDX: 0000000000000008 RSI: 0000000000008000 RDI: ffff8800545eba20
[ 1741.844015] RBP: ffff880078cd7c28 R08: ffff880037a7ab38 R09: 6db6db6db6db6db7
[ 1741.844015] R10: 00000000ffffffff R11: ffff880079e1f480 R12: ffff880079e1f480
[ 1741.844015] R13: ffff880037a7ab38 R14: 0000000000000020 R15: ffff8800379d6000
[ 1741.844015] FS:  00007fc8b64cb700(0000) GS:ffff88007e400000(0000) knlGS:0000000000000000
[ 1741.844015] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[ 1741.844015] CR2: 00007fc8c45a0cf0 CR3: 00000000517af000 CR4: 00000000000006f0
[ 1741.844015] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 1741.844015] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[ 1741.844015] Process aio-stress (pid: 9220, threadinfo ffff880078cd6000, task ffff880066c24c40)
[ 1741.844015] Stack:
[ 1741.844015]  ffff88005d9a9780 ffff880079e1f480 ffff880078cd7c78 ffffffff815f284d
[ 1741.844015]  ffff88005d9a9780 ffff8800379db080 ffff880078cd7c78 ffff880079e1f480
[ 1741.844015]  ffff8800379db000 ffff880037a7ab38 ffff8800379db000 ffff8800379d6000
[ 1741.844015] Call Trace:
[ 1741.844015]  [<ffffffff815f284d>] scsi_init_io+0x3d/0x150
[ 1741.844015]  [<ffffffff815f29d9>] scsi_setup_fs_cmnd+0x79/0xe0
[ 1741.844015]  [<ffffffff81600947>] sd_prep_fn+0x157/0xe40
[ 1741.844015]  [<ffffffff8133aedc>] blk_peek_request+0xbc/0x240
[ 1741.844015]  [<ffffffff815f1f7b>] scsi_request_fn+0x5b/0x4e0
[ 1741.844015]  [<ffffffff813370bb>] queue_unplugged+0x4b/0xd0
[ 1741.844015]  [<ffffffff8133b4b5>] blk_flush_plug_list+0x1f5/0x280
[ 1741.844015]  [<ffffffff8133b558>] blk_finish_plug+0x18/0x50
[ 1741.844015]  [<ffffffff8118afe3>] do_io_submit+0x253/0x760
[ 1741.844015]  [<ffffffff8118b500>] sys_io_submit+0x10/0x20
[ 1741.844015]  [<ffffffff81a1d302>] system_call_fastpath+0x16/0x1b
[ 1741.844015] Code: 24 38 4c 89 e6 48 8b 13 e8 cf d0 d4 ff 3b 43 08 77 19 89 43 08 41 8b 44 24 54 89 43 10 31 c0 5b 41 5c c9 c3 b8 02 00 00 00 eb f4 <0f> 0b 66 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 55 48 89 e5
[ 1741.844015] RIP  [<ffffffff815f25ef>] scsi_init_sgtable+0x5f/0x70
[ 1741.844015]  RSP <ffff880078cd7c18>
[ 1742.146710] BUG: spinlock lockup on CPU#1, aio-stress/9205, ffff880037a7b1e0
[ 1742.146710] Pid: 9205, comm: aio-stress Tainted: G        W   3.1.0-rc9-default+ #63
[ 1742.146710] Call Trace:
[ 1742.146710]  [<ffffffff81362736>] do_raw_spin_lock+0xf6/0x150
[ 1742.146710]  [<ffffffff81a14106>] _raw_spin_lock+0x56/0x70
[ 1742.146710]  [<ffffffff8133b477>] ? blk_flush_plug_list+0x1b7/0x280
[ 1742.146710]  [<ffffffff8133b477>] blk_flush_plug_list+0x1b7/0x280
[ 1742.146710]  [<ffffffff8133b558>] blk_finish_plug+0x18/0x50
[ 1742.146710]  [<ffffffff8118afe3>] do_io_submit+0x253/0x760
[ 1742.146710]  [<ffffffff8118b500>] sys_io_submit+0x10/0x20
[ 1742.146710]  [<ffffffff81a1d302>] system_call_fastpath+0x16/0x1b
[ 1742.149745] BUG: spinlock lockup on CPU#0, btrfs-submit-0/9187, ffff880037a7b1e0
[ 1742.149745] Pid: 9187, comm: btrfs-submit-0 Tainted: G        W   3.1.0-rc9-default+ #63
[ 1742.149745] Call Trace:
[ 1742.149745]  [<ffffffff81362736>] do_raw_spin_lock+0xf6/0x150
[ 1742.149745]  [<ffffffff81a1486f>] ? _raw_spin_lock_irq+0x1f/0x80
[ 1742.149745]  [<ffffffff81a148b2>] _raw_spin_lock_irq+0x62/0x80
[ 1742.149745]  [<ffffffff8133b784>] ? __make_request+0x1f4/0x330
[ 1742.149745]  [<ffffffff8133b784>] __make_request+0x1f4/0x330
[ 1742.149745]  [<ffffffff8133778d>] generic_make_request+0x1cd/0x520
[ 1742.149745]  [<ffffffff81092952>] ? print_lock_contention_bug+0x22/0xf0
[ 1742.149745]  [<ffffffff81337b5a>] submit_bio+0x7a/0xf0
[ 1742.149745]  [<ffffffff8136283e>] ? do_raw_spin_unlock+0x5e/0xb0
[ 1742.149745]  [<ffffffffa005cc84>] run_scheduled_bios+0x264/0x550 [btrfs]
[ 1742.149745]  [<ffffffffa005cf85>] pending_bios_fn+0x15/0x20 [btrfs]
[ 1742.149745]  [<ffffffffa0063f54>] worker_loop+0xb4/0x500 [btrfs]
[ 1742.149745]  [<ffffffffa0063ea0>] ? btrfs_queue_worker+0x340/0x340 [btrfs]
[ 1742.149745]  [<ffffffff8107cf26>] kthread+0xa6/0xb0
[ 1742.149745]  [<ffffffff81a1e584>] kernel_thread_helper+0x4/0x10
[ 1742.149745]  [<ffffffff81a14eb4>] ? retint_restore_args+0x13/0x13
[ 1742.149745]  [<ffffffff8107ce80>] ? __init_kthread_worker+0x70/0x70
[ 1742.149745]  [<ffffffff81a1e580>] ? gs_change+0x13/0x13
#16 lore raw

Re: [patch 07/66] btrfs: clear_extent_bit error push-up

Quoted 3 lines · David Sterba

still crashes in xfstests/113 with the following fixup. so there may be more occurences of the ret value clobbering, I closely reviewed only this patch. I'll verify with just that on top.

So it did not crash (though I've hit the NULL-deref in btrfs_print_leaf), but no errors related to clear_extent_bit.

david

#17 lore raw

Re: [patch 07/66] btrfs: clear_extent_bit error push-up [other BUG hit]

[18300.906594] ------------[ cut here ]------------
[18300.910518] kernel BUG at fs/btrfs/inode.c:1592!
[18300.910518] invalid opcode: 0000 [#1] SMP
[18300.910518] CPU 1
[18300.910518] Modules linked in: btrfs loop aoe [last unloaded: btrfs]
[18300.910518]
[18300.910518] Pid: 1853, comm: btrfs-fixup-0 Tainted: G        W   3.1.0-rc9-default+ #63 Intel Corporation Santa Rosa platform/Matanzas
[18300.910518] RIP: 0010:[<ffffffffa017a8f2>]  [<ffffffffa017a8f2>] btrfs_writepage_fixup_worker+0x152/0x160 [btrfs]
[18300.910518] RSP: 0018:ffff880000095da0  EFLAGS: 00010246
[18300.910518] RAX: 0000000000000000 RBX: ffff88007d8894f8 RCX: ffff880075e3a928
[18300.910518] RDX: 0000000000005958 RSI: 0000000000000001 RDI: ffff8800431fbad8
[18300.910518] RBP: ffff880000095df0 R08: 0000000000000000 R09: 0000000000000000
[18300.910518] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000306000
[18300.910518] R13: ffff8800431fbbe8 R14: 0000000000000000 R15: 0000000000306fff
[18300.910518] FS:  0000000000000000(0000) GS:ffff88007e600000(0000) knlGS:0000000000000000
[18300.910518] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[18300.910518] CR2: 00007fe2024f9000 CR3: 0000000064037000 CR4: 00000000000006e0
[18300.910518] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[18300.910518] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
[18300.910518] Process btrfs-fixup-0 (pid: 1853, threadinfo ffff880000094000, task ffff88000e3f4d80)
[18300.910518] Stack:
[18300.910518]  ffff88007947fbc0 ffff8800431fb8b0 ffff88007940b190 ffff8800689b7c38
[18300.910518]  ffff880000095dd0 ffff88007940b140 ffff88007947fbf0 ffff88007940b158
[18300.910518]  ffff880000095e40 ffff88007940b190 ffff880000095ea0 ffffffffa01a1e34
[18300.910518] Call Trace:
[18300.910518]  [<ffffffffa01a1e34>] worker_loop+0xb4/0x520 [btrfs]
[18300.910518]  [<ffffffffa01a1d80>] ? btrfs_queue_worker+0x330/0x330 [btrfs]
[18300.910518]  [<ffffffff8107cf26>] kthread+0xa6/0xb0
[18300.910518]  [<ffffffff81a1e584>] kernel_thread_helper+0x4/0x10
[18300.910518]  [<ffffffff81a146e0>] ? _raw_spin_unlock_irq+0x30/0x40
[18300.910518]  [<ffffffff81097c7d>] ? trace_hardirqs_on+0xd/0x10
[18300.910518]  [<ffffffff81a14eb4>] ? retint_restore_args+0x13/0x13
[18300.910518]  [<ffffffff8107ce80>] ? __init_kthread_worker+0x70/0x70
[18300.910518]  [<ffffffff81a1e580>] ? gs_change+0x13/0x13
[18300.910518] Code: 00 48 8b 7d b8 48 8d 4d c8 41 b8 50 00 00 00 4c 89 fa 4c 89 e6 e8 6f a3 01 00 eb b6 0f 0b 48 89 df e8 b3 dd f7 e0 0f 1f 00 eb 95 <0f> 0b 66 66 66 2e 0f 1f 84 00 00 00 00 00 55 48 89 e5 41 57 41
[18300.910518] RIP  [<ffffffffa017a8f2>] btrfs_writepage_fixup_worker+0x152/0x160 [btrfs]
[18300.910518]  RSP <ffff880000095da0>
[18301.262194] ---[ end trace de089b9ceb00d1b9 ]---

1583 ordered = btrfs_lookup_ordered_extent(inode, page_start);
1584 if (ordered) {
1585 unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start,
1586 page_end, &cached_state, GFP_NOFS);

1587                 unlock_page(page);
1588                 btrfs_start_ordered_extent(inode, ordered, 1);
1589                 goto again;

1590 }
1591
1592 BUG();

1593 ret = btrfs_set_extent_delalloc(inode, page_start, page_end,
1594 &cached_state);
1595 BUG_ON(ret < 0);
1596 ClearPageChecked(page);
1597 out:
1598 unlock_extent_cached(&BTRFS_I(inode)->io_tree, page_start, page_end,
1599 &cached_state, GFP_NOFS);
1600 out_page:

1601         unlock_page(page);
1602         page_cache_release(page);
1603         kfree(fixup);

1604 }

during xfstests/209 (and 10 seconds after I sent the previous mail of course).

david

#18 lore raw

PATCH 8/66 btrfs: convert_extent_bit error push-up

In reply to Jeff Mahoney

convert_extent_bit can fail with -ENOMEM but nothing actually catches the errors.

This patch catches the error with BUG_ON in the caller.

---
 fs/btrfs/extent_io.h   |    2 +-
 fs/btrfs/transaction.c |    5 +++--
 2 files changed, 4 insertions(+), 3 deletions(-)
fs/btrfs/extent_io.h +1 -1
@@ -220,7 +220,7 @@ int set_extent_dirty(struct extent_io_tr
 int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
 		       gfp_t mask) __must_check;
 int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
-		       int bits, int clear_bits, gfp_t mask);
+		       int bits, int clear_bits, gfp_t mask) __must_check;
 int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end,
 			struct extent_state **cached_state, gfp_t mask);
 int find_first_extent_bit(struct extent_io_tree *tree, u64 start,
fs/btrfs/transaction.c +3 -2
@@ -580,8 +580,9 @@ int btrfs_write_marked_extents(struct bt
 
 	while (!find_first_extent_bit(dirty_pages, start, &start, &end,
 				      mark)) {
-		convert_extent_bit(dirty_pages, start, end, EXTENT_NEED_WAIT, mark,
-				   GFP_NOFS);
+		err = convert_extent_bit(dirty_pages, start, end,
+					 EXTENT_NEED_WAIT, mark, GFP_NOFS);
+		BUG_ON(err < 0);
 		err = filemap_fdatawrite_range(mapping, start, end);
 		if (err)
 			werr = err;
#19 lore raw

PATCH 9/66 btrfs: unlock_extent error push-up

In reply to Jeff Mahoney

The previous patch pushed the clear_extent_bit error handling up a level, which included unlock_extent and unlock_extent_cache.

This patch pushes the BUG_ON up into the callers of those functions.

---
 fs/btrfs/compression.c      |    6 +-
 fs/btrfs/disk-io.c          |    7 +--
 fs/btrfs/extent_io.c        |   52 +++++++++++++----------
 fs/btrfs/extent_io.h        |    6 +-
 fs/btrfs/file.c             |   35 ++++++++-------
 fs/btrfs/free-space-cache.c |    9 ++--
 fs/btrfs/inode.c            |   98 ++++++++++++++++++++++++++------------------
 fs/btrfs/ioctl.c            |   26 +++++++----
 fs/btrfs/relocation.c       |   24 +++++++---
 9 files changed, 159 insertions(+), 104 deletions(-)
fs/btrfs/compression.c +4 -2
@@ -507,7 +507,8 @@ static noinline int add_ra_bio_pages(str
 		    (last_offset + PAGE_CACHE_SIZE > extent_map_end(em)) ||
 		    (em->block_start >> 9) != cb->orig_bio->bi_sector) {
 			free_extent_map(em);
-			unlock_extent(tree, last_offset, end, GFP_NOFS);
+			ret = unlock_extent(tree, last_offset, end, GFP_NOFS);
+			BUG_ON(ret < 0);
 			unlock_page(page);
 			page_cache_release(page);
 			break;
@@ -535,7 +536,8 @@ static noinline int add_ra_bio_pages(str
 			nr_pages++;
 			page_cache_release(page);
 		} else {
-			unlock_extent(tree, last_offset, end, GFP_NOFS);
+			ret = unlock_extent(tree, last_offset, end, GFP_NOFS);
+			BUG_ON(ret < 0);
 			unlock_page(page);
 			page_cache_release(page);
 			break;
fs/btrfs/disk-io.c +4 -3
@@ -326,7 +326,7 @@ static int verify_parent_transid(struct
 				 struct extent_buffer *eb, u64 parent_transid)
 {
 	struct extent_state *cached_state = NULL;
-	int ret;
+	int ret, err;
 
 	if (!parent_transid || btrfs_header_generation(eb) == parent_transid)
 		return 0;
@@ -347,8 +347,9 @@ static int verify_parent_transid(struct
 	ret = 1;
 	clear_extent_buffer_uptodate(io_tree, eb, &cached_state);
 out:
-	unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1,
-			     &cached_state, GFP_NOFS);
+	err = unlock_extent_cached(io_tree, eb->start, eb->start + eb->len - 1,
+				   &cached_state, GFP_NOFS);
+	BUG_ON(err < 0);
 	return ret;
 }
 
fs/btrfs/extent_io.c +30 -22

122 lines not on this page · raw message

fs/btrfs/extent_io.h +4 -2
@@ -182,9 +182,11 @@ int lock_extent(struct extent_io_tree *t
 int lock_extent_bits(struct extent_io_tree *tree, u64 start, u64 end,
 		     int bits, struct extent_state **cached, gfp_t mask)
 		     __must_check;
-int unlock_extent(struct extent_io_tree *tree, u64 start, u64 end, gfp_t mask);
+int unlock_extent(struct extent_io_tree *tree, u64 start, u64 end, gfp_t mask)
+		  __must_check;
 int unlock_extent_cached(struct extent_io_tree *tree, u64 start, u64 end,
-			 struct extent_state **cached, gfp_t mask);
+			 struct extent_state **cached, gfp_t mask)
+			 __must_check;
 int try_lock_extent(struct extent_io_tree *tree, u64 start, u64 end,
 		    gfp_t mask) __must_check;
 int extent_read_full_page(struct extent_io_tree *tree, struct page *page,
fs/btrfs/file.c +20 -15
@@ -1114,9 +1114,10 @@ again:
 		    ordered->file_offset + ordered->len > start_pos &&
 		    ordered->file_offset < last_pos) {
 			btrfs_put_ordered_extent(ordered);
-			unlock_extent_cached(&BTRFS_I(inode)->io_tree,
-					     start_pos, last_pos - 1,
-					     &cached_state, GFP_NOFS);
+			err = unlock_extent_cached(&BTRFS_I(inode)->io_tree,
+						   start_pos, last_pos - 1,
+						   &cached_state, GFP_NOFS);
+			BUG_ON(err < 0);
 			for (i = 0; i < num_pages; i++) {
 				unlock_page(pages[i]);
 				page_cache_release(pages[i]);
@@ -1134,9 +1135,10 @@ again:
 				      EXTENT_DO_ACCOUNTING, 0, 0,
 				      &cached_state, GFP_NOFS);
 		BUG_ON(err < 0);
-		unlock_extent_cached(&BTRFS_I(inode)->io_tree,
-				     start_pos, last_pos - 1, &cached_state,
-				     GFP_NOFS);
+		err = unlock_extent_cached(&BTRFS_I(inode)->io_tree,
+					   start_pos, last_pos - 1,
+					   &cached_state, GFP_NOFS);
+		BUG_ON(err < 0);
 	}
 	for (i = 0; i < num_pages; i++) {
 		clear_page_dirty_for_io(pages[i]);
@@ -1592,7 +1594,7 @@ static long btrfs_fallocate(struct file
 	u64 locked_end;
 	u64 mask = BTRFS_I(inode)->root->sectorsize - 1;
 	struct extent_map *em;
-	int ret;
+	int ret, err;
 
 	alloc_start = offset & ~mask;
 	alloc_end =  (offset + len + mask) & ~mask;
@@ -1635,9 +1637,10 @@ static long btrfs_fallocate(struct file
 		    ordered->file_offset + ordered->len > alloc_start &&
 		    ordered->file_offset < alloc_end) {
 			btrfs_put_ordered_extent(ordered);
-			unlock_extent_cached(&BTRFS_I(inode)->io_tree,
-					     alloc_start, locked_end,
-					     &cached_state, GFP_NOFS);
+			ret = unlock_extent_cached(&BTRFS_I(inode)->io_tree,
+						   alloc_start, locked_end,
+						   &cached_state, GFP_NOFS);
+			BUG_ON(ret < 0);
 			/*
 			 * we can't wait on the range with the transaction
 			 * running or with the extent lock held
@@ -1709,8 +1712,9 @@ static long btrfs_fallocate(struct file
 			break;
 		}
 	}
-	unlock_extent_cached(&BTRFS_I(inode)->io_tree, alloc_start, locked_end,
-			     &cached_state, GFP_NOFS);
+	err = unlock_extent_cached(&BTRFS_I(inode)->io_tree, alloc_start,
+				   locked_end, &cached_state, GFP_NOFS);
+	BUG_ON(err < 0);
 out:
 	mutex_unlock(&inode->i_mutex);
 	return ret;
@@ -1727,7 +1731,7 @@ static int find_desired_extent(struct in
 	u64 orig_start = *offset;
 	u64 len = i_size_read(inode);
 	u64 last_end = 0;
-	int ret = 0;
+	int ret = 0, err;
 
 	lockend = max_t(u64, root->sectorsize, lockend);
 	if (lockend <= lockstart)
@@ -1823,8 +1827,9 @@ static int find_desired_extent(struct in
 	if (!ret)
 		*offset = min(*offset, inode->i_size);
 out:
-	unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend,
-			     &cached_state, GFP_NOFS);
+	err = unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend,
+				   &cached_state, GFP_NOFS);
+	BUG_ON(err < 0);
 	return ret;
 }
 
fs/btrfs/free-space-cache.c +5 -4
@@ -821,7 +821,7 @@ int __btrfs_write_out_cache(struct btrfs
 	u64 start, end, len;
 	int entries = 0;
 	int bitmaps = 0;
-	int ret;
+	int ret, ret2;
 	int err = -1;
 
 	INIT_LIST_HEAD(&bitmap_list);
@@ -947,13 +947,13 @@ int __btrfs_write_out_cache(struct btrfs
 	ret = btrfs_dirty_pages(root, inode, io_ctl.pages, io_ctl.num_pages,
 				0, i_size_read(inode), &cached_state);
 	io_ctl_drop_pages(&io_ctl);
-	unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
+	ret2 = unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
 			     i_size_read(inode) - 1, &cached_state, GFP_NOFS);
+	BUG_ON(ret2 < 0);
 
 	if (ret)
 		goto out;
 
-
 	ret = filemap_write_and_wait(inode->i_mapping);
 	if (ret)
 		goto out;
@@ -1015,8 +1015,9 @@ out_nospc:
 		list_del_init(&entry->list);
 	}
 	io_ctl_drop_pages(&io_ctl);
-	unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
+	ret2 = unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
 			     i_size_read(inode) - 1, &cached_state, GFP_NOFS);
+	BUG_ON(ret2 < 0);
 	goto out;
 }
 
fs/btrfs/inode.c +60 -38

224 lines not on this page · raw message

fs/btrfs/ioctl.c +16 -10
@@ -786,7 +786,8 @@ static int should_defrag_range(struct in
 		err = lock_extent(io_tree, start, start + len - 1, GFP_NOFS);
 		BUG_ON(err < 0);
 		em = btrfs_get_extent(inode, NULL, 0, start, len, 0);
-		unlock_extent(io_tree, start, start + len - 1, GFP_NOFS);
+		err = unlock_extent(io_tree, start, start + len - 1, GFP_NOFS);
+		BUG_ON(err < 0);
 
 		if (IS_ERR(em))
 			return 0;
@@ -918,9 +919,10 @@ again:
 	    ordered->file_offset + ordered->len > page_start &&
 	    ordered->file_offset < page_end) {
 		btrfs_put_ordered_extent(ordered);
-		unlock_extent_cached(&BTRFS_I(inode)->io_tree,
-				     page_start, page_end - 1,
-				     &cached_state, GFP_NOFS);
+		ret = unlock_extent_cached(&BTRFS_I(inode)->io_tree,
+					   page_start, page_end - 1,
+					   &cached_state, GFP_NOFS);
+		BUG_ON(ret < 0);
 		for (i = 0; i < i_done; i++) {
 			unlock_page(pages[i]);
 			page_cache_release(pages[i]);
@@ -951,9 +953,10 @@ again:
 					&cached_state);
 	BUG_ON(ret < 0);
 
-	unlock_extent_cached(&BTRFS_I(inode)->io_tree,
-			     page_start, page_end - 1, &cached_state,
-			     GFP_NOFS);
+	ret = unlock_extent_cached(&BTRFS_I(inode)->io_tree,
+				   page_start, page_end - 1, &cached_state,
+				   GFP_NOFS);
+	BUG_ON(ret < 0);
 
 	for (i = 0; i < i_done; i++) {
 		clear_page_dirty_for_io(pages[i]);
@@ -2145,7 +2148,7 @@ static noinline long btrfs_ioctl_clone(s
 	struct btrfs_key key;
 	u32 nritems;
 	int slot;
-	int ret;
+	int ret, err;
 	u64 len = olen;
 	u64 bs = root->fs_info->sb->s_blocksize;
 	u64 hint_byte;
@@ -2257,7 +2260,9 @@ static noinline long btrfs_ioctl_clone(s
 		    !test_range_bit(&BTRFS_I(src)->io_tree, off, off+len,
 				   EXTENT_DELALLOC, 0, NULL))
 			break;
-		unlock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS);
+		ret = unlock_extent(&BTRFS_I(src)->io_tree, off,
+				    off+len, GFP_NOFS);
+		BUG_ON(ret < 0);
 		if (ordered)
 			btrfs_put_ordered_extent(ordered);
 		btrfs_wait_ordered_range(src, off, len);
@@ -2475,7 +2480,8 @@ next:
 	ret = 0;
 out:
 	btrfs_release_path(path);
-	unlock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS);
+	err = unlock_extent(&BTRFS_I(src)->io_tree, off, off+len, GFP_NOFS);
+	BUG_ON(err < 0);
 out_unlock:
 	mutex_unlock(&src->i_mutex);
 	mutex_unlock(&inode->i_mutex);
fs/btrfs/relocation.c +16 -8
@@ -1602,8 +1602,9 @@ int replace_file_extents(struct btrfs_tr
 
 				btrfs_drop_extent_cache(inode, key.offset, end,
 							1);
-				unlock_extent(&BTRFS_I(inode)->io_tree,
-					      key.offset, end, GFP_NOFS);
+				ret = unlock_extent(&BTRFS_I(inode)->io_tree,
+						    key.offset, end, GFP_NOFS);
+				BUG_ON(ret < 0);
 			}
 		}
 
@@ -1977,7 +1978,9 @@ static int invalidate_extent_cache(struc
 				  GFP_NOFS);
 		BUG_ON(ret < 0);
 		btrfs_drop_extent_cache(inode, start, end, 1);
-		unlock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+		ret = unlock_extent(&BTRFS_I(inode)->io_tree, start, end,
+				    GFP_NOFS);
+		BUG_ON(ret < 0);
 	}
 	return 0;
 }
@@ -2880,6 +2883,7 @@ int prealloc_file_extent_cluster(struct
 		goto out;
 
 	while (nr < cluster->nr) {
+		int err;
 		start = cluster->boundary[nr] - offset;
 		if (nr + 1 < cluster->nr)
 			end = cluster->boundary[nr + 1] - 1 - offset;
@@ -2893,7 +2897,9 @@ int prealloc_file_extent_cluster(struct
 		ret = btrfs_prealloc_file_range(inode, 0, start,
 						num_bytes, num_bytes,
 						end + 1, &alloc_hint);
-		unlock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+		err = unlock_extent(&BTRFS_I(inode)->io_tree, start, end,
+				    GFP_NOFS);
+		BUG_ON(err < 0);
 		if (ret)
 			break;
 		nr++;
@@ -2912,7 +2918,7 @@ int setup_extent_mapping(struct inode *i
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 	struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
 	struct extent_map *em;
-	int ret = 0;
+	int ret = 0, err;
 
 	em = alloc_extent_map();
 	if (!em)
@@ -2937,7 +2943,8 @@ int setup_extent_mapping(struct inode *i
 		}
 		btrfs_drop_extent_cache(inode, start, end, 0);
 	}
-	unlock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+	err = unlock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+	BUG_ON(err < 0);
 	return ret;
 }
 
@@ -3037,8 +3044,9 @@ static int relocate_file_extent_cluster(
 		BUG_ON(ret < 0);
 		set_page_dirty(page);
 
-		unlock_extent(&BTRFS_I(inode)->io_tree,
-			      page_start, page_end, GFP_NOFS);
+		ret = unlock_extent(&BTRFS_I(inode)->io_tree,
+				    page_start, page_end, GFP_NOFS);
+		BUG_ON(ret < 0);
 		unlock_page(page);
 		page_cache_release(page);
 
#20 lore raw

PATCH 10/66 btrfs: pin_down_extent should return void

In reply to Jeff Mahoney

pin_down_extent performs some operations which can't fail and then calls set_extent_dirty, which has two failure cases via set_extent_bit:
1) Return -EEXIST if exclusive bits are set
- Since it doesn't use any exclusive bits, this failure case can't occur.
2) Return -ENOMEM if memory can't be allocated
- Since it's called with gfp_flags & __GFP_NOFAIL, this failure case can't occur.

With no failure cases, it should return void.

---
 fs/btrfs/extent-tree.c |    8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)
fs/btrfs/extent-tree.c +3 -5
@@ -4290,9 +4290,9 @@ static u64 first_logical_byte(struct btr
 	return bytenr;
 }
 
-static int pin_down_extent(struct btrfs_root *root,
-			   struct btrfs_block_group_cache *cache,
-			   u64 bytenr, u64 num_bytes, int reserved)
+static void pin_down_extent(struct btrfs_root *root,
+			    struct btrfs_block_group_cache *cache,
+			    u64 bytenr, u64 num_bytes, int reserved)
 {
 	int ret;
 
@@ -4311,8 +4311,6 @@ static int pin_down_extent(struct btrfs_
 			       bytenr + num_bytes - 1,
 			       GFP_NOFS | __GFP_NOFAIL);
 	BUG_ON(ret < 0); /* __GFP_NOFAIL means it can't return -ENOMEM */
-
-	return 0;
 }
 
 /*
#21 lore raw

PATCH 11/66 btrfs: btrfs_pin_extent error push-up

In reply to Jeff Mahoney

btrfs_pin_extent looks up a block group and then calls pin_down_extent with it. If the lookup fails, it should return -ENOENT to allow callers to handle the error condition. For the three existing callers, it is a logic error if the lookup fails and a panic will occur.

---
 fs/btrfs/ctree.h       |    2 +-
 fs/btrfs/extent-tree.c |   20 +++++++++++++++-----
 fs/btrfs/tree-log.c    |   10 +++++++---
 3 files changed, 23 insertions(+), 9 deletions(-)
fs/btrfs/ctree.h +1 -1
@@ -2156,7 +2156,7 @@ int btrfs_lookup_extent_info(struct btrf
 			     struct btrfs_root *root, u64 bytenr,
 			     u64 num_bytes, u64 *refs, u64 *flags);
 int btrfs_pin_extent(struct btrfs_root *root,
-		     u64 bytenr, u64 num, int reserved);
+		     u64 bytenr, u64 num, int reserved) __must_check;
 int btrfs_cross_ref_exist(struct btrfs_trans_handle *trans,
 			  struct btrfs_root *root,
 			  u64 objectid, u64 offset, u64 bytenr);
fs/btrfs/extent-tree.c +15 -5
@@ -2100,8 +2100,14 @@ static int run_one_delayed_ref(struct bt
 		BUG_ON(extent_op);
 		head = btrfs_delayed_node_to_head(node);
 		if (insert_reserved) {
-			btrfs_pin_extent(root, node->bytenr,
-					 node->num_bytes, 1);
+			ret = btrfs_pin_extent(root, node->bytenr,
+					       node->num_bytes, 1);
+			if (ret)
+				btrfs_panic(root->fs_info, ret,
+					    "Cannot pin extent in range "
+					    "%llu(%llu)\n",
+					    node->bytenr, node->num_bytes);
+
 			if (head->is_data) {
 				ret = btrfs_del_csums(trans, root,
 						      node->bytenr,
@@ -4322,7 +4328,8 @@ int btrfs_pin_extent(struct btrfs_root *
 	struct btrfs_block_group_cache *cache;
 
 	cache = btrfs_lookup_block_group(root->fs_info, bytenr);
-	BUG_ON(!cache);
+	if (cache == NULL)
+		return -ENOENT;
 
 	pin_down_extent(root, cache, bytenr, num_bytes, reserved);
 
@@ -4818,8 +4825,11 @@ int btrfs_free_extent(struct btrfs_trans
 	if (root_objectid == BTRFS_TREE_LOG_OBJECTID) {
 		WARN_ON(owner >= BTRFS_FIRST_FREE_OBJECTID);
 		/* unlocks the pinned mutex */
-		btrfs_pin_extent(root, bytenr, num_bytes, 1);
-		ret = 0;
+		ret = btrfs_pin_extent(root, bytenr, num_bytes, 1);
+		if (ret)
+			btrfs_panic(root->fs_info, ret, "Cannot pin "
+				    "extent in range %llu(%llu)\n",
+				    bytenr, num_bytes);
 	} else if (owner < BTRFS_FIRST_FREE_OBJECTID) {
 		ret = btrfs_add_delayed_tree_ref(trans, bytenr, num_bytes,
 					parent, root_objectid, (int)owner,
fs/btrfs/tree-log.c +7 -3
@@ -275,9 +275,13 @@ static int process_one_buffer(struct btr
 			      struct extent_buffer *eb,
 			      struct walk_control *wc, u64 gen)
 {
-	if (wc->pin)
-		btrfs_pin_extent(log->fs_info->extent_root,
-				 eb->start, eb->len, 0);
+	if (wc->pin) {
+		int ret = btrfs_pin_extent(log->fs_info->extent_root,
+					   eb->start, eb->len, 0);
+		if (ret)
+			btrfs_panic(log->fs_info, ret, "Cannot pin extent in "
+				    "range %llu(%llu)\n", eb->start, eb->len);
+	}
 
 	if (btrfs_buffer_uptodate(eb, gen)) {
 		if (wc->write)
#22 lore raw

PATCH 12/66 btrfs: btrfs_drop_snapshot should return int

In reply to Jeff Mahoney

Commit cb1b69f4 (Btrfs: forced readonly when btrfs_drop_snapshot() fails) made btrfs_drop_snapshot return void because there were no callers checking the return value. That is the wrong order to handle error propogation since the caller will have no idea that an error has occured and continue on as if nothing went wrong.

---
 fs/btrfs/ctree.h       |    5 +++--
 fs/btrfs/extent-tree.c |    6 +++---
 fs/btrfs/relocation.c  |    3 ++-
 fs/btrfs/transaction.c |    7 +++++--
 4 files changed, 13 insertions(+), 8 deletions(-)
fs/btrfs/ctree.h +3 -2
@@ -2367,8 +2367,9 @@ static inline int btrfs_insert_empty_ite
 int btrfs_next_leaf(struct btrfs_root *root, struct btrfs_path *path);
 int btrfs_prev_leaf(struct btrfs_root *root, struct btrfs_path *path);
 int btrfs_leaf_free_space(struct btrfs_root *root, struct extent_buffer *leaf);
-void btrfs_drop_snapshot(struct btrfs_root *root,
-			 struct btrfs_block_rsv *block_rsv, int update_ref);
+int btrfs_drop_snapshot(struct btrfs_root *root,
+			struct btrfs_block_rsv *block_rsv, int update_ref)
+			__must_check;
 int btrfs_drop_subtree(struct btrfs_trans_handle *trans,
 			struct btrfs_root *root,
 			struct extent_buffer *node,
fs/btrfs/extent-tree.c +3 -3
@@ -6347,8 +6347,8 @@ static noinline int walk_up_tree(struct
  * also make sure backrefs for the shared block and all lower level
  * blocks are properly updated.
  */
-void btrfs_drop_snapshot(struct btrfs_root *root,
-			 struct btrfs_block_rsv *block_rsv, int update_ref)
+int btrfs_drop_snapshot(struct btrfs_root *root,
+			struct btrfs_block_rsv *block_rsv, int update_ref)
 {
 	struct btrfs_path *path;
 	struct btrfs_trans_handle *trans;
@@ -6513,7 +6513,7 @@ out_free:
 out:
 	if (err)
 		btrfs_std_error(root->fs_info, err);
-	return;
+	return err;
 }
 
 /*
fs/btrfs/relocation.c +2 -1
@@ -2269,7 +2269,8 @@ again:
 		} else {
 			list_del_init(&reloc_root->root_list);
 		}
-		btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0);
+		ret = btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0);
+		BUG_ON(ret < 0);
 	}
 
 	if (found) {
fs/btrfs/transaction.c +5 -2
@@ -1375,6 +1375,8 @@ int btrfs_clean_old_snapshots(struct btr
 	spin_unlock(&fs_info->trans_lock);
 
 	while (!list_empty(&list)) {
+		int ret;
+
 		root = list_entry(list.next, struct btrfs_root, root_list);
 		list_del(&root->root_list);
 
@@ -1382,9 +1384,10 @@ int btrfs_clean_old_snapshots(struct btr
 
 		if (btrfs_header_backref_rev(root->node) <
 		    BTRFS_MIXED_BACKREF_REV)
-			btrfs_drop_snapshot(root, NULL, 0);
+			ret = btrfs_drop_snapshot(root, NULL, 0);
 		else
-			btrfs_drop_snapshot(root, NULL, 1);
+			ret = btrfs_drop_snapshot(root, NULL, 1);
+		BUG_ON(ret < 0);
 	}
 	return 0;
 }
#23 lore raw

PATCH 13/66 btrfs: btrfs_start_transaction non-looped error push-up

In reply to Jeff Mahoney

This patch handles btrfs_start_transaction failures that don't occur in a loop and are obvious to simply push up. In all cases except the mark_garbage_root case, the error is already handled by BUG_ON in the caller.

---
 fs/btrfs/extent-tree.c |    6 +++++-
 fs/btrfs/relocation.c  |    6 ++++--
 fs/btrfs/tree-log.c    |    5 ++++-
 fs/btrfs/volumes.c     |    3 ++-
 4 files changed, 15 insertions(+), 5 deletions(-)
fs/btrfs/extent-tree.c +5 -1
@@ -6374,7 +6374,11 @@ int btrfs_drop_snapshot(struct btrfs_roo
 	}
 
 	trans = btrfs_start_transaction(tree_root, 0);
-	BUG_ON(IS_ERR(trans));
+	if (IS_ERR(trans)) {
+		kfree(wc);
+		btrfs_free_path(path);
+		return PTR_ERR(trans);
+	}
 
 	if (block_rsv)
 		trans->block_rsv = block_rsv;
fs/btrfs/relocation.c +4 -2
@@ -4118,7 +4118,8 @@ static noinline_for_stack int mark_garba
 	int ret;
 
 	trans = btrfs_start_transaction(root->fs_info->tree_root, 0);
-	BUG_ON(IS_ERR(trans));
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
 
 	memset(&root->root_item.drop_progress, 0,
 		sizeof(root->root_item.drop_progress));
@@ -4198,7 +4199,8 @@ int btrfs_recover_relocation(struct btrf
 					err = ret;
 					goto out;
 				}
-				mark_garbage_root(reloc_root);
+				ret = mark_garbage_root(reloc_root);
+				BUG_ON(ret);
 			}
 		}
 
fs/btrfs/tree-log.c +4 -1
@@ -3171,7 +3171,10 @@ int btrfs_recover_log_trees(struct btrfs
 	fs_info->log_root_recovering = 1;
 
 	trans = btrfs_start_transaction(fs_info->tree_root, 0);
-	BUG_ON(IS_ERR(trans));
+	if (IS_ERR(trans)) {
+		btrfs_free_path(path);
+		return PTR_ERR(trans);
+	}
 
 	wc.trans = trans;
 	wc.pin = 1;
fs/btrfs/volumes.c +2 -1
@@ -1932,7 +1932,8 @@ static int btrfs_relocate_chunk(struct b
 		return ret;
 
 	trans = btrfs_start_transaction(root, 0);
-	BUG_ON(IS_ERR(trans));
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
 
 	lock_chunks(root);
 
#24 lore raw

PATCH 14/66 btrfs: find_and_setup_root error push-up

In reply to Jeff Mahoney

find_and_setup_root BUGs when it encounters an error from btrfs_find_last_root, which can occur if a path can't be allocated.

This patch pushes it up to its callers where it is already handled.

---
 fs/btrfs/disk-io.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
fs/btrfs/disk-io.c +6 -5
@@ -1117,10 +1117,10 @@ static int __setup_root(u32 nodesize, u3
 	return 0;
 }
 
-static int find_and_setup_root(struct btrfs_root *tree_root,
-			       struct btrfs_fs_info *fs_info,
-			       u64 objectid,
-			       struct btrfs_root *root)
+static int __must_check find_and_setup_root(struct btrfs_root *tree_root,
+					    struct btrfs_fs_info *fs_info,
+					    u64 objectid,
+					    struct btrfs_root *root)
 {
 	int ret;
 	u32 blocksize;
@@ -1133,7 +1133,8 @@ static int find_and_setup_root(struct bt
 				   &root->root_item, &root->root_key);
 	if (ret > 0)
 		return -ENOENT;
-	BUG_ON(ret);
+	else if (ret < 0)
+		return ret;
 
 	generation = btrfs_root_generation(&root->root_item);
 	blocksize = btrfs_level_size(root, btrfs_root_level(&root->root_item));
#25 lore raw

PATCH 15/66 btrfs: btrfs_update_root error push-up

In reply to Jeff Mahoney

btrfs_update_root BUG's when it can't alloc a path, yet it can recover from a search error. This patch returns -ENOMEM instead.

---
 fs/btrfs/ctree.h     |    6 +++---
 fs/btrfs/root-tree.c |    4 +++-
 2 files changed, 6 insertions(+), 4 deletions(-)
fs/btrfs/ctree.h +3 -3
@@ -2400,9 +2400,9 @@ int btrfs_del_root(struct btrfs_trans_ha
 int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root
 		      *root, struct btrfs_key *key, struct btrfs_root_item
 		      *item);
-int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
-		      *root, struct btrfs_key *key, struct btrfs_root_item
-		      *item);
+int btrfs_update_root(struct btrfs_trans_handle *trans,
+		      struct btrfs_root *root, struct btrfs_key *key,
+		      struct btrfs_root_item *item) __must_check;
 int btrfs_find_last_root(struct btrfs_root *root, u64 objectid, struct
 			 btrfs_root_item *item, struct btrfs_key *key);
 int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid);
fs/btrfs/root-tree.c +3 -1
@@ -93,7 +93,9 @@ int btrfs_update_root(struct btrfs_trans
 	unsigned long ptr;
 
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return -ENOMEM;
+
 	ret = btrfs_search_slot(trans, root, key, path, 0, 1);
 	if (ret < 0)
 		goto out;
#26 lore raw

PATCH 16/66 btrfs: set_range_writeback should return void

In reply to Jeff Mahoney

set_range_writeback has no error conditions and should return void. Its callers already ignore the error code anyway.

There are internal error conditions but they are fatal and will cause a panic.

---
 fs/btrfs/extent_io.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
fs/btrfs/extent_io.c +5 -3
@@ -1253,7 +1253,7 @@ int unlock_extent(struct extent_io_tree
 /*
  * helper function to set both pages and extents in the tree writeback
  */
-static int set_range_writeback(struct extent_io_tree *tree, u64 start, u64 end)
+static void set_range_writeback(struct extent_io_tree *tree, u64 start, u64 end)
 {
 	unsigned long index = start >> PAGE_CACHE_SHIFT;
 	unsigned long end_index = end >> PAGE_CACHE_SHIFT;
@@ -1261,12 +1261,14 @@ static int set_range_writeback(struct ex
 
 	while (index <= end_index) {
 		page = find_get_page(tree->mapping, index);
-		BUG_ON(!page);
+		if (!page)
+			btrfs_panic(tree_fs_info(tree), -ENOENT,
+				    "Page not found in extent io tree at "
+				    "offset %llu", index << PAGE_CACHE_SHIFT);
 		set_page_writeback(page);
 		page_cache_release(page);
 		index++;
 	}
-	return 0;
 }
 
 /* find the first state struct with 'bits' set after 'start', and
#27 lore raw

PATCH 17/66 btrfs: wait_on_state should return void

In reply to Jeff Mahoney

wait_on_state has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/extent_io.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
fs/btrfs/extent_io.c +2 -3
@@ -621,8 +621,8 @@ search_again:
 	goto again;
 }
 
-static int wait_on_state(struct extent_io_tree *tree,
-			 struct extent_state *state)
+static void wait_on_state(struct extent_io_tree *tree,
+			  struct extent_state *state)
 		__releases(tree->lock)
 		__acquires(tree->lock)
 {
@@ -632,7 +632,6 @@ static int wait_on_state(struct extent_i
 	schedule();
 	spin_lock(&tree->lock);
 	finish_wait(&state->wq, &wait);
-	return 0;
 }
 
 /*
#28 lore raw

PATCH 18/66 btrfs: wait_extent_bit should return void

In reply to Jeff Mahoney

wait_extent_bit has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/extent_io.c |    3 +--
 fs/btrfs/extent_io.h |    2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)
fs/btrfs/extent_io.c +1 -2
@@ -639,7 +639,7 @@ static void wait_on_state(struct extent_
  * The range [start, end] is inclusive.
  * The tree lock is taken by this function
  */
-int wait_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int bits)
+void wait_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int bits)
 {
 	struct extent_state *state;
 	struct rb_node *node;
@@ -676,7 +676,6 @@ again:
 	}
 out:
 	spin_unlock(&tree->lock);
-	return 0;
 }
 
 static void set_state_bits(struct extent_io_tree *tree,
fs/btrfs/extent_io.h +1 -1
@@ -277,7 +277,7 @@ void memmove_extent_buffer(struct extent
 			   unsigned long src_offset, unsigned long len);
 void memset_extent_buffer(struct extent_buffer *eb, char c,
 			  unsigned long start, unsigned long len);
-int wait_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int bits);
+void wait_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int bits);
 int clear_extent_buffer_dirty(struct extent_io_tree *tree,
 			      struct extent_buffer *eb);
 int set_extent_buffer_dirty(struct extent_io_tree *tree,
#29 lore raw

PATCH 19/66 btrfs: __unlock_for_delalloc should return void

In reply to Jeff Mahoney

__unlock_for_delalloc has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/extent_io.c |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
fs/btrfs/extent_io.c +4 -5
@@ -1384,9 +1384,9 @@ out:
 	return found;
 }
 
-static noinline int __unlock_for_delalloc(struct inode *inode,
-					  struct page *locked_page,
-					  u64 start, u64 end)
+static noinline void __unlock_for_delalloc(struct inode *inode,
+					   struct page *locked_page,
+					   u64 start, u64 end)
 {
 	int ret;
 	struct page *pages[16];
@@ -1396,7 +1396,7 @@ static noinline int __unlock_for_delallo
 	int i;
 
 	if (index == locked_page->index && end_index == index)
-		return 0;
+		return;
 
 	while (nr_pages > 0) {
 		ret = find_get_pages_contig(inode->i_mapping, index,
@@ -1411,7 +1411,6 @@ static noinline int __unlock_for_delallo
 		index += ret;
 		cond_resched();
 	}
-	return 0;
 }
 
 static noinline int lock_delalloc_pages(struct inode *inode,
#30 lore raw

PATCH 20/66 btrfs: check_page_uptodate should return void

In reply to Jeff Mahoney

check_page_uptodate has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/extent_io.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
fs/btrfs/extent_io.c +1 -3
@@ -1805,14 +1805,12 @@ int test_range_bit(struct extent_io_tree
  * helper function to set a given page up to date if all the
  * extents in the tree for that page are up to date
  */
-static int check_page_uptodate(struct extent_io_tree *tree,
-			       struct page *page)
+static void check_page_uptodate(struct extent_io_tree *tree, struct page *page)
 {
 	u64 start = (u64)page->index << PAGE_CACHE_SHIFT;
 	u64 end = start + PAGE_CACHE_SIZE - 1;
 	if (test_range_bit(tree, start, end, EXTENT_UPTODATE, 1, NULL))
 		SetPageUptodate(page);
-	return 0;
 }
 
 /*
#31 lore raw

PATCH 21/66 btrfs: check_page_locked should return void

In reply to Jeff Mahoney

check_page_locked has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/extent_io.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
fs/btrfs/extent_io.c +1 -3
@@ -1817,14 +1817,12 @@ static void check_page_uptodate(struct e
  * helper function to unlock a page if all the extents in the tree
  * for that page are unlocked
  */
-static int check_page_locked(struct extent_io_tree *tree,
-			     struct page *page)
+static void check_page_locked(struct extent_io_tree *tree, struct page *page)
 {
 	u64 start = (u64)page->index << PAGE_CACHE_SHIFT;
 	u64 end = start + PAGE_CACHE_SIZE - 1;
 	if (!test_range_bit(tree, start, end, EXTENT_LOCKED, 0, NULL))
 		unlock_page(page);
-	return 0;
 }
 
 /*
#32 lore raw

PATCH 22/66 btrfs: check_page_writeback should return void

In reply to Jeff Mahoney

check_page_writeback has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/extent_io.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
fs/btrfs/extent_io.c +2 -3
@@ -1829,11 +1829,10 @@ static void check_page_locked(struct ext
  * helper function to end page writeback if all the extents
  * in the tree for that page are done with writeback
  */
-static int check_page_writeback(struct extent_io_tree *tree,
-			     struct page *page)
+static void check_page_writeback(struct extent_io_tree *tree,
+				 struct page *page)
 {
 	end_page_writeback(page);
-	return 0;
 }
 
 /* lots and lots of room for performance fixes in the end_bio funcs */
#33 lore raw

PATCH 23/66 btrfs: clear_extent_buffer_dirty should return void

In reply to Jeff Mahoney

clear_extent_buffer_dirty has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/extent_io.c |    3 +--
 fs/btrfs/extent_io.h |    2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)
fs/btrfs/extent_io.c +1 -2
@@ -3436,7 +3436,7 @@ void free_extent_buffer(struct extent_bu
 	WARN_ON(1);
 }
 
-int clear_extent_buffer_dirty(struct extent_io_tree *tree,
+void clear_extent_buffer_dirty(struct extent_io_tree *tree,
 			      struct extent_buffer *eb)
 {
 	unsigned long i;
@@ -3467,7 +3467,6 @@ int clear_extent_buffer_dirty(struct ext
 		spin_unlock_irq(&page->mapping->tree_lock);
 		unlock_page(page);
 	}
-	return 0;
 }
 
 int set_extent_buffer_dirty(struct extent_io_tree *tree,
fs/btrfs/extent_io.h +1 -1
@@ -278,7 +278,7 @@ void memmove_extent_buffer(struct extent
 void memset_extent_buffer(struct extent_buffer *eb, char c,
 			  unsigned long start, unsigned long len);
 void wait_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int bits);
-int clear_extent_buffer_dirty(struct extent_io_tree *tree,
+void clear_extent_buffer_dirty(struct extent_io_tree *tree,
 			      struct extent_buffer *eb);
 int set_extent_buffer_dirty(struct extent_io_tree *tree,
 			     struct extent_buffer *eb);
#34 lore raw

PATCH 24/66 btrfs: btrfs_cleanup_fs_uuids should return void

In reply to Jeff Mahoney

btrfs_cleanup_fs_uuids has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/volumes.c |    3 +--
 fs/btrfs/volumes.h |    2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)
fs/btrfs/volumes.c +1 -2
@@ -65,7 +65,7 @@ static void free_fs_devices(struct btrfs
 	kfree(fs_devices);
 }
 
-int btrfs_cleanup_fs_uuids(void)
+void btrfs_cleanup_fs_uuids(void)
 {
 	struct btrfs_fs_devices *fs_devices;
 
@@ -75,7 +75,6 @@ int btrfs_cleanup_fs_uuids(void)
 		list_del(&fs_devices->list);
 		free_fs_devices(fs_devices);
 	}
-	return 0;
 }
 
 static noinline struct btrfs_device *__find_device(struct list_head *head,
fs/btrfs/volumes.h +1 -1
@@ -202,7 +202,7 @@ int btrfs_add_device(struct btrfs_trans_
 		     struct btrfs_root *root,
 		     struct btrfs_device *device);
 int btrfs_rm_device(struct btrfs_root *root, char *device_path);
-int btrfs_cleanup_fs_uuids(void);
+void btrfs_cleanup_fs_uuids(void);
 int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len);
 int btrfs_grow_device(struct btrfs_trans_handle *trans,
 		      struct btrfs_device *device, u64 new_size);
#35 lore raw

PATCH 25/66 btrfs: run_scheduled_bios should return void

In reply to Jeff Mahoney

run_scheduled_bios has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/volumes.c |    3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
fs/btrfs/volumes.c +1 -2
@@ -127,7 +127,7 @@ static void requeue_list(struct btrfs_pe
  * the list if the block device is congested.  This way, multiple devices
  * can make progress from a single worker thread.
  */
-static noinline int run_scheduled_bios(struct btrfs_device *device)
+static noinline void run_scheduled_bios(struct btrfs_device *device)
 {
 	struct bio *pending;
 	struct backing_dev_info *bdi;
@@ -307,7 +307,6 @@ loop_lock:
 
 done:
 	blk_finish_plug(&plug);
-	return 0;
 }
 
 static void pending_bios_fn(struct btrfs_work *work)
#36 lore raw

PATCH 26/66 btrfs: btrfs_close_extra_devices should return void

In reply to Jeff Mahoney

btrfs_close_extra_devices has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/volumes.c |    3 +--
 fs/btrfs/volumes.h |    2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)
fs/btrfs/volumes.c +1 -2
@@ -437,7 +437,7 @@ error:
 	return ERR_PTR(-ENOMEM);
 }
 
-int btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices)
+void btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices)
 {
 	struct btrfs_device *device, *next;
 
@@ -470,7 +470,6 @@ again:
 	}
 
 	mutex_unlock(&uuid_mutex);
-	return 0;
 }
 
 static void __free_device(struct work_struct *work)
fs/btrfs/volumes.h +1 -1
@@ -197,7 +197,7 @@ int btrfs_open_devices(struct btrfs_fs_d
 int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
 			  struct btrfs_fs_devices **fs_devices_ret);
 int btrfs_close_devices(struct btrfs_fs_devices *fs_devices);
-int btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices);
+void btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices);
 int btrfs_add_device(struct btrfs_trans_handle *trans,
 		     struct btrfs_root *root,
 		     struct btrfs_device *device);
#37 lore raw

PATCH 27/66 btrfs: schedule_bio should return void

In reply to Jeff Mahoney

schedule_bio has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/volumes.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
fs/btrfs/volumes.c +1 -3
@@ -3268,7 +3268,7 @@ struct async_sched {
  * This will add one bio to the pending list for a device and make sure
  * the work struct is scheduled.
  */
-static noinline int schedule_bio(struct btrfs_root *root,
+static noinline void schedule_bio(struct btrfs_root *root,
 				 struct btrfs_device *device,
 				 int rw, struct bio *bio)
 {
@@ -3280,7 +3280,6 @@ static noinline int schedule_bio(struct
 		bio_get(bio);
 		submit_bio(rw, bio);
 		bio_put(bio);
-		return 0;
 	}
 
 	/*
@@ -3314,7 +3313,6 @@ static noinline int schedule_bio(struct
 	if (should_queue)
 		btrfs_queue_worker(&root->fs_info->submit_workers,
 				   &device->work);
-	return 0;
 }
 
 int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
#38 lore raw

PATCH 28/66 btrfs: fill_device_from_item should return void

In reply to Jeff Mahoney

fill_device_from_item has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/volumes.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)
fs/btrfs/volumes.c +1 -3
@@ -3513,7 +3513,7 @@ static int read_one_chunk(struct btrfs_r
 	return 0;
 }
 
-static int fill_device_from_item(struct extent_buffer *leaf,
+static void fill_device_from_item(struct extent_buffer *leaf,
 				 struct btrfs_dev_item *dev_item,
 				 struct btrfs_device *device)
 {
@@ -3530,8 +3530,6 @@ static int fill_device_from_item(struct
 
 	ptr = (unsigned long)btrfs_device_uuid(dev_item);
 	read_extent_buffer(leaf, device->uuid, ptr, BTRFS_UUID_SIZE);
-
-	return 0;
 }
 
 static int open_seed_devices(struct btrfs_root *root, u8 *fsid)
#39 lore raw

PATCH 29/66 btrfs: btrfs_queue_worker should return void

In reply to Jeff Mahoney

btrfs_queue_worker has no error conditions and should return void.

---
 fs/btrfs/async-thread.c |   14 ++++----------
 fs/btrfs/async-thread.h |    2 +-
 2 files changed, 5 insertions(+), 11 deletions(-)
fs/btrfs/async-thread.c +4 -10
@@ -95,7 +95,6 @@ static void start_new_worker_func(struct
 static int start_new_worker(struct btrfs_workers *queue)
 {
 	struct worker_start *start;
-	int ret;
 
 	start = kzalloc(sizeof(*start), GFP_NOFS);
 	if (!start)
@@ -103,10 +102,8 @@ static int start_new_worker(struct btrfs
 
 	start->work.func = start_new_worker_func;
 	start->queue = queue;
-	ret = btrfs_queue_worker(queue->atomic_worker_start, &start->work);
-	if (ret)
-		kfree(start);
-	return ret;
+	btrfs_queue_worker(queue->atomic_worker_start, &start->work);
+	return 0;
 }
 
 /*
@@ -665,7 +662,7 @@ void btrfs_set_work_high_prio(struct btr
 /*
  * places a struct btrfs_work into the pending queue of one of the kthreads
  */
-int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
+void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work)
 {
 	struct btrfs_worker_thread *worker;
 	unsigned long flags;
@@ -673,7 +670,7 @@ int btrfs_queue_worker(struct btrfs_work
 
 	/* don't requeue something already on a list */
 	if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags))
-		goto out;
+		return;
 
 	worker = find_worker(workers);
 	if (workers->ordered) {
@@ -712,7 +709,4 @@ int btrfs_queue_worker(struct btrfs_work
 	if (wake)
 		wake_up_process(worker->task);
 	spin_unlock_irqrestore(&worker->lock, flags);
-
-out:
-	return 0;
 }
fs/btrfs/async-thread.h +1 -1
@@ -109,7 +109,7 @@ struct btrfs_workers {
 	char *name;
 };
 
-int btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work);
+void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work);
 int btrfs_start_workers(struct btrfs_workers *workers, int num_workers);
 int btrfs_stop_workers(struct btrfs_workers *workers);
 void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max,
#40 lore raw

PATCH 30/66 btrfs: run_ordered_completions should return void

In reply to Jeff Mahoney

run_ordered_completions has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/async-thread.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
fs/btrfs/async-thread.c +2 -3
@@ -174,11 +174,11 @@ out:
 	spin_unlock_irqrestore(&workers->lock, flags);
 }
 
-static noinline int run_ordered_completions(struct btrfs_workers *workers,
+static noinline void run_ordered_completions(struct btrfs_workers *workers,
 					    struct btrfs_work *work)
 {
 	if (!workers->ordered)
-		return 0;
+		return;
 
 	set_bit(WORK_DONE_BIT, &work->flags);
 
@@ -216,7 +216,6 @@ static noinline int run_ordered_completi
 	}
 
 	spin_unlock(&workers->order_lock);
-	return 0;
 }
 
 static void put_worker(struct btrfs_worker_thread *worker)
#41 lore raw

PATCH 31/66 btrfs: btrfs_stop_workers should return void

In reply to Jeff Mahoney

btrfs_stop_workers has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/async-thread.c |    3 +--
 fs/btrfs/async-thread.h |    2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)
fs/btrfs/async-thread.c +1 -2
@@ -401,7 +401,7 @@ again:
 /*
  * this will wait for all the worker threads to shutdown
  */
-int btrfs_stop_workers(struct btrfs_workers *workers)
+void btrfs_stop_workers(struct btrfs_workers *workers)
 {
 	struct list_head *cur;
 	struct btrfs_worker_thread *worker;
@@ -429,7 +429,6 @@ int btrfs_stop_workers(struct btrfs_work
 		put_worker(worker);
 	}
 	spin_unlock_irq(&workers->lock);
-	return 0;
 }
 
 /*
fs/btrfs/async-thread.h +1 -1
@@ -111,7 +111,7 @@ struct btrfs_workers {
 
 void btrfs_queue_worker(struct btrfs_workers *workers, struct btrfs_work *work);
 int btrfs_start_workers(struct btrfs_workers *workers, int num_workers);
-int btrfs_stop_workers(struct btrfs_workers *workers);
+void btrfs_stop_workers(struct btrfs_workers *workers);
 void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max,
 			struct btrfs_workers *async_starter);
 int btrfs_requeue_work(struct btrfs_work *work);
#42 lore raw

PATCH 32/66 btrfs: btrfs_requeue_work should return void

In reply to Jeff Mahoney

btrfs_requeue_work has no error conditions and should return void. Its callers ignore the error code anyway.

---
 fs/btrfs/async-thread.c |    7 ++-----
 fs/btrfs/async-thread.h |    2 +-
 2 files changed, 3 insertions(+), 6 deletions(-)
fs/btrfs/async-thread.c +2 -5
@@ -613,14 +613,14 @@ found:
  * it was taken from.  It is intended for use with long running work functions
  * that make some progress and want to give the cpu up for others.
  */
-int btrfs_requeue_work(struct btrfs_work *work)
+void btrfs_requeue_work(struct btrfs_work *work)
 {
 	struct btrfs_worker_thread *worker = work->worker;
 	unsigned long flags;
 	int wake = 0;
 
 	if (test_and_set_bit(WORK_QUEUED_BIT, &work->flags))
-		goto out;
+		return;
 
 	spin_lock_irqsave(&worker->lock, flags);
 	if (test_bit(WORK_HIGH_PRIO_BIT, &work->flags))
@@ -647,9 +647,6 @@ int btrfs_requeue_work(struct btrfs_work
 	if (wake)
 		wake_up_process(worker->task);
 	spin_unlock_irqrestore(&worker->lock, flags);
-out:
-
-	return 0;
 }
 
 void btrfs_set_work_high_prio(struct btrfs_work *work)
fs/btrfs/async-thread.h +1 -1
@@ -114,6 +114,6 @@ int btrfs_start_workers(struct btrfs_wor
 void btrfs_stop_workers(struct btrfs_workers *workers);
 void btrfs_init_workers(struct btrfs_workers *workers, char *name, int max,
 			struct btrfs_workers *async_starter);
-int btrfs_requeue_work(struct btrfs_work *work);
+void btrfs_requeue_work(struct btrfs_work *work);
 void btrfs_set_work_high_prio(struct btrfs_work *work);
 #endif
#43 lore raw

PATCH 33/66 btrfs: tree-log: btrfs_end_log_trans should return void

In reply to Jeff Mahoney

btrfs_end_log_trans has no error conditions and should return void. Its callers ignore the error code anyway.

---
 fs/btrfs/tree-log.c |    3 +--
 fs/btrfs/tree-log.h |    2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)
fs/btrfs/tree-log.c +1 -2
index 483e280..2c45b3d 100644
@@ -212,14 +212,13 @@ int btrfs_pin_log_trans(struct btrfs_root *root)
  * indicate we're done making changes to the log tree
  * and wake up anyone waiting to do a sync
  */
-int btrfs_end_log_trans(struct btrfs_root *root)
+void btrfs_end_log_trans(struct btrfs_root *root)
 {
 	if (atomic_dec_and_test(&root->log_writers)) {
 		smp_mb();
 		if (waitqueue_active(&root->log_writer_wait))
 			wake_up(&root->log_writer_wait);
 	}
-	return 0;
 }
 
 
fs/btrfs/tree-log.h +1 -1
index 2270ac5..862ac81 100644
@@ -38,7 +38,7 @@ int btrfs_del_inode_ref_in_log(struct btrfs_trans_handle *trans,
 			       struct btrfs_root *root,
 			       const char *name, int name_len,
 			       struct inode *inode, u64 dirid);
-int btrfs_end_log_trans(struct btrfs_root *root);
+void btrfs_end_log_trans(struct btrfs_root *root);
 int btrfs_pin_log_trans(struct btrfs_root *root);
 int btrfs_log_inode_parent(struct btrfs_trans_handle *trans,
 		    struct btrfs_root *root, struct inode *inode,
#44 lore raw

PATCH 34/66 btrfs: tree-log: wait_for_writer should return void

In reply to Jeff Mahoney

wait_for_writer has no error conditions and should return void. Its callers already ignore the error codes anyway.

---
 fs/btrfs/tree-log.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)
fs/btrfs/tree-log.c +2 -3
index 2c45b3d..aac743b 100644
@@ -1964,8 +1964,8 @@ static int wait_log_commit(struct btrfs_trans_handle *trans,
 	return 0;
 }
 
-static int wait_for_writer(struct btrfs_trans_handle *trans,
-			   struct btrfs_root *root)
+static void wait_for_writer(struct btrfs_trans_handle *trans,
+			    struct btrfs_root *root)
 {
 	DEFINE_WAIT(wait);
 	while (atomic_read(&root->log_writers)) {
@@ -1978,7 +1978,6 @@ static int wait_for_writer(struct btrfs_trans_handle *trans,
 		mutex_lock(&root->log_mutex);
 		finish_wait(&root->log_writer_wait, &wait);
 	}
-	return 0;
 }
 
 /*
#45 lore raw

PATCH 35/66 btrfs: btrfs_init_compress should return void

In reply to Jeff Mahoney

btrfs_init_compress doesn't have any failure conditions, so return void.

---
 fs/btrfs/compression.c |    3 +--
 fs/btrfs/compression.h |    2 +-
 fs/btrfs/super.c       |    5 +----
 3 files changed, 3 insertions(+), 7 deletions(-)
fs/btrfs/compression.c +1 -2
index cca501b..0c0e842 100644
@@ -734,7 +734,7 @@ struct btrfs_compress_op *btrfs_compress_op[] = {
 	&btrfs_lzo_compress,
 };
 
-int __init btrfs_init_compress(void)
+void __init btrfs_init_compress(void)
 {
 	int i;
 
@@ -744,7 +744,6 @@ int __init btrfs_init_compress(void)
 		atomic_set(&comp_alloc_workspace[i], 0);
 		init_waitqueue_head(&comp_workspace_wait[i]);
 	}
-	return 0;
 }
 
 /*
fs/btrfs/compression.h +1 -1
index a12059f..9afb0a6 100644
@@ -19,7 +19,7 @@
 #ifndef __BTRFS_COMPRESSION_
 #define __BTRFS_COMPRESSION_
 
-int btrfs_init_compress(void);
+void btrfs_init_compress(void);
 void btrfs_exit_compress(void);
 
 int btrfs_compress_pages(int type, struct address_space *mapping,
fs/btrfs/super.c +1 -4
index 0152207..26e1dcf 100644
@@ -1347,9 +1347,7 @@ static int __init init_btrfs_fs(void)
 	if (err)
 		return err;
 
-	err = btrfs_init_compress();
-	if (err)
-		goto free_sysfs;
+	btrfs_init_compress();
 
 	err = btrfs_init_cachep();
 	if (err)
@@ -1390,7 +1388,6 @@ free_cachep:
 	btrfs_destroy_cachep();
 free_compress:
 	btrfs_exit_compress();
-free_sysfs:
 	btrfs_exit_sysfs();
 	return err;
 }
#46 lore raw

PATCH 36/66 btrfs: btrfs_invalidate_inodes should return void

In reply to Jeff Mahoney

btrfs_invalidate_inodes has no error conditions and should return void.

---
 fs/btrfs/ctree.h |    2 +-
 fs/btrfs/inode.c |    3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)
fs/btrfs/ctree.h +1 -1
index 7d90a9c..e8f0689 100644
@@ -2584,7 +2584,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root);
 void btrfs_orphan_commit_root(struct btrfs_trans_handle *trans,
 			      struct btrfs_root *root);
 int btrfs_cont_expand(struct inode *inode, loff_t oldsize, loff_t size);
-int btrfs_invalidate_inodes(struct btrfs_root *root);
+void btrfs_invalidate_inodes(struct btrfs_root *root);
 void btrfs_add_delayed_iput(struct inode *inode);
 void btrfs_run_delayed_iputs(struct btrfs_root *root);
 int btrfs_prealloc_file_range(struct inode *inode, int mode,
fs/btrfs/inode.c +1 -2
index 321c9cf..59c681b 100644
@@ -3861,7 +3861,7 @@ static void inode_tree_del(struct inode *inode)
 	}
 }
 
-int btrfs_invalidate_inodes(struct btrfs_root *root)
+void btrfs_invalidate_inodes(struct btrfs_root *root)
 {
 	struct rb_node *node;
 	struct rb_node *prev;
@@ -3921,7 +3921,6 @@ again:
 		node = rb_next(node);
 	}
 	spin_unlock(&root->inode_lock);
-	return 0;
 }
 
 static int btrfs_init_locked_inode(struct inode *inode, void *p)
#47 lore raw

PATCH 37/66 btrfs: __setup_root should return void

In reply to Jeff Mahoney

__setup_root has no error conditions and should return void. Its callers already ignore the error codes anyway.

---
 fs/btrfs/disk-io.c |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
fs/btrfs/disk-io.c +4 -5
@@ -1058,10 +1058,10 @@ int clean_tree_block(struct btrfs_trans_
 	return 0;
 }
 
-static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
-			u32 stripesize, struct btrfs_root *root,
-			struct btrfs_fs_info *fs_info,
-			u64 objectid)
+static void __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
+			 u32 stripesize, struct btrfs_root *root,
+			 struct btrfs_fs_info *fs_info,
+			 u64 objectid)
 {
 	root->node = NULL;
 	root->commit_root = NULL;
@@ -1114,7 +1114,6 @@ static int __setup_root(u32 nodesize, u3
 	root->defrag_running = 0;
 	root->root_key.objectid = objectid;
 	root->anon_dev = 0;
-	return 0;
 }
 
 static int __must_check find_and_setup_root(struct btrfs_root *tree_root,
#48 lore raw

PATCH 38/66 btrfs: btrfs_destroy_delalloc_inodes should return void

In reply to Jeff Mahoney

btrfs_destroy_delalloc_inodes has no error conditions and should return void. Its callers already ignore the error codes anyway.

---
 fs/btrfs/disk-io.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
fs/btrfs/disk-io.c +2 -4
@@ -54,7 +54,7 @@ static int btrfs_destroy_ordered_extents
 static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
 				      struct btrfs_root *root);
 static int btrfs_destroy_pending_snapshots(struct btrfs_transaction *t);
-static int btrfs_destroy_delalloc_inodes(struct btrfs_root *root);
+static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root);
 static int btrfs_destroy_marked_extents(struct btrfs_root *root,
 					struct extent_io_tree *dirty_pages,
 					int mark);
@@ -2939,7 +2939,7 @@ static int btrfs_destroy_pending_snapsho
 	return 0;
 }
 
-static int btrfs_destroy_delalloc_inodes(struct btrfs_root *root)
+static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root)
 {
 	struct btrfs_inode *btrfs_inode;
 	struct list_head splice;
@@ -2959,8 +2959,6 @@ static int btrfs_destroy_delalloc_inodes
 	}
 
 	spin_unlock(&root->fs_info->delalloc_lock);
-
-	return 0;
 }
 
 static int btrfs_destroy_marked_extents(struct btrfs_root *root,
#49 lore raw

PATCH 39/66 btrfs: btrfs_prepare_extent_commit should return void

In reply to Jeff Mahoney

btrfs_prepare_extent_commit has no error conditions and should return void. Its callers already ignore the error codes anyway.

---
 fs/btrfs/ctree.h       |    4 ++--
 fs/btrfs/extent-tree.c |    3 +--
 2 files changed, 3 insertions(+), 4 deletions(-)
fs/btrfs/ctree.h +2 -2
@@ -2207,8 +2207,8 @@ int btrfs_free_extent(struct btrfs_trans
 		      u64 root_objectid, u64 owner, u64 offset);
 
 int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len);
-int btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
-				struct btrfs_root *root);
+void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
+				 struct btrfs_root *root);
 int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
 			       struct btrfs_root *root);
 int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
fs/btrfs/extent-tree.c +1 -2
@@ -4385,7 +4385,7 @@ static int btrfs_update_reserved_bytes(s
 	return ret;
 }
 
-int btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
+void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
 				struct btrfs_root *root)
 {
 	struct btrfs_fs_info *fs_info = root->fs_info;
@@ -4415,7 +4415,6 @@ int btrfs_prepare_extent_commit(struct b
 	up_write(&fs_info->extent_commit_sem);
 
 	update_global_block_rsv(fs_info);
-	return 0;
 }
 
 static int unpin_extent_range(struct btrfs_root *root, u64 start, u64 end)
#50 lore raw

PATCH 40/66 btrfs: btrfs_set_block_group_rw should return void

In reply to Jeff Mahoney

btrfs_set_block_group_rw has no error conditions and should return void. Its callers already ignore the error codes anyway.

---
 fs/btrfs/ctree.h       |    4 ++--
 fs/btrfs/extent-tree.c |    3 +--
 2 files changed, 3 insertions(+), 4 deletions(-)
fs/btrfs/ctree.h +2 -2
@@ -2263,8 +2263,8 @@ void btrfs_block_rsv_release(struct btrf
 			     u64 num_bytes);
 int btrfs_set_block_group_ro(struct btrfs_root *root,
 			     struct btrfs_block_group_cache *cache);
-int btrfs_set_block_group_rw(struct btrfs_root *root,
-			     struct btrfs_block_group_cache *cache);
+void btrfs_set_block_group_rw(struct btrfs_root *root,
+			      struct btrfs_block_group_cache *cache);
 void btrfs_put_block_group_cache(struct btrfs_fs_info *info);
 u64 btrfs_account_ro_block_groups_free_space(struct btrfs_space_info *sinfo);
 int btrfs_error_unpin_extent_range(struct btrfs_root *root,
fs/btrfs/extent-tree.c +1 -2
@@ -6769,7 +6769,7 @@ u64 btrfs_account_ro_block_groups_free_s
 	return free_bytes;
 }
 
-int btrfs_set_block_group_rw(struct btrfs_root *root,
+void btrfs_set_block_group_rw(struct btrfs_root *root,
 			      struct btrfs_block_group_cache *cache)
 {
 	struct btrfs_space_info *sinfo = cache->space_info;
@@ -6785,7 +6785,6 @@ int btrfs_set_block_group_rw(struct btrf
 	cache->ro = 0;
 	spin_unlock(&cache->lock);
 	spin_unlock(&sinfo->lock);
-	return 0;
 }
 
 /*
#51 lore raw

PATCH 41/66 btrfs: setup_inline_extent_backref should return void

In reply to Jeff Mahoney

setup_inline_extent_backref has no error conditions and should return void. We set ret = 0 explicitly in insert_inline_extent_backref since it would have been set using the return value, which would have been 0.

---
 fs/btrfs/extent-tree.c |   23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)
fs/btrfs/extent-tree.c +11 -12
@@ -1556,13 +1556,13 @@ out:
  * helper to add new inline back ref
  */
 static noinline_for_stack
-int setup_inline_extent_backref(struct btrfs_trans_handle *trans,
-				struct btrfs_root *root,
-				struct btrfs_path *path,
-				struct btrfs_extent_inline_ref *iref,
-				u64 parent, u64 root_objectid,
-				u64 owner, u64 offset, int refs_to_add,
-				struct btrfs_delayed_extent_op *extent_op)
+void setup_inline_extent_backref(struct btrfs_trans_handle *trans,
+				 struct btrfs_root *root,
+				 struct btrfs_path *path,
+				 struct btrfs_extent_inline_ref *iref,
+				 u64 parent, u64 root_objectid,
+				 u64 owner, u64 offset, int refs_to_add,
+				 struct btrfs_delayed_extent_op *extent_op)
 {
 	struct extent_buffer *leaf;
 	struct btrfs_extent_item *ei;
@@ -1616,7 +1616,6 @@ int setup_inline_extent_backref(struct b
 		btrfs_set_extent_inline_ref_offset(leaf, iref, root_objectid);
 	}
 	btrfs_mark_buffer_dirty(leaf);
-	return 0;
 }
 
 static int lookup_extent_backref(struct btrfs_trans_handle *trans,
@@ -1735,10 +1734,10 @@ int insert_inline_extent_backref(struct
 		ret = update_inline_extent_backref(trans, root, path, iref,
 						   refs_to_add, extent_op);
 	} else if (ret == -ENOENT) {
-		ret = setup_inline_extent_backref(trans, root, path, iref,
-						  parent, root_objectid,
-						  owner, offset, refs_to_add,
-						  extent_op);
+		setup_inline_extent_backref(trans, root, path, iref, parent,
+					    root_objectid, owner, offset,
+					    refs_to_add, extent_op);
+		ret = 0;
 	}
 	return ret;
 }
#52 lore raw

PATCH 42/66 btrfs: btrfs_run_defrag_inodes should return void

In reply to Jeff Mahoney

btrfs_run_defrag_inodes has no error conditions and should return void. Its callers already ignore the error codes anyway.

---
 fs/btrfs/ctree.h |    2 +-
 fs/btrfs/file.c  |    3 +--
 2 files changed, 2 insertions(+), 3 deletions(-)
fs/btrfs/ctree.h +1 -1
@@ -2606,7 +2606,7 @@ int btrfs_defrag_file(struct inode *inod
 /* file.c */
 int btrfs_add_inode_defrag(struct btrfs_trans_handle *trans,
 			   struct inode *inode);
-int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info);
+void btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info);
 int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync);
 int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
 			    int skip_pinned);
fs/btrfs/file.c +1 -2
@@ -193,7 +193,7 @@ struct inode_defrag *btrfs_find_defrag_i
  * run through the list of inodes in the FS that need
  * defragging
  */
-int btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
+void btrfs_run_defrag_inodes(struct btrfs_fs_info *fs_info)
 {
 	struct inode_defrag *defrag;
 	struct btrfs_root *inode_root;
@@ -296,7 +296,6 @@ next_free:
 	 * wait for the defragger to stop
 	 */
 	wake_up(&fs_info->transaction_wait);
-	return 0;
 }
 
 /* simple helper to fault in pages and copy.  This should go away
#53 lore raw

PATCH 43/66 btrfs: Simplify btrfs_submit_bio_hook

In reply to Jeff Mahoney

btrfs_submit_bio_hook currently calls btrfs_bio_wq_end_io in either case of an if statement that determines one of the arguments.

This patch moves the function call outside of the if statement and uses it to only determine the different argument. This allows us to catch an error in one place in a more visually obvious way.

---
 fs/btrfs/inode.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)
fs/btrfs/inode.c +4 -3
index 59c681b..c0dc599 100644
@@ -1479,13 +1479,14 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio,
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 	int ret = 0;
 	int skip_sum;
+	int metadata = 0;
 
 	skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM;
 
 	if (btrfs_is_free_space_inode(root, inode))
-		ret = btrfs_bio_wq_end_io(root->fs_info, bio, 2);
-	else
-		ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0);
+		metadata = 2;
+
+	ret = btrfs_bio_wq_end_io(root->fs_info, bio, metadata);
 	BUG_ON(ret);
 
 	if (!(rw & REQ_WRITE)) {
#54 lore raw

PATCH 44/66 btrfs: Factor out tree->ops->merge_bio_hook call

In reply to Jeff Mahoney

In submit_extent_page, there's a visually noisy if statement that, in the midst of other conditions, does the tree dependency for tree->ops and tree->ops->merge_bio_hook before calling it, and then another condition afterwards. If an error is returned from merge_bio_hook, there's no way to catch it. It's considered a routine "1" return value instead of a failure.

This patch factors out the dependency check into a new local merge_bio routine and BUG's on an error. The if statement is less noisy as a side- effect.

---
 fs/btrfs/extent_io.c |   17 ++++++++++++++---
 fs/btrfs/inode.c     |    5 +++--
 2 files changed, 17 insertions(+), 5 deletions(-)
fs/btrfs/extent_io.c +14 -3
index 0575792..09095b8 100644
@@ -2058,6 +2058,19 @@ static int submit_one_bio(int rw, struct bio *bio, int mirror_num,
 	return ret;
 }
 
+static int merge_bio(struct extent_io_tree *tree, struct page *page,
+		     unsigned long offset, size_t size, struct bio *bio,
+		     unsigned long bio_flags)
+{
+	int ret = 0;
+	if (tree->ops && tree->ops->merge_bio_hook)
+		ret = tree->ops->merge_bio_hook(page, offset, size, bio,
+						bio_flags);
+	BUG_ON(ret < 0);
+	return ret;
+
+}
+
 static int submit_extent_page(int rw, struct extent_io_tree *tree,
 			      struct page *page, sector_t sector,
 			      size_t size, unsigned long offset,
@@ -2086,9 +2099,7 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree,
 				sector;
 
 		if (prev_bio_flags != bio_flags || !contig ||
-		    (tree->ops && tree->ops->merge_bio_hook &&
-		     tree->ops->merge_bio_hook(page, offset, page_size, bio,
-					       bio_flags)) ||
+		    merge_bio(tree, page, offset, page_size, bio, bio_flags) ||
 		    bio_add_page(bio, page, page_size, offset) < page_size) {
 			ret = submit_one_bio(rw, bio, mirror_num,
 					     prev_bio_flags);
fs/btrfs/inode.c +3 -2
index c0dc599..a06cb64 100644
@@ -1425,10 +1425,11 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
 	map_length = length;
 	ret = btrfs_map_block(map_tree, READ, logical,
 			      &map_length, NULL, 0);
-
+	/* Will always return 0 or 1 with map_multi == NULL */
+	BUG_ON(ret < 0);
 	if (map_length < length + size)
 		return 1;
-	return ret;
+	return 0;
 }
 
 /*
#55 lore raw

PATCH 45/66 btrfs: ->submit_bio_hook error push-up

In reply to Jeff Mahoney

This pushes failures from the submit_bio_hook callbacks, btrfs_submit_bio_hook and btree_submit_bio_hook into the callers, including callers of submit_one_bio where it catches the failures with BUG_ON.

It also pushes up through the ->readpage_io_failed_hook to end_bio_extent_writepage where the error is already caught with BUG_ON.

---
 fs/btrfs/disk-io.c   |    6 +++---
 fs/btrfs/extent_io.c |   33 +++++++++++++++++++++++----------
 fs/btrfs/inode.c     |    3 ++-
 3 files changed, 28 insertions(+), 14 deletions(-)
fs/btrfs/disk-io.c +3 -3
@@ -811,9 +811,9 @@ static int btree_submit_bio_hook(struct
 {
 	int ret;
 
-	ret = btrfs_bio_wq_end_io(BTRFS_I(inode)->root->fs_info,
-					  bio, 1);
-	BUG_ON(ret);
+	ret = btrfs_bio_wq_end_io(BTRFS_I(inode)->root->fs_info, bio, 1);
+	if (ret)
+		return ret;
 
 	if (!(rw & REQ_WRITE)) {
 		/*
fs/btrfs/extent_io.c +23 -10
@@ -1888,6 +1888,7 @@ static void end_bio_extent_writepage(str
 				uptodate = (err == 0);
 				continue;
 			}
+			BUG_ON(ret < 0);
 		}
 
 		if (!uptodate) {
@@ -1980,6 +1981,7 @@ static void end_bio_extent_readpage(stru
 				uncache_state(&cached);
 				continue;
 			}
+			BUG_ON(ret < 0);
 		}
 
 		if (uptodate) {
@@ -2034,8 +2036,8 @@ btrfs_bio_alloc(struct block_device *bde
 	return bio;
 }
 
-static int submit_one_bio(int rw, struct bio *bio, int mirror_num,
-			  unsigned long bio_flags)
+static int __must_check submit_one_bio(int rw, struct bio *bio,
+				       int mirror_num, unsigned long bio_flags)
 {
 	int ret = 0;
 	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
@@ -2105,6 +2107,7 @@ static int submit_extent_page(int rw, st
 		    bio_add_page(bio, page, page_size, offset) < page_size) {
 			ret = submit_one_bio(rw, bio, mirror_num,
 					     prev_bio_flags);
+			BUG_ON(ret < 0);
 			bio = NULL;
 		} else {
 			return 0;
@@ -2125,8 +2128,10 @@ static int submit_extent_page(int rw, st
 
 	if (bio_ret)
 		*bio_ret = bio;
-	else
+	else {
 		ret = submit_one_bio(rw, bio, mirror_num, bio_flags);
+		BUG_ON(ret < 0);
+	}
 
 	return ret;
 }
@@ -2349,8 +2354,10 @@ int extent_read_full_page(struct extent_
 
 	ret = __extent_read_full_page(tree, page, get_extent, &bio, 0,
 				      &bio_flags);
-	if (bio)
+	if (bio) {
 		ret = submit_one_bio(READ, bio, 0, bio_flags);
+		BUG_ON(ret < 0);
+	}
 	return ret;
 }
 
@@ -2752,10 +2759,12 @@ retry:
 static void flush_epd_write_bio(struct extent_page_data *epd)
 {
 	if (epd->bio) {
+		int ret;
 		if (epd->sync_io)
-			submit_one_bio(WRITE_SYNC, epd->bio, 0, 0);
+			ret = submit_one_bio(WRITE_SYNC, epd->bio, 0, 0);
 		else
-			submit_one_bio(WRITE, epd->bio, 0, 0);
+			ret = submit_one_bio(WRITE, epd->bio, 0, 0);
+		BUG_ON(ret < 0);
 		epd->bio = NULL;
 	}
 }
@@ -2871,8 +2880,10 @@ int extent_readpages(struct extent_io_tr
 		page_cache_release(page);
 	}
 	BUG_ON(!list_empty(pages));
-	if (bio)
-		submit_one_bio(READ, bio, 0, bio_flags);
+	if (bio) {
+		int ret = submit_one_bio(READ, bio, 0, bio_flags);
+		BUG_ON(ret < 0);
+	}
 	return 0;
 }
 
@@ -3704,8 +3715,10 @@ int read_extent_buffer_pages(struct exte
 		}
 	}
 
-	if (bio)
-		submit_one_bio(READ, bio, mirror_num, bio_flags);
+	if (bio) {
+		err = submit_one_bio(READ, bio, mirror_num, bio_flags);
+		BUG_ON(err < 0);
+	}
 
 	if (ret || !wait)
 		return ret;
fs/btrfs/inode.c +2 -1
@@ -1488,7 +1488,8 @@ static int btrfs_submit_bio_hook(struct
 		metadata = 2;
 
 	ret = btrfs_bio_wq_end_io(root->fs_info, bio, metadata);
-	BUG_ON(ret);
+	if (ret)
+		return ret;
 
 	if (!(rw & REQ_WRITE)) {
 		if (bio_flags & EXTENT_BIO_COMPRESSED) {
#56 lore raw

PATCH 46/66 btrfs: __add_reloc_root error push-up

In reply to Jeff Mahoney

This patch pushes kmalloc errors up to the caller and BUGs in the caller.

The BUG_ON for duplicate reloc tree root insertion is replaced with a panic explaining the issue.

---
 fs/btrfs/relocation.c |   22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)
fs/btrfs/relocation.c +16 -6
@@ -1219,14 +1219,15 @@ fail:
 /*
  * helper to add 'address of tree root -> reloc tree' mapping
  */
-static int __add_reloc_root(struct btrfs_root *root)
+static int __must_check __add_reloc_root(struct btrfs_root *root)
 {
 	struct rb_node *rb_node;
 	struct mapping_node *node;
 	struct reloc_control *rc = root->fs_info->reloc_ctl;
 
 	node = kmalloc(sizeof(*node), GFP_NOFS);
-	BUG_ON(!node);
+	if (!node)
+		return -ENOMEM;
 
 	node->bytenr = root->node->start;
 	node->data = root;
@@ -1235,7 +1236,12 @@ static int __add_reloc_root(struct btrfs
 	rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
 			      node->bytenr, &node->rb_node);
 	spin_unlock(&rc->reloc_root_tree.lock);
-	BUG_ON(rb_node);
+	if (rb_node) {
+		kfree(node);
+		btrfs_panic(root->fs_info, -EEXIST, "Duplicate root found "
+			    "for start=%llu while inserting into relocation "
+			    "tree\n");
+	}
 
 	list_add_tail(&root->root_list, &rc->reloc_roots);
 	return 0;
@@ -1351,6 +1357,7 @@ int btrfs_init_reloc_root(struct btrfs_t
 	struct btrfs_root *reloc_root;
 	struct reloc_control *rc = root->fs_info->reloc_ctl;
 	int clear_rsv = 0;
+	int ret;
 
 	if (root->reloc_root) {
 		reloc_root = root->reloc_root;
@@ -1370,7 +1377,8 @@ int btrfs_init_reloc_root(struct btrfs_t
 	if (clear_rsv)
 		trans->block_rsv = NULL;
 
-	__add_reloc_root(reloc_root);
+	ret = __add_reloc_root(reloc_root);
+	BUG_ON(ret < 0);
 	root->reloc_root = reloc_root;
 	return 0;
 }
@@ -4248,7 +4256,8 @@ int btrfs_recover_relocation(struct btrf
 				       reloc_root->root_key.offset);
 		BUG_ON(IS_ERR(fs_root));
 
-		__add_reloc_root(reloc_root);
+		err = __add_reloc_root(reloc_root);
+		BUG_ON(err < 0);
 		fs_root->reloc_root = reloc_root;
 	}
 
@@ -4450,7 +4459,8 @@ void btrfs_reloc_post_snapshot(struct bt
 	reloc_root = create_reloc_root(trans, root->reloc_root,
 				       new_root->root_key.objectid);
 
-	__add_reloc_root(reloc_root);
+	ret = __add_reloc_root(reloc_root);
+	BUG_ON(ret < 0);
 	new_root->reloc_root = reloc_root;
 
 	if (rc->create_reloc_tree) {
#57 lore raw

PATCH 47/66 btrfs: fixup_low_keys should return void

In reply to Jeff Mahoney

fixup_low_keys has no error conditions and should return void.

---
 fs/btrfs/ctree.c |   39 +++++++++++----------------------------
 1 files changed, 11 insertions(+), 28 deletions(-)
fs/btrfs/ctree.c +11 -28
index 011cab3..dedd3a1 100644
@@ -1864,15 +1864,12 @@ done:
  * fixing up pointers when a given leaf/node is not in slot 0 of the
  * higher levels
  *
- * If this fails to write a tree block, it returns -1, but continues
- * fixing up the blocks in ram so the tree is consistent.
  */
-static int fixup_low_keys(struct btrfs_trans_handle *trans,
-			  struct btrfs_root *root, struct btrfs_path *path,
-			  struct btrfs_disk_key *key, int level)
+static void fixup_low_keys(struct btrfs_trans_handle *trans,
+			   struct btrfs_root *root, struct btrfs_path *path,
+			   struct btrfs_disk_key *key, int level)
 {
 	int i;
-	int ret = 0;
 	struct extent_buffer *t;
 
 	for (i = level; i < BTRFS_MAX_LEVEL; i++) {
@@ -1885,7 +1882,6 @@ static int fixup_low_keys(struct btrfs_trans_handle *trans,
 		if (tslot != 0)
 			break;
 	}
-	return ret;
 }
 
 /*
@@ -2626,9 +2622,7 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans,
 		clean_tree_block(trans, root, right);
 
 	btrfs_item_key(right, &disk_key, 0);
-	wret = fixup_low_keys(trans, root, path, &disk_key, 1);
-	if (wret)
-		ret = wret;
+	fixup_low_keys(trans, root, path, &disk_key, 1);
 
 	/* then fixup the leaf pointer in the path */
 	if (path->slots[0] < push_items) {
@@ -2999,12 +2993,9 @@ again:
 			free_extent_buffer(path->nodes[0]);
 			path->nodes[0] = right;
 			path->slots[0] = 0;
-			if (path->slots[1] == 0) {
-				wret = fixup_low_keys(trans, root,
-						path, &disk_key, 1);
-				if (wret)
-					ret = wret;
-			}
+			if (path->slots[1] == 0)
+				fixup_low_keys(trans, root, path,
+					       &disk_key, 1);
 		}
 		btrfs_mark_buffer_dirty(right);
 		return ret;
@@ -3527,7 +3518,7 @@ int btrfs_insert_some_items(struct btrfs_trans_handle *trans,
 	ret = 0;
 	if (slot == 0) {
 		btrfs_cpu_key_to_disk(&disk_key, cpu_key);
-		ret = fixup_low_keys(trans, root, path, &disk_key, 1);
+		fixup_low_keys(trans, root, path, &disk_key, 1);
 	}
 
 	if (btrfs_leaf_free_space(root, leaf) < 0) {
@@ -3555,7 +3546,6 @@ int setup_items_for_insert(struct btrfs_trans_handle *trans,
 	u32 nritems;
 	unsigned int data_end;
 	struct btrfs_disk_key disk_key;
-	int ret;
 	struct extent_buffer *leaf;
 	int slot;
 
@@ -3616,10 +3606,9 @@ int setup_items_for_insert(struct btrfs_trans_handle *trans,
 
 	btrfs_set_header_nritems(leaf, nritems + nr);
 
-	ret = 0;
 	if (slot == 0) {
 		btrfs_cpu_key_to_disk(&disk_key, cpu_key);
-		ret = fixup_low_keys(trans, root, path, &disk_key, 1);
+		fixup_low_keys(trans, root, path, &disk_key, 1);
 	}
 	btrfs_unlock_up_safe(path, 1);
 	btrfs_mark_buffer_dirty(leaf);
@@ -3706,7 +3695,6 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 	struct extent_buffer *parent = path->nodes[level];
 	u32 nritems;
 	int ret = 0;
-	int wret;
 
 	nritems = btrfs_header_nritems(parent);
 	if (slot != nritems - 1) {
@@ -3726,9 +3714,7 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		struct btrfs_disk_key disk_key;
 
 		btrfs_node_key(parent, &disk_key, 0);
-		wret = fixup_low_keys(trans, root, path, &disk_key, level + 1);
-		if (wret)
-			ret = wret;
+		fixup_low_keys(trans, root, path, &disk_key, level + 1);
 	}
 	btrfs_mark_buffer_dirty(parent);
 	return ret;
@@ -3831,10 +3817,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 			struct btrfs_disk_key disk_key;
 
 			btrfs_item_key(leaf, &disk_key, 0);
-			wret = fixup_low_keys(trans, root, path,
-					      &disk_key, 1);
-			if (wret)
-				ret = wret;
+			fixup_low_keys(trans, root, path, &disk_key, 1);
 		}
 
 		/* delete the leaf if it is mostly empty */
#58 lore raw

PATCH 48/66 btrfs: setup_items_for_insert should return void

In reply to Jeff Mahoney

setup_items_for_insert now has no error conditions and should return void.

---
 fs/btrfs/ctree.c         |   26 ++++++++++----------------
 fs/btrfs/ctree.h         |    8 ++++----
 fs/btrfs/delayed-inode.c |    6 ++----
 3 files changed, 16 insertions(+), 24 deletions(-)
fs/btrfs/ctree.c +10 -16
index dedd3a1..fdaddcc 100644
@@ -2516,7 +2516,6 @@ static noinline int __push_leaf_left(struct btrfs_trans_handle *trans,
 	u32 old_left_nritems;
 	u32 nr;
 	int ret = 0;
-	int wret;
 	u32 this_item_size;
 	u32 old_left_item_size;
 
@@ -3212,11 +3211,9 @@ int btrfs_duplicate_item(struct btrfs_trans_handle *trans,
 		return ret;
 
 	path->slots[0]++;
-	ret = setup_items_for_insert(trans, root, path, new_key, &item_size,
-				     item_size, item_size +
-				     sizeof(struct btrfs_item), 1);
-	BUG_ON(ret);
-
+	setup_items_for_insert(trans, root, path, new_key, &item_size,
+			       item_size, item_size +
+			       sizeof(struct btrfs_item), 1);
 	leaf = path->nodes[0];
 	memcpy_extent_buffer(leaf,
 			     btrfs_item_ptr_offset(leaf, path->slots[0]),
@@ -3536,10 +3533,10 @@ out:
  * to save stack depth by doing the bulk of the work in a function
  * that doesn't call btrfs_search_slot
  */
-int setup_items_for_insert(struct btrfs_trans_handle *trans,
-			   struct btrfs_root *root, struct btrfs_path *path,
-			   struct btrfs_key *cpu_key, u32 *data_size,
-			   u32 total_data, u32 total_size, int nr)
+void setup_items_for_insert(struct btrfs_trans_handle *trans,
+			    struct btrfs_root *root, struct btrfs_path *path,
+			    struct btrfs_key *cpu_key, u32 *data_size,
+			    u32 total_data, u32 total_size, int nr)
 {
 	struct btrfs_item *item;
 	int i;
@@ -3617,7 +3614,6 @@ int setup_items_for_insert(struct btrfs_trans_handle *trans,
 		btrfs_print_leaf(root, leaf);
 		BUG();
 	}
-	return ret;
 }
 
 /*
@@ -3644,16 +3640,14 @@ int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
 	if (ret == 0)
 		return -EEXIST;
 	if (ret < 0)
-		goto out;
+		return ret;
 
 	slot = path->slots[0];
 	BUG_ON(slot < 0);
 
-	ret = setup_items_for_insert(trans, root, path, cpu_key, data_size,
+	setup_items_for_insert(trans, root, path, cpu_key, data_size,
 			       total_data, total_size, nr);
-
-out:
-	return ret;
+	return 0;
 }
 
 /*
fs/btrfs/ctree.h +4 -4
index c866167..ea47c73 100644
@@ -2344,10 +2344,10 @@ static inline int btrfs_del_item(struct btrfs_trans_handle *trans,
 	return btrfs_del_items(trans, root, path, path->slots[0], 1);
 }
 
-int setup_items_for_insert(struct btrfs_trans_handle *trans,
-			   struct btrfs_root *root, struct btrfs_path *path,
-			   struct btrfs_key *cpu_key, u32 *data_size,
-			   u32 total_data, u32 total_size, int nr);
+void setup_items_for_insert(struct btrfs_trans_handle *trans,
+			    struct btrfs_root *root, struct btrfs_path *path,
+			    struct btrfs_key *cpu_key, u32 *data_size,
+			    u32 total_data, u32 total_size, int nr);
 int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
 		      *root, struct btrfs_key *key, void *data, u32 data_size);
 int btrfs_insert_empty_items(struct btrfs_trans_handle *trans,
fs/btrfs/delayed-inode.c +2 -4
index b52c672..6211997 100644
@@ -738,10 +738,8 @@ static int btrfs_batch_insert_items(struct btrfs_trans_handle *trans,
 	btrfs_clear_path_blocking(path, NULL, 0);
 
 	/* insert the keys of the items */
-	ret = setup_items_for_insert(trans, root, path, keys, data_size,
-				     total_data_size, total_size, nitems);
-	if (ret)
-		goto error;
+	setup_items_for_insert(trans, root, path, keys, data_size,
+			       total_data_size, total_size, nitems);
 
 	/* insert the dir index items */
 	slot = path->slots[0];
#59 lore raw

PATCH 49/66 btrfs: del_ptr should return void

In reply to Jeff Mahoney

With fixup_low_keys now returning void, there are no error conditions for del_ptr to report so it should return void. We set ret = 0 explicitly in btrfs_del_items but I'm not convinced that the error handling code already there is correct.

---
 fs/btrfs/ctree.c |   39 +++++++++++++--------------------------
 1 files changed, 13 insertions(+), 26 deletions(-)
fs/btrfs/ctree.c +13 -26
index fdaddcc..c605fb3 100644
@@ -36,7 +36,7 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
 			      struct btrfs_root *root,
 			      struct extent_buffer *dst_buf,
 			      struct extent_buffer *src_buf);
-static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		   struct btrfs_path *path, int level, int slot);
 
 struct btrfs_path *btrfs_alloc_path(void)
@@ -994,10 +994,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
 		if (btrfs_header_nritems(right) == 0) {
 			clean_tree_block(trans, root, right);
 			btrfs_tree_unlock(right);
-			wret = del_ptr(trans, root, path, level + 1, pslot +
-				       1);
-			if (wret)
-				ret = wret;
+			del_ptr(trans, root, path, level + 1, pslot + 1);
 			root_sub_used(root, right->len);
 			btrfs_free_tree_block(trans, root, right, 0, 1);
 			free_extent_buffer(right);
@@ -1035,9 +1032,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
 	if (btrfs_header_nritems(mid) == 0) {
 		clean_tree_block(trans, root, mid);
 		btrfs_tree_unlock(mid);
-		wret = del_ptr(trans, root, path, level + 1, pslot);
-		if (wret)
-			ret = wret;
+		del_ptr(trans, root, path, level + 1, pslot);
 		root_sub_used(root, mid->len);
 		btrfs_free_tree_block(trans, root, mid, 0, 1);
 		free_extent_buffer(mid);
@@ -3683,12 +3678,11 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
  * the tree should have been previously balanced so the deletion does not
  * empty a node.
  */
-static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-		   struct btrfs_path *path, int level, int slot)
+static void del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+		    struct btrfs_path *path, int level, int slot)
 {
 	struct extent_buffer *parent = path->nodes[level];
 	u32 nritems;
-	int ret = 0;
 
 	nritems = btrfs_header_nritems(parent);
 	if (slot != nritems - 1) {
@@ -3711,7 +3705,6 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		fixup_low_keys(trans, root, path, &disk_key, level + 1);
 	}
 	btrfs_mark_buffer_dirty(parent);
-	return ret;
 }
 
 /*
@@ -3724,17 +3717,13 @@ static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
  * The path must have already been setup for deleting the leaf, including
  * all the proper balancing.  path->nodes[1] must be locked.
  */
-static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
-				   struct btrfs_root *root,
-				   struct btrfs_path *path,
-				   struct extent_buffer *leaf)
+static noinline void btrfs_del_leaf(struct btrfs_trans_handle *trans,
+				    struct btrfs_root *root,
+				    struct btrfs_path *path,
+				    struct extent_buffer *leaf)
 {
-	int ret;
-
 	WARN_ON(btrfs_header_generation(leaf) != trans->transid);
-	ret = del_ptr(trans, root, path, 1, path->slots[1]);
-	if (ret)
-		return ret;
+	del_ptr(trans, root, path, 1, path->slots[1]);
 
 	/*
 	 * btrfs_free_extent is expensive, we want to make sure we
@@ -3745,7 +3734,6 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans,
 	root_sub_used(root, leaf->len);
 
 	btrfs_free_tree_block(trans, root, leaf, 0, 1);
-	return 0;
 }
 /*
  * delete the item at the leaf level in path.  If that empties
@@ -3802,8 +3790,7 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		} else {
 			btrfs_set_path_blocking(path);
 			clean_tree_block(trans, root, leaf);
-			ret = btrfs_del_leaf(trans, root, path, leaf);
-			BUG_ON(ret);
+			btrfs_del_leaf(trans, root, path, leaf);
 		}
 	} else {
 		int used = leaf_space_used(leaf, 0, nritems);
@@ -3839,9 +3826,9 @@ int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 
 			if (btrfs_header_nritems(leaf) == 0) {
 				path->slots[1] = slot;
-				ret = btrfs_del_leaf(trans, root, path, leaf);
-				BUG_ON(ret);
+				btrfs_del_leaf(trans, root, path, leaf);
 				free_extent_buffer(leaf);
+				ret = 0;
 			} else {
 				/* if we're still in the path, make sure
 				 * we're dirty.  Otherwise, one of the
#60 lore raw

PATCH 50/66 btrfs: insert_ptr should return void

In reply to Jeff Mahoney

insert_ptr has no error conditions and should return void.

---
 fs/btrfs/ctree.c |   46 +++++++++++++---------------------------------
 1 files changed, 13 insertions(+), 33 deletions(-)
fs/btrfs/ctree.c +13 -33
index c605fb3..2604ec4 100644
@@ -2114,12 +2114,11 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
  *
  * slot and level indicate where you want the key to go, and
  * blocknr is the block the key points to.
- *
- * returns zero on success and < 0 on any error
  */
-static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
-		      *root, struct btrfs_path *path, struct btrfs_disk_key
-		      *key, u64 bytenr, int slot, int level)
+static void insert_ptr(struct btrfs_trans_handle *trans,
+		       struct btrfs_root *root, struct btrfs_path *path,
+		       struct btrfs_disk_key *key, u64 bytenr,
+		       int slot, int level)
 {
 	struct extent_buffer *lower;
 	int nritems;
@@ -2129,8 +2128,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
 	lower = path->nodes[level];
 	nritems = btrfs_header_nritems(lower);
 	BUG_ON(slot > nritems);
-	if (nritems == BTRFS_NODEPTRS_PER_BLOCK(root))
-		BUG();
+	BUG_ON(nritems == BTRFS_NODEPTRS_PER_BLOCK(root));
 	if (slot != nritems) {
 		memmove_extent_buffer(lower,
 			      btrfs_node_key_ptr_offset(slot + 1),
@@ -2143,7 +2141,6 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
 	btrfs_set_node_ptr_generation(lower, slot, trans->transid);
 	btrfs_set_header_nritems(lower, nritems + 1);
 	btrfs_mark_buffer_dirty(lower);
-	return 0;
 }
 
 /*
@@ -2164,7 +2161,6 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
 	struct btrfs_disk_key disk_key;
 	int mid;
 	int ret;
-	int wret;
 	u32 c_nritems;
 
 	c = path->nodes[level];
@@ -2221,11 +2217,8 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
 	btrfs_mark_buffer_dirty(c);
 	btrfs_mark_buffer_dirty(split);
 
-	wret = insert_ptr(trans, root, path, &disk_key, split->start,
-			  path->slots[level + 1] + 1,
-			  level + 1);
-	if (wret)
-		ret = wret;
+	insert_ptr(trans, root, path, &disk_key, split->start,
+		   path->slots[level + 1] + 1, level + 1);
 
 	if (path->slots[level] >= mid) {
 		path->slots[level] -= mid;
@@ -2722,8 +2715,6 @@ static noinline int copy_for_split(struct btrfs_trans_handle *trans,
 	int data_copy_size;
 	int rt_data_off;
 	int i;
-	int ret = 0;
-	int wret;
 	struct btrfs_disk_key disk_key;
 
 	nritems = nritems - mid;
@@ -2751,12 +2742,9 @@ static noinline int copy_for_split(struct btrfs_trans_handle *trans,
 	}
 
 	btrfs_set_header_nritems(l, mid);
-	ret = 0;
 	btrfs_item_key(right, &disk_key, 0);
-	wret = insert_ptr(trans, root, path, &disk_key, right->start,
-			  path->slots[1] + 1, 1);
-	if (wret)
-		ret = wret;
+	insert_ptr(trans, root, path, &disk_key, right->start,
+		   path->slots[1] + 1, 1);
 
 	btrfs_mark_buffer_dirty(right);
 	btrfs_mark_buffer_dirty(l);
@@ -2775,7 +2763,7 @@ static noinline int copy_for_split(struct btrfs_trans_handle *trans,
 
 	BUG_ON(path->slots[0] < 0);
 
-	return ret;
+	return 0;
 }
 
 /*
@@ -2964,12 +2952,8 @@ again:
 	if (split == 0) {
 		if (mid <= slot) {
 			btrfs_set_header_nritems(right, 0);
-			wret = insert_ptr(trans, root, path,
-					  &disk_key, right->start,
-					  path->slots[1] + 1, 1);
-			if (wret)
-				ret = wret;
-
+			insert_ptr(trans, root, path, &disk_key, right->start,
+				   path->slots[1] + 1, 1);
 			btrfs_tree_unlock(path->nodes[0]);
 			free_extent_buffer(path->nodes[0]);
 			path->nodes[0] = right;
@@ -2977,12 +2961,8 @@ again:
 			path->slots[1] += 1;
 		} else {
 			btrfs_set_header_nritems(right, 0);
-			wret = insert_ptr(trans, root, path,
-					  &disk_key,
-					  right->start,
+			insert_ptr(trans, root, path, &disk_key, right->start,
 					  path->slots[1], 1);
-			if (wret)
-				ret = wret;
 			btrfs_tree_unlock(path->nodes[0]);
 			free_extent_buffer(path->nodes[0]);
 			path->nodes[0] = right;
#61 lore raw

PATCH 51/66 btrfs: add_delayed_ref_head should return void

In reply to Jeff Mahoney

add_delayed_ref_head has no error conditions and should return void.

---
 fs/btrfs/delayed-ref.c |   29 ++++++++++-------------------
 1 files changed, 10 insertions(+), 19 deletions(-)
fs/btrfs/delayed-ref.c +10 -19
index 125cf76..caa9ade 100644
@@ -390,10 +390,10 @@ update_existing_head_ref(struct btrfs_delayed_ref_node *existing,
  * this does all the dirty work in terms of maintaining the correct
  * overall modification count.
  */
-static noinline int add_delayed_ref_head(struct btrfs_trans_handle *trans,
-					struct btrfs_delayed_ref_node *ref,
-					u64 bytenr, u64 num_bytes,
-					int action, int is_data)
+static noinline void add_delayed_ref_head(struct btrfs_trans_handle *trans,
+					 struct btrfs_delayed_ref_node *ref,
+					 u64 bytenr, u64 num_bytes,
+					 int action, int is_data)
 {
 	struct btrfs_delayed_ref_node *existing;
 	struct btrfs_delayed_ref_head *head_ref = NULL;
@@ -462,7 +462,6 @@ static noinline int add_delayed_ref_head(struct btrfs_trans_handle *trans,
 		delayed_refs->num_entries++;
 		trans->delayed_ref_updates++;
 	}
-	return 0;
 }
 
 /*
@@ -610,10 +609,8 @@ int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
 	 * insert both the head node and the new ref without dropping
 	 * the spin lock
 	 */
-	ret = add_delayed_ref_head(trans, &head_ref->node, bytenr, num_bytes,
-				   action, 0);
-	BUG_ON(ret);
-
+	add_delayed_ref_head(trans, &head_ref->node, bytenr, num_bytes,
+			     action, 0);
 	ret = add_delayed_tree_ref(trans, &ref->node, bytenr, num_bytes,
 				   parent, ref_root, level, action);
 	BUG_ON(ret);
@@ -655,10 +652,8 @@ int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
 	 * insert both the head node and the new ref without dropping
 	 * the spin lock
 	 */
-	ret = add_delayed_ref_head(trans, &head_ref->node, bytenr, num_bytes,
-				   action, 1);
-	BUG_ON(ret);
-
+	add_delayed_ref_head(trans, &head_ref->node, bytenr, num_bytes,
+			     action, 1);
 	ret = add_delayed_data_ref(trans, &ref->node, bytenr, num_bytes,
 				   parent, ref_root, owner, offset, action);
 	BUG_ON(ret);
@@ -672,7 +667,6 @@ int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
 {
 	struct btrfs_delayed_ref_head *head_ref;
 	struct btrfs_delayed_ref_root *delayed_refs;
-	int ret;
 
 	head_ref = kmalloc(sizeof(*head_ref), GFP_NOFS);
 	if (!head_ref)
@@ -683,11 +677,8 @@ int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
 	delayed_refs = &trans->transaction->delayed_refs;
 	spin_lock(&delayed_refs->lock);
 
-	ret = add_delayed_ref_head(trans, &head_ref->node, bytenr,
-				   num_bytes, BTRFS_UPDATE_DELAYED_HEAD,
-				   extent_op->is_data);
-	BUG_ON(ret);
-
+	add_delayed_ref_head(trans, &head_ref->node, bytenr, num_bytes,
+			     BTRFS_UPDATE_DELAYED_HEAD, extent_op->is_data);
 	spin_unlock(&delayed_refs->lock);
 	return 0;
 }
#62 lore raw

PATCH 52/66 btrfs: add_delayed_tree_ref should return void

In reply to Jeff Mahoney

add_delayed_tree_ref has no error conditions and should return void.

---
 fs/btrfs/delayed-ref.c |   15 ++++++---------
 1 files changed, 6 insertions(+), 9 deletions(-)
fs/btrfs/delayed-ref.c +6 -9
index caa9ade..3ae2401 100644
@@ -467,10 +467,10 @@ static noinline void add_delayed_ref_head(struct btrfs_trans_handle *trans,
 /*
  * helper to insert a delayed tree ref into the rbtree.
  */
-static noinline int add_delayed_tree_ref(struct btrfs_trans_handle *trans,
-					 struct btrfs_delayed_ref_node *ref,
-					 u64 bytenr, u64 num_bytes, u64 parent,
-					 u64 ref_root, int level, int action)
+static noinline void add_delayed_tree_ref(struct btrfs_trans_handle *trans,
+					  struct btrfs_delayed_ref_node *ref,
+					  u64 bytenr, u64 num_bytes, u64 parent,
+					  u64 ref_root, int level, int action)
 {
 	struct btrfs_delayed_ref_node *existing;
 	struct btrfs_delayed_tree_ref *full_ref;
@@ -515,7 +515,6 @@ static noinline int add_delayed_tree_ref(struct btrfs_trans_handle *trans,
 		delayed_refs->num_entries++;
 		trans->delayed_ref_updates++;
 	}
-	return 0;
 }
 
 /*
@@ -587,7 +586,6 @@ int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
 	struct btrfs_delayed_tree_ref *ref;
 	struct btrfs_delayed_ref_head *head_ref;
 	struct btrfs_delayed_ref_root *delayed_refs;
-	int ret;
 
 	BUG_ON(extent_op && extent_op->is_data);
 	ref = kmalloc(sizeof(*ref), GFP_NOFS);
@@ -611,9 +609,8 @@ int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
 	 */
 	add_delayed_ref_head(trans, &head_ref->node, bytenr, num_bytes,
 			     action, 0);
-	ret = add_delayed_tree_ref(trans, &ref->node, bytenr, num_bytes,
-				   parent, ref_root, level, action);
-	BUG_ON(ret);
+	add_delayed_tree_ref(trans, &ref->node, bytenr, num_bytes, parent,
+			     ref_root, level, action);
 	spin_unlock(&delayed_refs->lock);
 	return 0;
 }
#63 lore raw

PATCH 53/66 btrfs: add_delayed_data_ref should return void

In reply to Jeff Mahoney

add_delayed_data_ref has no error conditions and should return void.

---
 fs/btrfs/delayed-ref.c |   17 +++++++----------
 1 files changed, 7 insertions(+), 10 deletions(-)
fs/btrfs/delayed-ref.c +7 -10
index 3ae2401..b004960 100644
@@ -520,11 +520,11 @@ static noinline void add_delayed_tree_ref(struct btrfs_trans_handle *trans,
 /*
  * helper to insert a delayed data ref into the rbtree.
  */
-static noinline int add_delayed_data_ref(struct btrfs_trans_handle *trans,
-					 struct btrfs_delayed_ref_node *ref,
-					 u64 bytenr, u64 num_bytes, u64 parent,
-					 u64 ref_root, u64 owner, u64 offset,
-					 int action)
+static noinline void add_delayed_data_ref(struct btrfs_trans_handle *trans,
+					  struct btrfs_delayed_ref_node *ref,
+					  u64 bytenr, u64 num_bytes, u64 parent,
+					  u64 ref_root, u64 owner, u64 offset,
+					  int action)
 {
 	struct btrfs_delayed_ref_node *existing;
 	struct btrfs_delayed_data_ref *full_ref;
@@ -570,7 +570,6 @@ static noinline int add_delayed_data_ref(struct btrfs_trans_handle *trans,
 		delayed_refs->num_entries++;
 		trans->delayed_ref_updates++;
 	}
-	return 0;
 }
 
 /*
@@ -627,7 +626,6 @@ int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
 	struct btrfs_delayed_data_ref *ref;
 	struct btrfs_delayed_ref_head *head_ref;
 	struct btrfs_delayed_ref_root *delayed_refs;
-	int ret;
 
 	BUG_ON(extent_op && !extent_op->is_data);
 	ref = kmalloc(sizeof(*ref), GFP_NOFS);
@@ -651,9 +649,8 @@ int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
 	 */
 	add_delayed_ref_head(trans, &head_ref->node, bytenr, num_bytes,
 			     action, 1);
-	ret = add_delayed_data_ref(trans, &ref->node, bytenr, num_bytes,
-				   parent, ref_root, owner, offset, action);
-	BUG_ON(ret);
+	add_delayed_data_ref(trans, &ref->node, bytenr, num_bytes, parent,
+			     ref_root, owner, offset, action);
 	spin_unlock(&delayed_refs->lock);
 	return 0;
 }
#64 lore raw

PATCH 54/66 btrfs: Fix kfree of member instead of structure

In reply to Jeff Mahoney

Correctness fix: The kfree calls in the add_delayed_* functions free the node that's passed into it, but the node is a member of another structure. It works because it's always the first member of the containing structure, but it should really be using the containing structure itself.

---
 fs/btrfs/delayed-ref.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
fs/btrfs/delayed-ref.c +3 -3
index b004960..e388ca3 100644
@@ -455,7 +455,7 @@ static noinline void add_delayed_ref_head(struct btrfs_trans_handle *trans,
 		 * we've updated the existing ref, free the newly
 		 * allocated ref
 		 */
-		kfree(ref);
+		kfree(head_ref);
 	} else {
 		delayed_refs->num_heads++;
 		delayed_refs->num_heads_ready++;
@@ -510,7 +510,7 @@ static noinline void add_delayed_tree_ref(struct btrfs_trans_handle *trans,
 		 * we've updated the existing ref, free the newly
 		 * allocated ref
 		 */
-		kfree(ref);
+		kfree(full_ref);
 	} else {
 		delayed_refs->num_entries++;
 		trans->delayed_ref_updates++;
@@ -565,7 +565,7 @@ static noinline void add_delayed_data_ref(struct btrfs_trans_handle *trans,
 		 * we've updated the existing ref, free the newly
 		 * allocated ref
 		 */
-		kfree(ref);
+		kfree(full_ref);
 	} else {
 		delayed_refs->num_entries++;
 		trans->delayed_ref_updates++;
#65 lore raw

PATCH 55/66 btrfs: Use mempools for delayed refs

In reply to Jeff Mahoney

This patch converts the delayed ref code to use slab cache-backed mempools for allocating its nodes.

The allocations happen deep in the call path where error recovery is impossible.

By using mempools, we ensure that the allocations can't fail. Each mempool keeps a page of structures available for each type.

This also has an advantage of eliminating the error path from a big chunk of code, simplifying the error handling.

---
 fs/btrfs/delayed-ref.c |  119 ++++++++++++++++++++++++++++++++++++++----------
 fs/btrfs/delayed-ref.h |    6 ++-
 fs/btrfs/super.c       |    9 +++-
 3 files changed, 107 insertions(+), 27 deletions(-)
fs/btrfs/delayed-ref.c +94 -25
index e388ca3..a70c40d 100644
@@ -18,11 +18,20 @@
 
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/mempool.h>
 #include <linux/sort.h>
 #include "ctree.h"
 #include "delayed-ref.h"
 #include "transaction.h"
 
+static struct kmem_cache *ref_head_cache;
+static struct kmem_cache *tree_ref_cache;
+static struct kmem_cache *data_ref_cache;
+
+static mempool_t *ref_head_pool;
+static mempool_t *tree_ref_pool;
+static mempool_t *data_ref_pool;
+
 /*
  * delayed back reference update tracking.  For subvolume trees
  * we queue up extent allocations and backref maintenance for
@@ -455,7 +464,7 @@ static noinline void add_delayed_ref_head(struct btrfs_trans_handle *trans,
 		 * we've updated the existing ref, free the newly
 		 * allocated ref
 		 */
-		kfree(head_ref);
+		mempool_free(head_ref, ref_head_pool);
 	} else {
 		delayed_refs->num_heads++;
 		delayed_refs->num_heads_ready++;
@@ -510,7 +519,7 @@ static noinline void add_delayed_tree_ref(struct btrfs_trans_handle *trans,
 		 * we've updated the existing ref, free the newly
 		 * allocated ref
 		 */
-		kfree(full_ref);
+		mempool_free(full_ref, tree_ref_pool);
 	} else {
 		delayed_refs->num_entries++;
 		trans->delayed_ref_updates++;
@@ -565,7 +574,7 @@ static noinline void add_delayed_data_ref(struct btrfs_trans_handle *trans,
 		 * we've updated the existing ref, free the newly
 		 * allocated ref
 		 */
-		kfree(full_ref);
+		mempool_free(full_ref, data_ref_pool);
 	} else {
 		delayed_refs->num_entries++;
 		trans->delayed_ref_updates++;
@@ -587,15 +596,8 @@ int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
 	struct btrfs_delayed_ref_root *delayed_refs;
 
 	BUG_ON(extent_op && extent_op->is_data);
-	ref = kmalloc(sizeof(*ref), GFP_NOFS);
-	if (!ref)
-		return -ENOMEM;
-
-	head_ref = kmalloc(sizeof(*head_ref), GFP_NOFS);
-	if (!head_ref) {
-		kfree(ref);
-		return -ENOMEM;
-	}
+	ref = mempool_alloc(tree_ref_pool, GFP_NOFS);
+	head_ref = mempool_alloc(ref_head_pool, GFP_NOFS);
 
 	head_ref->extent_op = extent_op;
 
@@ -628,15 +630,8 @@ int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
 	struct btrfs_delayed_ref_root *delayed_refs;
 
 	BUG_ON(extent_op && !extent_op->is_data);
-	ref = kmalloc(sizeof(*ref), GFP_NOFS);
-	if (!ref)
-		return -ENOMEM;
-
-	head_ref = kmalloc(sizeof(*head_ref), GFP_NOFS);
-	if (!head_ref) {
-		kfree(ref);
-		return -ENOMEM;
-	}
+	ref = mempool_alloc(data_ref_pool, GFP_NOFS);
+	head_ref = mempool_alloc(ref_head_pool, GFP_NOFS);
 
 	head_ref->extent_op = extent_op;
 
@@ -662,10 +657,7 @@ int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
 	struct btrfs_delayed_ref_head *head_ref;
 	struct btrfs_delayed_ref_root *delayed_refs;
 
-	head_ref = kmalloc(sizeof(*head_ref), GFP_NOFS);
-	if (!head_ref)
-		return -ENOMEM;
-
+	head_ref = mempool_alloc(ref_head_pool, GFP_NOFS);
 	head_ref->extent_op = extent_op;
 
 	delayed_refs = &trans->transaction->delayed_refs;
@@ -694,3 +686,80 @@ btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr)
 		return btrfs_delayed_node_to_head(ref);
 	return NULL;
 }
+
+void btrfs_free_delayed_ref(struct btrfs_delayed_ref_node *ref)
+{
+	if (!ref->type)
+		mempool_free(ref, ref_head_pool);
+	else if (ref->type == BTRFS_SHARED_BLOCK_REF_KEY ||
+		 ref->type == BTRFS_TREE_BLOCK_REF_KEY)
+		mempool_free(ref, tree_ref_pool);
+	else if (ref->type == BTRFS_SHARED_DATA_REF_KEY ||
+		 ref->type == BTRFS_EXTENT_DATA_REF_KEY)
+		mempool_free(ref, data_ref_pool);
+	else
+		BUG();
+}
+
+void
+btrfs_destroy_delayed_ref_caches(void)
+{
+	if (data_ref_pool)
+		mempool_destroy(data_ref_pool);
+	if (data_ref_cache)
+		kmem_cache_destroy(data_ref_cache);
+
+	if (tree_ref_pool)
+		mempool_destroy(tree_ref_pool);
+	if (tree_ref_cache)
+		kmem_cache_destroy(tree_ref_cache);
+
+	if (ref_head_pool)
+		mempool_destroy(ref_head_pool);
+	if (ref_head_cache)
+		kmem_cache_destroy(ref_head_cache);
+}
+
+int __init
+btrfs_create_delayed_ref_caches(void)
+{
+	int objsize = sizeof(struct btrfs_delayed_ref_head);
+	ref_head_cache = kmem_cache_create("btrfs_delayed_ref_head", objsize,
+					   0, 0, NULL);
+	if (!ref_head_cache)
+		goto error;
+
+	ref_head_pool = mempool_create_slab_pool(PAGE_SIZE/objsize,
+						 ref_head_cache);
+	if (!ref_head_pool)
+		goto error;
+
+
+	objsize = sizeof(struct btrfs_delayed_tree_ref);
+	tree_ref_cache = kmem_cache_create("btrfs_delayed_tree_ref", objsize,
+					   0, 0, NULL);
+	if (!tree_ref_cache)
+		goto error;
+
+	tree_ref_pool = mempool_create_slab_pool(PAGE_SIZE/objsize,
+						 tree_ref_cache);
+	if (!tree_ref_pool)
+		goto error;
+
+
+	objsize = sizeof(struct btrfs_delayed_data_ref);
+	data_ref_cache = kmem_cache_create("btrfs_delayed_data_ref", objsize,
+					   0, 0, NULL);
+	if (!data_ref_cache)
+		goto error;
+
+	data_ref_pool = mempool_create_slab_pool(PAGE_SIZE/objsize,
+						 data_ref_cache);
+	if (!data_ref_pool)
+		goto error;
+
+	return 0;
+error:
+	btrfs_destroy_delayed_ref_caches();
+	return -ENOMEM;
+}
fs/btrfs/delayed-ref.h +5 -1
index e287e3b..6c41d8d 100644
@@ -142,12 +142,13 @@ struct btrfs_delayed_ref_root {
 	u64 run_delayed_start;
 };
 
+void btrfs_free_delayed_ref(struct btrfs_delayed_ref_node *ref);
 static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref)
 {
 	WARN_ON(atomic_read(&ref->refs) == 0);
 	if (atomic_dec_and_test(&ref->refs)) {
 		WARN_ON(ref->in_tree);
-		kfree(ref);
+		btrfs_free_delayed_ref(ref);
 	}
 }
 
@@ -202,4 +203,7 @@ btrfs_delayed_node_to_head(struct btrfs_delayed_ref_node *node)
 	WARN_ON(!btrfs_delayed_ref_is_head(node));
 	return container_of(node, struct btrfs_delayed_ref_head, node);
 }
+
+int btrfs_create_delayed_ref_caches(void);
+void btrfs_destroy_delayed_ref_caches(void);
 #endif
fs/btrfs/super.c +8 -1
index 26e1dcf..9719312 100644
@@ -1369,13 +1369,19 @@ static int __init init_btrfs_fs(void)
 	if (err)
 		goto free_delayed_inode;
 
-	err = register_filesystem(&btrfs_fs_type);
+	err = btrfs_create_delayed_ref_caches();
 	if (err)
 		goto unregister_ioctl;
 
+	err = register_filesystem(&btrfs_fs_type);
+	if (err)
+		goto free_delayed_ref_caches;
+
 	printk(KERN_INFO "%s loaded\n", BTRFS_BUILD_VERSION);
 	return 0;
 
+free_delayed_ref_caches:
+	btrfs_destroy_delayed_ref_caches();
 unregister_ioctl:
 	btrfs_interface_exit();
 free_delayed_inode:
@@ -1394,6 +1400,7 @@ free_compress:
 
 static void __exit exit_btrfs_fs(void)
 {
+	btrfs_destroy_delayed_ref_caches();
 	btrfs_destroy_cachep();
 	btrfs_delayed_inode_exit();
 	extent_map_exit();
#66 lore raw

PATCH 56/66 btrfs: Delayed ref mempool functions should return void

In reply to Jeff Mahoney

Now that the delayed ref code uses mempools, allocations can't fail, and there are no more error conditions to report.

This patch makes the following functions return void:
- btrfs_alloc_reserved_file_extent
- btrfs_add_delayed_tree_ref
- btrfs_add_delayed_data_ref
- btrfs_add_delayed_extent_op

---
 fs/btrfs/ctree.h       |    8 ++--
 fs/btrfs/delayed-ref.c |   27 +++++++---------
 fs/btrfs/delayed-ref.h |   24 +++++++-------
 fs/btrfs/extent-tree.c |   78 ++++++++++++++++++++---------------------------
 fs/btrfs/inode.c       |    6 +--
 5 files changed, 63 insertions(+), 80 deletions(-)
fs/btrfs/ctree.h +4 -4
index ea47c73..f704253 100644
@@ -2179,10 +2179,10 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
 					    struct btrfs_root *root,
 					    u64 bytenr, u32 blocksize,
 					    int level);
-int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
-				     struct btrfs_root *root,
-				     u64 root_objectid, u64 owner,
-				     u64 offset, struct btrfs_key *ins);
+void btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans,
+				      struct btrfs_root *root,
+				      u64 root_objectid, u64 owner,
+				      u64 offset, struct btrfs_key *ins);
 int btrfs_alloc_logged_file_extent(struct btrfs_trans_handle *trans,
 				   struct btrfs_root *root,
 				   u64 root_objectid, u64 owner, u64 offset,
fs/btrfs/delayed-ref.c +12 -15
index a70c40d..16aea4e 100644
@@ -586,10 +586,10 @@ static noinline void add_delayed_data_ref(struct btrfs_trans_handle *trans,
  * to make sure the delayed ref is eventually processed before this
  * transaction commits.
  */
-int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
-			       u64 bytenr, u64 num_bytes, u64 parent,
-			       u64 ref_root,  int level, int action,
-			       struct btrfs_delayed_extent_op *extent_op)
+void btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
+			        u64 bytenr, u64 num_bytes, u64 parent,
+			        u64 ref_root,  int level, int action,
+			        struct btrfs_delayed_extent_op *extent_op)
 {
 	struct btrfs_delayed_tree_ref *ref;
 	struct btrfs_delayed_ref_head *head_ref;
@@ -613,17 +613,16 @@ int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
 	add_delayed_tree_ref(trans, &ref->node, bytenr, num_bytes, parent,
 			     ref_root, level, action);
 	spin_unlock(&delayed_refs->lock);
-	return 0;
 }
 
 /*
  * add a delayed data ref. it's similar to btrfs_add_delayed_tree_ref.
  */
-int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
-			       u64 bytenr, u64 num_bytes,
-			       u64 parent, u64 ref_root,
-			       u64 owner, u64 offset, int action,
-			       struct btrfs_delayed_extent_op *extent_op)
+void btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
+			        u64 bytenr, u64 num_bytes,
+			        u64 parent, u64 ref_root,
+			        u64 owner, u64 offset, int action,
+			        struct btrfs_delayed_extent_op *extent_op)
 {
 	struct btrfs_delayed_data_ref *ref;
 	struct btrfs_delayed_ref_head *head_ref;
@@ -647,12 +646,11 @@ int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
 	add_delayed_data_ref(trans, &ref->node, bytenr, num_bytes, parent,
 			     ref_root, owner, offset, action);
 	spin_unlock(&delayed_refs->lock);
-	return 0;
 }
 
-int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
-				u64 bytenr, u64 num_bytes,
-				struct btrfs_delayed_extent_op *extent_op)
+void btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
+				 u64 bytenr, u64 num_bytes,
+				 struct btrfs_delayed_extent_op *extent_op)
 {
 	struct btrfs_delayed_ref_head *head_ref;
 	struct btrfs_delayed_ref_root *delayed_refs;
@@ -666,7 +664,6 @@ int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
 	add_delayed_ref_head(trans, &head_ref->node, bytenr, num_bytes,
 			     BTRFS_UPDATE_DELAYED_HEAD, extent_op->is_data);
 	spin_unlock(&delayed_refs->lock);
-	return 0;
 }
 
 /*
fs/btrfs/delayed-ref.h +12 -12
index 6c41d8d..8b2cec2 100644
@@ -152,18 +152,18 @@ static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref)
 	}
 }
 
-int btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
-			       u64 bytenr, u64 num_bytes, u64 parent,
-			       u64 ref_root, int level, int action,
-			       struct btrfs_delayed_extent_op *extent_op);
-int btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
-			       u64 bytenr, u64 num_bytes,
-			       u64 parent, u64 ref_root,
-			       u64 owner, u64 offset, int action,
-			       struct btrfs_delayed_extent_op *extent_op);
-int btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
-				u64 bytenr, u64 num_bytes,
-				struct btrfs_delayed_extent_op *extent_op);
+void btrfs_add_delayed_tree_ref(struct btrfs_trans_handle *trans,
+			        u64 bytenr, u64 num_bytes, u64 parent,
+			        u64 ref_root, int level, int action,
+			        struct btrfs_delayed_extent_op *extent_op);
+void btrfs_add_delayed_data_ref(struct btrfs_trans_handle *trans,
+			        u64 bytenr, u64 num_bytes,
+			        u64 parent, u64 ref_root,
+			        u64 owner, u64 offset, int action,
+			        struct btrfs_delayed_extent_op *extent_op);
+void btrfs_add_delayed_extent_op(struct btrfs_trans_handle *trans,
+			         u64 bytenr, u64 num_bytes,
+				 struct btrfs_delayed_extent_op *extent_op);
 
 struct btrfs_delayed_ref_head *
 btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr);
fs/btrfs/extent-tree.c +33 -45

129 lines not on this page · raw message

fs/btrfs/inode.c +2 -4
index 1a9574f..46f3d4a 100644
@@ -1706,10 +1706,8 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
 	ins.objectid = disk_bytenr;
 	ins.offset = disk_num_bytes;
 	ins.type = BTRFS_EXTENT_ITEM_KEY;
-	ret = btrfs_alloc_reserved_file_extent(trans, root,
-					root->root_key.objectid,
-					btrfs_ino(inode), file_pos, &ins);
-	BUG_ON(ret);
+	btrfs_alloc_reserved_file_extent(trans, root, root->root_key.objectid,
+					 btrfs_ino(inode), file_pos, &ins);
 	btrfs_free_path(path);
 
 	return 0;
#67 lore raw

PATCH 57/66 btrfs: btrfs_inc_extent_ref void return prep

In reply to Jeff Mahoney

btrfs_inc_extent_ref has no error conditions, but is used via process_func in __btrfs_mod_ref which requires it to return an int.

This patch cleans up the callers to eliminate error handling that will never be used. A later patch in this series makes both btrfs_inc_extent_ref and the other function used via process_func, btrfs_inc_extent_ref, return void.

---
 fs/btrfs/file.c       |   18 ++++++++----------
 fs/btrfs/ioctl.c      |    3 +--
 fs/btrfs/relocation.c |   34 ++++++++++++++--------------------
 fs/btrfs/tree-log.c   |    9 ++++-----
 4 files changed, 27 insertions(+), 37 deletions(-)
fs/btrfs/file.c +8 -10
index 74f50ba..314c08e 100644
@@ -673,12 +673,11 @@ next_slot:
 			btrfs_mark_buffer_dirty(leaf);
 
 			if (disk_bytenr > 0) {
-				ret = btrfs_inc_extent_ref(trans, root,
-						disk_bytenr, num_bytes, 0,
-						root->root_key.objectid,
-						new_key.objectid,
-						start - extent_offset);
-				BUG_ON(ret);
+				btrfs_inc_extent_ref(trans, root,
+						     disk_bytenr, num_bytes, 0,
+						     root->root_key.objectid,
+						     new_key.objectid,
+						     start - extent_offset);
 				*hint_byte = disk_bytenr;
 			}
 			key.offset = start;
@@ -959,10 +958,9 @@ again:
 						extent_end - split);
 		btrfs_mark_buffer_dirty(leaf);
 
-		ret = btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
-					   root->root_key.objectid,
-					   ino, orig_offset);
-		BUG_ON(ret);
+		btrfs_inc_extent_ref(trans, root, bytenr, num_bytes, 0,
+				     root->root_key.objectid,
+				     ino, orig_offset);
 
 		if (split == start) {
 			key.offset = start;
fs/btrfs/ioctl.c +1 -2
index a7450b3..4cef4f1 100644
@@ -2402,12 +2402,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
 								datal);
 				if (disko) {
 					inode_add_bytes(inode, datal);
-					ret = btrfs_inc_extent_ref(trans, root,
+					btrfs_inc_extent_ref(trans, root,
 							disko, diskl, 0,
 							root->root_key.objectid,
 							btrfs_ino(inode),
 							new_key.offset - datao);
-					BUG_ON(ret);
 				}
 			} else if (type == BTRFS_FILE_EXTENT_INLINE) {
 				u64 skip = 0;
fs/btrfs/relocation.c +14 -20
index f2ff530..4c65c4e 100644
@@ -1628,11 +1628,10 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
 		dirty = 1;
 
 		key.offset -= btrfs_file_extent_offset(leaf, fi);
-		ret = btrfs_inc_extent_ref(trans, root, new_bytenr,
-					   num_bytes, parent,
-					   btrfs_header_owner(leaf),
-					   key.objectid, key.offset);
-		BUG_ON(ret);
+		btrfs_inc_extent_ref(trans, root, new_bytenr,
+				     num_bytes, parent,
+				     btrfs_header_owner(leaf),
+				     key.objectid, key.offset);
 
 		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
 					parent, btrfs_header_owner(leaf),
@@ -1803,15 +1802,11 @@ again:
 					      path->slots[level], old_ptr_gen);
 		btrfs_mark_buffer_dirty(path->nodes[level]);
 
-		ret = btrfs_inc_extent_ref(trans, src, old_bytenr, blocksize,
-					path->nodes[level]->start,
-					src->root_key.objectid, level - 1, 0);
-		BUG_ON(ret);
-		ret = btrfs_inc_extent_ref(trans, dest, new_bytenr, blocksize,
-					0, dest->root_key.objectid, level - 1,
-					0);
-		BUG_ON(ret);
-
+		btrfs_inc_extent_ref(trans, src, old_bytenr, blocksize,
+				     path->nodes[level]->start,
+				     src->root_key.objectid, level - 1, 0);
+		btrfs_inc_extent_ref(trans, dest, new_bytenr, blocksize,
+				     0, dest->root_key.objectid, level - 1, 0);
 		ret = btrfs_free_extent(trans, src, new_bytenr, blocksize,
 					path->nodes[level]->start,
 					src->root_key.objectid, level - 1, 0);
@@ -2588,12 +2583,11 @@ static int do_relocation(struct btrfs_trans_handle *trans,
 						      trans->transid);
 			btrfs_mark_buffer_dirty(upper->eb);
 
-			ret = btrfs_inc_extent_ref(trans, root,
-						node->eb->start, blocksize,
-						upper->eb->start,
-						btrfs_header_owner(upper->eb),
-						node->level, 0);
-			BUG_ON(ret);
+			btrfs_inc_extent_ref(trans, root,
+					     node->eb->start, blocksize,
+					     upper->eb->start,
+					     btrfs_header_owner(upper->eb),
+					     node->level, 0);
 
 			ret = btrfs_drop_subtree(trans, root, eb, upper->eb);
 			BUG_ON(ret);
fs/btrfs/tree-log.c +4 -5
index aac743b..feb4575 100644
@@ -588,11 +588,10 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
 			ret = btrfs_lookup_extent(root, ins.objectid,
 						ins.offset);
 			if (ret == 0) {
-				ret = btrfs_inc_extent_ref(trans, root,
-						ins.objectid, ins.offset,
-						0, root->root_key.objectid,
-						key->objectid, offset);
-				BUG_ON(ret);
+				btrfs_inc_extent_ref(trans, root, ins.objectid,
+						     ins.offset, 0,
+						     root->root_key.objectid,
+						     key->objectid, offset);
 			} else {
 				/*
 				 * insert the extent pointer in the extent
#68 lore raw

PATCH 58/66 btrfs: btrfs_free_extent void return prep

In reply to Jeff Mahoney

btrfs_free_extent has no error conditions, but is used via process_func in __btrfs_mod_ref which requires it to return an int.

This patch cleans up the callers to eliminate error handling that will never be used. The next patch makes both btrfs_free_extent and the other function used via process_func, btrfs_inc_extent_ref, return void.

---
 fs/btrfs/extent-tree.c |    8 +++-----
 fs/btrfs/file.c        |   23 +++++++++--------------
 fs/btrfs/inode.c       |    9 ++++-----
 fs/btrfs/relocation.c  |   23 +++++++++--------------
 4 files changed, 25 insertions(+), 38 deletions(-)
fs/btrfs/extent-tree.c +3 -5
index fe95f37..dc91e4d 100644
@@ -4805,13 +4805,12 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans,
 		      u64 bytenr, u64 num_bytes, u64 parent,
 		      u64 root_objectid, u64 owner, u64 offset)
 {
-	int ret;
-
 	/*
 	 * tree log blocks never actually go into the extent allocation
 	 * tree, just update pinning info and exit early.
 	 */
 	if (root_objectid == BTRFS_TREE_LOG_OBJECTID) {
+		int ret;
 		WARN_ON(owner >= BTRFS_FIRST_FREE_OBJECTID);
 		/* unlocks the pinned mutex */
 		ret = btrfs_pin_extent(root, bytenr, num_bytes, 1);
@@ -6142,9 +6141,8 @@ skip:
 			parent = 0;
 		}
 
-		ret = btrfs_free_extent(trans, root, bytenr, blocksize, parent,
-					root->root_key.objectid, level - 1, 0);
-		BUG_ON(ret);
+		btrfs_free_extent(trans, root, bytenr, blocksize, parent,
+				  root->root_key.objectid, level - 1, 0);
 	}
 	btrfs_tree_unlock(next);
 	free_extent_buffer(next);
fs/btrfs/file.c +9 -14
index 314c08e..fa8f83e 100644
@@ -747,12 +747,11 @@ next_slot:
 				extent_end = ALIGN(extent_end,
 						   root->sectorsize);
 			} else if (disk_bytenr > 0) {
-				ret = btrfs_free_extent(trans, root,
-						disk_bytenr, num_bytes, 0,
-						root->root_key.objectid,
-						key.objectid, key.offset -
-						extent_offset);
-				BUG_ON(ret);
+				btrfs_free_extent(trans, root,
+						  disk_bytenr, num_bytes, 0,
+						  root->root_key.objectid,
+						  key.objectid, key.offset -
+						  extent_offset);
 				inode_sub_bytes(inode,
 						extent_end - key.offset);
 				*hint_byte = disk_bytenr;
@@ -984,10 +983,8 @@ again:
 		extent_end = other_end;
 		del_slot = path->slots[0] + 1;
 		del_nr++;
-		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
-					0, root->root_key.objectid,
-					ino, orig_offset);
-		BUG_ON(ret);
+		btrfs_free_extent(trans, root, bytenr, num_bytes, 0,
+				  root->root_key.objectid, ino, orig_offset);
 	}
 	other_start = 0;
 	other_end = start;
@@ -1001,10 +998,8 @@ again:
 		key.offset = other_start;
 		del_slot = path->slots[0];
 		del_nr++;
-		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
-					0, root->root_key.objectid,
-					ino, orig_offset);
-		BUG_ON(ret);
+		btrfs_free_extent(trans, root, bytenr, num_bytes, 0,
+				  root->root_key.objectid, ino, orig_offset);
 	}
 	if (del_nr == 0) {
 		fi = btrfs_item_ptr(leaf, path->slots[0],
fs/btrfs/inode.c +4 -5
index 46f3d4a..d8bb54e 100644
@@ -3270,11 +3270,10 @@ delete:
 		if (found_extent && (root->ref_cows ||
 				     root == root->fs_info->tree_root)) {
 			btrfs_set_path_blocking(path);
-			ret = btrfs_free_extent(trans, root, extent_start,
-						extent_num_bytes, 0,
-						btrfs_header_owner(leaf),
-						ino, extent_offset);
-			BUG_ON(ret);
+			btrfs_free_extent(trans, root, extent_start,
+					  extent_num_bytes, 0,
+					  btrfs_header_owner(leaf),
+					  ino, extent_offset);
 		}
 
 		if (found_type == BTRFS_INODE_ITEM_KEY)
fs/btrfs/relocation.c +9 -14
index 4c65c4e..c59eb2c 100644
@@ -1633,10 +1633,9 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
 				     btrfs_header_owner(leaf),
 				     key.objectid, key.offset);
 
-		ret = btrfs_free_extent(trans, root, bytenr, num_bytes,
-					parent, btrfs_header_owner(leaf),
-					key.objectid, key.offset);
-		BUG_ON(ret);
+		btrfs_free_extent(trans, root, bytenr, num_bytes,
+				  parent, btrfs_header_owner(leaf),
+				  key.objectid, key.offset);
 	}
 	if (dirty)
 		btrfs_mark_buffer_dirty(leaf);
@@ -1807,16 +1806,12 @@ again:
 				     src->root_key.objectid, level - 1, 0);
 		btrfs_inc_extent_ref(trans, dest, new_bytenr, blocksize,
 				     0, dest->root_key.objectid, level - 1, 0);
-		ret = btrfs_free_extent(trans, src, new_bytenr, blocksize,
-					path->nodes[level]->start,
-					src->root_key.objectid, level - 1, 0);
-		BUG_ON(ret);
-
-		ret = btrfs_free_extent(trans, dest, old_bytenr, blocksize,
-					0, dest->root_key.objectid, level - 1,
-					0);
-		BUG_ON(ret);
-
+		btrfs_free_extent(trans, src, new_bytenr, blocksize,
+				  path->nodes[level]->start,
+				  src->root_key.objectid, level - 1, 0);
+		btrfs_free_extent(trans, dest, old_bytenr, blocksize,
+				  0, dest->root_key.objectid, level - 1,
+				  0);
 		btrfs_unlock_up_safe(path, 0);
 
 		ret = level;
#69 lore raw

PATCH 59/66 btrfs: __btrfs_mod_refs process_func should return void

In reply to Jeff Mahoney

__btrfs_mod_ref's process_func function pointer calls btrfs_free_extent and btrfs_inc_extent_ref, which now both return only 0. This patches makes them return void and eliminates the error condition in __btrfs_mod_ref.

---
 fs/btrfs/ctree.h       |   16 ++++++++--------
 fs/btrfs/extent-tree.c |   39 ++++++++++++++-------------------------
 2 files changed, 22 insertions(+), 33 deletions(-)
fs/btrfs/ctree.h +8 -8
@@ -2201,20 +2201,20 @@ int btrfs_set_disk_extent_flags(struct b
 				struct btrfs_root *root,
 				u64 bytenr, u64 num_bytes, u64 flags,
 				int is_data);
-int btrfs_free_extent(struct btrfs_trans_handle *trans,
-		      struct btrfs_root *root,
-		      u64 bytenr, u64 num_bytes, u64 parent,
-		      u64 root_objectid, u64 owner, u64 offset);
+void btrfs_free_extent(struct btrfs_trans_handle *trans,
+		       struct btrfs_root *root,
+		       u64 bytenr, u64 num_bytes, u64 parent,
+		       u64 root_objectid, u64 owner, u64 offset);
 
 int btrfs_free_reserved_extent(struct btrfs_root *root, u64 start, u64 len);
 void btrfs_prepare_extent_commit(struct btrfs_trans_handle *trans,
 				 struct btrfs_root *root);
 int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans,
 			       struct btrfs_root *root);
-int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
-			 struct btrfs_root *root,
-			 u64 bytenr, u64 num_bytes, u64 parent,
-			 u64 root_objectid, u64 owner, u64 offset);
+void btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
+			  struct btrfs_root *root,
+			  u64 bytenr, u64 num_bytes, u64 parent,
+			  u64 root_objectid, u64 owner, u64 offset);
 
 int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans,
 				    struct btrfs_root *root);
fs/btrfs/extent-tree.c +14 -25
@@ -1832,10 +1832,10 @@ static int btrfs_discard_extent(struct b
 	return ret;
 }
 
-int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
-			 struct btrfs_root *root,
-			 u64 bytenr, u64 num_bytes, u64 parent,
-			 u64 root_objectid, u64 owner, u64 offset)
+void btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
+			  struct btrfs_root *root,
+			  u64 bytenr, u64 num_bytes, u64 parent,
+			  u64 root_objectid, u64 owner, u64 offset)
 {
 	BUG_ON(owner < BTRFS_FIRST_FREE_OBJECTID &&
 	       root_objectid == BTRFS_TREE_LOG_OBJECTID);
@@ -1849,7 +1849,6 @@ int btrfs_inc_extent_ref(struct btrfs_tr
 					   root_objectid, owner, offset,
 					   BTRFS_ADD_DELAYED_REF, NULL);
 	}
-	return 0;
 }
 
 static int __btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
@@ -2566,9 +2565,8 @@ static int __btrfs_mod_ref(struct btrfs_
 	struct btrfs_file_extent_item *fi;
 	int i;
 	int level;
-	int ret = 0;
-	int (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *,
-			    u64, u64, u64, u64, u64, u64);
+	void (*process_func)(struct btrfs_trans_handle *, struct btrfs_root *,
+			     u64, u64, u64, u64, u64, u64);
 
 	ref_root = btrfs_header_owner(buf);
 	nritems = btrfs_header_nritems(buf);
@@ -2603,24 +2601,16 @@ static int __btrfs_mod_ref(struct btrfs_
 
 			num_bytes = btrfs_file_extent_disk_num_bytes(buf, fi);
 			key.offset -= btrfs_file_extent_offset(buf, fi);
-			ret = process_func(trans, root, bytenr, num_bytes,
-					   parent, ref_root, key.objectid,
-					   key.offset);
-			if (ret)
-				goto fail;
+			process_func(trans, root, bytenr, num_bytes, parent,
+				     ref_root, key.objectid, key.offset);
 		} else {
 			bytenr = btrfs_node_blockptr(buf, i);
 			num_bytes = btrfs_level_size(root, level - 1);
-			ret = process_func(trans, root, bytenr, num_bytes,
-					   parent, ref_root, level - 1, 0);
-			if (ret)
-				goto fail;
+			process_func(trans, root, bytenr, num_bytes, parent,
+				     ref_root, level - 1, 0);
 		}
 	}
 	return 0;
-fail:
-	BUG();
-	return ret;
 }
 
 int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
@@ -4800,10 +4790,10 @@ out:
 	btrfs_put_block_group(cache);
 }
 
-int btrfs_free_extent(struct btrfs_trans_handle *trans,
-		      struct btrfs_root *root,
-		      u64 bytenr, u64 num_bytes, u64 parent,
-		      u64 root_objectid, u64 owner, u64 offset)
+void btrfs_free_extent(struct btrfs_trans_handle *trans,
+		       struct btrfs_root *root,
+		       u64 bytenr, u64 num_bytes, u64 parent,
+		       u64 root_objectid, u64 owner, u64 offset)
 {
 	/*
 	 * tree log blocks never actually go into the extent allocation
@@ -4826,7 +4816,6 @@ int btrfs_free_extent(struct btrfs_trans
 		btrfs_add_delayed_data_ref(trans, bytenr, num_bytes, parent,
 					   root_objectid, owner, offset,
 					   BTRFS_DROP_DELAYED_REF, NULL);
-	return 0;
 }
 
 static u64 stripe_align(struct btrfs_root *root, u64 val)
#70 lore raw

PATCH 60/66 btrfs: __btrfs_mod_ref should return void

In reply to Jeff Mahoney

Now that process_func can't return an error, __btrfs_mod_ref has no more error conditions and should return void.

---
 fs/btrfs/ctree.c       |   30 ++++++++++--------------------
 fs/btrfs/ctree.h       |    8 ++++----
 fs/btrfs/extent-tree.c |   34 +++++++++++++++-------------------
 3 files changed, 29 insertions(+), 43 deletions(-)
fs/btrfs/ctree.c +10 -20
index 2604ec4..bdaf3ad 100644
@@ -224,7 +224,6 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
 		      struct extent_buffer **cow_ret, u64 new_root_objectid)
 {
 	struct extent_buffer *cow;
-	int ret = 0;
 	int level;
 	struct btrfs_disk_key disk_key;
 
@@ -261,12 +260,9 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
 
 	WARN_ON(btrfs_header_generation(buf) > trans->transid);
 	if (new_root_objectid == BTRFS_TREE_RELOC_OBJECTID)
-		ret = btrfs_inc_ref(trans, root, cow, 1);
+		btrfs_inc_ref(trans, root, cow, 1);
 	else
-		ret = btrfs_inc_ref(trans, root, cow, 0);
-
-	if (ret)
-		return ret;
+		btrfs_inc_ref(trans, root, cow, 0);
 
 	btrfs_mark_buffer_dirty(cow);
 	*cow_ret = cow;
@@ -350,25 +346,21 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
 		if ((owner == root->root_key.objectid ||
 		     root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) &&
 		    !(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) {
-			ret = btrfs_inc_ref(trans, root, buf, 1);
-			BUG_ON(ret);
+			btrfs_inc_ref(trans, root, buf, 1);
 
 			if (root->root_key.objectid ==
 			    BTRFS_TREE_RELOC_OBJECTID) {
-				ret = btrfs_dec_ref(trans, root, buf, 0);
-				BUG_ON(ret);
-				ret = btrfs_inc_ref(trans, root, cow, 1);
-				BUG_ON(ret);
+				btrfs_dec_ref(trans, root, buf, 0);
+				btrfs_inc_ref(trans, root, cow, 1);
 			}
 			new_flags |= BTRFS_BLOCK_FLAG_FULL_BACKREF;
 		} else {
 
 			if (root->root_key.objectid ==
 			    BTRFS_TREE_RELOC_OBJECTID)
-				ret = btrfs_inc_ref(trans, root, cow, 1);
+				btrfs_inc_ref(trans, root, cow, 1);
 			else
-				ret = btrfs_inc_ref(trans, root, cow, 0);
-			BUG_ON(ret);
+				btrfs_inc_ref(trans, root, cow, 0);
 		}
 		if (new_flags != 0) {
 			ret = btrfs_set_disk_extent_flags(trans, root,
@@ -381,12 +373,10 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
 		if (flags & BTRFS_BLOCK_FLAG_FULL_BACKREF) {
 			if (root->root_key.objectid ==
 			    BTRFS_TREE_RELOC_OBJECTID)
-				ret = btrfs_inc_ref(trans, root, cow, 1);
+				btrfs_inc_ref(trans, root, cow, 1);
 			else
-				ret = btrfs_inc_ref(trans, root, cow, 0);
-			BUG_ON(ret);
-			ret = btrfs_dec_ref(trans, root, buf, 1);
-			BUG_ON(ret);
+				btrfs_inc_ref(trans, root, cow, 0);
+			btrfs_dec_ref(trans, root, buf, 1);
 		}
 		clean_tree_block(trans, root, buf);
 		*last_ref = 1;
fs/btrfs/ctree.h +4 -4
index b791b8f..51f2840 100644
@@ -2193,10 +2193,10 @@ int btrfs_reserve_extent(struct btrfs_trans_handle *trans,
 				  u64 empty_size, u64 hint_byte,
 				  u64 search_end, struct btrfs_key *ins,
 				  u64 data);
-int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-		  struct extent_buffer *buf, int full_backref);
-int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-		  struct extent_buffer *buf, int full_backref);
+void btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+		   struct extent_buffer *buf, int full_backref);
+void btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+		   struct extent_buffer *buf, int full_backref);
 int btrfs_set_disk_extent_flags(struct btrfs_trans_handle *trans,
 				struct btrfs_root *root,
 				u64 bytenr, u64 num_bytes, u64 flags,
fs/btrfs/extent-tree.c +15 -19
index c2dcfd8..fac996d 100644
@@ -2551,10 +2551,10 @@ out:
 	return ret;
 }
 
-static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
-			   struct btrfs_root *root,
-			   struct extent_buffer *buf,
-			   int full_backref, int inc)
+static void __btrfs_mod_ref(struct btrfs_trans_handle *trans,
+			    struct btrfs_root *root,
+			    struct extent_buffer *buf,
+			    int full_backref, int inc)
 {
 	u64 bytenr;
 	u64 num_bytes;
@@ -2573,7 +2573,7 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
 	level = btrfs_header_level(buf);
 
 	if (!root->ref_cows && level == 0)
-		return 0;
+		return;
 
 	if (inc)
 		process_func = btrfs_inc_extent_ref;
@@ -2610,19 +2610,18 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans,
 				     ref_root, level - 1, 0);
 		}
 	}
-	return 0;
 }
 
-int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-		  struct extent_buffer *buf, int full_backref)
+void btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+		   struct extent_buffer *buf, int full_backref)
 {
-	return __btrfs_mod_ref(trans, root, buf, full_backref, 1);
+	__btrfs_mod_ref(trans, root, buf, full_backref, 1);
 }
 
-int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-		  struct extent_buffer *buf, int full_backref)
+void btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+		   struct extent_buffer *buf, int full_backref)
 {
-	return __btrfs_mod_ref(trans, root, buf, full_backref, 0);
+	__btrfs_mod_ref(trans, root, buf, full_backref, 0);
 }
 
 static int write_one_cache_group(struct btrfs_trans_handle *trans,
@@ -5985,10 +5984,8 @@ static noinline int walk_down_proc(struct btrfs_trans_handle *trans,
 	/* wc->stage == UPDATE_BACKREF */
 	if (!(wc->flags[level] & flag)) {
 		BUG_ON(!path->locks[level]);
-		ret = btrfs_inc_ref(trans, root, eb, 1);
-		BUG_ON(ret);
-		ret = btrfs_dec_ref(trans, root, eb, 0);
-		BUG_ON(ret);
+		btrfs_inc_ref(trans, root, eb, 1);
+		btrfs_dec_ref(trans, root, eb, 0);
 		ret = btrfs_set_disk_extent_flags(trans, root, eb->start,
 						  eb->len, flag, 0);
 		BUG_ON(ret);
@@ -6204,10 +6201,9 @@ static noinline int walk_up_proc(struct btrfs_trans_handle *trans,
 	if (wc->refs[level] == 1) {
 		if (level == 0) {
 			if (wc->flags[level] & BTRFS_BLOCK_FLAG_FULL_BACKREF)
-				ret = btrfs_dec_ref(trans, root, eb, 1);
+				btrfs_dec_ref(trans, root, eb, 1);
 			else
-				ret = btrfs_dec_ref(trans, root, eb, 0);
-			BUG_ON(ret);
+				btrfs_dec_ref(trans, root, eb, 0);
 		}
 		/* make block locked assertion in clean_tree_block happy */
 		if (!path->locks[level] &&
#71 lore raw

PATCH 61/66 btrfs: clean_tree_block should return void

In reply to Jeff Mahoney

clean_tree_block has no error conditions and should return void. Its callers already ignore the error codes.

---
 fs/btrfs/disk-io.c |    5 ++---
 fs/btrfs/disk-io.h |    4 ++--
 2 files changed, 4 insertions(+), 5 deletions(-)
fs/btrfs/disk-io.c +2 -3
index fcb0f7f..e16a3e9 100644
@@ -1033,8 +1033,8 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
 
 }
 
-int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
-		     struct extent_buffer *buf)
+void clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+		      struct extent_buffer *buf)
 {
 	struct inode *btree_inode = root->fs_info->btree_inode;
 	if (btrfs_header_generation(buf) ==
@@ -1055,7 +1055,6 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		clear_extent_buffer_dirty(&BTRFS_I(btree_inode)->io_tree,
 					  buf);
 	}
-	return 0;
 }
 
 static void __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
fs/btrfs/disk-io.h +2 -2
index bec3ea4..5a2604a 100644
@@ -42,8 +42,8 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
 			 u64 parent_transid);
 struct extent_buffer *btrfs_find_create_tree_block(struct btrfs_root *root,
 						   u64 bytenr, u32 blocksize);
-int clean_tree_block(struct btrfs_trans_handle *trans,
-		     struct btrfs_root *root, struct extent_buffer *buf);
+void clean_tree_block(struct btrfs_trans_handle *trans,
+		      struct btrfs_root *root, struct extent_buffer *buf);
 struct btrfs_root *open_ctree(struct super_block *sb,
 			      struct btrfs_fs_devices *fs_devices,
 			      char *options);
#72 lore raw

PATCH 62/66 btrfs: btrfs_truncate_item should return void

In reply to Jeff Mahoney

btrfs_truncate_item has no error conditions and should return void.

---
 fs/btrfs/ctree.c       |   11 +++++------
 fs/btrfs/ctree.h       |    8 ++++----
 fs/btrfs/dir-item.c    |    4 ++--
 fs/btrfs/extent-tree.c |    3 +--
 fs/btrfs/file-item.c   |    4 ++--
 fs/btrfs/inode-item.c  |    3 +--
 fs/btrfs/inode.c       |    4 ++--
 7 files changed, 17 insertions(+), 20 deletions(-)
fs/btrfs/ctree.c +5 -6
index bdaf3ad..12c66ea 100644
@@ -3193,10 +3193,10 @@ int btrfs_duplicate_item(struct btrfs_trans_handle *trans,
  * off the end of the item or if we shift the item to chop bytes off
  * the front.
  */
-int btrfs_truncate_item(struct btrfs_trans_handle *trans,
-			struct btrfs_root *root,
-			struct btrfs_path *path,
-			u32 new_size, int from_end)
+void btrfs_truncate_item(struct btrfs_trans_handle *trans,
+			 struct btrfs_root *root,
+			 struct btrfs_path *path,
+			 u32 new_size, int from_end)
 {
 	int slot;
 	struct extent_buffer *leaf;
@@ -3213,7 +3213,7 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans,
 
 	old_size = btrfs_item_size_nr(leaf, slot);
 	if (old_size == new_size)
-		return 0;
+		return;
 
 	nritems = btrfs_header_nritems(leaf);
 	data_end = leaf_data_end(root, leaf);
@@ -3286,7 +3286,6 @@ int btrfs_truncate_item(struct btrfs_trans_handle *trans,
 		btrfs_print_leaf(root, leaf);
 		BUG();
 	}
-	return 0;
 }
 
 /*
fs/btrfs/ctree.h +4 -4
index 51f2840..5d1e06c 100644
@@ -2307,10 +2307,10 @@ int btrfs_block_can_be_shared(struct btrfs_root *root,
 			      struct extent_buffer *buf);
 int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root
 		      *root, struct btrfs_path *path, u32 data_size);
-int btrfs_truncate_item(struct btrfs_trans_handle *trans,
-			struct btrfs_root *root,
-			struct btrfs_path *path,
-			u32 new_size, int from_end);
+void btrfs_truncate_item(struct btrfs_trans_handle *trans,
+			 struct btrfs_root *root,
+			 struct btrfs_path *path,
+			 u32 new_size, int from_end);
 int btrfs_split_item(struct btrfs_trans_handle *trans,
 		     struct btrfs_root *root,
 		     struct btrfs_path *path,
fs/btrfs/dir-item.c +2 -2
index 31d84e7..c95fc70 100644
@@ -383,8 +383,8 @@ int btrfs_delete_one_dir_name(struct btrfs_trans_handle *trans,
 		start = btrfs_item_ptr_offset(leaf, path->slots[0]);
 		memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
 			item_len - (ptr + sub_item_len - start));
-		ret = btrfs_truncate_item(trans, root, path,
-					  item_len - sub_item_len, 1);
+		btrfs_truncate_item(trans, root, path,
+				    item_len - sub_item_len, 1);
 	}
 	return ret;
 }
fs/btrfs/extent-tree.c +1 -2
index fac996d..4ab965d 100644
@@ -1666,7 +1666,6 @@ int update_inline_extent_backref(struct btrfs_trans_handle *trans,
 	u32 item_size;
 	int size;
 	int type;
-	int ret;
 	u64 refs;
 
 	leaf = path->nodes[0];
@@ -1708,7 +1707,7 @@ int update_inline_extent_backref(struct btrfs_trans_handle *trans,
 			memmove_extent_buffer(leaf, ptr, ptr + size,
 					      end - ptr - size);
 		item_size -= size;
-		ret = btrfs_truncate_item(trans, root, path, item_size, 1);
+		btrfs_truncate_item(trans, root, path, item_size, 1);
 	}
 	btrfs_mark_buffer_dirty(leaf);
 	return 0;
fs/btrfs/file-item.c +2 -2
index 8d5272d..319129e 100644
@@ -514,7 +514,7 @@ static noinline int truncate_one_csum(struct btrfs_trans_handle *trans,
 		 */
 		u32 new_size = (bytenr - key->offset) >> blocksize_bits;
 		new_size *= csum_size;
-		ret = btrfs_truncate_item(trans, root, path, new_size, 1);
+		btrfs_truncate_item(trans, root, path, new_size, 1);
 	} else if (key->offset >= bytenr && csum_end > end_byte &&
 		   end_byte > key->offset) {
 		/*
@@ -526,7 +526,7 @@ static noinline int truncate_one_csum(struct btrfs_trans_handle *trans,
 		u32 new_size = (csum_end - end_byte) >> blocksize_bits;
 		new_size *= csum_size;
 
-		ret = btrfs_truncate_item(trans, root, path, new_size, 0);
+		btrfs_truncate_item(trans, root, path, new_size, 0);
 
 		key->offset = end_byte;
 		ret = btrfs_set_item_key_safe(trans, root, path, key);
fs/btrfs/inode-item.c +1 -2
index baa74f3..c04018c 100644
@@ -128,8 +128,7 @@ int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,
 	item_start = btrfs_item_ptr_offset(leaf, path->slots[0]);
 	memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
 			      item_size - (ptr + sub_item_len - item_start));
-	ret = btrfs_truncate_item(trans, root, path,
-				  item_size - sub_item_len, 1);
+	btrfs_truncate_item(trans, root, path, item_size - sub_item_len, 1);
 out:
 	btrfs_free_path(path);
 	return ret;
fs/btrfs/inode.c +2 -2
index d8bb54e..96a0fbd 100644
@@ -3243,8 +3243,8 @@ search_again:
 				}
 				size =
 				    btrfs_file_extent_calc_inline_size(size);
-				ret = btrfs_truncate_item(trans, root, path,
-							  size, 1);
+				btrfs_truncate_item(trans, root, path,
+						    size, 1);
 			} else if (root->ref_cows) {
 				inode_sub_bytes(inode, item_end + 1 -
 						found_key.offset);
#73 lore raw

PATCH 63/66 btrfs: btrfs_extend_item should return void

In reply to Jeff Mahoney

btrfs_extend_item has no error conditions and should return void.

---
 fs/btrfs/ctree.c       |    7 +++----
 fs/btrfs/ctree.h       |    5 +++--
 fs/btrfs/dir-item.c    |    5 ++---
 fs/btrfs/extent-tree.c |    5 ++---
 fs/btrfs/file-item.c   |    2 +-
 fs/btrfs/inode-item.c  |    2 +-
 fs/btrfs/tree-log.c    |    9 ++++-----
 7 files changed, 16 insertions(+), 19 deletions(-)
fs/btrfs/ctree.c +3 -4
index 12c66ea..4c9dc73 100644
@@ -3291,9 +3291,9 @@ void btrfs_truncate_item(struct btrfs_trans_handle *trans,
 /*
  * make the item pointed to by the path bigger, data_size is the new size.
  */
-int btrfs_extend_item(struct btrfs_trans_handle *trans,
-		      struct btrfs_root *root, struct btrfs_path *path,
-		      u32 data_size)
+void btrfs_extend_item(struct btrfs_trans_handle *trans,
+		       struct btrfs_root *root, struct btrfs_path *path,
+		       u32 data_size)
 {
 	int slot;
 	struct extent_buffer *leaf;
@@ -3351,7 +3351,6 @@ int btrfs_extend_item(struct btrfs_trans_handle *trans,
 		btrfs_print_leaf(root, leaf);
 		BUG();
 	}
-	return 0;
 }
 
 /*
fs/btrfs/ctree.h +3 -2
index 5d1e06c..5dee97f 100644
@@ -2305,8 +2305,9 @@ int btrfs_copy_root(struct btrfs_trans_handle *trans,
 		      struct extent_buffer **cow_ret, u64 new_root_objectid);
 int btrfs_block_can_be_shared(struct btrfs_root *root,
 			      struct extent_buffer *buf);
-int btrfs_extend_item(struct btrfs_trans_handle *trans, struct btrfs_root
-		      *root, struct btrfs_path *path, u32 data_size);
+void btrfs_extend_item(struct btrfs_trans_handle *trans,
+		       struct btrfs_root *root, struct btrfs_path *path,
+		       u32 data_size);
 void btrfs_truncate_item(struct btrfs_trans_handle *trans,
 			 struct btrfs_root *root,
 			 struct btrfs_path *path,
fs/btrfs/dir-item.c +2 -3
index c95fc70..7674330 100644
@@ -49,9 +49,8 @@ static struct btrfs_dir_item *insert_with_overflow(struct btrfs_trans_handle
 		di = btrfs_match_dir_item_name(root, path, name, name_len);
 		if (di)
 			return ERR_PTR(-EEXIST);
-		ret = btrfs_extend_item(trans, root, path, data_size);
-	}
-	if (ret < 0)
+		btrfs_extend_item(trans, root, path, data_size);
+	} else if (ret < 0)
 		return ERR_PTR(ret);
 	WARN_ON(ret > 0);
 	leaf = path->nodes[0];
fs/btrfs/extent-tree.c +2 -3
index 4ab965d..201822d 100644
@@ -974,7 +974,7 @@ static int convert_extent_item_v0(struct btrfs_trans_handle *trans,
 		return ret;
 	BUG_ON(ret);
 
-	ret = btrfs_extend_item(trans, root, path, new_size);
+	btrfs_extend_item(trans, root, path, new_size);
 
 	leaf = path->nodes[0];
 	item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
@@ -1572,7 +1572,6 @@ void setup_inline_extent_backref(struct btrfs_trans_handle *trans,
 	u64 refs;
 	int size;
 	int type;
-	int ret;
 
 	leaf = path->nodes[0];
 	ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
@@ -1581,7 +1580,7 @@ void setup_inline_extent_backref(struct btrfs_trans_handle *trans,
 	type = extent_ref_type(parent, owner);
 	size = btrfs_extent_inline_ref_size(type);
 
-	ret = btrfs_extend_item(trans, root, path, size);
+	btrfs_extend_item(trans, root, path, size);
 
 	ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_extent_item);
 	refs = btrfs_extent_refs(leaf, ei);
fs/btrfs/file-item.c +1 -1
index 319129e..4a73745 100644
@@ -778,7 +778,7 @@ again:
 		if (diff != csum_size)
 			goto insert;
 
-		ret = btrfs_extend_item(trans, root, path, diff);
+		btrfs_extend_item(trans, root, path, diff);
 		goto csum;
 	}
 
fs/btrfs/inode-item.c +1 -1
index c04018c..9f0d038 100644
@@ -164,7 +164,7 @@ int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
 			goto out;
 
 		old_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]);
-		ret = btrfs_extend_item(trans, root, path, ins_len);
+		btrfs_extend_item(trans, root, path, ins_len);
 		ref = btrfs_item_ptr(path->nodes[0], path->slots[0],
 				     struct btrfs_inode_ref);
 		ref = (struct btrfs_inode_ref *)((unsigned long)ref + old_size);
fs/btrfs/tree-log.c +4 -5
index feb4575..22e7da6 100644
@@ -380,12 +380,11 @@ insert:
 		u32 found_size;
 		found_size = btrfs_item_size_nr(path->nodes[0],
 						path->slots[0]);
-		if (found_size > item_size) {
+		if (found_size > item_size)
 			btrfs_truncate_item(trans, root, path, item_size, 1);
-		} else if (found_size < item_size) {
-			ret = btrfs_extend_item(trans, root, path,
-						item_size - found_size);
-		}
+		else if (found_size < item_size)
+			btrfs_extend_item(trans, root, path,
+					  item_size - found_size);
 	} else if (ret) {
 		return ret;
 	}
#74 lore raw

PATCH 64/66 btrfs: end_compressed_writeback should return void

In reply to Jeff Mahoney

end_compressed_writeback has no error conditions and should return void. Its callers already ignore the error code anyway.

---
 fs/btrfs/compression.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)
fs/btrfs/compression.c +2 -3
index 0c0e842..6c4d228 100644
@@ -225,8 +225,8 @@ out:
  * Clear the writeback bits on all of the file
  * pages for a compressed write
  */
-static noinline int end_compressed_writeback(struct inode *inode, u64 start,
-					     unsigned long ram_size)
+static noinline void end_compressed_writeback(struct inode *inode, u64 start,
+					      unsigned long ram_size)
 {
 	unsigned long index = start >> PAGE_CACHE_SHIFT;
 	unsigned long end_index = (start + ram_size - 1) >> PAGE_CACHE_SHIFT;
@@ -252,7 +252,6 @@ static noinline int end_compressed_writeback(struct inode *inode, u64 start,
 		index += ret;
 	}
 	/* the inode may be gone now */
-	return 0;
 }
 
 /*
#75 lore raw

PATCH 65/66 btrfs: copy_for_split should return void

In reply to Jeff Mahoney

copy_for_split has no error conditions and should return void. We return 0 from split_leaf instead of ret since ret would have been set using the return value from copy_for_split which would have been 0.

---
 fs/btrfs/ctree.c |   19 ++++++++-----------
 1 files changed, 8 insertions(+), 11 deletions(-)
fs/btrfs/ctree.c +8 -11
index 4c9dc73..263abce 100644
@@ -2695,12 +2695,12 @@ out:
  *
  * returns 0 if all went well and < 0 on failure.
  */
-static noinline int copy_for_split(struct btrfs_trans_handle *trans,
-			       struct btrfs_root *root,
-			       struct btrfs_path *path,
-			       struct extent_buffer *l,
-			       struct extent_buffer *right,
-			       int slot, int mid, int nritems)
+static noinline void copy_for_split(struct btrfs_trans_handle *trans,
+				    struct btrfs_root *root,
+				    struct btrfs_path *path,
+				    struct extent_buffer *l,
+				    struct extent_buffer *right,
+				    int slot, int mid, int nritems)
 {
 	int data_copy_size;
 	int rt_data_off;
@@ -2752,8 +2752,6 @@ static noinline int copy_for_split(struct btrfs_trans_handle *trans,
 	}
 
 	BUG_ON(path->slots[0] < 0);
-
-	return 0;
 }
 
 /*
@@ -2965,8 +2963,7 @@ again:
 		return ret;
 	}
 
-	ret = copy_for_split(trans, root, path, l, right, slot, mid, nritems);
-	BUG_ON(ret);
+	copy_for_split(trans, root, path, l, right, slot, mid, nritems);
 
 	if (split == 2) {
 		BUG_ON(num_doubles != 0);
@@ -2974,7 +2971,7 @@ again:
 		goto again;
 	}
 
-	return ret;
+	return 0;
 
 push_for_double:
 	push_for_double_split(trans, root, path, data_size);
#76 lore raw

PATCH 66/66 btrfs: update_inline_extent_backref should return void

In reply to Jeff Mahoney

Now that btrfs_truncate_item returns void, there are no more error conditions in update_inline_extent_backref and it should return void.

---
 fs/btrfs/extent-tree.c |   23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)
fs/btrfs/extent-tree.c +11 -12
@@ -1649,12 +1649,12 @@ static int lookup_extent_backref(struct
  * helper to update/remove inline back ref
  */
 static noinline_for_stack
-int update_inline_extent_backref(struct btrfs_trans_handle *trans,
-				 struct btrfs_root *root,
-				 struct btrfs_path *path,
-				 struct btrfs_extent_inline_ref *iref,
-				 int refs_to_mod,
-				 struct btrfs_delayed_extent_op *extent_op)
+void update_inline_extent_backref(struct btrfs_trans_handle *trans,
+				  struct btrfs_root *root,
+				  struct btrfs_path *path,
+				  struct btrfs_extent_inline_ref *iref,
+				  int refs_to_mod,
+				  struct btrfs_delayed_extent_op *extent_op)
 {
 	struct extent_buffer *leaf;
 	struct btrfs_extent_item *ei;
@@ -1709,7 +1709,6 @@ int update_inline_extent_backref(struct
 		btrfs_truncate_item(trans, root, path, item_size, 1);
 	}
 	btrfs_mark_buffer_dirty(leaf);
-	return 0;
 }
 
 static noinline_for_stack
@@ -1729,8 +1728,8 @@ int insert_inline_extent_backref(struct
 					   root_objectid, owner, offset, 1);
 	if (ret == 0) {
 		BUG_ON(owner < BTRFS_FIRST_FREE_OBJECTID);
-		ret = update_inline_extent_backref(trans, root, path, iref,
-						   refs_to_add, extent_op);
+		update_inline_extent_backref(trans, root, path, iref,
+					     refs_to_add, extent_op);
 	} else if (ret == -ENOENT) {
 		setup_inline_extent_backref(trans, root, path, iref, parent,
 					    root_objectid, owner, offset,
@@ -1765,12 +1764,12 @@ static int remove_extent_backref(struct
 				 struct btrfs_extent_inline_ref *iref,
 				 int refs_to_drop, int is_data)
 {
-	int ret;
+	int ret = 0;
 
 	BUG_ON(!is_data && refs_to_drop != 1);
 	if (iref) {
-		ret = update_inline_extent_backref(trans, root, path, iref,
-						   -refs_to_drop, NULL);
+		update_inline_extent_backref(trans, root, path, iref,
+					     -refs_to_drop, NULL);
 	} else if (is_data) {
 		ret = remove_extent_data_ref(trans, root, path, refs_to_drop);
 	} else {