mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
btrfs: don't prematurely free work in reada_start_machine_worker()
[ Upstream commit e732fe95e4 ]
Currently, reada_start_machine_worker() frees the reada_machine_work and
then calls __reada_start_machine() to do readahead. This is another
potential instance of the bug in "btrfs: don't prematurely free work in
run_ordered_work()".
There _might_ already be a deadlock here: reada_start_machine_worker()
can depend on itself through stacked filesystems (__read_start_machine()
-> reada_start_machine_dev() -> reada_tree_block_flagged() ->
read_extent_buffer_pages() -> submit_one_bio() ->
btree_submit_bio_hook() -> btrfs_map_bio() -> submit_stripe_bio() ->
submit_bio() onto a loop device can trigger readahead on the lower
filesystem).
Either way, let's fix it by freeing the work at the end.
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Omar Sandoval <osandov@fb.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
dc9d0a75ce
commit
736d28c704
@@ -752,21 +752,19 @@ static int reada_start_machine_dev(struct btrfs_device *dev)
|
|||||||
static void reada_start_machine_worker(struct btrfs_work *work)
|
static void reada_start_machine_worker(struct btrfs_work *work)
|
||||||
{
|
{
|
||||||
struct reada_machine_work *rmw;
|
struct reada_machine_work *rmw;
|
||||||
struct btrfs_fs_info *fs_info;
|
|
||||||
int old_ioprio;
|
int old_ioprio;
|
||||||
|
|
||||||
rmw = container_of(work, struct reada_machine_work, work);
|
rmw = container_of(work, struct reada_machine_work, work);
|
||||||
fs_info = rmw->fs_info;
|
|
||||||
|
|
||||||
kfree(rmw);
|
|
||||||
|
|
||||||
old_ioprio = IOPRIO_PRIO_VALUE(task_nice_ioclass(current),
|
old_ioprio = IOPRIO_PRIO_VALUE(task_nice_ioclass(current),
|
||||||
task_nice_ioprio(current));
|
task_nice_ioprio(current));
|
||||||
set_task_ioprio(current, BTRFS_IOPRIO_READA);
|
set_task_ioprio(current, BTRFS_IOPRIO_READA);
|
||||||
__reada_start_machine(fs_info);
|
__reada_start_machine(rmw->fs_info);
|
||||||
set_task_ioprio(current, old_ioprio);
|
set_task_ioprio(current, old_ioprio);
|
||||||
|
|
||||||
atomic_dec(&fs_info->reada_works_cnt);
|
atomic_dec(&rmw->fs_info->reada_works_cnt);
|
||||||
|
|
||||||
|
kfree(rmw);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __reada_start_machine(struct btrfs_fs_info *fs_info)
|
static void __reada_start_machine(struct btrfs_fs_info *fs_info)
|
||||||
|
|||||||
Reference in New Issue
Block a user