Commit Graph

4981 Commits

Author SHA1 Message Date
Linus Torvalds
115bd364ab f2fs-for-7.3-rc1
In this round, key enhancements focus on reducing inode management memory
 overhead, introducing resizable tail sections with unified pinned allocation,
 and boosting I/O throughput via parallel multi-device flushes and asynchronous
 f2fs_write_end_io() execution. We also add dynamic device alias reservations to
 allow on-the-fly space donation from user partitions.
 
 Alongside these features, critical bug fixes resolve folio race conditions,
 lingering dirty flags, dentry and block counter leaks, and potential deadloops
 in f2fs_fsync_node_pages(). Additional stability patches address error-path
 handling across symlink, sync, and rename/unlink operations, prevent pinned file
 fragmentation, and correct segment migration and free section accounting in
 free_segment_range.
 
 Enhancement:
  - reduce memory footprint of ino management
  - support dynamic reserve/release for device aliasing
  - issue multi-device flushes in parallel
  - add a way to run f2fs_write_end_io() asynchronously
  - support resizable tail section and unify pinned allocation
 
 Bug fix:
  - fix to pass folio->index to f2fs_sanity_check_node_footer()
  - fix folio_nr_pages() race after put in large folio invalidate
  - fix to clear dirty flag on folio in error path
  - accurately adjust free_sections during free_segment_range
  - fix to avoid potential deadloop in f2fs_fsync_node_pages()
  - fix the error path in symlink, device alias in rename/unlink,
    f2fs_sync_fs,
  - fix to migrate all curseg types during free_segment_range
  - fix to avoid pinfile fragment on fragment:{block, segment} mode
  - fix valid block count leak on data block allocation failure
  - fix dentry folio leak in find_in_level
  - reject overlapping move range after len expansion
  - fix some bugs related to file pinning, GC functions, i_size.
 
 And, the series includes a number of minor bug fixes.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE00UqedjCtOrGVvQiQBSofoJIUNIFAmqPybMACgkQQBSofoJI
 UNKp2g/+OP6XZi56hNTqscnKyKrDdVJnOcS/YOe7d1BR+070qmPTpyFjLgjng05K
 exu55rz9vJ3DlpFLsjMEo60DRlDEc5rR4AqymMjqFJH9424ZlxPpdDn6ofCVT0Ck
 D6RTf3y1HFSi4x7//gPQofR9y4MlDrH2Q7NPDriipqbymuNXEjrx/vdr2nq/kHUu
 2lbf7QQs08qYiyDxQcxOFdCdxUTrsEW/tkYZiwgbU2nCJ/eG2R59amgtYJg3SlVt
 xdrf+IaSS7kE5+mGCoBm0WooPpB507kHaoQpZYDj2uueFvEw7nFcSfOCXapOvg8U
 wFkRR0F/rZ4+AW/u4n8Ye7N4a7WjWMTBwfR3WJ2j+arhfn87vJZK6LQQlYwq16l4
 tRcQFcCrKsXHh5HY2OGj8DzTd40zryXujH566YioBCAXU312My1yFjeTJzjobbUW
 TclkfMl689iTr9pqBhIjKT2tTvZFLROYSLk5UBNFNSfA4PtsAAhqlUrE1ck3AuTA
 8kIjLmppfZEBqVuZCF0T1z9TXk0Bg0eM8qHbl/8SdDavmf1pF1BupLqchfdZp6Jr
 4iV1weK4dzmCF6++YDsNlvnBGyTbhiFdN7C5cMlv89PTSTUQZ45Me6JmNwrRDqyU
 MSTyiSSpI+3rAMO0h58PHi+QAOtM0f+S7C24ySkBBerBCbMTK6A=
 =xQ77
 -----END PGP SIGNATURE-----

Merge tag 'f2fs-for-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs

Pull f2fs updates from Jaegeuk Kim:
 "In this round, key enhancements focus on reducing inode management
  memory overhead, introducing resizable tail sections with unified
  pinned allocation, and boosting I/O throughput via parallel
  multi-device flushes and asynchronous f2fs_write_end_io() execution.
  We also add dynamic device alias reservations to allow on-the-fly
  space donation from user partitions.

  Alongside these features, critical bug fixes resolve folio race
  conditions, lingering dirty flags, dentry and block counter leaks, and
  potential deadloops in f2fs_fsync_node_pages(). Additional stability
  patches address error-path handling across symlink, sync, and
  rename/unlink operations, prevent pinned file fragmentation, and
  correct segment migration and free section accounting in
  free_segment_range.

  Enhancements:
   - reduce memory footprint of ino management
   - support dynamic reserve/release for device aliasing
   - issue multi-device flushes in parallel
   - add a way to run f2fs_write_end_io() asynchronously
   - support resizable tail section and unify pinned allocation

  Bug fixes:
   - fix to pass folio->index to f2fs_sanity_check_node_footer()
   - fix folio_nr_pages() race after put in large folio invalidate
   - fix to clear dirty flag on folio in error path
   - accurately adjust free_sections during free_segment_range
   - fix to avoid potential deadloop in f2fs_fsync_node_pages()
   - fix the error path in symlink, device alias in rename/unlink,
     f2fs_sync_fs
   - fix to migrate all curseg types during free_segment_range
   - fix to avoid pinfile fragment on fragment:{block, segment} mode
   - fix valid block count leak on data block allocation failure
   - fix dentry folio leak in find_in_level
   - reject overlapping move range after len expansion
   - fix some bugs related to file pinning, GC functions, i_size

  And, the series includes a number of minor bug fixes"

* tag 'f2fs-for-7.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (51 commits)
  f2fs: support resizable tail section and unify pinned allocation
  f2fs: don't leave the hashed inode while it's unlinked
  f2fs: accurately adjust free_sections during free_segment_range
  f2fs: fix to avoid potential deadloop in f2fs_fsync_node_pages()
  f2fs: use adjusted write range after f2fs_write_checks()
  f2fs: fix to propagate error from f2fs_sync_fs()
  f2fs: return symlink writeback errors
  f2fs: fix error handling on device alias check in rename and unlink
  f2fs: fix to reset all pinned status during fggc
  f2fs: use f2fs_{down, up}_(read, write}_trace() for nat_tree_lock
  f2fs: reduce memory footprint of ino management
  f2fs: fix i_size when pinned fallocate partially fails
  f2fs: fix to migrate all curseg types during free_segment_range
  f2fs: avoid setting SBI_NEED_FSCK on transient resize failure
  f2fs: fix to avoid pinfile fragment on fragment:{block, segment} mode
  f2fs: cleanup w/ f2fs_need_rand_{blk, seg, seg_blk}
  f2fs: fix to shrink gc_lock coverage in f2fs_gc_range()
  f2fs: fix to reclaim space in f2fs_allocate_pinning_section()
  f2fs: unify add/remove ino entry API for all ino types
  f2fs: fix to zero post-EOF data when extending file size
  ...
2026-08-28 10:48:48 -07:00
Daeho Jeong
c966d29e01 f2fs: support resizable tail section and unify pinned allocation
Currently, zoned block devices restrict pinned file allocations to
conventional zones at the beginning of the storage (before
first_seq_zone_segno), triggering range GC when conventional space is
exhausted.

On regular block devices, when preparing for future online filesystem
resizing (e.g. partition shrinking), pinned files must not be allocated
in the tail area that will be truncated, as pinned files cannot be
relocated by GC. Specifying the resizable tail area size (in sections)
allows uniform mount configuration across devices of different storage
capacities.

To support this, introduce a unified `pinned_area_max_secno` boundary
abstraction in `f2fs_sb_info`:
1. Add `-o resizable_tail_secno=%u` mount option to specify the number
   of sections at the tail of the filesystem reserved for resizing.
2. In `f2fs_fill_super()`, initialize `sbi->pinned_area_max_secno` as:
   min(MAIN_SECS(sbi) - resizable_tail_sec, zoned_max_sec).
3. In `get_new_segment()`, restrict segment allocation for pinned files
   (`pinning == true`) to `0 .. sbi->pinned_area_max_secno - 1`. If no
   free section is available in the pinned area, return -EAGAIN.
4. In `f2fs_allocate_pinning_section()`, unify the range GC trigger to
   run `f2fs_gc_range()` up to `sbi->pinned_area_max_secno` whenever
   `sbi->pinned_area_max_secno < MAIN_SECS(sbi)` and allocation
   returns -EAGAIN.
