Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

btrfs: scrub: cancel the run if there is a pending signal

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>

authored by

Qu Wenruo and committed by
David Sterba
937f99c7 c7b47850

+3 -2
+3 -2
fs/btrfs/scrub.c
··· 2074 2074 * Return <0 if we need to cancel the scrub, returned value will 2075 2075 * indicate the reason: 2076 2076 * - -ECANCELED - Being explicitly canceled through ioctl. 2077 - * - -EINTR - Being interrupted by fs/process freezing. 2077 + * - -EINTR - Being interrupted by signal or fs/process freezing. 2078 2078 */ 2079 2079 static int should_cancel_scrub(const struct scrub_ctx *sctx) 2080 2080 { ··· 2102 2102 * If we only check process freezing, then suspend with fs freezing 2103 2103 * will timeout, as the running scrub will prevent the fs from being frozen. 2104 2104 */ 2105 - if (fs_info->sb->s_writers.frozen > SB_UNFROZEN || freezing(current)) 2105 + if (fs_info->sb->s_writers.frozen > SB_UNFROZEN || 2106 + freezing(current) || signal_pending(current)) 2106 2107 return -EINTR; 2107 2108 return 0; 2108 2109 }