Commit a4454cd6 authored by Dave Chinner's avatar Dave Chinner Committed by Dave Chinner

xfs: factor the xfs_iunlink functions

Prep work that separates the locking that protects the unlinked list
from the actual operations being performed. This also helps document
the fact they are performing list insert  and remove operations. No
functional code change.
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
parent 04a98a03
......@@ -2115,39 +2115,20 @@ xfs_iunlink_update_inode(
return error;
}
/*
* This is called when the inode's link count has gone to 0 or we are creating
* a tmpfile via O_TMPFILE. The inode @ip must have nlink == 0.
*
* We place the on-disk inode on a list in the AGI. It will be pulled from this
* list when the inode is freed.
*/
STATIC int
xfs_iunlink(
static int
xfs_iunlink_insert_inode(
struct xfs_trans *tp,
struct xfs_perag *pag,
struct xfs_buf *agibp,
struct xfs_inode *ip)
{
struct xfs_mount *mp = tp->t_mountp;
struct xfs_perag *pag;
struct xfs_agi *agi;
struct xfs_buf *agibp;
struct xfs_agi *agi = agibp->b_addr;
xfs_agino_t next_agino;
xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
short bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS;
int error;
ASSERT(VFS_I(ip)->i_nlink == 0);
ASSERT(VFS_I(ip)->i_mode != 0);
trace_xfs_iunlink(ip);
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
/* Get the agi buffer first. It ensures lock ordering on the list. */
error = xfs_read_agi(pag, tp, &agibp);
if (error)
goto out;
agi = agibp->b_addr;
/*
* Get the index into the agi hash table for the list this inode will
* go on. Make sure the pointer isn't garbage and that this inode
......@@ -2157,8 +2138,7 @@ xfs_iunlink(
if (next_agino == agino ||
!xfs_verify_agino_or_null(pag, next_agino)) {
xfs_buf_mark_corrupt(agibp);
error = -EFSCORRUPTED;
goto out;
return -EFSCORRUPTED;
}
if (next_agino != NULLAGINO) {
......@@ -2171,7 +2151,7 @@ xfs_iunlink(
error = xfs_iunlink_update_inode(tp, ip, pag, next_agino,
&old_agino);
if (error)
goto out;
return error;
ASSERT(old_agino == NULLAGINO);
/*
......@@ -2180,11 +2160,42 @@ xfs_iunlink(
*/
error = xfs_iunlink_add_backref(pag, agino, next_agino);
if (error)
goto out;
return error;
}
/* Point the head of the list to point to this inode. */
error = xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, agino);
return xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, agino);
}
/*
* This is called when the inode's link count has gone to 0 or we are creating
* a tmpfile via O_TMPFILE. The inode @ip must have nlink == 0.
*
* We place the on-disk inode on a list in the AGI. It will be pulled from this
* list when the inode is freed.
*/
STATIC int
xfs_iunlink(
struct xfs_trans *tp,
struct xfs_inode *ip)
{
struct xfs_mount *mp = tp->t_mountp;
struct xfs_perag *pag;
struct xfs_buf *agibp;
int error;
ASSERT(VFS_I(ip)->i_nlink == 0);
ASSERT(VFS_I(ip)->i_mode != 0);
trace_xfs_iunlink(ip);
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
/* Get the agi buffer first. It ensures lock ordering on the list. */
error = xfs_read_agi(pag, tp, &agibp);
if (error)
goto out;
error = xfs_iunlink_insert_inode(tp, pag, agibp, ip);
out:
xfs_perag_put(pag);
return error;
......@@ -2305,18 +2316,15 @@ xfs_iunlink_map_prev(
return 0;
}
/*
* Pull the on-disk inode from the AGI unlinked list.
*/
STATIC int
xfs_iunlink_remove(
static int
xfs_iunlink_remove_inode(
struct xfs_trans *tp,
struct xfs_perag *pag,
struct xfs_buf *agibp,
struct xfs_inode *ip)
{
struct xfs_mount *mp = tp->t_mountp;
struct xfs_agi *agi;
struct xfs_buf *agibp;
struct xfs_agi *agi = agibp->b_addr;
struct xfs_buf *last_ibp;
struct xfs_dinode *last_dip = NULL;
xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
......@@ -2327,12 +2335,6 @@ xfs_iunlink_remove(
trace_xfs_iunlink_remove(ip);
/* Get the agi buffer first. It ensures lock ordering on the list. */
error = xfs_read_agi(pag, tp, &agibp);
if (error)
return error;
agi = agibp->b_addr;
/*
* Get the index into the agi hash table for the list this inode will
* go on. Make sure the head pointer isn't garbage.
......@@ -2397,6 +2399,28 @@ xfs_iunlink_remove(
next_agino);
}
/*
* Pull the on-disk inode from the AGI unlinked list.
*/
STATIC int
xfs_iunlink_remove(
struct xfs_trans *tp,
struct xfs_perag *pag,
struct xfs_inode *ip)
{
struct xfs_buf *agibp;
int error;
trace_xfs_iunlink_remove(ip);
/* Get the agi buffer first. It ensures lock ordering on the list. */
error = xfs_read_agi(pag, tp, &agibp);
if (error)
return error;
return xfs_iunlink_remove_inode(tp, pag, agibp, ip);
}
/*
* Look up the inode number specified and if it is not already marked XFS_ISTALE
* mark it stale. We should only find clean inodes in this lookup that aren't
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment