lkml.org 
[lkml]   [2022]   [Aug]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.19 1081/1157] btrfs: fix error handling of fallback uncompress write
    Date
    From: Naohiro Aota <naohiro.aota@wdc.com>

    [ Upstream commit 71aa147b4d9d81fa65afa6016f50d7818b64a54f ]

    When cow_file_range() fails in the middle of the allocation loop, it
    unlocks the pages but leaves the ordered extents intact. Thus, we need
    to call btrfs_cleanup_ordered_extents() to finish the created ordered
    extents.

    Also, we need to call end_extent_writepage() if locked_page is available
    because btrfs_cleanup_ordered_extents() never processes the region on
    the locked_page.

    Furthermore, we need to set the mapping as error if locked_page is
    unavailable before unlocking the pages, so that the errno is properly
    propagated to the user space.

    CC: stable@vger.kernel.org # 5.18+
    Reviewed-by: Filipe Manana <fdmanana@suse.com>
    Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
    Signed-off-by: David Sterba <dsterba@suse.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/btrfs/inode.c | 17 +++++++++++++++--
    1 file changed, 15 insertions(+), 2 deletions(-)

    diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
    index 52b2d1b48d2e..25872ee8594e 100644
    --- a/fs/btrfs/inode.c
    +++ b/fs/btrfs/inode.c
    @@ -927,8 +927,18 @@ static int submit_uncompressed_range(struct btrfs_inode *inode,
    goto out;
    }
    if (ret < 0) {
    - if (locked_page)
    + btrfs_cleanup_ordered_extents(inode, locked_page, start, end - start + 1);
    + if (locked_page) {
    + const u64 page_start = page_offset(locked_page);
    + const u64 page_end = page_start + PAGE_SIZE - 1;
    +
    + btrfs_page_set_error(inode->root->fs_info, locked_page,
    + page_start, PAGE_SIZE);
    + set_page_writeback(locked_page);
    + end_page_writeback(locked_page);
    + end_extent_writepage(locked_page, ret, page_start, page_end);
    unlock_page(locked_page);
    + }
    goto out;
    }

    @@ -1377,9 +1387,12 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
    * However, in case of unlock == 0, we still need to unlock the pages
    * (except @locked_page) to ensure all the pages are unlocked.
    */
    - if (!unlock && orig_start < start)
    + if (!unlock && orig_start < start) {
    + if (!locked_page)
    + mapping_set_error(inode->vfs_inode.i_mapping, ret);
    extent_clear_unlock_delalloc(inode, orig_start, start - 1,
    locked_page, 0, page_ops);
    + }

    /*
    * For the range (2). If we reserved an extent for our delalloc range
    --
    2.35.1


    \
     
     \ /
      Last update: 2022-08-16 03:04    [W:3.469 / U:0.368 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site