All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] Delayed inode error handling fixes
@ 2021-05-21 20:44 Josef Bacik
  2021-05-21 20:44 ` [PATCH 1/3] btrfs: make btrfs_release_delayed_iref handle the !iref case Josef Bacik
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Josef Bacik @ 2021-05-21 20:44 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Hello,

Here are 3 straightforward fixes, but they rely on eachother so I'm sending them
as a series.  The first changes how we do cleanup so that it can do the right
thing in the case that we don't have an iref, this is to make the code cleaner
in the error case.  The second patch is to fix the error handling in
__btrfs_update_delayed_inode so it actually does the proper cleanup if there's
an error.  And finally the last patch add's the abort() we need in order to not
leave behind improper inode items that trip up fsck during error injection
testing.  Thanks,

Josef

Josef Bacik (3):
  btrfs: make btrfs_release_delayed_iref handle the !iref case
  btrfs: fix error handling in __btrfs_update_delayed_inode
  btrfs: abort transaction if we fail to update the delayed inode

 fs/btrfs/delayed-inode.c | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)

-- 
2.26.3


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] btrfs: make btrfs_release_delayed_iref handle the !iref case
  2021-05-21 20:44 [PATCH 0/3] Delayed inode error handling fixes Josef Bacik
@ 2021-05-21 20:44 ` Josef Bacik
  2021-05-21 20:44 ` [PATCH 2/3] btrfs: fix error handling in __btrfs_update_delayed_inode Josef Bacik
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Josef Bacik @ 2021-05-21 20:44 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

Right now we only cleanup the delayed iref if we have
BTRFS_DELAYED_NODE_DEL_IREF set on the node.  However we have some error
conditions that need to cleanup the iref if it still exists, so to make
this code cleaner move the test_bit into btrfs_release_delayed_iref
itself and unconditionally call it in each of the cases instead.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/delayed-inode.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index 1a88f6214ebc..3ed4ecb49f8a 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -976,12 +976,15 @@ static void btrfs_release_delayed_iref(struct btrfs_delayed_node *delayed_node)
 {
 	struct btrfs_delayed_root *delayed_root;
 
-	ASSERT(delayed_node->root);
-	clear_bit(BTRFS_DELAYED_NODE_DEL_IREF, &delayed_node->flags);
-	delayed_node->count--;
+	if (test_and_clear_bit(BTRFS_DELAYED_NODE_DEL_IREF,
+			       &delayed_node->flags)) {
 
-	delayed_root = delayed_node->root->fs_info->delayed_root;
-	finish_one_item(delayed_root);
+		ASSERT(delayed_node->root);
+		delayed_node->count--;
+
+		delayed_root = delayed_node->root->fs_info->delayed_root;
+		finish_one_item(delayed_root);
+	}
 }
 
 static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans,
@@ -1024,7 +1027,7 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans,
 	btrfs_mark_buffer_dirty(leaf);
 
 	if (!test_bit(BTRFS_DELAYED_NODE_DEL_IREF, &node->flags))
-		goto no_iref;
+		goto out;
 
 	path->slots[0]++;
 	if (path->slots[0] >= btrfs_header_nritems(leaf))
@@ -1046,7 +1049,6 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans,
 	btrfs_del_item(trans, root, path);
 out:
 	btrfs_release_delayed_iref(node);
-no_iref:
 	btrfs_release_path(path);
 err_out:
 	btrfs_delayed_inode_release_metadata(fs_info, node, (ret < 0));
@@ -1898,8 +1900,7 @@ static void __btrfs_kill_delayed_node(struct btrfs_delayed_node *delayed_node)
 		btrfs_release_delayed_item(prev_item);
 	}
 
-	if (test_bit(BTRFS_DELAYED_NODE_DEL_IREF, &delayed_node->flags))
-		btrfs_release_delayed_iref(delayed_node);
+	btrfs_release_delayed_iref(delayed_node);
 
 	if (test_bit(BTRFS_DELAYED_NODE_INODE_DIRTY, &delayed_node->flags)) {
 		btrfs_delayed_inode_release_metadata(fs_info, delayed_node, false);
-- 
2.26.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] btrfs: fix error handling in __btrfs_update_delayed_inode
  2021-05-21 20:44 [PATCH 0/3] Delayed inode error handling fixes Josef Bacik
  2021-05-21 20:44 ` [PATCH 1/3] btrfs: make btrfs_release_delayed_iref handle the !iref case Josef Bacik