5. Expose `/sys/fs/f2fs/<dev>/pinned_area_max_secno` as a read-only
   sysfs node.

Signed-off-by: Daeho Jeong <daehojeong@google.com>
Signed-off-by: Sunmin Jeong <s_min.jeong@samsung.com>
Reviewed-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-27 04:47:36 +00:00
Jaegeuk Kim
24c1a47f1e f2fs: don't leave the hashed inode while it's unlinked
f2fs_symlink()
1. f2fs_new_inode
2. f2fs_add_link
3. write_being|end to fill the symlink path
4. flush dirty pages and or checkpoint

Step 4 is nice to succeed, which doesn't become a reason to roll back
the created symlink. OTOH, if we get an error till step 3, don't leave
its dentry and its inode.

Reviewed-by: Chao Yu <chao@kernel.org>
Reviewed-by: Wenjie Qi <qiwenjie@xiaomi.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-26 04:00:50 +00:00
Daeho Jeong
8c963d1738 f2fs: accurately adjust free_sections during free_segment_range
In free_segment_range(), MAIN_SECS(sbi) is temporarily reduced by `secs`
to restrict block allocation to the safe remaining main area while valid
blocks in the truncated range are evacuated by GC.

However, FREE_I(sbi)->free_sections tracks the total number of free
sections across the whole filesystem. If any sections within the
truncated range were already free upon entering free_segment_range(),
failing to deduct them from free_sections causes the filesystem to
overestimate available free sections in the active, reduced main area.
This leads to inconsistent free section accounting during GC data
migration and can trigger unexpected allocation failures or assertion
errors when space is tight.

Fix this by calculating the number of already-free sections in the
truncated range, deducting them from free_sections upon entering
free_segment_range(), and restoring them on exit.

Fixes: b4b10061ef ("f2fs: refactor resize_fs to avoid meta updates in progress")
Cc: stable@vger.kernel.org
Signed-off-by: Daeho Jeong <daehojeong@google.com>
Signed-off-by: Sunmin Jeong <s_min.jeong@samsung.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-25 15:32:48 +00:00
Chao Yu
ce366bfa82 f2fs: fix to avoid potential deadloop in f2fs_fsync_node_pages()
There is potential deadloop in race condition:

Thread A				Thread B
- fsync
 - f2fs_do_sync_file
  - f2fs_fsync_node_pages
   - last_fsync_dnode
    - folio_get(last_folio)
					- f2fs_setattr
					 - f2fs_truncate
					  - f2fs_truncate_blocks
					   - f2fs_do_truncate_blocks
					    - f2fs_truncate_inode_blocks
					     - truncate_dnode
					      - truncate_node
					       - invalidate_mapping_pages
					        - folio->mapping = NULL
   - is_node_folio alwasy return false
   - atomic && !marked is always true,
     then goto retry

Cc: stable@kernel.org
Fixes: 608514deba ("f2fs: set fsync mark only for the last dnode")
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-25 02:04:36 +00:00
Seongjae Jeong
3b2c5d35cf f2fs: use adjusted write range after f2fs_write_checks()
generic_write_checks() in f2fs_write_checks() can adjust iocb->ki_pos
for append writes and truncate the iterator to limit the number of bytes
to write.

In f2fs_file_write_iter(), the pinned-file overwrite check currently
uses the position and count saved before f2fs_write_checks(), so it
can check a range different from the actual write range.

The forced buffered I/O cleanup also uses orig_pos saved before
f2fs_write_checks(). For O_APPEND writes, this can make the cleanup
flush and invalidate the wrong page cache range.

Move the pinned-file overwrite check after f2fs_write_checks() and use
the adjusted iocb->ki_pos and iov_iter_count(from). Also save the
adjusted write position and use it for the forced buffered I/O cleanup.

Fixes: 3fdd89b452 ("f2fs: prevent writing without fallocate() for pinned files")
Fixes: 92318f20d7 ("f2fs: preserve direct write semantics when buffering is forced")
Signed-off-by: Seongjae Jeong <jsjlee1020@gmail.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-24 15:21:58 +00:00
Chao Yu
dafb84f092 f2fs: fix to propagate error from f2fs_sync_fs()
So that caller can detect any failure from f2fs_sync_fs().

Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-21 23:42:34 +00:00
Wenjie Qi
a2c73a7a67 f2fs: return symlink writeback errors
F2FS writes long symlink data with page_symlink() and then flushes the
symlink mapping to reduce the chance of exposing a broken symlink.

That flush result is currently ignored. If the writeback fails, symlink()
still returns success even though the symlink is not durable and the same
operation can already surface -EIO through syncfs().

Return the writeback error to userspace and skip the dirsync flush once the
symlink data flush has failed.

Fixes: d0cae97cb6 ("f2fs: flush symlink path to avoid broken symlink after POR")
Cc: stable@kernel.org
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-21 23:42:34 +00:00
Daeho Jeong
11d56d7a8e f2fs: fix error handling on device alias check in rename and unlink
In f2fs_rename() and f2fs_unlink(), directly returning -EPERM when
encountering a device aliasing file bypasses the cleanup path.

Fix this by setting err to -EPERM and jumping to the proper cleanup
labels (out_dir and out) instead of returning immediately.

Reported-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Signed-off-by: Daeho Jeong <daehojeong@google.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-21 23:42:33 +00:00
Chao Yu
2b8704b6a8 f2fs: fix to reset all pinned status during fggc
Otherwise, the pinned status may affect latter flow of fggc.

Cc: stable@kernel.org
Fixes: 9703d69d9d ("f2fs: support file pinning for zoned devices")
Cc: Daeho Jeong <daehojeong@google.com>
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-21 23:42:33 +00:00
Chao Yu
46d4246d8d f2fs: use f2fs_{down, up}_(read, write}_trace() for nat_tree_lock
Under heavy workloads or during background GC/fallocate operations,
nat_tree_lock can experience high lock contention between background
readers (e.g. f2fs_get_node_info() in gc_data_segment) and writers
(e.g. flush_nat_entries, set_node_addr, shrinker).

[375067.327986][T13777]  schedule+0x4c/0x114
[375067.327997][T13777]  f2fs_get_node_info+0x438/0x5c4
[375067.328002][T13777]  f2fs_get_inode_page+0x1e0/0x3f0
[375067.328013][T13777]  f2fs_iget+0x88/0x1180
[375067.328024][T13777]  f2fs_lookup+0x168/0x3a8
[375067.328035][T13777]  path_openat+0xa28/0x1b04
[375067.328046][T13777]  do_filp_open+0xac/0x130
[375067.328056][T13777]  do_sys_openat2+0x140/0x21c
[375067.328066][T13777]  __arm64_sys_openat+0x70/0x9c

[375067.330299][T13777]  schedule+0x4c/0x114
[375067.330310][T13777]  schedule_preempt_disabled+0x24/0x40
[375067.330321][T13777]  rwsem_down_write_slowpath+0x3b4/0x9d0
[375067.330332][T13777]  down_write+0x98/0x170
[375067.330343][T13777]  set_node_addr+0x74/0x4b4
[375067.330354][T13777]  f2fs_new_node_page+0xb0/0x280
[375067.330444][T13777]  f2fs_new_inode_page+0x3c/0x64
[375067.330455][T13777]  f2fs_init_inode_metadata+0x4c/0x47c
[375067.330461][T13777]  f2fs_add_regular_entry+0x258/0x5b8
[375067.330471][T13777]  f2fs_add_dentry+0x100/0x158
[375067.330476][T13777]  f2fs_do_add_link+0x84/0x140
[375067.330487][T13777]  f2fs_create+0xec/0x250

[375067.331759][T13777]  schedule+0x4c/0x114
[375067.331770][T13777]  f2fs_down_read+0x9c/0xc4
[375067.331781][T13777]  f2fs_need_inode_block_update+0x20/0x10c
[375067.331792][T13777]  f2fs_do_sync_file+0x478/0x830
[375067.331802][T13777]  f2fs_sync_file+0x2c/0x40

This patch converts nat_tree_lock to use the f2fs_{down,up}_{read,write}_trace
infrastructure.

Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-21 23:42:31 +00:00
Chao Yu
9a9ee7408a f2fs: reduce memory footprint of ino management
Currently, ino entries for APPEND_INO, UPDATE_INO, TRANS_DIR_INO, and
XATTR_DIR_INO allocate a 'struct ino_entry' slab object and attach it to
both a list and a radix tree solely for existence checks via
f2fs_exist_written_data().

