Message ID | 20180125180256.10844-2-bo.li.liu@oracle.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Jan 25, 2018 at 11:02:49AM -0700, Liu Bo wrote: > 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 enters the cow path. > > In case of free space inode, this ends up with a warning in > cow_file_range(). > > The same problem applies for 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> Reviewed-by: Josef Bacik <jbacik@fb.com> Thanks, Josef -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Jan 25, 2018 at 11:02:49AM -0700, Liu Bo wrote: > 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 enters the cow path. > > In case of free space inode, this ends up with a warning in > cow_file_range(). > > The same problem applies for 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> This and the other fixes sent in this batch have been added to next and I'm going to push them to 4.16 either during the merge window still or at rc1 time. Thanks. -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index e1a7f3c..ac1a1ac 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1257,6 +1257,8 @@ static noinline int csum_exist_in_range(struct btrfs_fs_info *fs_info, list_del(&sums->list); kfree(sums); } + if (ret < 0) + return ret; return 1; } @@ -1386,10 +1388,23 @@ static noinline int run_delalloc_nocow(struct inode *inode, 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 != -ENOENT) { + 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; @@ -1407,10 +1422,22 @@ static noinline int run_delalloc_nocow(struct inode *inode, * 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)) {
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 enters the cow path. In case of free space inode, this ends up with a warning in cow_file_range(). The same problem applies for 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> --- fs/btrfs/inode.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-)