Skip to content

Commit b767c2f

Browse files
fdmananakdave
authored andcommitted
btrfs: allow defrag to be interruptible
During defrag, at btrfs_defrag_file(), we have this loop that iterates over a file range in steps no larger than 256K subranges. If the range is too long, there's no way to interrupt it. So make the loop check in each iteration if there's signal pending, and if there is, break and return -AGAIN to userspace. Before kernel 5.16, we used to allow defrag to be cancelled through a signal, but that was lost with commit 7b50803 ("btrfs: defrag: use defrag_one_cluster() to implement btrfs_defrag_file()"). This change adds back the possibility to cancel a defrag with a signal and keeps the same semantics, returning -EAGAIN to user space (and not the usually more expected -EINTR). This is also motivated by a recent bug on 5.16 where defragging a 1 byte file resulted in iterating from file range 0 to (u64)-1, as hitting the bug triggered a too long loop, basically requiring one to reboot the machine, as it was not possible to cancel defrag. Fixes: 7b50803 ("btrfs: defrag: use defrag_one_cluster() to implement btrfs_defrag_file()") CC: stable@vger.kernel.org # 5.16 Reviewed-by: Qu Wenruo <wqu@suse.com> Signed-off-by: Filipe Manana <fdmanana@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
1 parent 6b34cd8 commit b767c2f

File tree

1 file changed

+5
-0
lines changed

1 file changed

+5
-0
lines changed

fs/btrfs/ioctl.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,6 +1546,11 @@ int btrfs_defrag_file(struct inode *inode, struct file_ra_state *ra,
15461546
/* The cluster size 256K should always be page aligned */
15471547
BUILD_BUG_ON(!IS_ALIGNED(CLUSTER_SIZE, PAGE_SIZE));
15481548

1549+
if (btrfs_defrag_cancelled(fs_info)) {
1550+
ret = -EAGAIN;
1551+
break;
1552+
}
1553+
15491554
/* We want the cluster end at page boundary when possible */
15501555
cluster_end = (((cur >> PAGE_SHIFT) +
15511556
(SZ_256K >> PAGE_SHIFT)) << PAGE_SHIFT) - 1;

0 commit comments

Comments
 (0)