Re: [PATCH v2] Btrfs: fix unexpected cow in run_delalloc_nocow

2018-03-07 Thread David Sterba
On Wed, Jan 31, 2018 at 05:09:13PM -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:  v2.6.28+
> Fixes: 17d217fe970d ("Btrfs: fix nodatasum handling in balancing code")
> Signed-off-by: Liu Bo 

For the record, this has been added to next some time ago and testing
was ok.
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] Btrfs: fix unexpected cow in run_delalloc_nocow

2018-01-31 Thread Liu Bo
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:  v2.6.28+
Fixes: 17d217fe970d ("Btrfs: fix nodatasum handling in balancing code")
Signed-off-by: Liu Bo 
---
v2: fix error handling after btrfs_cross_ref_exist().

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

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index e1a7f3c..8f2bd04 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(>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 < 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;
@@ -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)) {
-- 
2.9.4

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html