Re: [f2fs-dev] [RFC PATCH v2 0/5] f2fs: introduce inline extent mapping for inode data blocks

Yongpeng Yang <[email protected]> Mon, 13 Jul 2026 21:39:20 +0800
Newsgroups net.sourceforge.lists.linux-f2fs-devel
Message-ID <SEZPR02MB5662D6AE1DC030A20333BA2D99FA2@SEZPR02MB5662.apcprd02.prod.outlook.com>
On 7/2/26 22:30, Jaegeuk Kim via Linux-f2fs-devel wrote:
> On 06/25, Chao Yu via Linux-f2fs-devel wrote:
>> Sorry for the delay.
>>
>> On 5/29/26 16:56, Yongpeng Yang wrote:
>>> From: Yongpeng Yang <[email protected]>
>>>
>>> Changes since v1:
>>> - Introduce tracepoints for f2fs_iext_update_data_blkaddr and
>>>   f2fs_iext_lookup_blkaddr to aid debugging (new patch 5/5).
>>> - Bypass inline extent lookup for F2FS_GET_BLOCK_PRECACHE to ensure all
>>>   mappings are loaded into the read extent cache.
>>> - Unify the check for fofs exceeding direct_blocks range to use
>>>   "fofs >= direct_blocks" consistently.
>>> - Remove support for caching NULL_ADDR in inline extent area. If a fofs
>>>   within [0, direct_blocks) is not found in inline extent, it implies
>>>   NULL_ADDR. This simplifies merge and split logic.
>>> - Fix f2fs_iext_enable_inline_extent to use PTR_ERR instead of -ENOMEM.
>>> - Change f2fs_iext_convert_to_inline_extent return type to bool.
>>> - Add benchmark data covering 4K/8K/32K/64K random read.
>>> - Rename __is_extent_mergeable to __is_iextent_mergeable to avoid
>>>   naming collision with extent cache code.
>>> - Remove inode parameter from f2fs_iext_sanity_check (always NULL).
>>> - Reduce #ifdef CONFIG_F2FS_INLINE_EXTENT nesting in node.c.
>>> - Code style fixes to comply with kernel coding style.
>>>
>>> This patchset introduces an inline extent mapping mechanism for f2fs.
>>> Instead of storing individual block addresses in the inode's data block
>>> address area (i_addr[]), this feature packs contiguous block ranges into
>>> compact extent entries, significantly reducing the number of entries
>>> needed and enabling faster block address lookups via binary search.
>>>
>>> The inline extent format is identified by magic numbers in the inode
>>> data area and is transparent to the rest of f2fs -- when the extent
>>> area is full or cannot represent the mapping efficiently, it
>>> automatically converts back to the direct block address format.
>>>
>>> Patch 1: Preparatory refactoring -- replace raw pointer arithmetic
>>>          with f2fs_data_blkaddr() to abstract block address access.
>>> Patch 2: Core implementation -- data structures, extent operations
>>>          (lookup, insert, merge, split, truncate), format conversion,
>>>          and integration with f2fs data/node paths.
>>> Patch 3: ioctl interface -- allow per-file enable/disable of inline
>>>          extent format via F2FS_EXTENT_FL flag.
>>> Patch 4: sysfs interface -- runtime enable/disable toggle and file
>>>          extension list for automatic inline extent activation.
>>> Patch 5: Tracepoints for inline extent lookup and update operations.
>>>
>>> Test setup and results:
>>> =======================
>>>
>>> Platform: Xiaomi smartphone, UFS 4.0 storage
>>>
>>>   # Enable inline extent
>>>   echo 1 > /sys/fs/f2fs/<dev>/inline_extent_enable
>>>   echo 'mp4' > /sys/fs/f2fs/<dev>/inline_extent_extension_list
>>>
>>>   # Prepare data: write with 4K offset stride to create fragmented
>>>   # extents, then overwrite sequentially so inline extent can cache
>>>   # all mappings in compact form.
>>>   fio --name=test --filename=data.mp4 --rw=write:4k --bs=64M \
>>>       --size=8G --ioengine=libaio --direct=1
>>>   sync
>>>   fio --name=test --filename=data.mp4 --rw=write --bs=64M \
>>>       --size=8G --ioengine=libaio --direct=1
>>>   sync
>>>   echo 3 > /proc/sys/vm/drop_caches
>>>
>>>   # Benchmark: random buffered read, 1GB total IO
>>>   fio --name=buffer-read --ioengine=libaio --rw=randread --bs=$BS \
>>>       --size=8G --io_size=1G --numjobs=1 --filename=data.mp4
>>>
>>> Results (random read bandwidth, MiB/s):
>>> +---------------------------------------------------+
>>> | BS     | baseline | inline ext | improvement      |
>>> |--------+----------+------------+------------------|
>>> | 4K     | 35       | 36         | +2.5%            |
>>> | 8K     | 60       | 62         | +3%              |
>>> | 32K    | 179      | 191        | +6.8%            |
>>> | 64K    | 284      | 321        | +13%             |
>>> +---------------------------------------------------+
>>>
>>> The improvement comes from eliminating direct/indirect node page reads
>>> during block address lookup -- all mappings are stored directly in
>>> the inode page and found via O(log n) binary search.
>>>
>>> Yongpeng Yang (5):
>>>   f2fs: replace raw dnode pointer arithmetic with f2fs_data_blkaddr()
>>>   f2fs: introduce inline extent mapping for inode data blocks
>>>   f2fs: support setting inline extent flag via ioctl
>>>   f2fs: add sysfs interface for inline extent management
>>>   f2fs: introduce tracepoints for inline extent lookup and update
>>>
>>>  fs/f2fs/Kconfig             |  18 +
>>>  fs/f2fs/Makefile            |   1 +
>>>  fs/f2fs/data.c              | 157 ++++++-
>>>  fs/f2fs/debug.c             |   4 +
>>>  fs/f2fs/dir.c               |   9 +
>>>  fs/f2fs/f2fs.h              |  23 +-
>>>  fs/f2fs/file.c              |  93 +++-
>>>  fs/f2fs/iextent.c           | 873 ++++++++++++++++++++++++++++++++++++
>>>  fs/f2fs/iextent.h           | 187 ++++++++
>>>  fs/f2fs/inline.c            |   7 +
>>>  fs/f2fs/namei.c             |  48 ++
>>>  fs/f2fs/node.c              |  66 ++-
>>>  fs/f2fs/node.h              |   4 +
>>>  fs/f2fs/recovery.c          |  17 +
>>>  fs/f2fs/super.c             |  13 +
>>>  fs/f2fs/sysfs.c             |  52 +++
>>>  include/trace/events/f2fs.h |  79 ++++
>>>  17 files changed, 1635 insertions(+), 16 deletions(-)
>>
>> It's quite a large number of change (including f2fs-tools change) to support
>> this new feature, it causes the performance price ratio a little bit low.
>>
>> About inode disk layout, as we discuss offline, maybe we can add 4 or 8 ...
>> extents in i_extra_attr area of f2fs_inode structure, it can reduce the
>> change line and code complex, however, not sure how will it affect the
>> benefits.
>>
>> To Jaegeuk, please share your thoughts on this feature.
> 
> Agreed. Can we try to add more extents simply?

