From: Yongpeng Yang <[email protected]>

When `fileinfo->fi_flags` does not have the `FIEMAP_FLAG_SYNC` bit set
and inline data has not been persisted yet, the physical address of the
extent is calculated incorrectly for unwritten inline inodes.

root@vm:/mnt/f2fs# dd if=/dev/zero of=data.3k bs=3k count=1
root@vm:/mnt/f2fs# f2fs_io fiemap 0 100 data.3k
Fiemap: offset = 0 len = 100
        logical addr.    physical addr.   length           flags
0       0000000000000000 00000ffffffff16c 0000000000000c00 00000301

This patch fixes the issue by checking if the inode's address is valid.
If the inline inode is unwritten, set the physical address to 0 and
mark the extent with `FIEMAP_EXTENT_UNKNOWN | FIEMAP_EXTENT_DELALLOC`
flags.

Fixes: 67f8cf3cee6f ("f2fs: support fiemap for inline_data")
Signed-off-by: Yongpeng Yang <[email protected]>
---
 fs/f2fs/inline.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 0a1052d5ee62..86d2abbb40ff 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -792,7 +792,7 @@ int f2fs_read_inline_dir(struct file *file, struct 
dir_context *ctx,
 int f2fs_inline_data_fiemap(struct inode *inode,
                struct fiemap_extent_info *fieinfo, __u64 start, __u64 len)
 {
-       __u64 byteaddr, ilen;
+       __u64 byteaddr = 0, ilen;
        __u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED |
                FIEMAP_EXTENT_LAST;
        struct node_info ni;
@@ -825,9 +825,14 @@ int f2fs_inline_data_fiemap(struct inode *inode,
        if (err)
                goto out;
 
-       byteaddr = (__u64)ni.blk_addr << inode->i_sb->s_blocksize_bits;
-       byteaddr += (char *)inline_data_addr(inode, ifolio) -
-                                       (char *)F2FS_INODE(ifolio);
+       if (__is_valid_data_blkaddr(ni.blk_addr)) {
+               byteaddr = (__u64)ni.blk_addr << inode->i_sb->s_blocksize_bits;
+               byteaddr += (char *)inline_data_addr(inode, ifolio) -
+                                               (char *)F2FS_INODE(ifolio);
+       } else {
+               f2fs_bug_on(F2FS_I_SB(inode), ni.blk_addr != NEW_ADDR);
+               flags |= FIEMAP_EXTENT_DELALLOC | FIEMAP_EXTENT_UNKNOWN;
+       }
        err = fiemap_fill_next_extent(fieinfo, start, byteaddr, ilen, flags);
        trace_f2fs_fiemap(inode, start, byteaddr, ilen, flags, err);
 out:
-- 
2.43.0



_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to