diff options
Diffstat (limited to 'fs/xfs/libxfs/xfs_inode_util.c')
-rw-r--r-- | fs/xfs/libxfs/xfs_inode_util.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/fs/xfs/libxfs/xfs_inode_util.c b/fs/xfs/libxfs/xfs_inode_util.c index b6c6d321f6fc..fb68eeb58d0a 100644 --- a/fs/xfs/libxfs/xfs_inode_util.c +++ b/fs/xfs/libxfs/xfs_inode_util.c @@ -21,6 +21,7 @@ #include "xfs_error.h" #include "xfs_trace.h" #include "xfs_ag.h" +#include "xfs_inode_item.h" uint16_t xfs_flags2diflags( @@ -791,3 +792,50 @@ xfs_bumplink( inc_nlink(VFS_I(ip)); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); } + +/* Mark an inode free on disk. */ +int +xfs_dir_ifree( + struct xfs_trans *tp, + struct xfs_perag *pag, + struct xfs_inode *ip, + struct xfs_icluster *xic) +{ + int error; + + /* + * Pull the on-disk inode from the AGI unlinked list. + */ + error = xfs_iunlink_remove(tp, pag, ip); + if (error) + return error; + + error = xfs_difree(tp, pag, ip->i_ino, xic); + 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) { + kmem_free(ip->i_df.if_u1.if_data); + ip->i_df.if_u1.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 = ip->i_mount->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; +} |