summaryrefslogtreecommitdiff
path: root/tools/lib/python/kdoc
diff options
context:
space:
mode:
authorChao Yu <chao@kernel.org>2026-10-07 10:17:38 +0000
committerJaegeuk Kim <jaegeuk@kernel.org>2026-10-07 14:16:11 +0000
commit5edbb590dbd79005db12e06d629612ad44c936af (patch)
tree7c8974c41d4c9232c7e44df1f424c73418fb1993 /tools/lib/python/kdoc
parent63bb030f36b85782f1ec6157d78292466abad1c8 (diff)
Revert "f2fs: skip node_change lock for inline data writes"
This reverts commit 66eec36c2421383e5b32e9c1740f656474c80df8. Fault injection + shutdown stress test reports inconsistent inline data after "f2fs_io shutdown 2" (mode=lfs, nonzone, segs=1): [__chk_dentries:2067] [ 6]-[0x26] name[0MVNBi,Cv33...] len[0x20] ino[0x4190] type[0x7] [ASSERT] (fsck_chk_inode_blk:1142) --> [0x4190] junk inline data [fsck_chk_inode_blk:1150] ino[0x4190] has inline data! ... [FSCK] other corrupted bugs [Fail] ino 0x4190 is an encrypted symlink, the inode block pointed by the last checkpoint's NAT entry contains valid inline data, however F2FS_DATA_EXIST is not set in i_inline (i_size is stale as well). The node_change rwsem was taken in prepare_write_begin() for inline inodes in order to serialize write_begin with block_operations(): checkpoint holds node_change for write from the last check of F2FS_DIRTY_IMETA until all dirty node blocks are flushed, so either 1) FI_DATA_EXIST is set before the check, the inode is in DIRTY_META list, and f2fs_sync_inode_meta() -> f2fs_update_inode() syncs F2FS_DATA_EXIST and i_size into the inode block before it is written by checkpoint, or 2) FI_DATA_EXIST is set after block_operations(), then the inode block written by this checkpoint does not contain the new inline data. Commit 66eec36c2421 ("f2fs: skip node_change lock for inline data writes") skips the lock for writes which fit in inline area, assuming setting FI_DATA_EXIST only dirties inode metadata. However, dirtying inode metadata after F2FS_DIRTY_IMETA was checked, while f2fs_write_inline_data() (which never holds any checkpoint lock) copies inline data into the inode block, breaks the above ordering, then checkpoint persists an inode block which has inline data but stale i_inline/i_size: - f2fs_symlink - f2fs_write_checkpoint - f2fs_add_link - block_operations - f2fs_init_inode_metadata : i_inline = F2FS_INLINE_DATA - f2fs_update_parent_metadata : clear FI_NEW_INODE - f2fs_flush_inline_data - f2fs_lock_all - f2fs_down_write(node_change) : F2FS_DIRTY_IMETA is zero, skip f2fs_sync_inode_meta() - page_symlink - f2fs_write_begin - prepare_write_begin : missed f2fs_map_lock(), i.e. f2fs_down_read(node_change), so it isn't blocked by checkpoint - set_inode_flag(FI_DATA_EXIST) : inode becomes dirty, too late - f2fs_write_end - f2fs_i_size_write - filemap_write_and_wait_range - f2fs_write_single_data_page - f2fs_write_inline_data - memcpy_from_folio - f2fs_mark_cache_dirty : ientry has inline data, but no F2FS_DATA_EXIST in i_inline - f2fs_down_write(node_write) - f2fs_writeback_node_caches - __write_node_cache : write ientry w/ stale i_inline : F2FS_DIRTY_IMETA isn't rechecked - f2fs_flush_nat_entries - do_checkpoint - f2fs_io shutdown 2 : dirty inode is lost, fsck finds "junk inline data" Besides the fsck error, for regular inline file, stale i_size may cause data loss after sudden power-off even if checkpoint is committed. Let's revert the commit to restore node_change serialization for inline data writes, and add a comment above f2fs_map_lock(). Fixes: 66eec36c2421 ("f2fs: skip node_change lock for inline data writes") Cc: Seongjae Jeong <jsjlee1020@gmail.com> Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'tools/lib/python/kdoc')
0 files changed, 0 insertions, 0 deletions