linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Ian Kent <raven@themaw.net>
To: Josef Bacik <josef@redhat.com>
Cc: Yoshinori Sano <yoshinori.sano@gmail.com>,
	chris.mason@oracle.com, linux-btrfs@vger.kernel.org
Subject: Re: On Removing BUG_ON macros
Date: Thu, 11 Nov 2010 12:32:06 +0800	[thread overview]
Message-ID: <1289449926.3078.9.camel@localhost> (raw)
In-Reply-To: <1289228524.3309.51.camel@localhost>

On Mon, 2010-11-08 at 23:02 +0800, Ian Kent wrote:
> On Mon, 2010-11-08 at 09:15 -0500, Josef Bacik wrote:
> > On Mon, Nov 08, 2010 at 10:06:13PM +0800, Ian Kent wrote:
> > > On Mon, 2010-11-08 at 07:42 -0500, Josef Bacik wrote:
> > > > On Mon, Nov 08, 2010 at 10:54:07AM +0800, Ian Kent wrote:
> > > > > On Sun, 2010-11-07 at 09:51 -0500, Josef Bacik wrote:
> > > > > > On Sun, Nov 07, 2010 at 04:16:47PM +0900, Yoshinori Sano wrote:
> > > > > > > This is a question I've posted on the #btrfs IRC channel today.
> > > > > > > hyperair adviced me to contact with Josef Bacik or Chris Mason.
> > > > > > > So, I post my question to this maling list.
> > > > > > > 
> > > > > > > Here are my post on the IRC:
> > > > > > > 
> > > > > > > Actually, I want to remove BUG_ON(ret) around the Btrfs code.
> > > > > > > The motivation is to make the Btrfs code more robust.
> > > > > > > First of all, is this meaningless?
> > > > > > > 
> > > > > > > For example, there are code like the following:
> > > > > > > 
> > > > > > >     struct btrfs_path *path;
> > > > > > >     path = btrfs_alloc_path();
> > > > > > >     BUG_ON(!path);
> > > > > > > 
> > > > > > > This is a frequenty used pattern of current Btrfs code.
> > > > > > > A btrfs_alloc_path()'s caller has to deal with the allocation failure
> > > > > > > instead of using BUG_ON.  However, (this is what most interesting
> > > > > > > thing for me) can the caller do any proper error handlings here?
> > > > > > > I mean, is this a critical situation where we cannot recover from?
> > > > > > >
> > > > > > 
> > > > > > No we're just lazy ;).  Tho making sure the caller can recover from getting
> > > > > > -ENOMEM is very important, which is why in some of these paths we just do BUG_ON
> > > > > > since fixing the callers is tricky.  A good strategy for things like this is to
> > > > > > do something like
> > > > > > 
> > > > > > static int foo = 1;
> > > > > > 
> > > > > > path = btrfs_alloc_path();
> > > > > > if (!path || !(foo % 1000))
> > > > > > 	return -ENOMEM;
> > > > > > foo++;
> > > > > 
> > > > > Hahaha, I love it.
> > > > > 
> > > > > So, return ENOMEM every 1000 times we call the containing function!
> > > > > 
> > > > > > 
> > > > > > that way you can catch all the callers and make sure we're handling the error
> > > > > > all the way up the chain properly.  Thanks,
> > > > > 
> > > > > Yeah, I suspect this approach will be a bit confusing though.
> > > > > 
> > > > > I believe that it will be more effective, although time consuming, to
> > > > > work through the call tree function by function. Although, as I have
> > > > > said, the problem is working out what needs to be done to recover,
> > > > > rather than working out what the callers are. I'm not at all sure yet
> > > > > but I also suspect that it may not be possible to recover in some cases,
> > > > > which will likely lead to serious rework of some subsystems (but, hey,
> > > > > who am I to say, I really don't have any clue yet).
> > > > >
> > > > 
> > > > So we talked about this at plumbers.  First thing we need is a way to flip the
> > > > filesystem read only, that way we can deal with the simple corruption cases.
> > > 
> > > Right, yes.
> > > 
> > > > And then we can start looking at these harder cases where it's really unclear
> > > > about how to recover.
> > > 
> > > I have a way to go before I will even understand these cases.
> > > 
> > > > 
> > > > Thankfully because we're COW we really shouldn't have any cases that we have to
> > > > unwind anything, we just fail the operation and go on our happy merry way.  The
> > > > only tricky thing is where we get ENOMEM when say inserting the metadata for
> > > > data after writing out the data, since that will leave data just sitting around.
> > > > Probably should look at what NFS does with dirty pages when the server hangs up.
> > > 
> > > OK, that's a though for me to focus on while I'm trying to work out
> > > what's going on ... mmm.
> > > 
> > > Indeed, a large proportion of these are handling ENOMEM.
> > > 
> > > I somehow suspect your heavily focused on disk io itself when I'm still
> > > back thinking about house keeping of operations, in the process of being
> > > queued and those currently being processed, the later being the
> > > difficult case. But I'll eventually get to worrying about io as part of
> > > that process. It's also worth mentioning that my scope is also quite
> > > narrow at this stage, focusing largely on the transaction subsystem,
> > > although that tends to pull in a fair amount of other code too.
> > > 
> > 
> > So the transaction stuff should be relatively simple since we shouldn't have too
> > much to clean up if the transaction fails to allocate.  Maybe point out some
> > places where you are having trouble and I can frame up what we'd want to do to
> > give you an idea of where to go?  Thanks,
> 
> Thanks, I will when I have something to discuss or maybe I'll start with
> the couple I have, when I get a chance to get back to it anyway.
> 

How about we discuss this patch to start with?

The places where I have put "/* TODO: What to do here? */" are the
places where I couldn't work out what to do or if some sort of recovery
is needed or what effect a failure might have on continued operations.

btrfs - resolve bug_on()s in btrfs_record_root_in_trans()

From: Ian Kent <raven@themaw.net>


---

 fs/btrfs/ctree.c       |    3 ++-
 fs/btrfs/disk-io.c     |    3 ++-
 fs/btrfs/extent-tree.c |    4 +++-
 fs/btrfs/inode.c       |    7 +++++--
 fs/btrfs/ioctl.c       |    8 ++++++--
 fs/btrfs/relocation.c  |   30 +++++++++++++++++++++++-------
 fs/btrfs/root-tree.c   |    4 +++-
 fs/btrfs/transaction.c |   15 ++++++++++++---
 fs/btrfs/tree-log.c    |    1 +
 9 files changed, 57 insertions(+), 18 deletions(-)


diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 9ac1715..a1f46fa 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -3832,7 +3832,8 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root
 	unsigned long ptr;
 
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return -ENOMEM;
 	ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size);
 	if (!ret) {
 		leaf = path->nodes[0];
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index b40dfe4..066af87 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1105,7 +1105,8 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
 		     root, fs_info, location->objectid);
 
 	path = btrfs_alloc_path();
