Linux Btrfs filesystem development
 help / color / mirror / Atom feed
From: Qu Wenruo <quwenruo.btrfs@gmx.com>
To: Askar Safin <safinaskar@gmail.com>
Cc: dsterba@suse.com, linux-btrfs@vger.kernel.org,
	lists@colorremedies.com, wqu@suse.com
Subject: Re: [PATCH RFC] btrfs: exit scrub and balance early if the fs is being frozen
Date: Thu, 16 Oct 2025 09:31:14 +1030	[thread overview]
Message-ID: <5517a3cd-1afa-4db0-bf8b-439f3ba410ed@gmx.com> (raw)
In-Reply-To: <20251015111217.5538-1-safinaskar@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 3062 bytes --]



在 2025/10/15 21:42, Askar Safin 写道:
> I just noticed that suspend behavior depends on whether "btrfs scrub" is
> started in terminal window or as a systemd service. I think this is because
> systemd tries to freeze user session when suspending, but doesn't freeze
> services.

I don't think it's the case, as the pm suspend-to-ram requires all user 
space programs to be frozen.

I guess the difference is in the systemd's handling of user slice.
Maybe it is sending some signal first, then freeze for the time-out 
case, but directly freeze for the service.

Anyway, mind to test the attached newer patch?

This one also adds the extra signal checking (including the regular 
SIGINT and fatal ones), hope it would be the last testing patch.

Please apply it upon clean upstream branch (aka, no previous test 
patches applied).


But if the latest patch doesn't work, I'm running out of ideas.
Inside the kernel I can only find out how to check signals and freezing 
status, but if systemd is not using those two ways, I have no more ideas.

Thanks,
Qu

