summaryrefslogtreecommitdiff
path: root/fs/f2fs
AgeCommit message (Collapse)Author
2026-09-14f2fs: describe xattr block layout dynamicallyKelvin Zhang
The usable capacity of dedicated on-disk extended attribute blocks and inline xattr regions scales with the filesystem block size. Parameterize VALID_XATTR_BLOCK_SIZE and MAX_INLINE_XATTR_SIZE to calculate usable xattr limits dynamically from sbi->blocksize rather than hardcoding PAGE_SIZE or DEF_ADDRS_PER_INODE. Update mount option consistency validation for inline_xattr_size to evaluate allowed boundaries dynamically against the runtime block size. Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-09-14f2fs: describe {i,d,id}node block layout dynamicallyKelvin Zhang
An inode block ends with five i_nid entries followed by a node footer. Data block address pointers (i_addr[]) precede them. Similarly, direct and indirect node blocks contain data addresses or node IDs followed by a node footer at the end of the block. Describe struct f2fs_inode, struct direct_node, and struct indirect_node using flexible array members. Compute the locations of i_nid and node footers dynamically from the filesystem block size. Introduce F2FS_INODE_NIDS() and F2FS_NODE_FOOTER() helpers to access these tail fields. Compute sbi->addrs_per_inode, sbi->addrs_per_block, and sbi->nids_per_block in init_sb_info(), and update node management, file mapping, and recovery paths accordingly. Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-09-14f2fs: describe dentry block layout dynamicallyKelvin Zhang
An on-disk directory block contains a bitmap, reserved padding, an array of directory entries (struct f2fs_dir_entry), and matching filename slots. A fixed compile-time structure couples their offsets to 4KB blocks and relies on static reserved-space definitions. Remove struct f2fs_dentry_block and compute region offsets (bitmap bytes, directory-entry count, and filename slots) dynamically from the filesystem block size. Access directory blocks through struct f2fs_dentry_ptr views initialized with the runtime geometry. Update directory operations, inline dentry handling, and recovery paths to use the dynamic block layout. No functional change is introduced for 4KB blocks. Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-09-14f2fs: describe orphan block layout dynamicallyKelvin Zhang
An on-disk orphan block contains a variable-length array of 32-bit inode numbers followed by a fixed footer at the end of the block. A compile-time whole-block structure cannot represent the footer position when the block size varies at runtime. Remove struct f2fs_orphan_block, introduce struct f2fs_orphan_block_footer, and compute sbi->orphans_per_block dynamically in init_sb_info(). Add helpers to access the inode entry array and footer from a block buffer. Update orphan inode recovery, checkpointing, and mount paths to use the parameterized helpers. This preserves the on-disk format while decoupling orphan handling from compile-time constants. Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-09-14f2fs: describe NAT block layout dynamicallyKelvin Zhang
A NAT block is a filesystem-block-sized array of struct f2fs_nat_entry elements. The compile-time NAT_ENTRY_PER_BLOCK definition hardcodes the NAT capacity to a 4KB block size. Replace the fixed array in struct f2fs_nat_block with a C flexible array member, and calculate sbi->nat_entries_per_block dynamically in init_sb_info(). Parameterize NAT geometry helpers (NAT_ENTRY_PER_BLOCK, NAT_BLOCK_OFFSET, f2fs_start_nid, NAT_BLK_CNT, and f2fs_nat_bitmap_size) with sbi. Update call sites across node management, checkpointing, GC, and sysfs. This is a layout-only change without behavioral differences for 4KB blocks. Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-09-14f2fs: describe SIT block layout dynamicallyKelvin Zhang
An SIT block consists of an on-disk array of struct f2fs_sit_entry elements whose total capacity depends on the filesystem block size. The existing fixed SIT_ENTRY_PER_BLOCK macro hardcodes a 4KB block size. Convert the entries array in struct f2fs_sit_block into a C flexible array member, and calculate sbi->sit_entries_per_block dynamically in init_sb_info(). Parameterize SIT indexing helpers (SIT_ENTRY_PER_BLOCK, SIT_BLOCK_OFFSET, SIT_BLK_CNT, and f2fs_start_segno) to take struct f2fs_sb_info *sbi, and update all call sites across segment management, checkpointing, and mount. This is a layout-only change; valid 4KB filesystems retain identical runtime geometry and behavior. Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-09-14f2fs: initialize sb_info early in f2fs_fill_superKelvin Zhang
Previously, init_sb_info() was invoked late in f2fs_fill_super(), after processing superblock error tracking, mount options, and sb->s_maxbytes. However, read_raw_super_block() reads the superblock folio directly from the block device mapping using folio page offsets. This makes the initial static sb_set_blocksize(sb, F2FS_BLKSIZE) call redundant. Move init_sb_info() to execute immediately after sbi->raw_super is attached, allowing the block device block size to be set dynamically via sb_set_blocksize(sb, sbi->blocksize). This early initialization also prepares for upcoming patches that add dynamically computed filesystem geometry fields, such as sbi->addrs_per_block and sbi->nids_per_block, to init_sb_info(). These fields are required by earlier initialization steps, including mount option consistency checks and sb->s_maxbytes computation. Signed-off-by: Kelvin Zhang <zhangxp1998@gmail.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-09-14f2fs: drop pending discard commands before reserving device aliasDaeho Jeong
When reserving a device alias via f2fs_ioc_reserve_dev_alias(), f2fs_reserve_device_alias() bulk-marks all blocks in the target device range as valid in SIT. However, if the device was previously in the released state, stale pending discard commands covering that range may still exist in dcc->root. When f2fs_issue_discard_thread later processes those commands, __check_sit_bitmap() detects valid blocks in the discard range and triggers a kernel BUG(). To fix this: 1. Introduce f2fs_drop_discard_cmd_range() to traverse the discard rbtree, drop all pending D_PREP discard commands in the range, and wait for any in-flight discard bios under dcc->cmd_lock. 2. Call f2fs_drop_discard_cmd_range() in f2fs_ioc_reserve_dev_alias() before f2fs_reserve_device_alias(). Reported-by: Wenjie Qi <qiwenjie@xiaomi.com> Fixes: eae3faf210bd ("f2fs: support dynamic reserve/release for device aliasing") Cc: stable@vger.kernel.org Signed-off-by: Daeho Jeong <daehojeong@google.com> Reviewed-by: Chao Yu <chao@kernel.org> Reviewed-by: Wenjie Qi <qiwenjie@xiaomi.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-09-03f2fs: wait for inode record work before clearing ino bitmapsWenjie Qi
APPEND/UPDATE inode state recording was moved to the inode eviction workqueue. These entries were later converted to bitmap values stored in XArrays, but the workqueue drain was left behind in the list cleanup loop where it is now a no-op. During unmount, inode eviction work can therefore remain queued when f2fs_release_ino_entry() destroys the bitmap XArrays. A delayed worker can repopulate them before the workqueue is finally destroyed, leaking newly allocated XArray nodes when the F2FS superblock is freed. Wait for APPEND/UPDATE inode record work before destroying each bitmap XArray, restoring the required ordering. Fixes: 9a9ee7408a1f ("f2fs: reduce memory footprint of ino management") 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-28Merge tag 'f2fs-for-7.3-rc1' of ↵Linus Torvalds
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-27f2fs: support resizable tail section and unify pinned allocationDaeho Jeong
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-26f2fs: don't leave the hashed inode while it's unlinkedJaegeuk Kim
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-25f2fs: accurately adjust free_sections during free_segment_rangeDaeho Jeong
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: b4b10061ef98 ("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-25f2fs: fix to avoid potential deadloop in f2fs_fsync_node_pages()Chao Yu
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: 608514deba38 ("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-24f2fs: use adjusted write range after f2fs_write_checks()Seongjae Jeong
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: 3fdd89b452c2 ("f2fs: prevent writing without fallocate() for pinned files") Fixes: 92318f20d703 ("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-21f2fs: fix to propagate error from f2fs_sync_fs()Chao Yu
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-21f2fs: return symlink writeback errorsWenjie Qi
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: d0cae97cb600 ("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-21f2fs: fix error handling on device alias check in rename and unlinkDaeho Jeong
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-21f2fs: fix to reset all pinned status during fggcChao Yu
Otherwise, the pinned status may affect latter flow of fggc. Cc: stable@kernel.org Fixes: 9703d69d9d15 ("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-21f2fs: use f2fs_{down, up}_(read, write}_trace() for nat_tree_lockChao Yu
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-21f2fs: reduce memory footprint of ino managementChao Yu
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-21f2fs: fix i_size when pinned fallocate partially failsZhan Xusheng
From: Zhan Xusheng <zhanxusheng@xiaomi.com> Commit 4275b59673eb ("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 88f2cfc5fa90 ("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: 4275b59673eb ("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-21f2fs: fix to migrate all curseg types during free_segment_rangeDaeho Jeong
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: d0b9e42ab615 ("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-21f2fs: avoid setting SBI_NEED_FSCK on transient resize failureDaeho Jeong
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-17Merge tag 'fscrypt-for-linus' of git://git.kernel.org/pub/scm/fs/fscrypt/linuxLinus Torvalds
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-17f2fs: fix to avoid pinfile fragment on fragment:{block, segment} modeChao Yu
pinfile fallocate() conflicts w/ mode=fragment:{block,segment} mount option, result in fragment blocks in pinfile, it violate semantics of pinfile introduced in commit f5a53edcf01e ("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: 6691d940b0e0 ("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-17f2fs: cleanup w/ f2fs_need_rand_{blk, seg, seg_blk}Chao Yu
No logic changes. Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2026-08-17f2fs: fix to shrink gc_lock coverage in f2fs_gc_range()Chao Yu
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-17f2fs: fix to reclaim space in f2fs_allocate_pinning_section()Chao Yu
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: 9703d69d9d15 ("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-17Merge tag 'vfs-7.3-rc1.super' of ↵Linus Torvalds
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-17Merge tag 'vfs-7.3-rc1.misc' of ↵Linus Torvalds
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-17Merge tag 'vfs-7.3-rc1.lookup' of ↵Linus Torvalds
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-17Merge tag 'vfs-7.3-rc1.iomap' of ↵Linus Torvalds
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-12f2fs: unify add/remove ino entry API for all ino typesChao Yu
- 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-12f2fs: fix to zero post-EOF data when extending file sizeChao Yu
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-12f2fs: fix to off-by-one issue in f2fs_zero_post_eof_page()Chao Yu
Otherwise, it will drop one more page after new_size which is not necessary. Cc: stable@kernel.org Fixes: ba8dac350faf ("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-11f2fs: call __add_ino_entry out of the eviction pathJaegeuk Kim
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-11f2fs: refactor f2fs_evict_inode having three major partsJaegeuk Kim
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-11f2fs: support dynamic reserve/release for device aliasingDaeho Jeong
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-07f2fs: fix to pass folio->index to f2fs_sanity_check_node_footer()Chao Yu
Otherwise in f2fs_sanity_check_node_footer(), it will check the same nid incorrectly. Cc: stable@kernel.org Fixes: 0a736109c9d2 ("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-07f2fs: issue multi-device flushes in parallelYonggil Song
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-07f2fs: print error information in f2fs_put_super()Chao Yu
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-05f2fs: fix to clear dirty flag on folio in error pathChao Yu
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: b42b179bda9f ("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-05f2fs: avoid unnecessary shrink in f2fs_shrink_scan()Chao Yu
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-05f2fs: fix to return -EFSCORRUPTED in f2fs_get_node_info() correctlyChao Yu
Otherwise, it will cache wrong nat info in cache. Cc: stable@kernel.org Fixes: 3cb396a2c790 ("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-05f2fs: fix valid block count leak on data block allocation failureChen Changcheng
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: 7d009e048d7c ("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-05f2fs: protect critical_task_priority updates with s_umountWenjie Qi
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: 52190933c37a ("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-05f2fs: avoid NULL checkpoint thread access in sysfsWenjie Qi
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: e65920661708 ("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-04f2fs: Run f2fs_write_end_io() asynchronouslyBart Van Assche
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-04f2fs: reject invalid recovered filename lengthsWenjie Qi
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>