-	BUG_ON(!path);
+	if (!path)
+		return ERR_PTR(-ENOMEM);
 	ret = btrfs_search_slot(NULL, tree_root, location, path, 0, 0);
 	if (ret == 0) {
 		l = path->nodes[0];
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index a541bc8..d737cea6 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -7821,8 +7821,10 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root,
 		}
 
 		mutex_lock(&extent_root->fs_info->trans_mutex);
-		btrfs_record_root_in_trans(found_root);
+		ret = btrfs_record_root_in_trans(found_root);
 		mutex_unlock(&extent_root->fs_info->trans_mutex);
+		if (ret < 0)
+			goto out;
 		if (ref_path->owner_objectid >= BTRFS_FIRST_FREE_OBJECTID) {
 			/*
 			 * try to update data extent references while
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 5132c9a..184b86a 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -6521,8 +6521,11 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 	btrfs_set_trans_block_group(trans, new_dir);
 
-	if (dest != root)
-		btrfs_record_root_in_trans(trans, dest);
+	if (dest != root) {
+		ret = btrfs_record_root_in_trans(trans, dest);
+		if (ret)
+			goto out_fail;
+	}
 
 	ret = btrfs_set_inode_index(new_dir, &index);
 	if (ret)
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 463d91b..ba94d60 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -311,7 +311,9 @@ static noinline int create_subvol(struct btrfs_root *root,
 	new_root = btrfs_read_fs_root_no_name(root->fs_info, &key);
 	BUG_ON(IS_ERR(new_root));
 
-	btrfs_record_root_in_trans(trans, new_root);
+	ret = btrfs_record_root_in_trans(trans, new_root);
+	if (ret)
+		goto fail;
 
 	ret = btrfs_create_subvol_root(trans, new_root, new_dirid,
 				       BTRFS_I(dir)->block_group);
@@ -1442,7 +1444,9 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
 				dentry->d_name.len);
 	BUG_ON(ret);
 
-	btrfs_record_root_in_trans(trans, dest);
+	err = btrfs_record_root_in_trans(trans, dest);
+	if (err)
+		goto out_up_write;
 
 	memset(&dest->root_item.drop_progress, 0,
 		sizeof(dest->root_item.drop_progress));
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 045c9c2..2e81b07 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -1264,7 +1264,8 @@ static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,
 	int ret;
 
 	root_item = kmalloc(sizeof(*root_item), GFP_NOFS);
-	BUG_ON(!root_item);
+	if (!root_item)
+		return ERR_PTR(-ENOMEM);
 
 	root_key.objectid = BTRFS_TREE_RELOC_OBJECTID;
 	root_key.type = BTRFS_ROOT_ITEM_KEY;
@@ -1274,7 +1275,10 @@ static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,
 		/* called by btrfs_init_reloc_root */
 		ret = btrfs_copy_root(trans, root, root->commit_root, &eb,
 				      BTRFS_TREE_RELOC_OBJECTID);
-		BUG_ON(ret);
+		if (ret) {
+			kfree(root_item);
+			return ERR_PTR(ret);
+		}
 
 		btrfs_set_root_last_snapshot(&root->root_item,
 					     trans->transid - 1);
@@ -1288,7 +1292,10 @@ static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,
 		 */
 		ret = btrfs_copy_root(trans, root, root->node, &eb,
 				      BTRFS_TREE_RELOC_OBJECTID);
-		BUG_ON(ret);
+		if (ret) {
+			kfree(root_item);
+			return ERR_PTR(ret);
+		}
 	}
 
 	memcpy(root_item, &root->root_item, sizeof(*root_item));