Since these ino types only track binary existence status, we can embed
the information directly into radix tree value entries as a bitmap:

- The Linux radix tree/XArray supports in-place value entries via
  xa_mk_value() / xa_to_value(), which tag the least significant bit
  to store an unallocated integer value of BITS_PER_XA_VALUE bits
  (BITS_PER_LONG - 1) directly in the slot pointer.
- For each inode, (ino / BITS_PER_XA_VALUE) serves as the radix tree
  slot index, and (ino % BITS_PER_XA_VALUE) is used as the bit offset
  within the slot's bitmap.

For example, when tracking ino = 7:
- Before: Allocate a 'struct ino_entry' ({ .ino = 7 }), insert its
  pointer into the radix tree at index = 7, and link it to im->ino_list.
- After: Compute slot_index = 7 / BITS_PER_XA_VALUE (index 0) and
  bit_offset = 7 % BITS_PER_XA_VALUE (bit 7), then set bit 7 in the
  value entry via xa_mk_value(bitmap) at index 0, without allocating
  a slab object or linking to a list.

Additionally:
- In-place slot updates are performed via radix_tree_replace_slot(), and
  slots are deleted with radix_tree_delete() once the bitmap is zeroed.
- Reorder the ino list enum so ORPHAN_INO and FLUSH_INO (which still
  require struct ino_entry and list traversal) remain separated, while
  bitmap-based trees are torn down using xa_destroy().

This eliminates 'struct ino_entry' slab allocations and linked-list
tracking for these ino types, significantly reducing memory consumption.

Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-21 01:00:52 +00:00
Zhan Xusheng
0f448bb376 f2fs: fix i_size when pinned fallocate partially fails
From: Zhan Xusheng <zhanxusheng@xiaomi.com>

