From: Chao Yu Date: Wed, 5 Mar 2025 09:11:47 +0000 (+0800) Subject: f2fs: do sanity check on xattr node footer in f2fs_get_xnode_page() X-Git-Tag: v6.15-rc1~151^2~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2aac2538a97d35b0a1beb60dce6001f5625b82e6;p=thirdparty%2Fkernel%2Flinux.git f2fs: do sanity check on xattr node footer in f2fs_get_xnode_page() This patch introduces a new wrapper f2fs_get_xnode_page(), then, caller can use it to load xattr block to page cache, meanwhile it will do sanity check on xattr node footer. Signed-off-by: Chao Yu Signed-off-by: Jaegeuk Kim --- diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 59e8fdcf4abeb..9ddf73c627f55 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3703,6 +3703,7 @@ void f2fs_ra_node_page(struct f2fs_sb_info *sbi, nid_t nid); struct page *f2fs_get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid); struct folio *f2fs_get_inode_folio(struct f2fs_sb_info *sbi, pgoff_t ino); struct page *f2fs_get_inode_page(struct f2fs_sb_info *sbi, pgoff_t ino); +struct page *f2fs_get_xnode_page(struct f2fs_sb_info *sbi, pgoff_t xnid); struct page *f2fs_get_node_page_ra(struct page *parent, int start); int f2fs_move_node_page(struct page *node_page, int gc_type); void f2fs_flush_inline_data(struct f2fs_sb_info *sbi); diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 89f1b4b92776a..f958ce9f58aed 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1245,7 +1245,7 @@ int f2fs_truncate_xattr_node(struct inode *inode) if (!nid) return 0; - npage = f2fs_get_node_page(sbi, nid); + npage = f2fs_get_xnode_page(sbi, nid); if (IS_ERR(npage)) return PTR_ERR(npage); @@ -1461,7 +1461,9 @@ static int sanity_check_node_footer(struct f2fs_sb_info *sbi, enum node_type ntype) { if (unlikely(nid != nid_of_node(page) || - (ntype == NODE_TYPE_INODE && !IS_INODE(page)))) { + (ntype == NODE_TYPE_INODE && !IS_INODE(page)) || + (ntype == NODE_TYPE_XATTR && + !f2fs_has_xattr_block(ofs_of_node(page))))) { f2fs_warn(sbi, "inconsistent node block, node_type:%d, nid:%lu, " "node_footer[nid:%u,ino:%u,ofs:%u,cpver:%llu,blkaddr:%u]", ntype, nid, nid_of_node(page), ino_of_node(page), @@ -1551,6 +1553,14 @@ struct page *f2fs_get_inode_page(struct f2fs_sb_info *sbi, pgoff_t ino) return &folio->page; } +struct page *f2fs_get_xnode_page(struct f2fs_sb_info *sbi, pgoff_t xnid) +{ + struct folio *folio = __get_node_folio(sbi, xnid, NULL, 0, + NODE_TYPE_XATTR); + + return &folio->page; +} + struct page *f2fs_get_node_page_ra(struct page *parent, int start) { struct f2fs_sb_info *sbi = F2FS_P_SB(parent); diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h index 5079c6a2298d4..103a437e64255 100644 --- a/fs/f2fs/node.h +++ b/fs/f2fs/node.h @@ -56,6 +56,7 @@ enum { enum node_type { NODE_TYPE_REGULAR, NODE_TYPE_INODE, + NODE_TYPE_XATTR, }; /* diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index d5b42e1005d82..c691b35618ad5 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c @@ -303,7 +303,7 @@ static int read_xattr_block(struct inode *inode, void *txattr_addr) void *xattr_addr; /* The inode already has an extended attribute block. */ - xpage = f2fs_get_node_page(sbi, xnid); + xpage = f2fs_get_xnode_page(sbi, xnid); if (IS_ERR(xpage)) return PTR_ERR(xpage); @@ -475,7 +475,7 @@ static inline int write_all_xattrs(struct inode *inode, __u32 hsize, /* write to xattr node block */ if (F2FS_I(inode)->i_xattr_nid) { - xpage = f2fs_get_node_page(sbi, F2FS_I(inode)->i_xattr_nid); + xpage = f2fs_get_xnode_page(sbi, F2FS_I(inode)->i_xattr_nid); if (IS_ERR(xpage)) { err = PTR_ERR(xpage); f2fs_alloc_nid_failed(sbi, new_nid);