> 
> So I retested everything.
> 
> All tests were done with my distro's version of btrfs-progs (6.14-1).
> My distro is Debian Trixie.
> I have btrfs raid-1, which spans two actual partitions, 3.5 TiB each.
> 
> Let's start with unpatched v6.18-rc1.
> 
> - scrub in win, freeze_filesystems=0 - suspend doesn't work
> 
> - scrub as a service, freeze_filesystems=0 - suspend doesn't work
> 
> - scrub in win, freeze_filesystems=1
> suspend takes 6-10 mins. I. e. the system hangs for 6-10 mins and then
> suspends. I suspect this is time needed to complete scrub
> 
> - scrub as a service, freeze_filesystems=1 - the same
> 
> Also: on unpatched kernel "btrfs scrub" terminates instantly if it receives
> INT, but doesn't terminate if it receives KILL, TERM or HUP.
> 
> Now v6.18-rc1 with your old 7 Jul 2025 patch
> ( https://lore.kernel.org/linux-btrfs/9606fae20bff6c1fbe14dc7b067f3b333c2a955b.1751847905.git.wqu@suse.com/ ).
> 
> - scrub in win, freeze_filesystems=0 - suspend doesn't work
> 
> - scrub as a service, freeze_filesystems=0 - suspend doesn't work
> 
> - scrub in win, freeze_filesystems=1
> suspend takes 1 min. I. e. the system hangs for 1 min, then suspends
> 
> - scrub as a service, freeze_filesystems=1
> suspend works perfectly. I. e. the system instantly suspends. I don't even
> notice 19s delay you are talking about
> 
> Now v6.18-rc1 with your new 15 Oct 2025 patch
> ( https://lore.kernel.org/linux-btrfs/8c3628d5-8fce-45a1-b29c-65c2c52f1c06@gmx.com/ ).
> 
> - scrub in win, freeze_filesystems=0 - hangs for 60s, then suspends
> 
> - scrub as a service, freeze_filesystems=0 - works perfectly, i. e. suspends instantly
> 
> - scrub in win, freeze_filesystems=1 - hangs for 60s, then suspends
> here is journalctl: https://zerobin.net/?7b394069a9050b8d#7PrnCDJV2t9inNFS3/EhxHJUS24iSGX7FAmjUstKKr4=
> 
> - scrub as a service, freeze_filesystems=1 - works perfectly, i. e. suspends instantly
> 

[-- Attachment #2: 0001-btrfs-cancel-the-scrub-if-the-fs-or-the-process-is-b.patch --]
[-- Type: text/x-patch, Size: 2817 bytes --]

From e56bff151de2c98ad489ab0721b1d68e58b45129 Mon Sep 17 00:00:00 2001
Message-ID: <e56bff151de2c98ad489ab0721b1d68e58b45129.1760569187.git.wqu@suse.com>
From: Qu Wenruo <wqu@suse.com>
Date: Wed, 15 Oct 2025 17:07:00 +1030
Subject: [PATCH] btrfs: cancel the scrub if the fs or the process is being
 frozen

It's a known bug that btrfs scrub/dev-replace can prevent the fs from
suspending.

There are at least two factors involved:

- Holding super_block::s_writers for the whole scrub/dev-replace
  duration
  We hold that mutex through mnt_want_write_file() for the whole
  scrub/dev-replace duration.

  That will prevent the fs being frozen.
  It's tunable for the kernel to suspend the fs before suspending, if
  that's the case, btrfs will refuse to freeze and break the suspension.

- Stuck in kernel space for a long time
  During suspension all user progresses (and some kernel threads) will
  be frozen.
  But if a user space progress has fallen into kernel and do not return
  for a long time, it will make suspension to time out.

  Unfortunately scrub/dev-replace is a long running ioctl, and it will
  prevent the btrfs-progs from returning to user space.

Address them in one go:

- Introduce a new helper should_cancel_scrub()
  Which checks both fs and process freezing.

- Cancel the run if should_cancel_scrub() is true
  The check is done at scrub_simple_mirror() and
  scrub_raid56_parity_stripe().

  Unfortunately canceling is the only feasible solution here, pausing is
  not possible as we will still stay in the kernel state thus will still
  prevent the process from being frozen.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/scrub.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index fe266785804e..1ddcd8a88610 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -2234,6 +2234,22 @@ static int scrub_raid56_parity_stripe(struct scrub_ctx *sctx,
 	return ret;
 }
 
+static bool should_cancel_scrub(struct btrfs_fs_info *fs_info)
+{
+	/*
+	 * If some one is trying to freeze the fs or the scrub process,
+	 * cancel the run.
+	 */
+	if (fs_info->sb->s_writers.frozen > SB_UNFROZEN ||
+	    freezing(current))
+		return true;
+
+	/* Also check for pending signals. */
+	if (signal_pending(current))
+		return true;
+	return false;
+}
+
 /*
  * Scrub one range which can only has simple mirror based profile.
  * (Including all range in SINGLE/DUP/RAID1/RAID1C*, and each stripe in
@@ -2263,7 +2279,8 @@ static int scrub_simple_mirror(struct scrub_ctx *sctx,
 
 		/* Canceled? */
 		if (atomic_read(&fs_info->scrub_cancel_req) ||
-		    atomic_read(&sctx->cancel_req)) {
+		    atomic_read(&sctx->cancel_req) ||
+		    should_cancel_scrub(fs_info)) {
 			ret = -ECANCELED;
 			break;
 		}
-- 
2.50.1


  reply	other threads:[~2025-10-15 23:01 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-07  0:25 [PATCH RFC] btrfs: exit scrub and balance early if the fs is being frozen Qu Wenruo
2025-07-07  5:23 ` Qu Wenruo
2025-07-07 12:30   ` David Sterba
2025-07-07 12:37     ` Daniel Vacek
2025-07-07 22:16     ` Qu Wenruo
2025-07-07 12:25 ` David Sterba
2025-10-12  8:23 ` Askar Safin
2025-10-12 23:56   ` Qu Wenruo
2025-10-15  4:05     ` Askar Safin
2025-10-15  7:00   ` Qu Wenruo
2025-10-15  7:59     ` Askar Safin
2025-10-15  8:07       ` Qu Wenruo
2025-10-15 11:12     ` Askar Safin
2025-10-15 23:01       ` Qu Wenruo [this message]
2025-10-16  8:40         ` Askar Safin
2025-10-16  9:46           ` Qu Wenruo

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=5517a3cd-1afa-4db0-bf8b-439f3ba410ed@gmx.com \
    --to=quwenruo.btrfs@gmx.com \
    --cc=dsterba@suse.com \
    --cc=linux-btrfs@vger.kernel.org \
    --cc=lists@colorremedies.com \
    --cc=safinaskar@gmail.com \
    --cc=wqu@suse.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