Commit 4275b59673 ("f2fs: fix to round down start offset of fallocate
for pin file") moved the allocation loop's start down to a section
boundary, but the error path still converts @expanded against @pg_start,
which holds the unrounded start.

@pg_start exists for that conversion: commit 88f2cfc5fa ("f2fs: fix to
update last i_size if fallocate partially succeeds") added it as an
immutable base because map.m_lblk moves every round.  Each round now maps
exactly sec_blks blocks starting from rounddown(pg_start, sec_blks), so
pg_start + expanded overshoots the last allocated block by
pg_start % sec_blks, and a partial failure leaves i_size covering a tail
that was never allocated.  Nothing corrects that afterwards either, since
file_dont_truncate() has already cleared FADVISE_TRUNC_BIT.

It needs a start offset that is not section aligned plus a fallocate that
hits ENOSPC partway, so the error path runs with expanded > 0.  On an
80 MiB image with 2 MiB sections:

  truncate -s 80M img
  mkfs.f2fs -s 1 -f img
  mount -o loop img /mnt
  touch /mnt/pinned
  f2fs_io pinfile set /mnt/pinned
  # 2093056 = block 511, so pg_start % sec_blks = 511
  f2fs_io fallocate 0 2093056 536870912 /mnt/pinned
  stat -c %s /mnt/pinned
  filefrag -v /mnt/pinned

The last extent ends at block 10737 either way.  Before, i_size is
46075904, block 11249, so 511 blocks of it were never allocated, and
filefrag does not mark the last extent eof.  After, i_size is 43982848,
block 10738, and eof is back.  A kernel from before that commit also
shows no overshoot.

Keep @pg_start pointing at where allocation actually begins.

Fixes: 4275b59673 ("f2fs: fix to round down start offset of fallocate for pin file")
Cc: stable@vger.kernel.org
Signed-off-by: Zhan Xusheng <zhanxusheng@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-21 01:00:38 +00:00
Daeho Jeong
8ec06f50dd f2fs: fix to migrate all curseg types during free_segment_range
In free_segment_range(), the curseg evacuation loop only iterates up to
NR_CURSEG_PERSIST_TYPE (0..5), missing non-persistent in-memory curseg
types such as CURSEG_COLD_DATA_PINNED and CURSEG_ALL_DATA_ATGC.

Even though these in-memory curseg types are not saved in the on-disk
checkpoint header, they still occupy active physical segments at runtime.
If an active in-memory curseg happens to be allocated within the segment
range being truncated during filesystem shrink, failing to evacuate it
will cause subsequent writes to the curseg attempting out-of-bounds I/O
on the truncated storage range.

Fix this by expanding the curseg evacuation loop upper bound to
NR_CURSEG_TYPE to ensure all active curseg types are safely migrated
out of the target range.

Fixes: d0b9e42ab6 ("f2fs: introduce inmem curseg")
Cc: stable@vger.kernel.org
Signed-off-by: Daeho Jeong <daehojeong@google.com>
Signed-off-by: Sunmin Jeong <s_min.jeong@samsung.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-21 01:00:38 +00:00
Daeho Jeong
258c95150c f2fs: avoid setting SBI_NEED_FSCK on transient resize failure
When free_segment_range() fails in f2fs_resize_fs(), no on-disk
superblock or filesystem metadata has been modified yet, and
free_segment_range() safely restores all in-memory counters before
returning.

However, the current error recovery path unconditionally sets the
SBI_NEED_FSCK flag and prints a scary error message on any error,
forcing an unnecessary and time-consuming fsck.f2fs repair on the
subsequent mount/reboot.

Fix this by separating the error recovery path with a dedicated
recover_user_blocks label to bypass setting SBI_NEED_FSCK on
free_segment_range() failures.

Signed-off-by: Daeho Jeong <daehojeong@google.com>
Signed-off-by: Sunmin Jeong <s_min.jeong@samsung.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-21 01:00:38 +00:00
Linus Torvalds
1d7443e4dc fscrypt updates for 7.3
The main change this cycle is a significant simplification that's been
 overdue for a while now: standardizing on a single file contents
 encryption implementation in ext4 and f2fs, instead of having two.
 
 Specifically, the original filesystem-layer file contents encryption
 implementation is removed, and the blk-crypto implementation is now
 used unconditionally. blk-crypto delegates either to inline crypto
 hardware or to the CPU via blk-crypto-fallback. The latter is
 functionally equivalent to the original filesystem-layer code.
 
 The blk-crypto implementation already existed, but previously it was
 used only when the filesystem was mounted with "-o inlinecrypt". Now,
 "-o inlinecrypt" just selects whether inline crypto hardware is used.
 
 To allow maintaining that user control over hardware use, the
 blk-crypto API is extended with a new flag BLK_CRYPTO_CFG_ALLOW_HW.
 
 Overall, this removes quite a bit of redundant code from ext4, f2fs,
 and fs/crypto/. It should make things easier for ongoing filesystem
 efforts such as iomap support, large folios, and btrfs encryption.
 (btrfs had already been planning to use blk-crypto exclusively.)
 
 There are two small behavior changes of note:
 
 - Direct I/O now works on encrypted files even without
   "-o inlinecrypt", rather than falling back to buffered I/O. This is
   effectively a bugfix, though I'll continue to keep an eye out for
   any user that may have been depending on the buffered I/O fallback.
 
 - IV_INO_LBLK_32 policies are no longer supported in certain cases
   that didn't make sense and have no known uses.
 
 This has been in linux-next since July 22 with no reported issues.
 All encryption xfstests pass on ext4 and f2fs. As usual I've also been
 using it on a system with an fscrypt-encrypted home directory. Of
 course, the blk-crypto code paths also aren't new and were already
 being used on many systems via the inlinecrypt mount option.
 
 In addition to the main change described above, there are a few other
 cleanups such as using lock guards for mutexes, improving
 documentation, and removing a workaround for outdated gcc versions.
 -----BEGIN PGP SIGNATURE-----
 
 iIoEABYIADIWIQSacvsUNc7UX4ntmEPzXCl4vpKOKwUCaoDumhQcZWJpZ2dlcnNA
 a2VybmVsLm9yZwAKCRDzXCl4vpKOKwk1AP9gAHdxAK2tr+Wpklkos/qTMR3a7h2I
 xLmgwhLHmHoHTgD/cD+0eMoK4RIVVGS/73Bf7oF2qY5jOyfi1aGh4ERQ0AA=
 =0+o6
 -----END PGP SIGNATURE-----

Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux

Pull fscrypt updates from Eric Biggers:
 "The main change this cycle is a significant simplification that's been
  overdue for a while now: standardizing on a single file contents
  encryption implementation in ext4 and f2fs, instead of having two.

  Specifically, the original filesystem-layer file contents encryption
  implementation is removed, and the blk-crypto implementation is now
  used unconditionally. blk-crypto delegates either to inline crypto
  hardware or to the CPU via blk-crypto-fallback. The latter is
  functionally equivalent to the original filesystem-layer code.

  The blk-crypto implementation already existed, but previously it was
  used only when the filesystem was mounted with "-o inlinecrypt". Now,
  "-o inlinecrypt" just selects whether inline crypto hardware is used.

  To allow maintaining that user control over hardware use, the
  blk-crypto API is extended with a new flag BLK_CRYPTO_CFG_ALLOW_HW.

  Overall, this removes quite a bit of redundant code from ext4, f2fs,
  and fs/crypto/. It should make things easier for ongoing filesystem
  efforts such as iomap support, large folios, and btrfs encryption
  (btrfs had already been planning to use blk-crypto exclusively.)

  There are two small behavior changes of note:

   - Direct I/O now works on encrypted files even without "-o inlinecrypt",
     rather than falling back to buffered I/O. This is effectively a
     bugfix, though I'll continue to keep an eye out for any user that
     may have been depending on the buffered I/O fallback.

   - IV_INO_LBLK_32 policies are no longer supported in certain cases
     that didn't make sense and have no known uses.

  This has been in linux-next since July 22 with no reported issues. All
  encryption xfstests pass on ext4 and f2fs. As usual I've also been
  using it on a system with an fscrypt-encrypted home directory. Of
  course, the blk-crypto code paths also aren't new and were already
  being used on many systems via the inlinecrypt mount option.

  In addition to the main change described above, there are a few other
  cleanups such as using lock guards for mutexes, improving
  documentation, and removing a workaround for outdated gcc versions"

* tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linux: (29 commits)
  blk-crypto: Update docs for blk-crypto-fallback motivation
  blk-crypto: Remove unused function blk_crypto_config_supported()
  fscrypt: Update docs for data path
  fscrypt: Remove unused function fscrypt_finalize_bounce_page()
  f2fs: Update outdated comment in f2fs_write_begin()
  fs: Update outdated comment for SB_INLINECRYPT
  fscrypt: Update encryption policy version docs
  fscrypt: Replace some variable-size memsets with fixed-size
  fscrypt: Add safety checks to non-block-based en/decryption
  fscrypt: Merge bio.c and inline_crypt.c into block.c
  fscrypt: Remove unused functions and workqueue
  fscrypt: Remove fs-layer zeroout code
  fscrypt: Remove fscrypt_dio_supported()
  fscrypt: Replace calls to fscrypt_inode_uses_inline_crypto()
  fs/buffer: Remove fs-layer decryption code
  f2fs: Remove fs-layer file contents en/decryption code
  ext4: Further de-generalize the bio postprocessing code
  ext4: Make ext4_bio_write_folio() return void
  ext4: Remove fs-layer file contents en/decryption code
  Documentation: fscrypt: Update docs for inlinecrypt
  ...
2026-08-17 19:04:16 -07:00
Chao Yu
0a1703eba2 f2fs: fix to avoid pinfile fragment on fragment:{block, segment} mode
pinfile fallocate() conflicts w/ mode=fragment:{block,segment} mount option,
result in fragment blocks in pinfile, it violate semantics of pinfile
introduced in commit f5a53edcf0 ("f2fs: support aligned pinned file").

mkfs.f2fs -f /dev/vdb
mount -t f2fs -o mode=fragment:block /dev/vdb /mnt/f2fs/
dd if=/dev/zero of=/mnt/f2fs/file bs=1M count=3900
sync
touch /mnt/f2fs/pinfile
f2fs_io pinfile set /mnt/f2fs/pinfile
f2fs_io fallocate 0 0 $((1024*1024*16)) /mnt/f2fs/pinfile
sync
f2fs_io fiemap 0 $((1024*1024*16)) /mnt/f2fs/pinfile

[Before]
fallocate failed: No space left on device
Fiemap: offset = 0 len = 16777216
        logical addr.    physical addr.   length           flags
0       0000000000000000 00000000d7200000 0000000000004000 00001000
1       0000000000004000 00000000d7207000 0000000000001000 00001000
2       0000000000005000 00000000d720c000 0000000000002000 00001000
3       0000000000007000 00000000d7211000 0000000000001000 00001000
4       0000000000008000 00000000d7214000 0000000000001000 00001000
5       0000000000009000 00000000d7218000 0000000000001000 00001000
6       000000000000a000 00000000d721d000 0000000000001000 00001000
7       000000000000b000 00000000d721f000 0000000000004000 00001000
...
96      00000000000f1000 00000000d73e9000 0000000000004000 00001000
97      00000000000f5000 00000000d73f1000 0000000000003000 00001000
98      00000000000f8000 00000000d73f5000 0000000000004000 00001000
99      00000000000fc000 00000000d73fa000 0000000000001000 00001000
100     00000000000fd000 00000000d73ff000 0000000000001000 00001001

[After]
fallocated a file: i_size=16777216, i_blocks=32808
Fiemap: offset = 0 len = 16777216
        logical addr.    physical addr.   length           flags
0       0000000000000000 0000000018a00000 0000000000400000 00001000
1       0000000000400000 0000000019000000 0000000000400000 00001000
2       0000000000800000 0000000032400000 0000000000200000 00001000
3       0000000000a00000 0000000038000000 0000000000200000 00001000
4       0000000000c00000 0000000039c00000 0000000000200000 00001000
5       0000000000e00000 0000000044c00000 0000000000200000 00001001

Let's ignore mode=fragment:{block,segment} mount option while fallocate()
on pinfile.

Fixes: 6691d940b0 ("f2fs: introduce fragment allocation mode mount option")
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-17 21:43:38 +00:00
Chao Yu
6da62bbde4 f2fs: cleanup w/ f2fs_need_rand_{blk, seg, seg_blk}
No logic changes.

Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-17 21:43:38 +00:00
Chao Yu
5d49025a4e f2fs: fix to shrink gc_lock coverage in f2fs_gc_range()
In f2fs_allocate_pinning_section(), we will hold gc_lock before calling
f2fs_gc_range() to migrate section in conventional zone, we may suffer
worse case because we may need to traverse and migrate multiple sections
if we failed to move blocks in section due to lot of reasons: ENOMEM,
fail to migrate block of pinfile, racing on i_gc_rwsem.

To avoid hold gc_lock for long time to block checkpoint, let's hold
the lock and only try to migrate one section.

Cc: Daeho Jeong <daehojeong@google.com>
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-17 21:43:38 +00:00
Chao Yu
fa487f56ef f2fs: fix to reclaim space in f2fs_allocate_pinning_section()
It needs to trigger checkpoint to free space reclaimed by f2fs_gc_range(),
otherwise, fallocate() on pinfile will fail easily even there is slash
space in conventional zone.

[Testcase]
nullblk_create.sh 512 2 1024 1024
mkfs.f2fs /dev/nullb0 -f -m
mount /dev/nullb0 /mnt/f2fs/
touch /mnt/f2fs/pinfile
f2fs_io pinfile set /mnt/f2fs/pinfile
mkdir /mnt/f2fs/dir/
for((i=0;i<3934;i++)) do { dd if=/dev/zero of=/mnt/f2fs/dir/$i bs=1M count=1;} done
sync
for((i=0;i<3934;i+=2)) do { rm /mnt/f2fs/dir/$i;} done
for((i=0;i<1950;i++)) do { rm /mnt/f2fs/dir/$i;} done
sync
f2fs_io fallocate 0 0 $((1024*1024*1024)) /mnt/f2fs/pinfile
sync
stat /mnt/f2fs/pinfile
f2fs_io fiemap 0 $((1024*1024*1024)) /mnt/f2fs/pinfile

[Before]
fallocate failed: Resource temporarily unavailable
  File: /mnt/f2fs/pinfile
  Size: 109051904       Blocks: 213208     IO Block: 4096   regular file
Device: 250,0   Inode: 4           Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2026-08-12 20:04:02.264000000 +0800
Modify: 2026-08-12 20:04:26.784000000 +0800
Change: 2026-08-12 20:04:26.784000000 +0800
 Birth: -
root@localhost:~#
root@localhost:~#
root@localhost:~#
root@localhost:~# f2fs_io fiemap 0 $((1024*1024*1024)) /mnt/f2fs/pinfile
Fiemap: offset = 0 len = 1073741824
        logical addr.    physical addr.   length           flags
0       0000000000000000 0000000002e00000 0000000000200000 00001000
1       0000000000200000 000000002dc00000 0000000000400000 00001000
2       0000000000600000 000000002e400000 0000000000600000 00001000
3       0000000000c00000 000000007a400000 0000000005c00000 00001001

[After]
  File: /mnt/f2fs/pinfile
  Size: 1073741824      Blocks: 2099216    IO Block: 4096   regular file
Device: 250,0   Inode: 4           Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2026-08-12 19:47:49.428000000 +0800
Modify: 2026-08-12 19:49:06.808000000 +0800
Change: 2026-08-12 19:49:06.808000000 +0800
 Birth: -
Fiemap: offset = 0 len = 1073741824
        logical addr.    physical addr.   length           flags
0       0000000000000000 0000000002e00000 0000000000200000 00001000
1       0000000000200000 000000003aa00000 0000000000400000 00001000
2       0000000000600000 000000003b400000 0000000000200000 00001000
3       0000000000800000 000000007a200000 0000000005e00000 00001000
4       0000000006600000 0000000002800000 0000000000200000 00001000
5       0000000006800000 0000000003200000 0000000000400000 00001000
6       0000000006c00000 0000000003000000 0000000000200000 00001000
7       0000000006e00000 0000000003600000 0000000037200000 00001000
8       000000003e000000 000000003b200000 0000000000200000 00001000
9       000000003e200000 000000003a800000 0000000000200000 00001000
10      000000003e400000 000000003ae00000 0000000000400000 00001000
11      000000003e800000 000000003b600000 0000000001800000 00001001

Cc: stable@kernel.org
Fixes: 9703d69d9d ("f2fs: support file pinning for zoned devices")
Cc: Daeho Jeong <daehojeong@google.com>
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-17 21:43:38 +00:00
Linus Torvalds
1781f0b3d7 vfs-7.3-rc1.super
Please consider pulling these changes from the signed vfs-7.3-rc1.super tag.
 
 Thanks!
 Christian
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCan7RJQAKCRCRxhvAZXjc
 oroBAP40BufiChnC6I9Ev79QWF+Pfri1r/3AR4xXRG4HkXQaYQD/YE+Ria3+Bt35
 +tWU66cYlQ/+9LfU8DJ3KXm7jPUBiQA=
 =hXLH
 -----END PGP SIGNATURE-----

Merge tag 'vfs-7.3-rc1.super' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs superblock updates from Christian Brauner:

 - Make it possible to share a block device between multiple
   filesystems.

   erofs can mount read-only blob devices shared between many
   superblocks, but because we only tracked a single superblock a
   freeze, thaw, removal or sync on such a device was never propagated
   to all the superblocks using it, and there was no way to find them.

   Add an efficient table to lookup all superblocks using a given block
   device.

 - A bunch of pre-existing fixes fell out of this work:

   A block-device freeze racing a btrfs device change could leave the
   whole filesystem stuck frozen. A bdev_freeze() issued by "dmsetup
   suspend" or an LVM snapshot resolves that holder to freeze the
   filesystem. and bdev_thaw() resolves it again to thaw. A freeze
   landing while btrfs is adding, removing or replacing a device freezes
   the filesystem. The membership change then drops that link. So the
   matching thaw could no longer find the superblock.

   Forbid freezing a device for the duration of a membership change,
   modelled on deny_write_access()/allow_write_access().

* tag 'vfs-7.3-rc1.super' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (24 commits)
  super: fix dying superblock warning messages
  block: reject block device inodes with i_rdev == 0 in lookup_bdev()
  selftests/filesystems: add ustat() coverage
  fs: look up the superblock via the device table in user_get_super()
  super: make fs_holder_ops private
  f2fs: open via dedicated fs bdev helpers
  erofs: open via dedicated fs bdev helpers
  fs: tolerate per-superblock freeze errors on shared devices
  fs: look up superblocks via the device table in fs_holder_ops
  ext4: open via dedicated fs bdev helpers
  btrfs: open via dedicated fs bdev helpers
  xfs: port to fs_bdev_file_open_by_path()
  fs: add dedicated block device open helpers for filesystems
  fs: maintain a global device-to-superblock table
  ocfs2: don't reset s_dev on dismount
  ext4: use anonymous devices for KUnit test superblocks
  fs, block: move blk_mode_t and fop_flags_t into <linux/types.h>
  super: take lock after last reference count
  super: convert s_count to refcount_t s_passive
  btrfs: deny freezing devices undergoing a replace
  ...
2026-08-17 13:57:04 -07:00
Linus Torvalds
1c3e8cef79 vfs-7.3-rc1.misc
Please consider pulling these changes from the signed vfs-7.3-rc1.misc tag.
 
 Thanks!
 Christian
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCan7RJQAKCRCRxhvAZXjc
 otI6AQCIwshv02UI9fmbTC9pFr8b+v/9IWQwdVULaH61HXgICQD7BE/CktL8nfRs
 zCzGS6kBdWgiOA6bdVpgGGLqiMRnQgo=
 =Kc+G
 -----END PGP SIGNATURE-----

Merge tag 'vfs-7.3-rc1.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull misc vfs updates from Christian Brauner:
 "Bigger cleanups:

   - The lockref dead-count handling is tidied up.

     The open-coded check for a count below zero as the dead marker
     relies on information the caller should not have.

   - make put_mnt_ns() leave mounts connected. Destroying a mount
     namespace disconnected its mounts from their mount points. So a
     file descriptor still open on the parent of a mount point could be
     used to peek under it.

     Locked mounts were already kept connected to prevent exactly that.
     But a mount is only locked when its tree is copied across a user
     namespace boundary. So a mount namespace set up by a privileged
     component had no locked mounts and its mounts were disconnected.
     Passing UMOUNT_CONNECTED keeps every mount connected and prevents
     that bug.

   - vfs_prepare_mode() passes S_IFDIR for directories. I meant to fix
     that ago but didn't get to it. So now someone finally did it.

     This kills the exception where the mode could be 0 when a directory
     was created whereas every other creation operation passed it
     explicitly already.

   - move long delayed work for ufs, jffs2, hfsplus, hfs and affs from
     the per-cpu system_long_wq to the new unbound system_dfl_long_wq.

     None of that work relies on per-cpu state and the work item is
     enqueued with queue_delayed_work() whose timer is global anyway. So
     it may as well benefit from scheduler task placement.

  Smaller fixes and cleanups:

   - unlock_buffer() and journal_end_buffer_io_sync() use
     clear_and_wake_up_bit()

   - the pipe page pools are unified into a single per-pipe pool and the
     extra wake_up(rd_wait) is limited to EPOLLET consumers

   - eventpoll now computes its timer slack lazily in ep_poll()

   - shrink_dcache_for_umount() keeps making progress on busy roots

   - excess xarray nodes are freed in clear_inode()

   - romfs detects hard link cycles

   - the user path of nested backing files is fixed

   - pidfd holds exec_update_lock around the namespace ioctl

   - non-memcg-aware nr_cached_objects is skipped during memcg slab
     shrink

   - iomap_write_iter() always returns status

   - mangle_path() is renamed to seq_mangle_path()

   - inode timestamp accessors are annotated

   - new regression test for pipe->poll_usage.

   - a few documentation, kernel-doc and selftest fixes"

* tag 'vfs-7.3-rc1.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (67 commits)
  selftests/namespaces: Fix racy pipe handshake in timens and pidns_separate
  selftests/epoll: add a regression test for pipe->poll_usage
  pipe: only enable the extra wake_up(rd_wait) for EPOLLET consumers
  pidfd: hold exec_update_lock around namespace ioctl
  fs: fix user path of nested backing files
  fs: remove stale inode_insert5() kernel-doc parameter
  fs: fix switch/case indentation in sysfs() syscall
  fs: document semantics of kstat::{uid,gid} fields
  dcache: keep shrink_dcache_for_umount() making progress on busy roots
  seq_file: rename mangle_path to seq_mangle_path
  nstree: add/fix struct ns_id_req kernel-doc member fields
  dcache: use lockref routines for dead count checks
  lockref: tidy up dead count handling
  initramfs: fix typo in reserve_initrd_mem comment
  fs/pipe: unify the page pools into a single per-pipe pool
  fs: annotate inode timestamp accessors
  eventpoll: compute timer slack lazily in ep_poll()
  selftests/filesystems: add mntns cleanup test
  put_mnt_ns(): leave mounts connected
  affs: Move long delayed work on system_dfl_long_wq
  ...
2026-08-17 12:56:12 -07:00
Linus Torvalds
ab5ed08f2d vfs-7.3-rc1.lookup
Please consider pulling these changes from the signed vfs-7.3-rc1.lookup tag.
 
 Thanks!
 Christian
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCan7RJQAKCRCRxhvAZXjc
 ouj6AQCnBHstCt5RRimywLYU+eTmdKe203zRQYxXpwlYOAzm7wEAm1mIC7/Of6bD
 jkiJilcPDcyYcJsqwBw/Vcz5HR+v8wo=
 =TX6K
 -----END PGP SIGNATURE-----

Merge tag 'vfs-7.3-rc1.lookup' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs lookup updates from Christian Brauner:
 "This refactors lookup_open() and adds vfs_lookup_open() for nfsd.

  mnt_want_write() and parent locking are moved into lookup_open()
  itself.

  audit_inode_child() is also now called in lookup_open() on failure.
  That is the calling convention in vfs_create() and vfs_mkdir(), but
  lookup_open() made no such call when atomic_open() should have created
  a file and did not. And neither did the regular ->create() path fwiw.

  This also contains work to remove the unneeded excl argument from the
  ->create() inode op"

* tag 'vfs-7.3-rc1.lookup' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  fs/namei.c: fix coding style in atomic_open() and lookup_open()
  fs/namei.c: fix kerneldoc of atomic_open() and vfs_lookup_open()
  fs/namei.c: update stale comments in lookup_open()
  Remove excl arg to ->create inode_operation
  fs/namei.c: update kerneldoc of atomic_open()
  vfs: call audit_inode_child() in lookup_open() on failure
  vfs: move create error && negative dentry case in lookup_open() up
  VFS: add vfs_lookup_open() for nfsd
  VFS: move delegated_inode retry loop into lookup_open()
  VFS: move mnt_want_write() and locking into lookup_open()
2026-08-17 12:03:34 -07:00
Linus Torvalds
9ea8d6197d vfs-7.3-rc1.iomap
Please consider pulling these changes from the signed vfs-7.3-rc1.iomap tag.
 
 Thanks!
 Christian
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRAhzRXHqcMeLMyaSiRxhvAZXjcogUCan7RJQAKCRCRxhvAZXjc
 oqOjAP9eZsO4M7OQpTKPgg3Sq2O9QCVgXBy4SVFba7DrbZHLZAEA/NWE+4udJzeL
 j1Xb2VAyMc4S+Ze/O8sMml5Dyh4V5wE=
 =34r1
 -----END PGP SIGNATURE-----

Merge tag 'vfs-7.3-rc1.iomap' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull iomap updates from Christian Brauner:
 "The bulk of this is the conversion of iomap to a single ->iomap_next()
  callback and thus finishing the move to an iterator model.

  Every iomap operation drove its iteration through a struct iomap_ops
  holding ->iomap_begin() and ->iomap_end(). iomap_iter() only ever sees
  those as pointers. That means every step of every iteration is an
  indirect call.

  This collapses both into one ->iomap_next() callback that finishes the
  previous mapping and produces the next one. This lets callers inline
  the iteration loop and pass its ->iomap_next() as a compile time
  constant. That means the compiler can turn it into a direct and hence
  inlineable call.

  This also allows future callers to express custom logic to drive the
  iteration forward better. xfs, btrfs, ext4, ext2, erofs, f2fs, gfs2,
  hpfs, fuse, exfat, zonefs, ntfs, ntfs3 and the block device mapping
  are all converted. No functional changes are intended.

  This also adds a simple direct I/O path for small reads. On Gen5 NVMe
  the __iomap_dio_rw() dominates 4K random reads. The same single-core
  io_uring poll mode workload reaches ~3.2M IOPS against the raw block
  device but only ~1.92M through ext4 or XFS.

  __iomap_dio_rw(), iomap_iter(), iomap_dio_bio_iter() and kfree() were
  at the top of the profile. The new path is very lightweight if no
  special behavior is requested. The bio comes from a dedicated bioset
  and laid out so the whole request is a single cacheline aligned
  allocation. Completion runs inline.

  That takes ext4 from 1.92M to 2.19M IOPS in the original workload. fio
  shows around:
   - 4% at libaio queue depths of 64 and up
   - around 5% for io_uring
   - up to 10% for io_uring poll mode at depth 256
  on both ext4 and xfs.

  A few other patches:

   - iomap_folio_mark_uptodate() lets a filesystem that writes into the
     page cache outside the iomap read and write paths keep iomap's
     internal uptodate bitmap in sync, which fuse needs for
     server-pushed notify stores before it can enable large folios;

   - two fixes for iomap_bio_read_folio_range_sync(): a potential crash
     when device integrity behavior is changed and a missing
     bio_uninit().

   - a folio batch release fix on iomap callback failures

   - FGP_NOFS is dropped from iomap_get_folio()

   - documentation fix"

* tag 'vfs-7.3-rc1.iomap' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs: (29 commits)
  iomap: iomap_bio_read_folio_range_sync is missing a call to bio_uninit
  iomap: don't free integrity payload that doesn't exist
  docs: fix grammatical error in iomap docs
  exfat: convert iomap ops to ->iomap_next()
  fuse: convert iomap ops to ->iomap_next()
  hpfs: convert iomap ops to ->iomap_next()
  gfs2: convert iomap ops to ->iomap_next()
  f2fs: convert iomap ops to ->iomap_next()
  block: convert iomap ops to ->iomap_next()
  ext2: convert iomap ops to ->iomap_next()
  zonefs: convert iomap ops to ->iomap_next()
  erofs: convert iomap ops to ->iomap_next()
  ext4: convert iomap ops to ->iomap_next()
  ntfs: convert iomap ops to ->iomap_next()
  ntfs3: convert iomap ops to ->iomap_next()
  btrfs: convert iomap ops to ->iomap_next()
  xfs: convert iomap ops to ->iomap_next()
  iomap: add ->iomap_next()
  iomap: use GFP_NOWAIT when application for iomap_dio_simple allocations
  iomap: decouple simple direct I/O reads from iomap_dio_rw
  ...
2026-08-17 10:03:55 -07:00
Chao Yu
d3915a0a35 f2fs: unify add/remove ino entry API for all ino types
- Call f2fs_add_ino_entry() and f2fs_remove_ino_entry() for ORPHAN_INO
- introduce __f2fs_add_ino_entry() to wrap __add_ino_entry(), so that
both f2fs_add_ino_entry() and f2fs_set_dirty_device() will call
__f2fs_add_ino_entry().

So, after this change:

		add			delete			lookup
ORPHAN_INO	f2fs_add_ino_entry	f2fs_remove_ino_entry	N/A
FLUSH_INO	f2fs_set_dirty_device	f2fs_remove_ino_entry	f2fs_is_dirty_device
APPEND_INO	f2fs_add_ino_entry	f2fs_remove_ino_entry	f2fs_exist_written_data
UPDATA_INO	f2fs_add_ino_entry	f2fs_remove_ino_entry	f2fs_exist_written_data
TRANS_DIR_INO	f2fs_add_ino_entry	N/A			f2fs_exist_written_data
XATTR_DIR_INO	f2fs_add_ino_entry	N/A			f2fs_exist_written_data

Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-12 20:18:52 +00:00
Chao Yu
5eced87b7d f2fs: fix to zero post-EOF data when extending file size
generic/794  4s ... - output mismatch (see /share/git/fstests/results//generic/794.out.bad)
    --- tests/generic/794.out   2026-06-12 08:46:32.766426241 +0800
    +++ /share/git/fstests/results//generic/794.out.bad 2026-07-05 18:32:55.000000000 +0800
    @@ -1,4 +1,16 @@
     QA output created by 794
     append_write
    +FAIL: non-zero data in gap [4080,4096) after shutdown+remount
    +000000 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a  >ZZZZZZZZZZZZZZZZ<
    +*
    +001000
     truncate_up
    ...
    (Run 'diff -u /share/git/fstests/tests/generic/794.out /share/git/fstests/results//generic/794.out.bad'  to see the entire diff)
Ran: generic/794
Failures: generic/794
Failed 1 of 1 tests

Steps of generic/794:
1. write 4096 bytes to file w/ 0x5a
2. use fiemap to get PBA of first block in file
3. truncate file to 4080
4. umount; write 4096 bytes to file w/ 0x5a directly via PBA; mount
5. extend filesize via
   a) append 4096 from offset 4096, or
   b) truncate 8192, or
   c) fallocate 4096 from offset 4096
