[f2fs-dev] [RFC PATCH v3 1/2] fsck.f2fs: adapt to inline extent inode layout
Yongpeng Yang <[email protected]> Fri, 24 Jul 2026 20:59:58 +0800
| Newsgroups | net.sourceforge.lists.linux-f2fs-devel |
|---|---|
| Message-ID | <[email protected]> |
From: Yongpeng Yang <[email protected]> The kernel inline extent feature has been designed to place the inline extent area after struct f2fs_inode->i_extra_end, inside the i_extra_isize region. f2fs-tools only needs to track the inode layout change and keep the inline extent consistent with the largest cached extent. Adapt to the new on-disk inode layout: - Split struct f2fs_inode->i_compr_blocks (was __le64) into __le32 i_compr_blocks + __le32 i_inline_ext_capacity, matching the kernel change. i_inline_ext_capacity records the number of inline extent entries reserved in the inode. - Add struct f2fs_iext_header, the header of the inline extent area located right after i_extra_end[]. - Update all i_compr_blocks accesses (fsck.c, inject.c, mount.c, segment.c) to use le32 helpers. Keep the inline extent consistent with the largest extent: - Add f2fs_invalidate_inline_extent(), which resets the inline extent entry count to 0. - The inline extent shares its lifetime with the largest extent cache: whenever i_ext is dropped or truncated (in fsck_chk_inode_blk() and update_data_blkaddr()), invalidate the inline extent as well so a stale mapping is never left behind. Signed-off-by: Yongpeng Yang <[email protected]> --- fsck/fsck.c | 9 ++++++--- fsck/inject.c | 6 +++--- fsck/mount.c | 3 ++- fsck/segment.c | 2 +- include/f2fs_fs.h | 22 +++++++++++++++++++++- 5 files changed, 33 insertions(+), 9 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 497cca0..9b8f34c 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -919,7 +919,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, u32 i_flags = le32_to_cpu(node_blk->i.i_flags); bool compressed = i_flags & F2FS_COMPR_FL; bool compr_rel = node_blk->i.i_inline & F2FS_COMPRESS_RELEASED; - u64 i_compr_blocks = le64_to_cpu(node_blk->i.i_compr_blocks); + u64 i_compr_blocks = le32_to_cpu(node_blk->i.i_compr_blocks); nid_t i_xattr_nid = le32_to_cpu(node_blk->i.i_xattr_nid); int ofs; char *en; @@ -1204,6 +1204,7 @@ check_next: qf_last_blkofs[cur_qtype] = child.pgofs; } else if (c.fix_on) { node_blk->i.i_ext.len = cpu_to_le32(idx); + f2fs_invalidate_inline_extent(&node_blk->i); need_fix = 1; break; } @@ -1332,7 +1333,7 @@ check: if (compressed && i_compr_blocks != cbc->cnt) { if (c.fix_on) { - node_blk->i.i_compr_blocks = cpu_to_le64(cbc->cnt); + node_blk->i.i_compr_blocks = cpu_to_le32(cbc->cnt); need_fix = 1; FIX_MSG("[0x%x] i_compr_blocks=0x%08"PRIx64" -> 0x%x", nid, i_compr_blocks, cbc->cnt); @@ -1476,8 +1477,10 @@ skip_dot_fix: } /* drop extent information to avoid potential wrong access */ - if (need_fix && f2fs_dev_is_writable() && !is_aliasing) + if (need_fix && f2fs_dev_is_writable() && !is_aliasing) { node_blk->i.i_ext.len = 0; + f2fs_invalidate_inline_extent(&node_blk->i); + } if ((c.feature & F2FS_FEATURE_INODE_CHKSUM) && f2fs_has_extra_isize(&node_blk->i)) { diff --git a/fsck/inject.c b/fsck/inject.c index 60a2d20..fa09f1e 100644 --- a/fsck/inject.c +++ b/fsck/inject.c @@ -1088,9 +1088,9 @@ static int inject_inode(struct f2fs_sb_info *sbi, struct f2fs_node *node, inode->i_inode_checksum = cpu_to_le32((u32)opt->val); } else if (!strcmp(opt->mb, "i_compr_blocks")) { MSG(0, "Info: inject inode i_compr_blocks of nid %u: " - "%"PRIu64" -> %"PRIu64"\n", opt->nid, - le64_to_cpu(inode->i_compr_blocks), (u64)opt->val); - inode->i_compr_blocks = cpu_to_le64((u64)opt->val); + "%u -> %u\n", opt->nid, + le32_to_cpu(inode->i_compr_blocks), (u32)opt->val); + inode->i_compr_blocks = cpu_to_le32((u32)opt->val); } else if (!strcmp(opt->mb, "i_addr")) { /* do not care if it is inline data */ if (opt->idx >= DEF_ADDRS_PER_INODE) { diff --git a/fsck/mount.c b/fsck/mount.c index f7985dc..8c14c97 100644 --- a/fsck/mount.c +++ b/fsck/mount.c @@ -344,7 +344,7 @@ void print_inode_info(struct f2fs_sb_info *sbi, DISP_u32(inode, i_crtime_nsec); } if (c.feature & F2FS_FEATURE_COMPRESSION) { - DISP_u64(inode, i_compr_blocks); + DISP_u32(inode, i_compr_blocks); DISP_u8(inode, i_compress_algorithm); DISP_u8(inode, i_log_cluster_size); DISP_u16(inode, i_compress_flag); @@ -2574,6 +2574,7 @@ void update_data_blkaddr(struct f2fs_sb_info *sbi, nid_t nid, endaddr = startaddr + le32_to_cpu(node_blk->i.i_ext.len); if (oldaddr >= startaddr && oldaddr < endaddr) { node_blk->i.i_ext.len = 0; + f2fs_invalidate_inline_extent(&node_blk->i); /* update inode block */ if (node_blk_alloced) diff --git a/fsck/segment.c b/fsck/segment.c index 96de22a..2222b6e 100644 --- a/fsck/segment.c +++ b/fsck/segment.c @@ -725,7 +725,7 @@ int f2fs_build_file(struct f2fs_sb_info *sbi, struct dentry *de) /* update inode meta */ node_blk->i.i_size = cpu_to_le64(off); if (!c.compress.readonly) { - node_blk->i.i_compr_blocks = cpu_to_le64(cblocks); + node_blk->i.i_compr_blocks = cpu_to_le32(cblocks); node_blk->i.i_blocks += cpu_to_le64(cblocks); } ASSERT(update_inode(sbi, node_blk, &ni.blk_addr) >= 0); diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h index 1b24a3c..a06defb 100644 --- a/include/f2fs_fs.h +++ b/include/f2fs_fs.h @@ -929,6 +929,15 @@ struct f2fs_extent { static_assert(sizeof(struct f2fs_extent) == 12, ""); +/* + * f2fs_iext_header: header for inline extent area in i_extra_attr region. + * Placed right after i_extra_end[0], before the extent array. + */ +struct f2fs_iext_header { + __le32 cnt; /* current # of valid extents */ + struct f2fs_extent exts[]; +} __attribute__((packed)); + #define F2FS_NAME_LEN 255 /* max output length of pretty_print_filename() including null terminator */ @@ -1079,7 +1088,8 @@ struct f2fs_inode { __le32 i_inode_checksum;/* inode meta checksum */ __le64 i_crtime; /* creation time */ __le32 i_crtime_nsec; /* creation time in nano scale */ - __le64 i_compr_blocks; /* # of compressed blocks */ + __le32 i_compr_blocks; /* # of compressed blocks */ + __le32 i_inline_ext_capacity; /* # of inline extent entries */ __u8 i_compress_algorithm; /* compress algorithm */ __u8 i_log_cluster_size; /* log of cluster size */ __le16 i_compress_flag; /* compress flag */ @@ -1730,6 +1740,16 @@ static inline bool f2fs_has_extra_isize(struct f2fs_inode *inode) return (inode->i_inline & F2FS_EXTRA_ATTR); } +static inline void f2fs_invalidate_inline_extent(struct f2fs_inode *inode) +{ + if (f2fs_has_extra_isize(inode) && + le32_to_cpu(inode->i_inline_ext_capacity) > 0) { + struct f2fs_iext_header *eh = + (struct f2fs_iext_header *)inode->i_extra_end; + eh->cnt = 0; + } +} + static inline int __get_extra_isize(struct f2fs_inode *inode) { if (f2fs_has_extra_isize(inode)) -- 2.43.0 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel