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

xfs: use perag through unlink processing

Unlinked lists are held in the perag, and freeing of inodes needs to
be passed a perag, too, so look up the perag early in the unlink
processing and use it throughout.
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
parent 8237fbf5
...@@ -2134,35 +2134,33 @@ xfs_difree_finobt( ...@@ -2134,35 +2134,33 @@ xfs_difree_finobt(
*/ */
int int
xfs_difree( xfs_difree(
struct xfs_trans *tp, /* transaction pointer */ struct xfs_trans *tp,
xfs_ino_t inode, /* inode to be freed */ struct xfs_perag *pag,
struct xfs_icluster *xic) /* cluster info if deleted */ xfs_ino_t inode,
struct xfs_icluster *xic)
{ {
/* REFERENCED */ /* REFERENCED */
xfs_agblock_t agbno; /* block number containing inode */ xfs_agblock_t agbno; /* block number containing inode */
struct xfs_buf *agbp; /* buffer for allocation group header */ struct xfs_buf *agbp; /* buffer for allocation group header */
xfs_agino_t agino; /* allocation group inode number */ xfs_agino_t agino; /* allocation group inode number */
xfs_agnumber_t agno; /* allocation group number */
int error; /* error return value */ int error; /* error return value */
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
struct xfs_inobt_rec_incore rec;/* btree record */ struct xfs_inobt_rec_incore rec;/* btree record */
struct xfs_perag *pag;
/* /*
* Break up inode number into its components. * Break up inode number into its components.
*/ */
agno = XFS_INO_TO_AGNO(mp, inode); if (pag->pag_agno != XFS_INO_TO_AGNO(mp, inode)) {
if (agno >= mp->m_sb.sb_agcount) { xfs_warn(mp, "%s: agno != pag->pag_agno (%d != %d).",
xfs_warn(mp, "%s: agno >= mp->m_sb.sb_agcount (%d >= %d).", __func__, XFS_INO_TO_AGNO(mp, inode), pag->pag_agno);
__func__, agno, mp->m_sb.sb_agcount);
ASSERT(0); ASSERT(0);
return -EINVAL; return -EINVAL;
} }
agino = XFS_INO_TO_AGINO(mp, inode); agino = XFS_INO_TO_AGINO(mp, inode);
if (inode != XFS_AGINO_TO_INO(mp, agno, agino)) { if (inode != XFS_AGINO_TO_INO(mp, pag->pag_agno, agino)) {
xfs_warn(mp, "%s: inode != XFS_AGINO_TO_INO() (%llu != %llu).", xfs_warn(mp, "%s: inode != XFS_AGINO_TO_INO() (%llu != %llu).",
__func__, (unsigned long long)inode, __func__, (unsigned long long)inode,
(unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino)); (unsigned long long)XFS_AGINO_TO_INO(mp, pag->pag_agno, agino));
ASSERT(0); ASSERT(0);
return -EINVAL; return -EINVAL;
} }
...@@ -2176,7 +2174,7 @@ xfs_difree( ...@@ -2176,7 +2174,7 @@ xfs_difree(
/* /*
* Get the allocation group header. * Get the allocation group header.
*/ */
error = xfs_ialloc_read_agi(mp, tp, agno, &agbp); error = xfs_ialloc_read_agi(mp, tp, pag->pag_agno, &agbp);
if (error) { if (error) {
xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.", xfs_warn(mp, "%s: xfs_ialloc_read_agi() returned error %d.",
__func__, error); __func__, error);
...@@ -2186,7 +2184,6 @@ xfs_difree( ...@@ -2186,7 +2184,6 @@ xfs_difree(
/* /*
* Fix up the inode allocation btree. * Fix up the inode allocation btree.
*/ */
pag = agbp->b_pag;
error = xfs_difree_inobt(mp, tp, agbp, pag, agino, xic, &rec); error = xfs_difree_inobt(mp, tp, agbp, pag, agino, xic, &rec);
if (error) if (error)
goto error0; goto error0;
......
...@@ -39,17 +39,8 @@ xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o) ...@@ -39,17 +39,8 @@ xfs_make_iptr(struct xfs_mount *mp, struct xfs_buf *b, int o)
int xfs_dialloc(struct xfs_trans **tpp, xfs_ino_t parent, umode_t mode, int xfs_dialloc(struct xfs_trans **tpp, xfs_ino_t parent, umode_t mode,
xfs_ino_t *new_ino); xfs_ino_t *new_ino);
/* int xfs_difree(struct xfs_trans *tp, struct xfs_perag *pag,
* Free disk inode. Carefully avoids touching the incore inode, all xfs_ino_t ino, struct xfs_icluster *ifree);
* manipulations incore are the caller's responsibility.
* The on-disk inode is not changed by this operation, only the
* btree (free inode mask) is changed.
*/
int /* error */
xfs_difree(
struct xfs_trans *tp, /* transaction pointer */
xfs_ino_t inode, /* inode to be freed */
struct xfs_icluster *ifree); /* cluster info if deleted */
/* /*
* Return the location of the inode in imap, for mapping it into a buffer. * Return the location of the inode in imap, for mapping it into a buffer.
......
...@@ -45,7 +45,8 @@ kmem_zone_t *xfs_inode_zone; ...@@ -45,7 +45,8 @@ kmem_zone_t *xfs_inode_zone;
#define XFS_ITRUNC_MAX_EXTENTS 2 #define XFS_ITRUNC_MAX_EXTENTS 2
STATIC int xfs_iunlink(struct xfs_trans *, struct xfs_inode *); STATIC int xfs_iunlink(struct xfs_trans *, struct xfs_inode *);
STATIC int xfs_iunlink_remove(struct xfs_trans *, struct xfs_inode *); STATIC int xfs_iunlink_remove(struct xfs_trans *tp, struct xfs_perag *pag,
struct xfs_inode *);
/* /*
* helper function to extract extent size hint from inode * helper function to extract extent size hint from inode
...@@ -1241,7 +1242,11 @@ xfs_link( ...@@ -1241,7 +1242,11 @@ xfs_link(
* Handle initial link state of O_TMPFILE inode * Handle initial link state of O_TMPFILE inode
*/ */
if (VFS_I(sip)->i_nlink == 0) { if (VFS_I(sip)->i_nlink == 0) {
error = xfs_iunlink_remove(tp, sip); struct xfs_perag *pag;
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, sip->i_ino));
error = xfs_iunlink_remove(tp, pag, sip);
xfs_perag_put(pag);
if (error) if (error)
goto error_return; goto error_return;
} }
...@@ -1934,7 +1939,7 @@ xfs_iunlink_destroy( ...@@ -1934,7 +1939,7 @@ xfs_iunlink_destroy(
STATIC int STATIC int
xfs_iunlink_update_bucket( xfs_iunlink_update_bucket(
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_perag *pag,
struct xfs_buf *agibp, struct xfs_buf *agibp,
unsigned int bucket_index, unsigned int bucket_index,
xfs_agino_t new_agino) xfs_agino_t new_agino)
...@@ -1943,10 +1948,10 @@ xfs_iunlink_update_bucket( ...@@ -1943,10 +1948,10 @@ xfs_iunlink_update_bucket(
xfs_agino_t old_value; xfs_agino_t old_value;
int offset; int offset;
ASSERT(xfs_verify_agino_or_null(tp->t_mountp, agno, new_agino)); ASSERT(xfs_verify_agino_or_null(tp->t_mountp, pag->pag_agno, new_agino));
old_value = be32_to_cpu(agi->agi_unlinked[bucket_index]); old_value = be32_to_cpu(agi->agi_unlinked[bucket_index]);
trace_xfs_iunlink_update_bucket(tp->t_mountp, agno, bucket_index, trace_xfs_iunlink_update_bucket(tp->t_mountp, pag->pag_agno, bucket_index,
old_value, new_agino); old_value, new_agino);
/* /*
...@@ -1970,7 +1975,7 @@ xfs_iunlink_update_bucket( ...@@ -1970,7 +1975,7 @@ xfs_iunlink_update_bucket(
STATIC void STATIC void
xfs_iunlink_update_dinode( xfs_iunlink_update_dinode(
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_perag *pag,
xfs_agino_t agino, xfs_agino_t agino,
struct xfs_buf *ibp, struct xfs_buf *ibp,
struct xfs_dinode *dip, struct xfs_dinode *dip,
...@@ -1980,9 +1985,9 @@ xfs_iunlink_update_dinode( ...@@ -1980,9 +1985,9 @@ xfs_iunlink_update_dinode(
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
int offset; int offset;
ASSERT(xfs_verify_agino_or_null(mp, agno, next_agino)); ASSERT(xfs_verify_agino_or_null(mp, pag->pag_agno, next_agino));
trace_xfs_iunlink_update_dinode(mp, agno, agino, trace_xfs_iunlink_update_dinode(mp, pag->pag_agno, agino,
be32_to_cpu(dip->di_next_unlinked), next_agino); be32_to_cpu(dip->di_next_unlinked), next_agino);
dip->di_next_unlinked = cpu_to_be32(next_agino); dip->di_next_unlinked = cpu_to_be32(next_agino);
...@@ -2000,7 +2005,7 @@ STATIC int ...@@ -2000,7 +2005,7 @@ STATIC int
xfs_iunlink_update_inode( xfs_iunlink_update_inode(
struct xfs_trans *tp, struct xfs_trans *tp,
struct xfs_inode *ip, struct xfs_inode *ip,
xfs_agnumber_t agno, struct xfs_perag *pag,
xfs_agino_t next_agino, xfs_agino_t next_agino,
xfs_agino_t *old_next_agino) xfs_agino_t *old_next_agino)
{ {
...@@ -2010,7 +2015,7 @@ xfs_iunlink_update_inode( ...@@ -2010,7 +2015,7 @@ xfs_iunlink_update_inode(
xfs_agino_t old_value; xfs_agino_t old_value;
int error; int error;
ASSERT(xfs_verify_agino_or_null(mp, agno, next_agino)); ASSERT(xfs_verify_agino_or_null(mp, pag->pag_agno, next_agino));
error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &ibp); error = xfs_imap_to_bp(mp, tp, &ip->i_imap, &ibp);
if (error) if (error)
...@@ -2019,7 +2024,7 @@ xfs_iunlink_update_inode( ...@@ -2019,7 +2024,7 @@ xfs_iunlink_update_inode(
/* Make sure the old pointer isn't garbage. */ /* Make sure the old pointer isn't garbage. */
old_value = be32_to_cpu(dip->di_next_unlinked); old_value = be32_to_cpu(dip->di_next_unlinked);
if (!xfs_verify_agino_or_null(mp, agno, old_value)) { if (!xfs_verify_agino_or_null(mp, pag->pag_agno, old_value)) {
xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip, xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip,
sizeof(*dip), __this_address); sizeof(*dip), __this_address);
error = -EFSCORRUPTED; error = -EFSCORRUPTED;
...@@ -2042,7 +2047,7 @@ xfs_iunlink_update_inode( ...@@ -2042,7 +2047,7 @@ xfs_iunlink_update_inode(
} }
/* Ok, update the new pointer. */ /* Ok, update the new pointer. */
xfs_iunlink_update_dinode(tp, agno, XFS_INO_TO_AGINO(mp, ip->i_ino), xfs_iunlink_update_dinode(tp, pag, XFS_INO_TO_AGINO(mp, ip->i_ino),
ibp, dip, &ip->i_imap, next_agino); ibp, dip, &ip->i_imap, next_agino);
return 0; return 0;
out: out:
...@@ -2063,10 +2068,10 @@ xfs_iunlink( ...@@ -2063,10 +2068,10 @@ xfs_iunlink(
struct xfs_inode *ip) struct xfs_inode *ip)
{ {
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
struct xfs_perag *pag;
struct xfs_agi *agi; struct xfs_agi *agi;
struct xfs_buf *agibp; struct xfs_buf *agibp;
xfs_agino_t next_agino; xfs_agino_t next_agino;
xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ip->i_ino);
xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino); xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
short bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS; short bucket_index = agino % XFS_AGI_UNLINKED_BUCKETS;
int error; int error;
...@@ -2075,10 +2080,12 @@ xfs_iunlink( ...@@ -2075,10 +2080,12 @@ xfs_iunlink(
ASSERT(VFS_I(ip)->i_mode != 0); ASSERT(VFS_I(ip)->i_mode != 0);
trace_xfs_iunlink(ip); 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. */ /* Get the agi buffer first. It ensures lock ordering on the list. */
error = xfs_read_agi(mp, tp, agno, &agibp); error = xfs_read_agi(mp, tp, pag->pag_agno, &agibp);
if (error) if (error)
return error; goto out;
agi = agibp->b_addr; agi = agibp->b_addr;
/* /*
...@@ -2088,9 +2095,10 @@ xfs_iunlink( ...@@ -2088,9 +2095,10 @@ xfs_iunlink(
*/ */
next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); next_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]);
if (next_agino == agino || if (next_agino == agino ||
!xfs_verify_agino_or_null(mp, agno, next_agino)) { !xfs_verify_agino_or_null(mp, pag->pag_agno, next_agino)) {
xfs_buf_mark_corrupt(agibp); xfs_buf_mark_corrupt(agibp);
return -EFSCORRUPTED; error = -EFSCORRUPTED;
goto out;
} }
if (next_agino != NULLAGINO) { if (next_agino != NULLAGINO) {
...@@ -2100,23 +2108,26 @@ xfs_iunlink( ...@@ -2100,23 +2108,26 @@ xfs_iunlink(
* There is already another inode in the bucket, so point this * There is already another inode in the bucket, so point this
* inode to the current head of the list. * inode to the current head of the list.
*/ */
error = xfs_iunlink_update_inode(tp, ip, agno, next_agino, error = xfs_iunlink_update_inode(tp, ip, pag, next_agino,
&old_agino); &old_agino);
if (error) if (error)
return error; goto out;
ASSERT(old_agino == NULLAGINO); ASSERT(old_agino == NULLAGINO);
/* /*
* agino has been unlinked, add a backref from the next inode * agino has been unlinked, add a backref from the next inode
* back to agino. * back to agino.
*/ */
error = xfs_iunlink_add_backref(agibp->b_pag, agino, next_agino); error = xfs_iunlink_add_backref(pag, agino, next_agino);
if (error) if (error)
return error; goto out;
} }
/* Point the head of the list to point to this inode. */ /* Point the head of the list to point to this inode. */
return xfs_iunlink_update_bucket(tp, agno, agibp, bucket_index, agino); error = xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index, agino);
out:
xfs_perag_put(pag);
return error;
} }
/* Return the imap, dinode pointer, and buffer for an inode. */ /* Return the imap, dinode pointer, and buffer for an inode. */
...@@ -2164,14 +2175,13 @@ xfs_iunlink_map_ino( ...@@ -2164,14 +2175,13 @@ xfs_iunlink_map_ino(
STATIC int STATIC int
xfs_iunlink_map_prev( xfs_iunlink_map_prev(
struct xfs_trans *tp, struct xfs_trans *tp,
xfs_agnumber_t agno, struct xfs_perag *pag,
xfs_agino_t head_agino, xfs_agino_t head_agino,
xfs_agino_t target_agino, xfs_agino_t target_agino,
xfs_agino_t *agino, xfs_agino_t *agino,
struct xfs_imap *imap, struct xfs_imap *imap,
struct xfs_dinode **dipp, struct xfs_dinode **dipp,
struct xfs_buf **bpp, struct xfs_buf **bpp)
struct xfs_perag *pag)
{ {
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
xfs_agino_t next_agino; xfs_agino_t next_agino;
...@@ -2183,7 +2193,8 @@ xfs_iunlink_map_prev( ...@@ -2183,7 +2193,8 @@ xfs_iunlink_map_prev(
/* See if our backref cache can find it faster. */ /* See if our backref cache can find it faster. */
*agino = xfs_iunlink_lookup_backref(pag, target_agino); *agino = xfs_iunlink_lookup_backref(pag, target_agino);
if (*agino != NULLAGINO) { if (*agino != NULLAGINO) {
error = xfs_iunlink_map_ino(tp, agno, *agino, imap, dipp, bpp); error = xfs_iunlink_map_ino(tp, pag->pag_agno, *agino, imap,
dipp, bpp);
if (error) if (error)
return error; return error;
...@@ -2199,7 +2210,7 @@ xfs_iunlink_map_prev( ...@@ -2199,7 +2210,7 @@ xfs_iunlink_map_prev(
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
} }
trace_xfs_iunlink_map_prev_fallback(mp, agno); trace_xfs_iunlink_map_prev_fallback(mp, pag->pag_agno);
/* Otherwise, walk the entire bucket until we find it. */ /* Otherwise, walk the entire bucket until we find it. */
next_agino = head_agino; next_agino = head_agino;
...@@ -2210,8 +2221,8 @@ xfs_iunlink_map_prev( ...@@ -2210,8 +2221,8 @@ xfs_iunlink_map_prev(
xfs_trans_brelse(tp, *bpp); xfs_trans_brelse(tp, *bpp);
*agino = next_agino; *agino = next_agino;
error = xfs_iunlink_map_ino(tp, agno, next_agino, imap, dipp, error = xfs_iunlink_map_ino(tp, pag->pag_agno, next_agino, imap,
bpp); dipp, bpp);
if (error) if (error)
return error; return error;
...@@ -2220,7 +2231,7 @@ xfs_iunlink_map_prev( ...@@ -2220,7 +2231,7 @@ xfs_iunlink_map_prev(
* Make sure this pointer is valid and isn't an obvious * Make sure this pointer is valid and isn't an obvious
* infinite loop. * infinite loop.
*/ */
if (!xfs_verify_agino(mp, agno, unlinked_agino) || if (!xfs_verify_agino(mp, pag->pag_agno, unlinked_agino) ||
next_agino == unlinked_agino) { next_agino == unlinked_agino) {
XFS_CORRUPTION_ERROR(__func__, XFS_CORRUPTION_ERROR(__func__,
XFS_ERRLEVEL_LOW, mp, XFS_ERRLEVEL_LOW, mp,
...@@ -2240,6 +2251,7 @@ xfs_iunlink_map_prev( ...@@ -2240,6 +2251,7 @@ xfs_iunlink_map_prev(
STATIC int STATIC int
xfs_iunlink_remove( xfs_iunlink_remove(
struct xfs_trans *tp, struct xfs_trans *tp,
struct xfs_perag *pag,
struct xfs_inode *ip) struct xfs_inode *ip)
{ {
struct xfs_mount *mp = tp->t_mountp; struct xfs_mount *mp = tp->t_mountp;
...@@ -2247,7 +2259,6 @@ xfs_iunlink_remove( ...@@ -2247,7 +2259,6 @@ xfs_iunlink_remove(
struct xfs_buf *agibp; struct xfs_buf *agibp;
struct xfs_buf *last_ibp; struct xfs_buf *last_ibp;
struct xfs_dinode *last_dip = NULL; struct xfs_dinode *last_dip = NULL;
xfs_agnumber_t agno = XFS_INO_TO_AGNO(mp, ip->i_ino);
xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino); xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
xfs_agino_t next_agino; xfs_agino_t next_agino;
xfs_agino_t head_agino; xfs_agino_t head_agino;
...@@ -2257,7 +2268,7 @@ xfs_iunlink_remove( ...@@ -2257,7 +2268,7 @@ xfs_iunlink_remove(
trace_xfs_iunlink_remove(ip); trace_xfs_iunlink_remove(ip);
/* Get the agi buffer first. It ensures lock ordering on the list. */ /* Get the agi buffer first. It ensures lock ordering on the list. */
error = xfs_read_agi(mp, tp, agno, &agibp); error = xfs_read_agi(mp, tp, pag->pag_agno, &agibp);
if (error) if (error)
return error; return error;
agi = agibp->b_addr; agi = agibp->b_addr;
...@@ -2267,7 +2278,7 @@ xfs_iunlink_remove( ...@@ -2267,7 +2278,7 @@ xfs_iunlink_remove(
* go on. Make sure the head pointer isn't garbage. * go on. Make sure the head pointer isn't garbage.
*/ */
head_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]); head_agino = be32_to_cpu(agi->agi_unlinked[bucket_index]);
if (!xfs_verify_agino(mp, agno, head_agino)) { if (!xfs_verify_agino(mp, pag->pag_agno, head_agino)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
agi, sizeof(*agi)); agi, sizeof(*agi));
return -EFSCORRUPTED; return -EFSCORRUPTED;
...@@ -2278,7 +2289,7 @@ xfs_iunlink_remove( ...@@ -2278,7 +2289,7 @@ xfs_iunlink_remove(
* the old pointer value so that we can update whatever was previous * the old pointer value so that we can update whatever was previous
* to us in the list to point to whatever was next in the list. * to us in the list to point to whatever was next in the list.
*/ */
error = xfs_iunlink_update_inode(tp, ip, agno, NULLAGINO, &next_agino); error = xfs_iunlink_update_inode(tp, ip, pag, NULLAGINO, &next_agino);
if (error) if (error)
return error; return error;
...@@ -2290,8 +2301,7 @@ xfs_iunlink_remove( ...@@ -2290,8 +2301,7 @@ xfs_iunlink_remove(
* this inode's backref to point from the next inode. * this inode's backref to point from the next inode.
*/ */
if (next_agino != NULLAGINO) { if (next_agino != NULLAGINO) {
error = xfs_iunlink_change_backref(agibp->b_pag, next_agino, error = xfs_iunlink_change_backref(pag, next_agino, NULLAGINO);
NULLAGINO);
if (error) if (error)
return error; return error;
} }
...@@ -2301,14 +2311,13 @@ xfs_iunlink_remove( ...@@ -2301,14 +2311,13 @@ xfs_iunlink_remove(
xfs_agino_t prev_agino; xfs_agino_t prev_agino;
/* We need to search the list for the inode being freed. */ /* We need to search the list for the inode being freed. */
error = xfs_iunlink_map_prev(tp, agno, head_agino, agino, error = xfs_iunlink_map_prev(tp, pag, head_agino, agino,
&prev_agino, &imap, &last_dip, &last_ibp, &prev_agino, &imap, &last_dip, &last_ibp);
agibp->b_pag);
if (error) if (error)
return error; return error;
/* Point the previous inode on the list to the next inode. */ /* Point the previous inode on the list to the next inode. */
xfs_iunlink_update_dinode(tp, agno, prev_agino, last_ibp, xfs_iunlink_update_dinode(tp, pag, prev_agino, last_ibp,
last_dip, &imap, next_agino); last_dip, &imap, next_agino);
/* /*
...@@ -2324,7 +2333,7 @@ xfs_iunlink_remove( ...@@ -2324,7 +2333,7 @@ xfs_iunlink_remove(
} }
/* Point the head of the list to the next unlinked inode. */ /* Point the head of the list to the next unlinked inode. */
return xfs_iunlink_update_bucket(tp, agno, agibp, bucket_index, return xfs_iunlink_update_bucket(tp, pag, agibp, bucket_index,
next_agino); next_agino);
} }
...@@ -2335,12 +2344,11 @@ xfs_iunlink_remove( ...@@ -2335,12 +2344,11 @@ xfs_iunlink_remove(
*/ */
static void static void
xfs_ifree_mark_inode_stale( xfs_ifree_mark_inode_stale(
struct xfs_buf *bp, struct xfs_perag *pag,
struct xfs_inode *free_ip, struct xfs_inode *free_ip,
xfs_ino_t inum) xfs_ino_t inum)
{ {
struct xfs_mount *mp = bp->b_mount; struct xfs_mount *mp = pag->pag_mount;
struct xfs_perag *pag = bp->b_pag;
struct xfs_inode_log_item *iip; struct xfs_inode_log_item *iip;
struct xfs_inode *ip; struct xfs_inode *ip;
...@@ -2430,10 +2438,11 @@ xfs_ifree_mark_inode_stale( ...@@ -2430,10 +2438,11 @@ xfs_ifree_mark_inode_stale(
* inodes that are in memory - they all must be marked stale and attached to * inodes that are in memory - they all must be marked stale and attached to
* the cluster buffer. * the cluster buffer.
*/ */
STATIC int static int
xfs_ifree_cluster( xfs_ifree_cluster(
struct xfs_inode *free_ip,
struct xfs_trans *tp, struct xfs_trans *tp,
struct xfs_perag *pag,
struct xfs_inode *free_ip,
struct xfs_icluster *xic) struct xfs_icluster *xic)
{ {
struct xfs_mount *mp = free_ip->i_mount; struct xfs_mount *mp = free_ip->i_mount;
...@@ -2495,7 +2504,7 @@ xfs_ifree_cluster( ...@@ -2495,7 +2504,7 @@ xfs_ifree_cluster(
* already marked XFS_ISTALE. * already marked XFS_ISTALE.
*/ */
for (i = 0; i < igeo->inodes_per_cluster; i++) for (i = 0; i < igeo->inodes_per_cluster; i++)
xfs_ifree_mark_inode_stale(bp, free_ip, inum + i); xfs_ifree_mark_inode_stale(pag, free_ip, inum + i);
xfs_trans_stale_inode_buf(tp, bp); xfs_trans_stale_inode_buf(tp, bp);
xfs_trans_binval(tp, bp); xfs_trans_binval(tp, bp);
...@@ -2518,9 +2527,11 @@ xfs_ifree( ...@@ -2518,9 +2527,11 @@ xfs_ifree(
struct xfs_trans *tp, struct xfs_trans *tp,
struct xfs_inode *ip) struct xfs_inode *ip)
{ {
int error; struct xfs_mount *mp = ip->i_mount;
struct xfs_perag *pag;
struct xfs_icluster xic = { 0 }; struct xfs_icluster xic = { 0 };
struct xfs_inode_log_item *iip = ip->i_itemp; struct xfs_inode_log_item *iip = ip->i_itemp;
int error;
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
ASSERT(VFS_I(ip)->i_nlink == 0); ASSERT(VFS_I(ip)->i_nlink == 0);
...@@ -2528,16 +2539,18 @@ xfs_ifree( ...@@ -2528,16 +2539,18 @@ xfs_ifree(
ASSERT(ip->i_disk_size == 0 || !S_ISREG(VFS_I(ip)->i_mode)); ASSERT(ip->i_disk_size == 0 || !S_ISREG(VFS_I(ip)->i_mode));
ASSERT(ip->i_nblocks == 0); ASSERT(ip->i_nblocks == 0);
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
/* /*
* Pull the on-disk inode from the AGI unlinked list. * Pull the on-disk inode from the AGI unlinked list.
*/ */
error = xfs_iunlink_remove(tp, ip); error = xfs_iunlink_remove(tp, pag, ip);
if (error) if (error)
return error; goto out;
error = xfs_difree(tp, ip->i_ino, &xic); error = xfs_difree(tp, pag, ip->i_ino, &xic);
if (error) if (error)
return error; goto out;
/* /*
* Free any local-format data sitting around before we reset the * Free any local-format data sitting around before we reset the
...@@ -2552,7 +2565,7 @@ xfs_ifree( ...@@ -2552,7 +2565,7 @@ xfs_ifree(
VFS_I(ip)->i_mode = 0; /* mark incore inode as free */ VFS_I(ip)->i_mode = 0; /* mark incore inode as free */
ip->i_diflags = 0; ip->i_diflags = 0;
ip->i_diflags2 = ip->i_mount->m_ino_geo.new_diflags2; ip->i_diflags2 = mp->m_ino_geo.new_diflags2;
ip->i_forkoff = 0; /* mark the attr fork not in use */ ip->i_forkoff = 0; /* mark the attr fork not in use */
ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS; ip->i_df.if_format = XFS_DINODE_FMT_EXTENTS;
if (xfs_iflags_test(ip, XFS_IPRESERVE_DM_FIELDS)) if (xfs_iflags_test(ip, XFS_IPRESERVE_DM_FIELDS))
...@@ -2571,8 +2584,9 @@ xfs_ifree( ...@@ -2571,8 +2584,9 @@ xfs_ifree(
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
if (xic.deleted) if (xic.deleted)
error = xfs_ifree_cluster(ip, tp, &xic); error = xfs_ifree_cluster(tp, pag, ip, &xic);
out:
xfs_perag_put(pag);
return error; return error;
} }
...@@ -3176,8 +3190,13 @@ xfs_rename( ...@@ -3176,8 +3190,13 @@ xfs_rename(
* in future. * in future.
*/ */
if (wip) { if (wip) {
struct xfs_perag *pag;
ASSERT(VFS_I(wip)->i_nlink == 0); ASSERT(VFS_I(wip)->i_nlink == 0);
error = xfs_iunlink_remove(tp, wip);
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, wip->i_ino));
error = xfs_iunlink_remove(tp, pag, wip);
xfs_perag_put(pag);
if (error) if (error)
goto out_trans_cancel; goto out_trans_cancel;
......
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