Linux Btrfs filesystem development
 help / color / mirror / Atom feed
* [PATCH] btrfs: retry flushing for del_balance_item() if the transaction is interrupted
@ 2023-08-16 10:28 Qu Wenruo
  2023-08-16 12:45 ` Filipe Manana
  0 siblings, 1 reply; 5+ messages in thread
From: Qu Wenruo @ 2023-08-16 10:28 UTC (permalink / raw)
  To: linux-btrfs

[BUG]

There is an internal bug report that there are only 3 lines of btrfs
errors, then btrfs falls read-only:

 [358958.022131] BTRFS info (device dm-9): balance: canceled
 [358958.022148] BTRFS: error (device dm-9) in __cancel_balance:4014: errno=-4 unknown
 [358958.022150] BTRFS info (device dm-9): forced readonly

[CAUSE]
The error number -4 is -EINTR, and according to the code line (although
backported kernel, the code is still relevant upstream), it's the
btrfs_handle_fs_error() call inside reset_balance_state().

This can happen when we try to start a transaction which requires
metadata flushing.

This metadata flushing can be interrupted by signal, thus it can return
-EINTR.

For our case, the -EINTR is deadly because we don't handle the error at
all, and immediately mark the fs read-only in the following call chain:

reset_balance_state()
|- del_balance_item()
|  `- btrfs_start_transation_fallback_global_rsv()
|     `- start_transaction()
|	 `- btrfs_block_rsv_add()
|	    `- __reserve_bytes()
|	       `- handle_reserve_ticket()
|		  `- wait_reserve_ticket()
|		     `- prepare_to_wait_event()
|			This wait has TASK_KILLABLE, thus can be
|			interrupted.
|			Thus we return -EINTR.
|
|- IS_ERR(trans) triggered
|- btrfs_handle_fs_error()
   The fs is marked read-only.

[FIX]
For this particular call site, we can not afford just erroring out with
-EINTR.

This patch would fix the error by retry until either we got a valid
transaction handle, or got an error other than -EINTR.

Since we're here, also enhance the error message a little to make it
more readable.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/volumes.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 189da583bb67..e83711fe31bb 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3507,7 +3507,15 @@ static int del_balance_item(struct btrfs_fs_info *fs_info)
 	if (!path)
 		return -ENOMEM;
 
-	trans = btrfs_start_transaction_fallback_global_rsv(root, 0);
+	do {
+		/*
+		 * The transaction starting here can be interrupted, but if we
+		 * just error out we would mark the fs read-only.
+		 * Thus here we try to start the transaction again if it's
+		 * interrupted.
+		 */
+		trans = btrfs_start_transaction_fallback_global_rsv(root, 0);
+	} while (IS_ERR(trans) && PTR_ERR(trans) == -EINTR);
 	if (IS_ERR(trans)) {
 		btrfs_free_path(path);
 		return PTR_ERR(trans);
@@ -3594,7 +3602,7 @@ static void reset_balance_state(struct btrfs_fs_info *fs_info)
 	kfree(bctl);
 	ret = del_balance_item(fs_info);
 	if (ret)
-		btrfs_handle_fs_error(fs_info, ret, NULL);
+		btrfs_handle_fs_error(fs_info, ret, "failed to delete balance item");
 }
 
 /*
-- 
2.41.0


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

end of thread, other threads:[~2023-08-17  8:05 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-16 10:28 [PATCH] btrfs: retry flushing for del_balance_item() if the transaction is interrupted Qu Wenruo
2023-08-16 12:45 ` Filipe Manana
2023-08-16 21:54   ` Qu Wenruo
2023-08-17  7:39     ` Filipe Manana
2023-08-17  8:04       ` Qu Wenruo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox