[f2fs-dev] [RFC PATCH v4 0/3] f2fs: introduce inline extent mapping for inode data blocks

Yongpeng Yang <[email protected]> Thu, 6 Aug 2026 21:19:00 +0800
Newsgroups net.sourceforge.lists.linux-f2fs-devel
Message-ID <[email protected]>
From: Yongpeng Yang <[email protected]>

Changes since v3:
- Do not cache NEW_ADDR in the inline extent area. A NEW_ADDR write is
  now handled exactly like NULL_ADDR: it only unmaps the block.
- Simplify the insert path. A single-block overwrite is now expressed as
  four small steps:
  1) reserve room for a possible split.
  2) unmap the old mapping of the block.
  3) insert the new mapping.
  4) try to merge the inserted mapping with its left and right.
- Remove the inline-extent code-coverage statistics.

v3: https://lore.kernel.org/all/[email protected]/

Changes since v2:
- Inline extent no longer covers direct block mappings. The inline
  extent area is now placed after struct f2fs_inode->i_extra_end,
  inside the i_extra_isize region. This removes the need for format
  conversion and for f2fs-tools to understand/modify the inline extent
  on-disk format.
- Split struct f2fs_inode->i_compr_blocks (was __le64) into __le32
  i_compr_blocks + __le32 i_inline_ext_capacity, where
  i_inline_ext_capacity records the per-inode inline extent capacity.
- Dropped [RFC PATCH v2 1/5] "replace raw dnode pointer arithmetic with
  f2fs_data_blkaddr()": f2fs_truncate_data_blocks_range no longer needs
  changes to accommodate the redesigned inline extent.
- Dropped [RFC PATCH v2 3/5] "support setting inline extent flag via
  ioctl": format conversion between inline extent and the direct block
  address array is no longer needed.
- Re-ran the performance tests (see updated numbers below).

v2: https://lore.kernel.org/all/[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.

v1: https://lore.kernel.org/all/[email protected]/

This patchset introduces an inline extent mapping mechanism for f2fs.
Instead of storing individual block addresses for indirect-node blocks,
this feature packs contiguous block ranges into compact extent entries
stored directly in the inode, reducing indirect/double-indirect node
page reads and enabling O(log n) block address lookup via binary search.

Design overview:
- The inline extent area is placed immediately after i_extra_end in the
  on-disk inode, within the i_extra_isize region. Its size (number of
  extent entries) is determined by the new field i_inline_ext_capacity.
- On-disk layout:
    [i_extra_isize .. i_extra_end] [f2fs_iext_header | f2fs_extent[cap]]
    |<------------------ i_extra_isize (in bytes) ------------------->|
- Inline extent only caches mappings for indirect blocks
  (fofs >= ADDRS_PER_INODE). Direct block mappings continue to use
  i_addr[], so no format conversion is required.
- Per-inode capacity is decided at file creation time based on the
  configured file-extension matching rules (see sysfs below).
- Mutually exclusive with compression.

Patch 1: Core implementation -- data structures, extent operations
         (lookup, insert, merge, split, truncate), and integration
         with the f2fs data/node/inode/recovery paths.
Patch 2: sysfs interface -- runtime enable/disable toggle and the file
         extension list (with optional per-extension capacity) for
         automatic inline extent activation.
Patch 3: Tracepoints for inline extent lookup and update operations.

Test setup (Xiaomi smartphone, UFS 4.0 storage):

  echo 1 > /sys/fs/f2fs/<dev>/inline_extent_enable
  echo 'mp4:256' > /sys/fs/f2fs/<dev>/inline_extent_extension_list
  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
  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     | 31.6     | 32.4       | +2.5%            |
| 8K     | 55.4     | 58.5       | +5.6%            |
| 32K    | 155.3    | 166.8      | +7.4%            |
| 64K    | 229.8    | 255.3      | +11.1%           |
| 128K   | 337.8    | 388        | +14.9%           |
+---------------------------------------------------+

The improvement comes from eliminating indirect/double-indirect node
page reads during block address lookup -- indirect-block mappings are
stored directly in the inode page and found via binary search.

Yongpeng Yang (3):
  f2fs: introduce inline extent mapping for inode data blocks
  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              | 146 +++++++++-
 fs/f2fs/dir.c               |   1 +
 fs/f2fs/f2fs.h              |  44 ++-
 fs/f2fs/file.c              |   1 +
 fs/f2fs/iextent.c           | 535 ++++++++++++++++++++++++++++++++++++
 fs/f2fs/iextent.h           | 136 +++++++++
 fs/f2fs/inline.c            |   1 +
 fs/f2fs/inode.c             |  41 ++-
 fs/f2fs/namei.c             |  67 +++++
 fs/f2fs/node.c              |  38 ++-
 fs/f2fs/node.h              |   4 +
 fs/f2fs/recovery.c          |  15 +
 fs/f2fs/super.c             |  29 ++
 fs/f2fs/sysfs.c             |  91 ++++++
 include/linux/f2fs_fs.h     |   3 +-
 include/trace/events/f2fs.h |  79 ++++++
 18 files changed, 1229 insertions(+), 21 deletions(-)
 create mode 100644 fs/f2fs/iextent.c
 create mode 100644 fs/f2fs/iextent.h

-- 
2.43.0



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