Thanks for the feedback and sorry for the delay! Here is a simpler
design I'd like to propose for adding more extents:

1) Shrink i_compr_blocks from __le64 to __le32, reuse the freed upper
   32 bits as a new field: i_inline_ext_capacity.

   The in-kernel fi->i_compr_blocks is already atomic_t (32-bit), so
   the 64-bit on-disk width was never fully utilized.

       /* before */
       __le64 i_compr_blocks;

       /* after */
       __le32 i_compr_blocks;
       __le32 i_inline_ext_capacity;  /* # of extent entries */

2) Place the inline extent area immediately after i_extra_end[0].
   The area format is: struct f2fs_iext_header followed by a
   struct f2fs_extent array, reusing the same inline extent format
   from v2, but without the magic number (since i_inline_ext_capacity
   already indicates the presence and size of the area).

3) Prohibit compressed files from using inline extents.

   On little-endian, the split maps to:

       offset +0: i_compr_blocks        (original le64 low 32 bits)
       offset +4: i_inline_ext_capacity  (original le64 high 32 bits)

   For compressed files i_inline_ext_capacity is always 0, so old fsck
   reading the full 64-bit i_compr_blocks gets the same value as the
   new 32-bit field. For non-compressed files i_compr_blocks is 0
   regardless, so there is no conflict either.

4) Include the inline extent area size in i_extra_isize.

       i_extra_isize = base_extra_size
                     + sizeof(struct f2fs_iext_header)
                     + i_inline_ext_capacity * sizeof(struct f2fs_extent)

   Old kernels use i_extra_isize to skip the extra attribute region,
   so the inline extent area is simply invisible to them, it will not
   be misinterpreted as i_addr[] block addresses.

5) i_inline_ext_capacity is configurable at mkfs/tunefs time. When it
   is 0, no extra space is consumed beyond i_extra_end, so there is no
   impact on inodes that do not use inline extents.

Please review this layout modification.

Thanks
Yongpeng,

> 
>>
>> Thanks,
>>
>>>  create mode 100644 fs/f2fs/iextent.c
>>>  create mode 100644 fs/f2fs/iextent.h
>>>
>>
>>
>>
>> _______________________________________________
>> Linux-f2fs-devel mailing list
>> [email protected]
>> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
> 
> 
> _______________________________________________
> Linux-f2fs-devel mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel



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