On 02/03, Yongpeng Yang wrote:
> From: Yongpeng Yang <[email protected]>
> 
> f2fs_fiemap() calls f2fs_map_blocks() to obtain the block mapping a
> file, and then merges contiguous mappings into extents. If the mapping
> is found in the read extent cache, node blocks do not need to be read.
> However, in the following scenario, a contiguous extent can be split
> into two extents:
> 
> root@vm:/mnt/f2fs# dd if=/dev/zero of=data.4M bs=1M count=4 && sync
> root@vm:/mnt/f2fs# dd if=/dev/zero of=data.4M bs=1M count=2 seek=2 
> conv=notrunc && sync
> root@vm:/mnt/f2fs# echo 3 > /proc/sys/vm/drop_caches # drop 2M~4M extent cache
> root@vm:/mnt/f2fs# dd if=/dev/zero of=data.4M bs=1M count=2 seek=0 
> conv=notrunc && sync
> root@vm:/mnt/f2fs# f2fs_io fiemap 0 1024 data.4M
> Fiemap: offset = 0 len = 1024
> logical addr.    physical addr.   length           flags
> 0     0000000000000000 0000000006400000 0000000000200000 00001000
> 1     0000000000200000 0000000006600000 0000000000200000 00001001
> 
> Although the physical addresses of the ranges 0~2MB and 2M~4MB are
> contiguous, the mapping for the 2M~4MB range is not present in memory.
> When the physical addresses for the 0~2MB range are updated, no merge
> happens because the adjacent mapping is missing from the in-memory
> cache. As a result, fiemap reports two separate extents instead of a
> single contiguous one.
> 
> The root cause is that the read extent cache does not guarantee that all
> blocks of an extent are present in memory. Therefore, when the extent
> length returned by f2fs_map_blocks_cached() is smaller than maxblocks,
> the remaining mappings are retrieved via f2fs_get_dnode_of_data() to
> ensure correct fiemap extent boundary handling.
> 
> Fixes: cd8fc5226bef ("f2fs: remove the create argument to f2fs_map_blocks")
> Signed-off-by: Yongpeng Yang <[email protected]>
> ---
>  fs/f2fs/data.c | 14 ++++++++++++--
>  1 file changed, 12 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 42f15fd9c68e..eedadccf86bb 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1623,8 +1623,18 @@ int f2fs_map_blocks(struct inode *inode, struct 
> f2fs_map_blocks *map, int flag)
>       lfs_dio_write = (flag == F2FS_GET_BLOCK_DIO && f2fs_lfs_mode(sbi) &&
>                               map->m_may_create);
>  
> -     if (!map->m_may_create && f2fs_map_blocks_cached(inode, map, flag))
> -             goto out;
> +     if (!map->m_may_create) {
> +             if (f2fs_map_blocks_cached(inode, map, flag)) {
> +                     if (map->m_len == maxblocks)
> +                             goto out;
> +                     else {
> +                             pgofs = (pgoff_t)map->m_lblk + map->m_len;
> +                             end = map->m_lblk + maxblocks;
> +                             ofs = map->m_len;
> +                             goto next_dnode;
> +                     }
> +             }
> +     }

This patch makes a system panic.

>  
>       map->m_bdev = inode->i_sb->s_bdev;
>       map->m_multidev_dio =
> -- 
> 2.43.0


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

Reply via email to