@@ -1308,13 +1315,16 @@ static struct btrfs_root *create_reloc_root(struct btrfs_trans_handle *trans,
 
 	ret = btrfs_insert_root(trans, root->fs_info->tree_root,
 				&root_key, root_item);
-	BUG_ON(ret);
+	if (ret) {
+		kfree(root_item);
+		return ERR_PTR(ret);
+	}
 	kfree(root_item);
 
 	reloc_root = btrfs_read_fs_root_no_radix(root->fs_info->tree_root,
 						 &root_key);
-	BUG_ON(IS_ERR(reloc_root));
-	reloc_root->last_trans = trans->transid;
+	if (!IS_ERR(reloc_root))
+		reloc_root->last_trans = trans->transid;
 	return reloc_root;
 }
 
@@ -1346,6 +1356,8 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,
 	reloc_root = create_reloc_root(trans, root, root->root_key.objectid);
 	if (clear_rsv)
 		trans->block_rsv = NULL;
+	if (IS_ERR(reloc_root))
+		return PTR_ERR(reloc_root);
 
 	__add_reloc_root(reloc_root);
 	root->reloc_root = reloc_root;
@@ -2275,10 +2287,12 @@ struct btrfs_root *select_reloc_root(struct btrfs_trans_handle *trans,
 		BUG_ON(!root->ref_cows);
 
 		if (root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) {
+			/* TODO: what to do here? */
 			record_reloc_root_in_trans(trans, root);
 			break;
 		}
 
+		/* TODO: what to do here? */
 		btrfs_record_root_in_trans(trans, root);
 		root = root->reloc_root;
 
@@ -2715,7 +2729,9 @@ static int relocate_tree_block(struct btrfs_trans_handle *trans,
 		if (root->ref_cows) {
 			BUG_ON(node->new_bytenr);
 			BUG_ON(!list_empty(&node->list));
-			btrfs_record_root_in_trans(trans, root);
+			ret = btrfs_record_root_in_trans(trans, root);
+			if (ret)
+				goto out;
 			root = root->reloc_root;
 			node->new_bytenr = root->node->start;
 			node->root = root;
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
index 6a1086e..045c924 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -140,7 +140,9 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root
 	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;
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 1fffbc0..615264f 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -104,14 +104,18 @@ static noinline int record_root_in_trans(struct btrfs_trans_handle *trans,
 					 struct btrfs_root *root)
 {
 	if (root->ref_cows && root->last_trans < trans->transid) {
+		int ret;
+
 		WARN_ON(root == root->fs_info->extent_root);
 		WARN_ON(root->commit_root != root->node);
 
+		/* TODO: cleanup tag set on error?  */
 		radix_tree_tag_set(&root->fs_info->fs_roots_radix,
 			   (unsigned long)root->root_key.objectid,
 			   BTRFS_ROOT_TRANS_TAG);
 		root->last_trans = trans->transid;
-		btrfs_init_reloc_root(trans, root);
+		ret = btrfs_init_reloc_root(trans, root);
+		return ret;
 	}
 	return 0;
 }
@@ -119,6 +123,8 @@ static noinline int record_root_in_trans(struct btrfs_trans_handle *trans,
 int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
 			       struct btrfs_root *root)
 {
+	int ret;
+
 	if (!root->ref_cows)
 		return 0;
 
@@ -128,9 +134,9 @@ int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
 		return 0;
 	}
 
-	record_root_in_trans(trans, root);
+	ret = record_root_in_trans(trans, root);
 	mutex_unlock(&root->fs_info->trans_mutex);
-	return 0;
+	return ret;
 }
 
 /* wait for commit against the current transaction to become unblocked
@@ -227,6 +233,7 @@ again:
 
 	if (type != TRANS_JOIN_NOLOCK)
 		mutex_lock(&root->fs_info->trans_mutex);
+	/* TODO: what to do here? */
 	record_root_in_trans(h, root);
 	if (type != TRANS_JOIN_NOLOCK)
 		mutex_unlock(&root->fs_info->trans_mutex);
@@ -943,6 +950,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
 	dentry = pending->dentry;
 	parent_inode = dentry->d_parent->d_inode;
 	parent_root = BTRFS_I(parent_inode)->root;
+	/* TODO: What to do here? */
 	record_root_in_trans(trans, parent_root);
 
 	/*
@@ -961,6 +969,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
 	ret = btrfs_update_inode(trans, parent_root, parent_inode);
 	BUG_ON(ret);
 
+	/* TODO: What to do here? */
 	record_root_in_trans(trans, root);
 	btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
 	memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index a29f193..bc25896 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -3106,6 +3106,7 @@ again:
 		BUG_ON(!wc.replay_dest);
 
 		wc.replay_dest->log_root = log;
+		/* TODO: What to do here? */
 		btrfs_record_root_in_trans(trans, wc.replay_dest);
 		ret = walk_log_tree(trans, log, &wc);
 		BUG_ON(ret);



  reply	other threads:[~2010-11-11  4:32 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-11-07  7:16 On Removing BUG_ON macros Yoshinori Sano
2010-11-07 14:51 ` Josef Bacik
2010-11-08  2:54   ` Ian Kent
2010-11-08 12:42     ` Josef Bacik
2010-11-08 14:06       ` Ian Kent
2010-11-08 14:15         ` Josef Bacik
2010-11-08 15:02           ` Ian Kent
2010-11-11  4:32             ` Ian Kent [this message]
2010-12-01 18:31               ` Josef Bacik
2010-11-09  6:13       ` Yoshinori Sano
2010-11-08 13:17   ` Yoshinori Sano
2010-11-08 13:28     ` Josef Bacik
2010-11-08 23:02       ` Yoshinori Sano
2010-11-08  2:36 ` Ian Kent

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1289449926.3078.9.camel@localhost \
    --to=raven@themaw.net \
    --cc=chris.mason@oracle.com \
    --cc=josef@redhat.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=yoshinori.sano@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).