lkml.org 
[lkml]   [2018]   [Apr]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.15 59/72] Btrfs: fix unexpected cow in run_delalloc_nocow
    Date
    4.15-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Liu Bo <bo.li.liu@oracle.com>

    commit 5811375325420052fcadd944792a416a43072b7f upstream.

    Fstests generic/475 provides a way to fail metadata reads while
    checking if checksum exists for the inode inside run_delalloc_nocow(),
    and csum_exist_in_range() interprets error (-EIO) as inode having
    checksum and makes its caller enter the cow path.

    In case of free space inode, this ends up with a warning in
    cow_file_range().

    The same problem applies to btrfs_cross_ref_exist() since it may also
    read metadata in between.

    With this, run_delalloc_nocow() bails out when errors occur at the two
    places.

    cc: <stable@vger.kernel.org> v2.6.28+
    Fixes: 17d217fe970d ("Btrfs: fix nodatasum handling in balancing code")
    Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
    Signed-off-by: David Sterba <dsterba@suse.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/btrfs/inode.c | 37 ++++++++++++++++++++++++++++++++-----
    1 file changed, 32 insertions(+), 5 deletions(-)

    --- a/fs/btrfs/inode.c
    +++ b/fs/btrfs/inode.c
    @@ -1257,6 +1257,8 @@ static noinline int csum_exist_in_range(
    list_del(&sums->list);
    kfree(sums);
    }
    + if (ret < 0)
    + return ret;
    return 1;
    }

    @@ -1389,10 +1391,23 @@ next_slot:
    goto out_check;
    if (btrfs_extent_readonly(fs_info, disk_bytenr))
    goto out_check;
    - if (btrfs_cross_ref_exist(root, ino,
    - found_key.offset -
    - extent_offset, disk_bytenr))
    + ret = btrfs_cross_ref_exist(root, ino,
    + found_key.offset -
    + extent_offset, disk_bytenr);
    + if (ret) {
    + /*
    + * ret could be -EIO if the above fails to read
    + * metadata.
    + */
    + if (ret < 0) {
    + if (cow_start != (u64)-1)
    + cur_offset = cow_start;
    + goto error;
    + }
    +
    + WARN_ON_ONCE(nolock);
    goto out_check;
    + }
    disk_bytenr += extent_offset;
    disk_bytenr += cur_offset - found_key.offset;
    num_bytes = min(end + 1, extent_end) - cur_offset;
    @@ -1410,10 +1425,22 @@ next_slot:
    * this ensure that csum for a given extent are
    * either valid or do not exist.
    */
    - if (csum_exist_in_range(fs_info, disk_bytenr,
    - num_bytes)) {
    + ret = csum_exist_in_range(fs_info, disk_bytenr,
    + num_bytes);
    + if (ret) {
    if (!nolock)
    btrfs_end_write_no_snapshotting(root);
    +
    + /*
    + * ret could be -EIO if the above fails to read
    + * metadata.
    + */
    + if (ret < 0) {
    + if (cow_start != (u64)-1)
    + cur_offset = cow_start;
    + goto error;
    + }
    + WARN_ON_ONCE(nolock);
    goto out_check;
    }
    if (!btrfs_inc_nocow_writers(fs_info, disk_bytenr)) {

    \
     
     \ /
      Last update: 2018-04-06 15:53    [W:3.317 / U:0.136 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site