]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
f2fs: fix incorrect file address mapping when inline inode is unwritten
authorYongpeng Yang <yangyongpeng@xiaomi.com>
Tue, 19 May 2026 16:18:07 +0000 (12:18 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 23 May 2026 11:03:35 +0000 (13:03 +0200)
[ Upstream commit 68a0178981a0f493295afa29f8880246e561494c ]

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.

Cc: stable@kernel.org
Fixes: 67f8cf3cee6f ("f2fs: support fiemap for inline_data")
Signed-off-by: Yongpeng Yang <yangyongpeng@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
[ renamed `ifolio` to `ipage` in `inline_data_addr()` and `F2FS_INODE()` calls ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/f2fs/inline.c

index d5e8f3e40cc93bf54fcb3d2b09c6ac79332a9987..92bbdb272a6d930ab0f3469e19aeb70e93796b4d 100644 (file)
@@ -791,7 +791,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;
@@ -824,9 +824,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, ipage) -
-                                       (char *)F2FS_INODE(ipage);
+       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, ipage) -
+                                               (char *)F2FS_INODE(ipage);
+       } 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: