]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: iget for metadata inodes
authorDarrick J. Wong <djwong@kernel.org>
Mon, 25 Nov 2024 21:14:17 +0000 (13:14 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 24 Dec 2024 02:01:25 +0000 (18:01 -0800)
Source kernel commit df2e495bb92c84a401b6b90c835a9d1be84a3a0f

Create a xfs_trans_metafile_iget function for metadata inodes to ensure
that when we try to iget a metadata file, the inode is allocated and its
file mode matches the metadata file type the caller expects.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
include/libxfs.h
include/xfs_inode.h
libxfs/Makefile
libxfs/inode.c
libxfs/libxfs_api_defs.h
libxfs/xfs_metafile.h [new file with mode: 0644]

index fe8e6584f1caca688949cf275bcb3a70baa525c0..0356bc57b956a9cf41c271f74ad976f0b83695e9 100644 (file)
@@ -95,6 +95,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]))
index e03521bc9aaaa202c8c7bb24254758667e1dd52f..6f2d23987d5f8ab598ee43da93dafa1c72382d9b 100644 (file)
@@ -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 */
index 470583006de69a0f4a4a7f7cd4bb6ed8ec5af0ca..765c84a16408f8232c925671a1b22bdd105d893f 100644 (file)
@@ -55,6 +55,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 \
index 9230ad24a5cb6c00a7773b8c53f10ad9527e827b..1eb0bccae48906f6539b76eae75be5b23d609529 100644 (file)
@@ -205,6 +205,61 @@ out_destroy:
        return error;
 }
 
+/*
+ * Get a metadata inode.
+ *
+ * The metafile type must match the file mode exactly.
+ */
+int
+libxfs_trans_metafile_iget(
+       struct xfs_trans        *tp,
+       xfs_ino_t               ino,
+       enum xfs_metafile_type  metafile_type,
+       struct xfs_inode        **ipp)
+{
+       struct xfs_mount        *mp = tp->t_mountp;
+       struct xfs_inode        *ip;
+       umode_t                 mode;
+       int                     error;
+
+       error = libxfs_iget(mp, tp, ino, 0, &ip);
+       if (error)
+               return error;
+
+       if (metafile_type == XFS_METAFILE_DIR)
+               mode = S_IFDIR;
+       else
+               mode = S_IFREG;
+       if (inode_wrong_type(VFS_I(ip), mode))
+               goto bad_rele;
+
+       *ipp = ip;
+       return 0;
+bad_rele:
+       libxfs_irele(ip);
+       return -EFSCORRUPTED;
+}
+
+/* Grab a metadata file if the caller doesn't already have a transaction. */
+int
+libxfs_metafile_iget(
+       struct xfs_mount        *mp,
+       xfs_ino_t               ino,
+       enum xfs_metafile_type  metafile_type,
+       struct xfs_inode        **ipp)
+{
+       struct xfs_trans        *tp;
+       int                     error;
+
+       error = libxfs_trans_alloc_empty(mp, &tp);
+       if (error)
+               return error;
+
+       error = libxfs_trans_metafile_iget(tp, ino, metafile_type, ipp);
+       libxfs_trans_cancel(tp);
+       return error;
+}
+
 static void
 libxfs_idestroy(
        struct xfs_inode        *ip)
index 92e26eebabfed87282fbaafb8569037659bf5d6b..fefae9256555a08ec4b791858fa0593d6559ce89 100644 (file)
 #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
 #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_trans_metafile_iget                libxfs_trans_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 (file)
index 0000000..60fe189
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2018-2024 Oracle.  All Rights Reserved.
+ * Author: Darrick J. Wong <djwong@kernel.org>
+ */
+#ifndef __XFS_METAFILE_H__
+#define __XFS_METAFILE_H__
+
+/* Code specific to kernel/userspace; must be provided externally. */
+
+int xfs_trans_metafile_iget(struct xfs_trans *tp, xfs_ino_t ino,
+               enum xfs_metafile_type metafile_type, struct xfs_inode **ipp);
+int xfs_metafile_iget(struct xfs_mount *mp, xfs_ino_t ino,
+               enum xfs_metafile_type metafile_type, struct xfs_inode **ipp);
+
+#endif /* __XFS_METAFILE_H__ */