6. verify the gap is zeroed in memory [4080,4096)
7. sync range 4096 from offset 4096; shutdown -f (flush meta before shutdown)
8. umount; mount; verify [4080,4096) is zeroed or not.

When extending file size (e.g. via truncate, fallocate, or write) across an
unaligned EOF boundary, we need to ensure that post-EOF data in the partial
page is zeroed out in pagecache and marked dirty, then writeback the cache to
persist zeroed data before committing inode w/ updated i_size.

This help to prevent stale disk data beyond the previous EOF from being exposed
after remounting or crash recovery.

Since f2fs is a LFS filesystem, we only support direct write via PBA in pinfile,
and pinfile has section-aligned filesize, so in Android, there should no problem,
but for other usage in different environment, let's fix this w/ fsync_mode=strict
mount option.

Cc: stable@kernel.org
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-12 20:18:42 +00:00
Chao Yu
b2205d3cfd f2fs: fix to off-by-one issue in f2fs_zero_post_eof_page()
Otherwise, it will drop one more page after new_size which is not
necessary.

Cc: stable@kernel.org
Fixes: ba8dac350f ("f2fs: fix to zero post-eof page")
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-12 20:18:35 +00:00
Jaegeuk Kim
314c9e476f f2fs: call __add_ino_entry out of the eviction path
The f2fs_evict_inode() can be called during the direct reclaim path, but
__add_ino_entry requires allocating some memory. Since we don't need to
do that in that context, let's migrate it in other workqueue context.

Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-11 16:20:52 +00:00
Jaegeuk Kim
0d7477640f f2fs: refactor f2fs_evict_inode having three major parts
1. f2fs_pre_evict_inode()
 : drop all in-memory structures

