Unlike PAGE_SIZE == sectorsize case, read in subpage btrfs are always
merged if the range is in the same page:

E.g:
For regular sectorsize case, if we want to read range [0, 16K) of a
file, the bio will look like:

 0       4K      8K      12K     16K
 | bvec 1| bvec 2| bvec 3| bvec 4|

But for subpage case, above 16K can be merged into one bvec:

 0       4K      8K      12K     16K
 |              bvec 1           |

This means our bvec is no longer 1:1 mapped to btrfs sector.

This makes repair much harder to do, if we want to do sector perfect
repair.

For now, just skip validation for subpage read repair, this means:
- We will submit extra range to repair
  Even if we only have one sector error for above read, we will
  still submit full 16K to over-write the bad copy

- Less chance to get good copy
  Now the repair granularity is much lower, we need a copy with
  all sectors correct to be able to submit a repair.

Sector perfect repair needs more modification, but for now the new
behavior should be good enough for us to test the basis of subpage
support.

Signed-off-by: Qu Wenruo <w...@suse.com>
---
 fs/btrfs/extent_io.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 152aface4eeb..81931c02c0e4 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2651,6 +2651,19 @@ static bool btrfs_io_needs_validation(struct inode 
*inode, struct bio *bio)
        if (bio->bi_status == BLK_STS_OK)
                return false;
 
+       /*
+        * For subpage case, read bio are always submitted as multiple-sector
+        * bio if the range is in the same page.
+        * For now, let's just skip the validation, and do page sized repair.
+        *
+        * This reduce the granularity for repair, meaning if we have two
+        * copies with different csum mismatch at different location, we're
+        * unable to repair in subpage case.
+        *
+        * TODO: Make validation code to be fully subpage compatible
+        */
+       if (blocksize < PAGE_SIZE)
+               return false;
        /*
         * We need to validate each sector individually if the failed I/O was
         * for multiple sectors.
-- 
2.31.1

Reply via email to