lkml.org 
[lkml]   [2019]   [Dec]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 136/161] btrfs: dont prematurely free work in reada_start_machine_worker()
    Date
    From: Omar Sandoval <osandov@fb.com>

    [ Upstream commit e732fe95e4cad35fc1df278c23a32903341b08b3 ]

    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>
    ---
    fs/btrfs/reada.c | 10 ++++------
    1 file changed, 4 insertions(+), 6 deletions(-)

    diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c
    index 3a4e15b39cc1..440c0d5d2050 100644
    --- a/fs/btrfs/reada.c
    +++ b/fs/btrfs/reada.c
    @@ -734,21 +734,19 @@ static int reada_start_machine_dev(struct btrfs_device *dev)
    static void reada_start_machine_worker(struct btrfs_work *work)
    {
    struct reada_machine_work *rmw;
    - struct btrfs_fs_info *fs_info;
    int old_ioprio;

    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),
    task_nice_ioprio(current));
    set_task_ioprio(current, BTRFS_IOPRIO_READA);
    - __reada_start_machine(fs_info);
    + __reada_start_machine(rmw->fs_info);
    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)
    --
    2.20.1


    \
     
     \ /
      Last update: 2019-12-29 19:15    [W:4.091 / U:0.344 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site