When testing with a mixed zoned / convention device combination, there
are regular but not 100% reproducible failures in xfstests generic/113
where the __is_valid_data_blkaddr assert hits due to finding a hole.

This seems to be because f2fs_map_blocks can set this flag on a hole
when it was found in the extent cache.

Rework f2fs_iomap_begin to just check the special block numbers directly.
This has the added benefits of the WARN_ON showing which invalid block
address we found, and being properly error out on delalloc blocks that
are confusingly called unwritten but not actually suitable for direct
I/O.

Fixes: 1517c1a7a445 ("f2fs: implement iomap operations")
Signed-off-by: Christoph Hellwig <h...@lst.de>
---
 fs/f2fs/data.c | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index a71e818cd67b43..541d625d94be42 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -4134,20 +4134,24 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t 
offset, loff_t length,
         */
        map.m_len = fscrypt_limit_io_blocks(inode, map.m_lblk, map.m_len);
 
-       if (map.m_flags & (F2FS_MAP_MAPPED | F2FS_MAP_UNWRITTEN)) {
-               iomap->length = blks_to_bytes(inode, map.m_len);
-               if (map.m_flags & F2FS_MAP_MAPPED) {
-                       iomap->type = IOMAP_MAPPED;
-                       iomap->flags |= IOMAP_F_MERGED;
-               } else {
-                       iomap->type = IOMAP_UNWRITTEN;
-               }
-               if (WARN_ON_ONCE(!__is_valid_data_blkaddr(map.m_pblk)))
-                       return -EINVAL;
+       /*
+        * We should never see delalloc or compressed extents here based on
+        * prior flushing and checks.
+        */
+       if (WARN_ON_ONCE(map.m_pblk == NEW_ADDR))
+               return -EINVAL;
+       if (WARN_ON_ONCE(map.m_pblk == COMPRESS_ADDR))
+               return -EINVAL;
 
+       if (map.m_pblk != NULL_ADDR) {
+               iomap->length = blks_to_bytes(inode, map.m_len);
+               iomap->type = IOMAP_MAPPED;
+               iomap->flags |= IOMAP_F_MERGED;
                iomap->bdev = map.m_bdev;
                iomap->addr = blks_to_bytes(inode, map.m_pblk);
        } else {
+               if (flags & IOMAP_WRITE)
+                       return -ENOTBLK;
                iomap->length = blks_to_bytes(inode, next_pgofs) -
                                iomap->offset;
                iomap->type = IOMAP_HOLE;
-- 
2.30.2



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to