2. f2fs_delete_inode()
 : truncate inode blocks, if it was unlinked.

3. f2fs_post_evict_inode()
 : update inode records for future access

Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-11 04:16:04 +00:00
Daeho Jeong
eae3faf210 f2fs: support dynamic reserve/release for device aliasing
This patch adds a dynamic management feature to the existing device
aliasing functionality. It allows users to dynamically reserve or
release specific devices from the filesystem's free pool at runtime
through new ioctls.

To support this, three new ioctls are introduced:
- F2FS_IOC_RESERVE_DEV_ALIAS: This reclaims the space occupied by a
  device aliasing file. It first performs a capacity check, resets GC
  victim information for the target range, marks the segments as in-use
  to prevent new allocations, and then triggers GC to migrate existing
  valid data out of the range. Finally, it reserves these blocks in the
  SIT to effectively exclude the device from the usable capacity.

- F2FS_IOC_RELEASE_DEV_ALIAS: This releases the reserved space of a
  previously reserved device aliasing file. It truncates the blocks
  associated with the file, which makes them available for general
  filesystem allocation again.

- F2FS_IOC_GET_DEV_ALIAS_STATUS: This retrieves the current aliasing
  status of a device aliasing file, returning whether the file is
  released (inactive alias) or reserved (active alias, with blocks
  fully allocated on the device).

