xfs: hoist inode free function to libxfs

Create a libxfs helper function that marks an inode free on disk.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Darrick J. Wong 2024-07-02 11:22:44 -07:00
parent c1f0bad423
commit 1964435d19
3 changed files with 58 additions and 34 deletions

View File

@ -22,6 +22,7 @@
#include "xfs_trace.h"
#include "xfs_ag.h"
#include "xfs_iunlink_item.h"
#include "xfs_inode_item.h"
uint16_t
xfs_flags2diflags(
@ -695,3 +696,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;
}

View 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);
@ -48,6 +50,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);

View File

@ -1945,36 +1945,10 @@ xfs_ifree(
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
/*
* 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);
error = xfs_inode_uninit(tp, pag, ip, &xic);
if (error)
goto out;
error = xfs_iunlink_remove(tp, pag, ip);
if (error)
goto out;
/*
* 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;
if (xfs_iflags_test(ip, XFS_IPRESERVE_DM_FIELDS))
xfs_iflags_clear(ip, XFS_IPRESERVE_DM_FIELDS);
@ -1983,13 +1957,6 @@ xfs_ifree(
iip->ili_fields &= ~(XFS_ILOG_AOWNER | XFS_ILOG_DOWNER);
spin_unlock(&iip->ili_lock);
/*
* 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);
if (xic.deleted)
error = xfs_ifree_cluster(tp, pag, ip, &xic);
out: