From 814b330b8bd0ebc805036d2978b57e4217f78e60 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 28 May 2024 21:10:54 -0700 Subject: [PATCH] xfs: iget for metadata inodes Create a xfs_imeta_iget function for metadata inodes to ensure that when we try to iget a metadata file, the inobt thinks a metadata inode is in use and that the file type matches what we are expecting. Signed-off-by: Darrick J. Wong --- include/libxfs.h | 1 + include/xfs_inode.h | 5 +++++ libxfs/Makefile | 1 + libxfs/inode.c | 30 ++++++++++++++++++++++++++++++ libxfs/libxfs_api_defs.h | 4 ++++ libxfs/xfs_metafile.h | 14 ++++++++++++++ 6 files changed, 55 insertions(+) create mode 100644 libxfs/xfs_metafile.h diff --git a/include/libxfs.h b/include/libxfs.h index c49f22935..1e55d42d5 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -93,6 +93,7 @@ struct iomap; #include "xfs_btree_mem.h" #include "xfs_parent.h" #include "xfs_ag_resv.h" +#include "xfs_metafile.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) diff --git a/include/xfs_inode.h b/include/xfs_inode.h index 4fe2826f9..27c050357 100644 --- a/include/xfs_inode.h +++ b/include/xfs_inode.h @@ -210,6 +210,11 @@ static inline struct timespec64 inode_set_ctime_current(struct inode *inode) return now; } +static inline bool inode_wrong_type(const struct inode *inode, umode_t mode) +{ + return (inode->i_mode ^ mode) & S_IFMT; +} + typedef struct xfs_inode { struct cache_node i_node; struct xfs_mount *i_mount; /* fs mount struct ptr */ diff --git a/libxfs/Makefile b/libxfs/Makefile index 1f713d555..39809c498 100644 --- a/libxfs/Makefile +++ b/libxfs/Makefile @@ -54,6 +54,7 @@ HFILES = \ xfs_inode_buf.h \ xfs_inode_fork.h \ xfs_inode_util.h \ + xfs_metafile.h \ xfs_parent.h \ xfs_quota_defs.h \ xfs_refcount.h \ diff --git a/libxfs/inode.c b/libxfs/inode.c index 9230ad24a..35fc2632e 100644 --- a/libxfs/inode.c +++ b/libxfs/inode.c @@ -205,6 +205,36 @@ out_destroy: return error; } +/* + * Get a metadata inode. The file type part of @mode must match the inode + * exactly. Caller must supply a transaction (even if empty) to avoid + * livelocking if the inobt has a cycle. + */ +int +libxfs_metafile_iget( + struct xfs_trans *tp, + xfs_ino_t ino, + umode_t mode, + struct xfs_inode **ipp) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_inode *ip; + int error; + + error = libxfs_iget(mp, tp, ino, XFS_IGET_UNTRUSTED, &ip); + if (error) + return error; + + if (inode_wrong_type(VFS_I(ip), mode)) + goto bad_rele; + + *ipp = ip; + return 0; +bad_rele: + libxfs_irele(ip); + return -EFSCORRUPTED; +} + static void libxfs_idestroy( struct xfs_inode *ip) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 48fed384a..f70fa86bd 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -185,6 +185,7 @@ #define xfs_iext_next libxfs_iext_next #define xfs_ifork_zap_attr libxfs_ifork_zap_attr #define xfs_imap_to_bp libxfs_imap_to_bp + #define xfs_initialize_perag libxfs_initialize_perag #define xfs_initialize_perag_data libxfs_initialize_perag_data #define xfs_init_local_fork libxfs_init_local_fork @@ -209,8 +210,11 @@ #define xfs_log_calc_minimum_size libxfs_log_calc_minimum_size #define xfs_log_get_max_trans_res libxfs_log_get_max_trans_res #define xfs_log_sb libxfs_log_sb + +#define xfs_metafile_iget libxfs_metafile_iget #define xfs_mode_to_ftype libxfs_mode_to_ftype #define xfs_mkdir_space_res libxfs_mkdir_space_res + #define xfs_parent_addname libxfs_parent_addname #define xfs_parent_finish libxfs_parent_finish #define xfs_parent_hashval libxfs_parent_hashval diff --git a/libxfs/xfs_metafile.h b/libxfs/xfs_metafile.h new file mode 100644 index 000000000..ea0ba76be --- /dev/null +++ b/libxfs/xfs_metafile.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2018-2024 Oracle. All Rights Reserved. + * Author: Darrick J. Wong + */ +#ifndef __XFS_METAFILE_H__ +#define __XFS_METAFILE_H__ + +/* Code specific to kernel/userspace; must be provided externally. */ + +int xfs_metafile_iget(struct xfs_trans *tp, xfs_ino_t ino, umode_t mode, + struct xfs_inode **ipp); + +#endif /* __XFS_METAFILE_H__ */ -- 2.50.1