Signed-off-by: Daeho Jeong <daehojeong@google.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-11 04:16:04 +00:00
Chao Yu
7e188e9f94 f2fs: fix to pass folio->index to f2fs_sanity_check_node_footer()
Otherwise in f2fs_sanity_check_node_footer(), it will check the
same nid incorrectly.

Cc: stable@kernel.org
Fixes: 0a736109c9 ("f2fs: fix to do sanity check on node footer in __write_node_folio()")
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-07 23:00:44 +00:00
Yonggil Song
e1116f8e98 f2fs: issue multi-device flushes in parallel
On a multi-device setup, submit_flush_wait() walked the dirty devices
in order and aborted the whole loop on the first device whose flush
failed, leaving the remaining dirty devices un-flushed. Each device
still needs its own data made durable, so a failure on one device must
not skip the others. It also waited for one device's flush to complete
before issuing the next, even though the devices have independent
flush queues and could be flushed concurrently.

Flush every dirty device best-effort and in parallel instead: build
one PREFLUSH bio per dirty device, submit them all, then wait for
every completion, returning the first error seen (0 if all succeed).
This bounds the flush window by the slowest device rather than the sum
of all of them. No caller depends on the previous early-abort
behaviour -- fsync only checks whether the return value is zero
(fs/f2fs/file.c). The checkpoint path (f2fs_flush_device_cache) is
unaffected; this only touches the fsync flush path.

The per-device bio/completion array is small and bounded (at most
MAX_DEVICES entries), so allocate it with __GFP_NOFAIL rather than
keeping a separate serial fallback path for allocation failure.

Signed-off-by: Yonggil Song <yonggil.song@samsung.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-07 21:40:25 +00:00
Chao Yu
5d59e6a377 f2fs: print error information in f2fs_put_super()
So that we can know in which path we may missed to account the
reference correclty: normal path or error handling path.

Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-07 21:40:02 +00:00
Chao Yu
5b86eab84a f2fs: fix to clear dirty flag on folio in error path
If node block is corrupted due to chksum mismatch or inconsistent
footer info, it needs to drop clear flag of node folio, in order
to persist inconsistent node data to storage.

Cc: stable@kernel.org
Fixes: b42b179bda ("f2fs: fix to do checksum even if inode page is uptodate")
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-05 21:20:15 +00:00
Chao Yu
7173538c41 f2fs: avoid unnecessary shrink in f2fs_shrink_scan()
In f2fs_shrink_scan(), let's check if we have already shrinked enough
number of memory before calling f2fs_shrink_read_extent_tree().

Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-05 21:19:52 +00:00
Chao Yu
026d7aeadf f2fs: fix to return -EFSCORRUPTED in f2fs_get_node_info() correctly
Otherwise, it will cache wrong nat info in cache.

Cc: stable@kernel.org
Fixes: 3cb396a2c7 ("f2fs: fix to do sanity check on nat entry of quota inode")
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-05 21:19:35 +00:00
Chen Changcheng
0f9af07ecc f2fs: fix valid block count leak on data block allocation failure
In __allocate_data_block(), when allocating a new data block
(dn->data_blkaddr == NULL_ADDR), inc_valid_block_count() is
called first to increment total_valid_block_count and i_blocks.
If the subsequent f2fs_allocate_data_block() fails, the function
returns the error directly without rolling back the
already-incremented block counts, causing a permanent leak.

Fix this by calling dec_valid_block_count() to undo the
increment before returning the error. The condition
old_blkaddr == NULL_ADDR precisely identifies the case where
inc_valid_block_count() was called.

Fixes: 7d009e048d ("f2fs: fix to handle segment allocation failure correctly")
Cc: <stable@vger.kernel.org>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Chen Changcheng <chenchangcheng@kylinos.cn>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-05 01:30:52 +00:00
Wenjie Qi
8e4692c6c1 f2fs: protect critical_task_priority updates with s_umount
The sysfs store path already takes s_umount for GC thread control
entries, and ckpt_thread_ioprio is covered as well.

critical_task_priority also updates checkpoint or GC kthread scheduling
state, but it is not covered by that serialization. It can race with
remount or teardown paths that are stopping those threads.

Protect critical_task_priority sysfs writes with s_umount too.

Fixes: 52190933c3 ("f2fs: sysfs: introduce critical_task_priority")
Cc: stable@kernel.org
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-05 01:30:45 +00:00
Wenjie Qi
5cb33b00c8 f2fs: avoid NULL checkpoint thread access in sysfs
checkpoint_merge can be enabled even when no checkpoint merge thread is
running. A read-only mount is one case: f2fs does not start
f2fs_issue_ckpt there, but ckpt_thread_ioprio is still writable through
sysfs.

The ckpt_thread_ioprio store path updates the saved ioprio value and,
when checkpoint_merge is enabled, calls set_task_ioprio() for the
checkpoint thread. If cprc->f2fs_issue_ckpt is NULL, that dereferences a
NULL task pointer.

Protect ckpt_thread_ioprio sysfs writes with s_umount as well, so the
checkpoint thread cannot disappear under the store path while updating
its ioprio.

