]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs: hoist inode free function to libxfs
authorDarrick J. Wong <djwong@kernel.org>
Tue, 9 Jan 2024 17:42:20 +0000 (09:42 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 10 Apr 2024 00:21:34 +0000 (17:21 -0700)
Create a libxfs helper function that marks an inode free on disk.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
libxfs/xfs_inode_util.c
libxfs/xfs_inode_util.h

index d1234a26494962592f9336eda89148c797c28c82..4f5864491bad22bea0a2595fec2ece70e6add18e 100644 (file)
@@ -668,3 +668,54 @@ xfs_bumplink(
 
        xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
 }
+
+/* Free an inode in the ondisk index and zero it out. */
+int
+xfs_inode_uninit(
+       struct xfs_trans        *tp,
+       struct xfs_perag        *pag,
+       struct xfs_inode        *ip,
+       struct xfs_icluster     *xic)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+       int                     error;
+
+       /*
+        * Free the inode first so that we guarantee that the AGI lock is going
+        * to be taken before we remove the inode from the unlinked list. This
+        * makes the AGI lock -> unlinked list modification order the same as
+        * used in O_TMPFILE creation.
+        */
+       error = xfs_difree(tp, pag, ip->i_ino, xic);
+       if (error)
+               return error;
+
+       error = xfs_iunlink_remove(tp, pag, ip);
+       if (error)
+               return error;
+
+       /*
+        * Free any local-format data sitting around before we reset the
+        * data fork to extents format.  Note that the attr fork data has
+        * already been freed by xfs_attr_inactive.
+        */
+       if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) {
+               kfree(ip->i_df.if_data);
+               ip->i_df.if_data = NULL;
+               ip->i_df.if_bytes = 0;
+       }
+
+       VFS_I(ip)->i_mode = 0;          /* mark incore inode as free */
+       ip->i_diflags = 0;
+       ip->i_diflags2 = mp->m_ino_geo.new_diflags2;
+       ip->i_forkoff = 0;              /* mark the attr fork not in use */
+       ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
+
+       /*
+        * Bump the generation count so no one will be confused
+        * by reincarnations of this inode.
+        */
+       VFS_I(ip)->i_generation++;
+       xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+       return 0;
+}
index a2a1796a72ff348e050bf0a71e85e72d7c3f199b..844a5530845eefa20cc970661ba8475b63a43601 100644 (file)
@@ -6,6 +6,8 @@
 #ifndef        __XFS_INODE_UTIL_H__
 #define        __XFS_INODE_UTIL_H__
 
+struct xfs_icluster;
+
 uint16_t       xfs_flags2diflags(struct xfs_inode *ip, unsigned int xflags);
 uint64_t       xfs_flags2diflags2(struct xfs_inode *ip, unsigned int xflags);
 uint32_t       xfs_dic2xflags(struct xfs_inode *ip);
@@ -57,6 +59,9 @@ void xfs_trans_ichgtime(struct xfs_trans *tp, struct xfs_inode *ip, int flags);
 void xfs_inode_init(struct xfs_trans *tp, const struct xfs_icreate_args *args,
                struct xfs_inode *ip);
 
+int xfs_inode_uninit(struct xfs_trans *tp, struct xfs_perag *pag,
+               struct xfs_inode *ip, struct xfs_icluster *xic);
+
 int xfs_iunlink(struct xfs_trans *tp, struct xfs_inode *ip);
 int xfs_iunlink_remove(struct xfs_trans *tp, struct xfs_perag *pag,
                struct xfs_inode *ip);