Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

f2fs: fix incorrect file address mapping when inline inode is unwritten

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>

authored by

Yongpeng Yang and committed by
Jaegeuk Kim
68a01789 5604129b

+9 -4
+9 -4
fs/f2fs/inline.c
··· 792 792 int f2fs_inline_data_fiemap(struct inode *inode, 793 793 struct fiemap_extent_info *fieinfo, __u64 start, __u64 len) 794 794 { 795 - __u64 byteaddr, ilen; 795 + __u64 byteaddr = 0, ilen; 796 796 __u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED | 797 797 FIEMAP_EXTENT_LAST; 798 798 struct node_info ni; ··· 825 825 if (err) 826 826 goto out; 827 827 828 - byteaddr = (__u64)ni.blk_addr << inode->i_sb->s_blocksize_bits; 829 - byteaddr += (char *)inline_data_addr(inode, ifolio) - 830 - (char *)F2FS_INODE(ifolio); 828 + if (__is_valid_data_blkaddr(ni.blk_addr)) { 829 + byteaddr = (__u64)ni.blk_addr << inode->i_sb->s_blocksize_bits; 830 + byteaddr += (char *)inline_data_addr(inode, ifolio) - 831 + (char *)F2FS_INODE(ifolio); 832 + } else { 833 + f2fs_bug_on(F2FS_I_SB(inode), ni.blk_addr != NEW_ADDR); 834 + flags |= FIEMAP_EXTENT_DELALLOC | FIEMAP_EXTENT_UNKNOWN; 835 + } 831 836 err = fiemap_fill_next_extent(fieinfo, start, byteaddr, ilen, flags); 832 837 trace_f2fs_fiemap(inode, start, byteaddr, ilen, flags, err); 833 838 out: