]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: scrub: cancel the run if there is a pending signal
authorQu Wenruo <wqu@suse.com>
Sun, 19 Oct 2025 00:45:28 +0000 (11:15 +1030)
committerDavid Sterba <dsterba@suse.com>
Mon, 24 Nov 2025 21:34:32 +0000 (22:34 +0100)
Unlike relocation, scrub never checks pending signals, and even for
relocation is only explicitly checking for fatal signal (SIGKILL), not
for regular ones.

Thankfully relocation can still be interrupted by regular signals by
the usage of wait_on_bit(), which is called with TASK_INTERRUPTIBLE.

Do the same for scrub/dev-replace, so that regular signals can also
cancel the scrub/replace run, and more importantly handle v2 cgroup
freezing which is based on signal handling code inside the kernel, and
freezing() function will not return true for v2 cgroup freezing.

This will address the problem that systemd slice freezing will timeout
on long running scrub/dev-replace.

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <wqu@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/scrub.c

index 9738caa355c4247e748b8d1cc813c367b74e7fe0..5959511288c4e3955ed148b39fe0e6404e51477f 100644 (file)
@@ -2074,7 +2074,7 @@ static int queue_scrub_stripe(struct scrub_ctx *sctx, struct btrfs_block_group *
  * Return <0 if we need to cancel the scrub, returned value will
  * indicate the reason:
  * - -ECANCELED - Being explicitly canceled through ioctl.
- * - -EINTR     - Being interrupted by fs/process freezing.
+ * - -EINTR     - Being interrupted by signal or fs/process freezing.
  */
 static int should_cancel_scrub(const struct scrub_ctx *sctx)
 {
@@ -2102,7 +2102,8 @@ static int should_cancel_scrub(const struct scrub_ctx *sctx)
         * If we only check process freezing, then suspend with fs freezing
         * will timeout, as the running scrub will prevent the fs from being frozen.
         */
-       if (fs_info->sb->s_writers.frozen > SB_UNFROZEN || freezing(current))
+       if (fs_info->sb->s_writers.frozen > SB_UNFROZEN ||
+           freezing(current) || signal_pending(current))
                return -EINTR;
        return 0;
 }