]> git.ipfire.org Git - thirdparty/kernel/stable.git/commit
btrfs: make btrfs_discard_workfn() block_group ref explicit
authorBoris Burkov <boris@bur.io>
Mon, 3 Mar 2025 23:01:05 +0000 (15:01 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 4 Jun 2025 12:41:57 +0000 (14:41 +0200)
commit4e74f91a6f70a2754fbfa6c98fd8086a8a4ea3ef
treeb9732d993b4927d8395badbd6ea0772b594df2df
parenta4666a812792d273aa1fcf9ac1d48dc65d338520
btrfs: make btrfs_discard_workfn() block_group ref explicit

[ Upstream commit 895c6721d310c036dcfebb5ab845822229fa35eb ]

Currently, the async discard machinery owns a ref to the block_group
when the block_group is queued on a discard list. However, to handle
races with discard cancellation and the discard workfn, we have a
specific logic to detect that the block_group is *currently* running in
the workfn, to protect the workfn's usage amidst cancellation.

As far as I can tell, this doesn't have any overt bugs (though
finish_discard_pass() and remove_from_discard_list() racing can have a
surprising outcome for the caller of remove_from_discard_list() in that
it is again added at the end).

But it is needlessly complicated to rely on locking and the nullity of
discard_ctl->block_group. Simplify this significantly by just taking a
refcount while we are in the workfn and unconditionally drop it in both
the remove and workfn paths, regardless of if they race.

Reviewed-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Boris Burkov <boris@bur.io>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/btrfs/discard.c