From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9AC033AAF65 for ; Tue, 1 Sep 2026 11:48:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788263330; cv=none; b=QVtEgCCSUdNiz0swoddjgYuME0QZF5sJ1l1W3+/PNF7/q8wBM9RyBv/KW4lbPG42rpu8Tt8DHIcm8pOi2mQTP7WNqTLesjHwcJnh7De+gH54hVrwrBqfKzqds8bJn0gi2e5dw0M1gDvqJYoi09OFVYKamIGHHfb4bDTF1jZRIxE= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788263330; c=relaxed/simple; bh=ymFjaFcBK22bZeAMj84oS54A8G51MPN0n/moYw0WwkY=; h=Message-ID:Date:MIME-Version:Cc:Subject:To:References:From: In-Reply-To:Content-Type; b=Uxzdfx65cdjgA4ty+ndJyGPz1w5UZgGl2d4SkYUjqhDqWn+l83Z3+aMmg6YccoQ6gfqc0PxHF2u6TGJicU1bSsx/gG3xo/KwWSL5b2c+ntWxTZdIf106flLEkTOvJV5TNGuWMqSRs19kuqt599xzyBazgQ9LPII3KH8DmePx1YU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jRL96uGR; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jRL96uGR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5A1B51F000E9; Tue, 1 Sep 2026 11:48:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788263328; bh=OTIJKezHBFM/U98rr6J9IfB/cemhLkCTwUb1zFg2+Lg=; h=Date:Cc:Subject:To:References:From:In-Reply-To; b=jRL96uGR88hSdH2F9pBiGRXJ/u0Qd4LVD44uVJU69sLuHOlGLD17DJyx48o0P3fe8 HCBQGgBv8s5mugz4gWiJOl6XjJl0XBbdccUbF4UKuAqQWsjoML0Qlnx1d/VcL5rDGR m6foM7fayuc+BxeqNeJ0rERIhyZncwVujo+Qr/ef6F/QjnKEPIHtb7FCUPMo15gTHo 46w0bOJB5V1j82zco153h552UvXh7jDyei+/rWktuF+fq/AvJb9bYDts2t12HCfi3o 6qbUZxDoK3zkI83Y1g7JU9ZMbqAPcWVBeFFsHs1TMTifAhxc/e4BswGqPBFsRIK7r3 5AUizHpuPGz8w== Message-ID: <63f1e1ae-444f-406f-b76d-312cd0b76bdb@kernel.org> Date: Tue, 1 Sep 2026 19:48:45 +0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Cc: chao@kernel.org, jaegeuk@kernel.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v7 06/11] f2fs: describe {i,d,id}node block layout dynamically To: Kelvin Zhang , linux-f2fs-devel@lists.sourceforge.net References: Content-Language: en-US From: Chao Yu In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit On 9/1/26 06:08, Kelvin Zhang wrote: > 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 > --- > fs/f2fs/data.c | 2 +- > fs/f2fs/f2fs.h | 32 ++++++++++++++++++------- > fs/f2fs/gc.c | 2 +- > fs/f2fs/inline.c | 3 +-- > fs/f2fs/inode.c | 5 ++-- > fs/f2fs/node.c | 4 +--- > fs/f2fs/node.h | 53 +++++++++++++++++++---------------------- > fs/f2fs/super.c | 5 ++++ > include/linux/f2fs_fs.h | 26 +++++++++++++++----- > 9 files changed, 79 insertions(+), 53 deletions(-) > > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c > index 6ae0eb37d20f..751b7a457d9a 100644 > --- a/fs/f2fs/data.c > +++ b/fs/f2fs/data.c > @@ -2027,7 +2027,7 @@ static int f2fs_xattr_fiemap(struct inode *inode, > > phys = F2FS_BLK_TO_BYTES(ni.blk_addr); > offset = offsetof(struct f2fs_inode, i_addr) + > - sizeof(__le32) * (DEF_ADDRS_PER_INODE - > + sizeof(__le32) * (DEF_ADDRS_PER_INODE_SBI(sbi) - > get_inline_xattr_addrs(inode)); > > phys += offset; > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > index d2e54573ed34..247e56522441 100644 > --- a/fs/f2fs/f2fs.h > +++ b/fs/f2fs/f2fs.h > @@ -1853,6 +1853,9 @@ struct f2fs_sb_info { > unsigned int log_blocksize; /* log2 block size */ > unsigned int blocksize; /* block size */ > unsigned int nat_entries_per_block; /* NAT entries in a block */ > + unsigned int addrs_per_inode; /* addresses in an inode block */ > + unsigned int addrs_per_block; /* addresses in a direct node block */ > + unsigned int nids_per_block; /* node IDs in an indirect node block */ > unsigned int sit_entries_per_block; /* SIT entries in a block */ > unsigned int orphans_per_block; /* orphan inodes in a block */ > unsigned int dentries_per_block; /* dentries in a block */ > @@ -2248,6 +2251,7 @@ static inline struct f2fs_sb_info *F2FS_F_SB(const struct folio *folio) > > #define SIT_ENTRY_PER_BLOCK(sbi) ((sbi)->sit_entries_per_block) > #define NAT_ENTRY_PER_BLOCK(sbi) ((sbi)->nat_entries_per_block) > +#define DEF_ADDRS_PER_INODE_SBI(sbi) ((sbi)->addrs_per_inode) #define DEF_ADDRS_PER_INODE > #define F2FS_ORPHANS_PER_BLOCK(sbi) ((sbi)->orphans_per_block) > #define GET_ORPHAN_BLOCKS(sbi, n) DIV_ROUND_UP((n), \ > F2FS_ORPHANS_PER_BLOCK(sbi)) > @@ -2297,6 +2301,12 @@ static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi) > return (struct f2fs_checkpoint *)(sbi->ckpt); > } > > +static inline struct node_footer *F2FS_NODE_FOOTER(const struct folio *folio) > +{ > + return folio_address(folio) + F2FS_BLKSIZE - > + sizeof(struct node_footer); > +} > + > static inline struct f2fs_node *F2FS_NODE(const struct folio *folio) > { > return (struct f2fs_node *)folio_address(folio); > @@ -2307,6 +2317,12 @@ static inline struct f2fs_inode *F2FS_INODE(const struct folio *folio) > return &((struct f2fs_node *)folio_address(folio))->i; > } > > +static inline __le32 *F2FS_INODE_NIDS(const struct folio *folio) > +{ > + return folio_address(folio) + F2FS_BLKSIZE - sizeof(struct node_footer) - > + SIZE_OF_I_NID; > +} > + > static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi) > { > return (struct f2fs_nm_info *)(sbi->nm_info); > @@ -3277,13 +3293,11 @@ static inline void f2fs_radix_tree_insert(struct radix_tree_root *root, > cond_resched(); > } > > -#define RAW_IS_INODE(p) ((p)->footer.nid == (p)->footer.ino) > - > static inline bool IS_INODE(const struct folio *folio) > { > - struct f2fs_node *p = F2FS_NODE(folio); > + struct node_footer *footer = F2FS_NODE_FOOTER(folio); > > - return RAW_IS_INODE(p); > + return footer->nid == footer->ino; > } > > static inline int offset_in_addr(struct f2fs_inode *i) > @@ -3292,9 +3306,11 @@ static inline int offset_in_addr(struct f2fs_inode *i) > (le16_to_cpu(i->i_extra_isize) / sizeof(__le32)) : 0; > } > > -static inline __le32 *blkaddr_in_node(struct f2fs_node *node) > +static inline __le32 *blkaddr_in_node(const struct folio *folio) > { > - return RAW_IS_INODE(node) ? node->i.i_addr : node->dn.addr; > + struct f2fs_node *node = F2FS_NODE(folio); > + > + return IS_INODE(folio) ? node->i.i_addr : node->dn.addr; > } > > static inline int f2fs_has_extra_attr(struct inode *inode); > @@ -3311,7 +3327,7 @@ static inline unsigned int get_dnode_base(struct inode *inode, > static inline __le32 *get_dnode_addr(struct inode *inode, > struct folio *node_folio) > { > - return blkaddr_in_node(F2FS_NODE(node_folio)) + > + return blkaddr_in_node(node_folio) + > get_dnode_base(inode, node_folio); > } > > @@ -3639,7 +3655,7 @@ void *inline_xattr_addr(struct inode *inode, const struct folio *folio) > { > struct f2fs_inode *ri = F2FS_INODE(folio); > > - return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE - > + return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE_SBI(F2FS_I_SB(inode)) - > get_inline_xattr_addrs(inode)]); > } > > diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c > index c15c6ba91597..f15ab07a7347 100644 > --- a/fs/f2fs/gc.c > +++ b/fs/f2fs/gc.c > @@ -1176,7 +1176,7 @@ static bool is_alive(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, > > if (IS_INODE(node_folio)) { > base = offset_in_addr(F2FS_INODE(node_folio)); > - max_addrs = DEF_ADDRS_PER_INODE; > + max_addrs = DEF_ADDRS_PER_INODE_SBI(sbi); > } else { > base = 0; > max_addrs = DEF_ADDRS_PER_BLOCK; > diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c > index 718dd785865a..73cd9b6ddcc5 100644 > --- a/fs/f2fs/inline.c > +++ b/fs/f2fs/inline.c > @@ -36,14 +36,13 @@ bool f2fs_may_inline_data(struct inode *inode) > > static bool inode_has_blocks(struct inode *inode, struct folio *ifolio) > { > - struct f2fs_inode *ri = F2FS_INODE(ifolio); > int i; > > if (F2FS_HAS_BLOCKS(inode)) > return true; > > for (i = 0; i < DEF_NIDS_PER_INODE; i++) { > - if (ri->i_nid[i]) > + if (F2FS_INODE_NIDS(ifolio)[i]) > return true; > } > return false; > diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c > index 96cc0e777567..fda9ee3bfc61 100644 > --- a/fs/f2fs/inode.c > +++ b/fs/f2fs/inode.c > @@ -150,9 +150,8 @@ bool f2fs_enable_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio) > > static __u32 f2fs_inode_chksum(struct f2fs_sb_info *sbi, struct folio *folio) > { > - struct f2fs_node *node = F2FS_NODE(folio); > - struct f2fs_inode *ri = &node->i; > - __le32 ino = node->footer.ino; > + struct f2fs_inode *ri = F2FS_INODE(folio); > + __le32 ino = F2FS_NODE_FOOTER(folio)->ino; > __le32 gen = ri->i_generation; > __u32 chksum, chksum_seed; > __u32 dummy_cs = 0; > diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c > index 960c6657d0d6..e3f594f7bcce 100644 > --- a/fs/f2fs/node.c > +++ b/fs/f2fs/node.c > @@ -3001,7 +3001,6 @@ int f2fs_recover_inode_page(struct f2fs_sb_info *sbi, struct folio *folio) > int f2fs_restore_node_summary(struct f2fs_sb_info *sbi, > unsigned int segno, struct f2fs_summary_block *sum) > { > - struct f2fs_node *rn; > struct f2fs_summary *sum_entry; > block_t addr; > int i, idx, last_offset, nrpages; > @@ -3023,8 +3022,7 @@ int f2fs_restore_node_summary(struct f2fs_sb_info *sbi, > if (IS_ERR(folio)) > return PTR_ERR(folio); > > - rn = F2FS_NODE(folio); > - sum_entry->nid = rn->footer.nid; > + sum_entry->nid = F2FS_NODE_FOOTER(folio)->nid; > sum_entry->version = 0; > sum_entry->ofs_in_node = 0; > sum_entry++; > diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h > index 0dce97aac5fc..6a2b7c63f4a3 100644 > --- a/fs/f2fs/node.h > +++ b/fs/f2fs/node.h > @@ -252,73 +252,68 @@ static inline void set_to_next_nat(struct f2fs_sb_info *sbi, > > static inline nid_t ino_of_node(const struct folio *node_folio) > { > - struct f2fs_node *rn = F2FS_NODE(node_folio); > - return le32_to_cpu(rn->footer.ino); > + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->ino); > } > > static inline nid_t nid_of_node(const struct folio *node_folio) > { > - struct f2fs_node *rn = F2FS_NODE(node_folio); > - return le32_to_cpu(rn->footer.nid); > + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->nid); > } > > static inline unsigned int ofs_of_node(const struct folio *node_folio) > { > - struct f2fs_node *rn = F2FS_NODE(node_folio); > - unsigned flag = le32_to_cpu(rn->footer.flag); > + unsigned int flag = le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->flag); > return flag >> OFFSET_BIT_SHIFT; > } > > static inline __u64 cpver_of_node(const struct folio *node_folio) > { > - struct f2fs_node *rn = F2FS_NODE(node_folio); > - return le64_to_cpu(rn->footer.cp_ver); > + return le64_to_cpu(F2FS_NODE_FOOTER(node_folio)->cp_ver); > } > > static inline block_t next_blkaddr_of_node(const struct folio *node_folio) > { > - struct f2fs_node *rn = F2FS_NODE(node_folio); > - return le32_to_cpu(rn->footer.next_blkaddr); > + return le32_to_cpu(F2FS_NODE_FOOTER(node_folio)->next_blkaddr); > } > > static inline void fill_node_footer(const struct folio *folio, nid_t nid, > nid_t ino, unsigned int ofs, bool reset) > { > struct f2fs_node *rn = F2FS_NODE(folio); > + struct node_footer *footer = F2FS_NODE_FOOTER(folio); > unsigned int old_flag = 0; > > if (reset) > - memset(rn, 0, sizeof(*rn)); > + memset(rn, 0, F2FS_BLKSIZE); > else > - old_flag = le32_to_cpu(rn->footer.flag); > + old_flag = le32_to_cpu(footer->flag); > > - rn->footer.nid = cpu_to_le32(nid); > - rn->footer.ino = cpu_to_le32(ino); > + footer->nid = cpu_to_le32(nid); > + footer->ino = cpu_to_le32(ino); > > /* should remain old flag bits such as COLD_BIT_SHIFT */ > - rn->footer.flag = cpu_to_le32((ofs << OFFSET_BIT_SHIFT) | > + footer->flag = cpu_to_le32((ofs << OFFSET_BIT_SHIFT) | > (old_flag & OFFSET_BIT_MASK)); > } > > static inline void copy_node_footer(const struct folio *dst, > const struct folio *src) > { > - struct f2fs_node *src_rn = F2FS_NODE(src); > - struct f2fs_node *dst_rn = F2FS_NODE(dst); > - memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer)); > + memcpy(F2FS_NODE_FOOTER(dst), F2FS_NODE_FOOTER(src), > + sizeof(struct node_footer)); > } > > static inline void fill_node_footer_blkaddr(struct folio *folio, block_t blkaddr) > { > struct f2fs_checkpoint *ckpt = F2FS_CKPT(F2FS_F_SB(folio)); > - struct f2fs_node *rn = F2FS_NODE(folio); > + struct node_footer *footer = F2FS_NODE_FOOTER(folio); > __u64 cp_ver = cur_cp_version(ckpt); > > if (__is_set_ckpt_flags(ckpt, CP_CRC_RECOVERY_FLAG)) > cp_ver |= (cur_cp_crc(ckpt) << 32); > > - rn->footer.cp_ver = cpu_to_le64(cp_ver); > - rn->footer.next_blkaddr = cpu_to_le32(blkaddr); > + footer->cp_ver = cpu_to_le64(cp_ver); > + footer->next_blkaddr = cpu_to_le32(blkaddr); > } > > static inline bool is_recoverable_dnode(const struct folio *folio) > @@ -378,11 +373,12 @@ static inline bool IS_DNODE(const struct folio *node_folio) > static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i) > { > struct f2fs_node *rn = F2FS_NODE(folio); > + __le32 *inode_nids = F2FS_INODE_NIDS(folio); > > f2fs_folio_wait_writeback(folio, NODE, true, true); > > if (i) > - rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid); > + inode_nids[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid); > else > rn->in.nid[off] = cpu_to_le32(nid); > return folio_mark_dirty(folio); > @@ -391,9 +387,10 @@ static inline int set_nid(struct folio *folio, int off, nid_t nid, bool i) > static inline nid_t get_nid(const struct folio *folio, int off, bool i) > { > struct f2fs_node *rn = F2FS_NODE(folio); > + const __le32 *inode_nids = F2FS_INODE_NIDS(folio); > > if (i) > - return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]); > + return le32_to_cpu(inode_nids[off - NODE_DIR1_BLOCK]); > return le32_to_cpu(rn->in.nid[off]); > } > > @@ -406,8 +403,7 @@ static inline nid_t get_nid(const struct folio *folio, int off, bool i) > > static inline int is_node(const struct folio *folio, int type) > { > - struct f2fs_node *rn = F2FS_NODE(folio); > - return le32_to_cpu(rn->footer.flag) & BIT(type); > + return le32_to_cpu(F2FS_NODE_FOOTER(folio)->flag) & BIT(type); > } > > #define is_cold_node(folio) is_node(folio, COLD_BIT_SHIFT) > @@ -416,14 +412,13 @@ static inline int is_node(const struct folio *folio, int type) > > static inline void __set_mark(const struct folio *folio, bool mark, int type) > { > - struct f2fs_node *rn = F2FS_NODE(folio); > - unsigned int flag = le32_to_cpu(rn->footer.flag); > - > + struct node_footer *footer = F2FS_NODE_FOOTER(folio); > + unsigned int flag = le32_to_cpu(footer->flag); > if (mark) > flag |= BIT(type); > else > flag &= ~BIT(type); > - rn->footer.flag = cpu_to_le32(flag); > + footer->flag = cpu_to_le32(flag); > } > > static inline void set_cold_node(const struct folio *folio, bool is_dir) > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c > index 8d2224e585d3..fcaeaacaab33 100644 > --- a/fs/f2fs/super.c > +++ b/fs/f2fs/super.c > @@ -4384,6 +4384,11 @@ static void init_sb_info(struct f2fs_sb_info *sbi) > sbi->blocksize = BIT(sbi->log_blocksize); > sbi->nat_entries_per_block = sbi->blocksize / > sizeof(struct f2fs_nat_entry); > + sbi->addrs_per_inode = (sbi->blocksize - OFFSET_OF_END_OF_I_EXT - > + SIZE_OF_I_NID - sizeof(struct node_footer)) / sizeof(__le32); > + sbi->addrs_per_block = (sbi->blocksize - > + sizeof(struct node_footer)) / sizeof(__le32); > + sbi->nids_per_block = sbi->addrs_per_block; > sbi->sit_entries_per_block = sbi->blocksize / > sizeof(struct f2fs_sit_entry); > sbi->orphans_per_block = (sbi->blocksize - > diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h > index d1059a27e1b9..3d0fe2c78e12 100644 > --- a/include/linux/f2fs_fs.h > +++ b/include/linux/f2fs_fs.h > @@ -16,6 +16,7 @@ > #define F2FS_MAX_LOG_SECTOR_SIZE PAGE_SHIFT /* Max is Block Size */ > #define F2FS_LOG_SECTORS_PER_BLOCK (PAGE_SHIFT - 9) /* log number for sector/blk */ > #define F2FS_BLKSIZE PAGE_SIZE /* support only block == page */ > +#define F2FS_MAX_BLKSIZE PAGE_SIZE It's unused in this patch? > #define F2FS_BLKSIZE_BITS PAGE_SHIFT /* bits for F2FS_BLKSIZE */ > #define F2FS_MAX_EXTENSION 64 /* # of extension entries */ > #define F2FS_EXTENSION_LEN 8 /* max size of extension */ > @@ -343,18 +344,25 @@ struct f2fs_inode { > */ > __le32 i_extra_end[0]; /* for attribute size calculation */ > } __packed; > - __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */ > + DECLARE_FLEX_ARRAY(__le32, i_addr); /* data block pointers */ > }; > - __le32 i_nid[DEF_NIDS_PER_INODE]; /* direct(2), indirect(2), > - double_indirect(1) node id */ Can you please keep the comments? /* direct(2), indirect(2), double_indirect(1) node id */ > + /* > + * __le32 i_nid[DEF_NIDS_PER_INODE]; > + * > + * It is stored immediately before the node footer at the end of the > + * filesystem block. Its offset depends on the filesystem block size, so > + * locate it dynamically with F2FS_INODE_NIDS(). > + */ > } __packed; > > struct direct_node { > - __le32 addr[DEF_ADDRS_PER_BLOCK]; /* array of data block address */ > + /* The address count depends on the filesystem block size. */ > + DECLARE_FLEX_ARRAY(__le32, addr); /* array of data block address */ > } __packed; > > struct indirect_node { > - __le32 nid[NIDS_PER_BLOCK]; /* array of data block address */ > + /* The node ID count depends on the filesystem block size. */ > + DECLARE_FLEX_ARRAY(__le32, nid); /* array of data block address */ > } __packed; > > enum { > @@ -373,7 +381,13 @@ struct f2fs_node { > struct direct_node dn; > struct indirect_node in; > }; > - struct node_footer footer; > + /* > + * struct node_footer footer; > + * > + * It is stored at the end of the filesystem block, after the inode or > + * direct/indirect node data. Its offset depends on the filesystem block > + * size, so locate it dynamically with F2FS_NODE_FOOTER(). > + */ > } __packed; > > /*