Fixes: e659206617 ("f2fs: add ckpt_thread_ioprio sysfs node")
Cc: stable@kernel.org
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-05 01:30:45 +00:00
Bart Van Assche
3de6b80941 f2fs: Run f2fs_write_end_io() asynchronously
The bio_for_each_segment_all() loop can take more than 10 ms for a large
bio on an ARM little core. This is too much for interrupt context. Hence
perform the write bio completion work asynchronously if a bio is large and
if f2fs_write_end_io() is called from atomic context. This patch reduces
the time spent in f2fs_write_end_io() from about 10 ms to about 150
microseconds on an Arm Cortex-A520 core if the max_atc_write_bio_size
parameter is changed to 16384.

Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-04 00:18:37 +00:00
Wenjie Qi
6dc2b804a0 f2fs: reject invalid recovered filename lengths
Recovery uses raw_inode->i_namelen directly when rebuilding fsynced
dentries. A zero-length name uses no dentry slots, so recovery can
report success without recreating the dentry.

Treat zero-length and oversized recovered names as corruption, mark
NEED_FSCK, and stop recovery with -EFSCORRUPTED.

Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-04 00:18:37 +00:00
Zhan Xusheng
0f046e45af f2fs: Remove unused curseg_segno() and curseg_alloc_type()
The only callers of curseg_segno() and curseg_alloc_type() were removed by
commit 5a4fed7cd9 ("f2fs: simplify do_checkpoint"); both helpers have
been unused since then.

Being static inline functions they do not trigger -Wunused-function, so
the dead code has gone unnoticed.  Remove them.  No functional change.

Signed-off-by: Zhan Xusheng <zhanxusheng@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-04 00:18:36 +00:00
Joanne Chang
9ec09d5f4b f2fs: dirty directory inodes on mtime/ctime update
Xfstests generic/547 sometimes fail with mismatched directory metadata
before and after a power failure. This happens because when a directory
entry is added, renamed, or deleted, its mtime and ctime are updated and
the inode is marked dirty via
f2fs_mark_inode_dirty_sync(dir, sync=false). The sync=false flag means
the dirty inode is not added to the global DIRTY_META list. Therefore,
subsequent checkpoints skip flushing these updated directory blocks,
causing directory timestamps to revert to stale values after a sudden
power failure.

Address this by changing the dirtying parameter to sync=true during
directory entry mutations and renames. This forces F2FS to immediately
queue the updated directory blocks on the global DIRTY_META list,
ensuring timestamps are committed to checkpoints.

Fixes: 7c45729a4d ("f2fs: keep dirty inodes selectively for checkpoint")
Cc: stable@vger.kernel.org
Signed-off-by: Joanne Chang <joannechien@google.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-04 00:18:36 +00:00
Zhan Xusheng
575f6f8ef2 f2fs: don't drop the top folio order in the f2fs_iostat tracepoint
The f2fs_iostat tracepoint stores the per-order read folio counts in a
fixed-size array and prints a fixed number of buckets, both hardcoded to
11. The sysfs iostat accounting array is instead sized by NR_PAGE_ORDERS
(= MAX_PAGE_ORDER + 1), which is not always 11:

	arm64 16K pages -> MAX_PAGE_ORDER 11 -> NR_PAGE_ORDERS 12
	arm64 64K pages -> MAX_PAGE_ORDER 13 -> NR_PAGE_ORDERS 14

f2fs enables large folios for immutable, non-compressed files, and the
read folio order is bounded by MAX_PAGECACHE_ORDER, i.e.
min(MAX_XAS_ORDER, PREFERRED_MAX_PAGECACHE_ORDER). With THP enabled this
reaches order 11 on 16K/64K base-page kernels (MAX_XAS_ORDER caps it at
11). So an order-11 read folio is possible there and is accounted into
index 11 of the array.

On those configurations the sysfs file reports the order-11 count
correctly, but the tracepoint silently drops it: the memcpy is capped at
min(NR_PAGE_ORDERS, 11), so index 11 is never copied and the trace
disagrees with sysfs. There is no memory-safety issue, only the order-11
bucket missing from the trace; 4K-page kernels (NR_PAGE_ORDERS == 11,
max order <= 9) are unaffected.

Size the array and the printed buckets by a ceiling that covers the
largest possible NR_PAGE_ORDERS (14) with headroom, and add a
BUILD_BUG_ON() so any future growth of NR_PAGE_ORDERS fails the build
loudly instead of silently truncating again. The human-readable
"order=count" output is preserved.

Fixes: cb8ff3ead9 ("f2fs: add page-order information for large folio reads in iostat")
Cc: stable@vger.kernel.org
Signed-off-by: Zhan Xusheng <zhanxusheng@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-04 00:18:36 +00:00
Chao Yu
1b4db09b7f f2fs: fix to avoid move_range and defragment on device_alias file
It's forbidden to migrate blocks of device alias file.

Cc: stable@kernel.org
Fixes: 128d333f0d ("f2fs: introduce device aliasing file")
Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-04 00:18:36 +00:00
Hao-Qun Huang
28c1ef094e f2fs: reject overlapping move range after len expansion
F2FS_IOC_MOVE_RANGE treats a zero length as a request to move data
from pos_in to EOF. However, the same-file overlap check runs before
that expansion, so a request with len == 0 bypasses the overlap
rejection added for same-file moves.

For example, with a four-block file, moving from block 0 to block 1
with len == 0 is accepted by the old check because pos_in + len is
still pos_in at that point. The code then expands len to cover the
rest of the file and calls __exchange_data_block() on overlapping
source and destination ranges in the same inode, which is the
data-corruption case the overlap check was meant to reject.

Move the overlap check after the source range has been validated and
len == 0 has been expanded, so it sees the effective length. This is a
no-op for non-zero len (the value is unchanged there) and keeps the
existing early return for identical positions.

Fixes: d95fd91c1a ("f2fs: exclude special cases for f2fs_move_file_range")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-fable-5
Signed-off-by: Hao-Qun Huang <alvinhuang0603@gmail.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-04 00:18:36 +00:00
Wenjie Qi
f8a4108800 f2fs: return writeback error from collapse range
f2fs_collapse_range() writes back pages moved by f2fs_do_collapse(),
but ignores the return value. If writeback fails, the ioctl can still
truncate page cache, shrink blocks, and report success.

Return the error before truncating page cache or updating the file size.

Fixes: b4ace33703 ("f2fs: support FALLOC_FL_COLLAPSE_RANGE")
Cc: stable@kernel.org
Assisted-by: Codex:gpt-5.5
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-03 23:49:32 +00:00
Wenjie Qi
8517133274 f2fs: only redirty pinned folios in redirty_blocks
redirty_blocks() pins folios with read_cache_folio() and then walks the
same range again with filemap_lock_folio() to redirty them and drop the
references it took.

Commit 5951fee46b ("f2fs: Use a folio in redirty_blocks()") changed
the second pass to a do/while loop. If read_cache_folio() fails before
anything is pinned, page_idx does not advance but the cleanup loop still
runs once.

If readahead has already populated the failed folio in page cache, that
extra iteration finds it and folio_put_refs(folio, 2) drops one
reference too many. Later drop_caches or reclaim can then report
"BUG: Bad page state".

Only redirty the range that was pinned successfully.

Fixes: 5951fee46b ("f2fs: Use a folio in redirty_blocks()")
Cc: stable@kernel.org
Assisted-by: Codex:gpt-5.5
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-03 23:47:55 +00:00
Wenjie Qi
01027b2fcb f2fs: limit recovery filename logging to stored length
F2FS stores recovery filenames as a length plus a fixed-size i_name
buffer.  The buffer is not NUL-terminated, but recover_inode() and
recover_dentry() print it with %s.

For a 255-byte filename, recovery logging can read past i_name into the
following raw inode fields.

Print the name with a precision bounded by i_namelen and F2FS_NAME_LEN.

Fixes: f356fe0cba ("f2fs: add debug msgs in the recovery routine")
Cc: stable@kernel.org
Assisted-by: Codex:gpt-5.5
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-03 23:41:19 +00:00
Wenjie Qi
e533889fc2 f2fs: validate MOVE_RANGE destination size
F2FS_IOC_MOVE_RANGE checks the source range, but not the destination end
before updating i_size. A source hole can expose this: __clone_blkaddrs()
skips NULL_ADDR entries and returns success, so the caller can still extend
the destination inode with unchecked pos_out + len.

Reject destination overflow and use inode_newsize_ok() before extending
the destination inode.

Fixes: 4dd6f977fc ("f2fs: support an ioctl to move a range of data blocks")
Cc: stable@kernel.org
Assisted-by: Codex:gpt-5.5
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-03 23:40:24 +00:00