@ 2021-05-21 20:44 ` Josef Bacik
  2021-05-21 20:44 ` [PATCH 3/3] btrfs: abort transaction if we fail to update the delayed inode Josef Bacik
  2021-05-24 19:44 ` [PATCH 0/3] Delayed inode error handling fixes David Sterba
  3 siblings, 0 replies; 5+ messages in thread
From: Josef Bacik @ 2021-05-21 20:44 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

If we get an error while looking up the inode item we'll simply bail
without cleaning up the delayed node.  This results in this style of
warning happening on commit

------------[ cut here ]------------
WARNING: CPU: 0 PID: 76403 at fs/btrfs/delayed-inode.c:1365 btrfs_assert_delayed_root_empty+0x5b/0x90
CPU: 0 PID: 76403 Comm: fsstress Tainted: G        W         5.13.0-rc1+ #373
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-2.fc32 04/01/2014
RIP: 0010:btrfs_assert_delayed_root_empty+0x5b/0x90
RSP: 0018:ffffb8bb815a7e50 EFLAGS: 00010286
RAX: 0000000000000000 RBX: ffff95d6d07e1888 RCX: ffff95d6c0fa3000
RDX: 0000000000000002 RSI: 000000000029e91c RDI: ffff95d6c0fc8060
RBP: ffff95d6c0fc8060 R08: 00008d6d701a2c1d R09: 0000000000000000
R10: ffff95d6d1760ea0 R11: 0000000000000001 R12: ffff95d6c15a4d00
R13: ffff95d6c0fa3000 R14: 0000000000000000 R15: ffffb8bb815a7e90
FS:  00007f490e8dbb80(0000) GS:ffff95d73bc00000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f6e75555cb0 CR3: 00000001101ce001 CR4: 0000000000370ef0
Call Trace:
 btrfs_commit_transaction+0x43c/0xb00
 ? finish_wait+0x80/0x80
 ? vfs_fsync_range+0x90/0x90
 iterate_supers+0x8c/0x100
 ksys_sync+0x50/0x90
 __do_sys_sync+0xa/0x10
 do_syscall_64+0x3d/0x80
 entry_SYSCALL_64_after_hwframe+0x44/0xae

Because the iref isn't dropped and this leaves an elevated node->count,
so any release just re-queues it onto the delayed inodes list.  Fix this
by going to the out label to handle the proper cleanup of the delayed
node.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/delayed-inode.c | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index 3ed4ecb49f8a..263f3ab3009c 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -1012,12 +1012,10 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans,
 	nofs_flag = memalloc_nofs_save();
 	ret = btrfs_lookup_inode(trans, root, path, &key, mod);
 	memalloc_nofs_restore(nofs_flag);
-	if (ret > 0) {
-		btrfs_release_path(path);
-		return -ENOENT;
-	} else if (ret < 0) {
-		return ret;
-	}
+	if (ret > 0)
+		ret = -ENOENT;
+	if (ret < 0)
+		goto out;
 
 	leaf = path->nodes[0];
 	inode_item = btrfs_item_ptr(leaf, path->slots[0],
-- 
2.26.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] btrfs: abort transaction if we fail to update the delayed inode
  2021-05-21 20:44 [PATCH 0/3] Delayed inode error handling fixes Josef Bacik
  2021-05-21 20:44 ` [PATCH 1/3] btrfs: make btrfs_release_delayed_iref handle the !iref case Josef Bacik
  2021-05-21 20:44 ` [PATCH 2/3] btrfs: fix error handling in __btrfs_update_delayed_inode Josef Bacik
@ 2021-05-21 20:44 ` Josef Bacik
  2021-05-24 19:44 ` [PATCH 0/3] Delayed inode error handling fixes David Sterba
  3 siblings, 0 replies; 5+ messages in thread
From: Josef Bacik @ 2021-05-21 20:44 UTC (permalink / raw)
  To: linux-btrfs, kernel-team

If we fail to update the delayed inode we need to abort the transaction,
because we could leave an inode with the improper counts or some other
such corruption behind.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/delayed-inode.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index 263f3ab3009c..6ce6d8a839d7 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -1052,6 +1052,9 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans,
 	btrfs_delayed_inode_release_metadata(fs_info, node, (ret < 0));
 	btrfs_release_delayed_inode(node);
 
+	if (ret && ret != -ENOENT)
+		btrfs_abort_transaction(trans, ret);
+
 	return ret;
 
 search:
-- 
2.26.3


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 0/3] Delayed inode error handling fixes
  2021-05-21 20:44 [PATCH 0/3] Delayed inode error handling fixes Josef Bacik
                   ` (2 preceding siblings ...)
  2021-05-21 20:44 ` [PATCH 3/3] btrfs: abort transaction if we fail to update the delayed inode Josef Bacik
@ 2021-05-24 19:44 ` David Sterba
  3 siblings, 0 replies; 5+ messages in thread
From: David Sterba @ 2021-05-24 19:44 UTC (permalink / raw)
  To: Josef Bacik; +Cc: linux-btrfs, kernel-team

On Fri, May 21, 2021 at 04:44:06PM -0400, Josef Bacik wrote:
> Hello,
> 
> Here are 3 straightforward fixes, but they rely on eachother so I'm sending them
> as a series.  The first changes how we do cleanup so that it can do the right
> thing in the case that we don't have an iref, this is to make the code cleaner
> in the error case.  The second patch is to fix the error handling in
> __btrfs_update_delayed_inode so it actually does the proper cleanup if there's
> an error.  And finally the last patch add's the abort() we need in order to not
> leave behind improper inode items that trip up fsck during error injection
> testing.  Thanks,
> 
> Josef
> 
> Josef Bacik (3):
>   btrfs: make btrfs_release_delayed_iref handle the !iref case
>   btrfs: fix error handling in __btrfs_update_delayed_inode
>   btrfs: abort transaction if we fail to update the delayed inode

Added to misc-next, thanks. I've copied the changelog from patch 3 as
comment before the transaction abort.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-05-24 19:46 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-21 20:44 [PATCH 0/3] Delayed inode error handling fixes Josef Bacik
2021-05-21 20:44 ` [PATCH 1/3] btrfs: make btrfs_release_delayed_iref handle the !iref case Josef Bacik
2021-05-21 20:44 ` [PATCH 2/3] btrfs: fix error handling in __btrfs_update_delayed_inode Josef Bacik
2021-05-21 20:44 ` [PATCH 3/3] btrfs: abort transaction if we fail to update the delayed inode Josef Bacik
2021-05-24 19:44 ` [PATCH 0/3] Delayed inode error handling fixes David Sterba

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.