xfs: simplify and remove xfs_ireclaim
xfs_ireclaim has to get and put te pag structure because it is only called with the inode to reclaim. The one caller of this function already has a reference on the pag and a pointer to is, so move the radix tree delete to the caller and remove xfs_ireclaim completely. This avoids a xfs_perag_get/put on every inode being reclaimed. The overhead was noticed in a bug report at: https://bugzilla.kernel.org/show_bug.cgi?id=16348 Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Alex Elder <aelder@sgi.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
parent
ec53d1dbb3
commit
2f11feabb1
@ -855,7 +855,36 @@ xfs_reclaim_inode(
|
|||||||
reclaim:
|
reclaim:
|
||||||
xfs_ifunlock(ip);
|
xfs_ifunlock(ip);
|
||||||
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
xfs_iunlock(ip, XFS_ILOCK_EXCL);
|
||||||
xfs_ireclaim(ip);
|
|
||||||
|
XFS_STATS_INC(xs_ig_reclaims);
|
||||||
|
/*
|
||||||
|
* Remove the inode from the per-AG radix tree.
|
||||||
|
*
|
||||||
|
* Because radix_tree_delete won't complain even if the item was never
|
||||||
|
* added to the tree assert that it's been there before to catch
|
||||||
|
* problems with the inode life time early on.
|
||||||
|
*/
|
||||||
|
write_lock(&pag->pag_ici_lock);
|
||||||
|
if (!radix_tree_delete(&pag->pag_ici_root,
|
||||||
|
XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino)))
|
||||||
|
ASSERT(0);
|
||||||
|
write_unlock(&pag->pag_ici_lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here we do an (almost) spurious inode lock in order to coordinate
|
||||||
|
* with inode cache radix tree lookups. This is because the lookup
|
||||||
|
* can reference the inodes in the cache without taking references.
|
||||||
|
*
|
||||||
|
* We make that OK here by ensuring that we wait until the inode is
|
||||||
|
* unlocked after the lookup before we go ahead and free it. We get
|
||||||
|
* both the ilock and the iolock because the code may need to drop the
|
||||||
|
* ilock one but will still hold the iolock.
|
||||||
|
*/
|
||||||
|
xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
|
||||||
|
xfs_qm_dqdetach(ip);
|
||||||
|
xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
|
||||||
|
|
||||||
|
xfs_inode_free(ip);
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ xfs_inode_alloc(
|
|||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void
|
void
|
||||||
xfs_inode_free(
|
xfs_inode_free(
|
||||||
struct xfs_inode *ip)
|
struct xfs_inode *ip)
|
||||||
{
|
{
|
||||||
@ -417,57 +417,6 @@ xfs_iget(
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* This is called free all the memory associated with an inode.
|
|
||||||
* It must free the inode itself and any buffers allocated for
|
|
||||||
* if_extents/if_data and if_broot. It must also free the lock
|
|
||||||
* associated with the inode.
|
|
||||||
*
|
|
||||||
* Note: because we don't initialise everything on reallocation out
|
|
||||||
* of the zone, we must ensure we nullify everything correctly before
|
|
||||||
* freeing the structure.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
xfs_ireclaim(
|
|
||||||
struct xfs_inode *ip)
|
|
||||||
{
|
|
||||||
struct xfs_mount *mp = ip->i_mount;
|
|
||||||
struct xfs_perag *pag;
|
|
||||||
xfs_agino_t agino = XFS_INO_TO_AGINO(mp, ip->i_ino);
|
|
||||||
|
|
||||||
XFS_STATS_INC(xs_ig_reclaims);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Remove the inode from the per-AG radix tree.
|
|
||||||
*
|
|
||||||
* Because radix_tree_delete won't complain even if the item was never
|
|
||||||
* added to the tree assert that it's been there before to catch
|
|
||||||
* problems with the inode life time early on.
|
|
||||||
*/
|
|
||||||
pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
|
|
||||||
write_lock(&pag->pag_ici_lock);
|
|
||||||
if (!radix_tree_delete(&pag->pag_ici_root, agino))
|
|
||||||
ASSERT(0);
|
|
||||||
write_unlock(&pag->pag_ici_lock);
|
|
||||||
xfs_perag_put(pag);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Here we do an (almost) spurious inode lock in order to coordinate
|
|
||||||
* with inode cache radix tree lookups. This is because the lookup
|
|
||||||
* can reference the inodes in the cache without taking references.
|
|
||||||
*
|
|
||||||
* We make that OK here by ensuring that we wait until the inode is
|
|
||||||
* unlocked after the lookup before we go ahead and free it. We get
|
|
||||||
* both the ilock and the iolock because the code may need to drop the
|
|
||||||
* ilock one but will still hold the iolock.
|
|
||||||
*/
|
|
||||||
xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
|
|
||||||
xfs_qm_dqdetach(ip);
|
|
||||||
xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
|
|
||||||
|
|
||||||
xfs_inode_free(ip);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a wrapper routine around the xfs_ilock() routine
|
* This is a wrapper routine around the xfs_ilock() routine
|
||||||
* used to centralize some grungy code. It is used in places
|
* used to centralize some grungy code. It is used in places
|
||||||
|
@ -450,7 +450,7 @@ void xfs_ilock_demote(xfs_inode_t *, uint);
|
|||||||
int xfs_isilocked(xfs_inode_t *, uint);
|
int xfs_isilocked(xfs_inode_t *, uint);
|
||||||
uint xfs_ilock_map_shared(xfs_inode_t *);
|
uint xfs_ilock_map_shared(xfs_inode_t *);
|
||||||
void xfs_iunlock_map_shared(xfs_inode_t *, uint);
|
void xfs_iunlock_map_shared(xfs_inode_t *, uint);
|
||||||
void xfs_ireclaim(xfs_inode_t *);
|
void xfs_inode_free(struct xfs_inode *ip);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* xfs_inode.c prototypes.
|
* xfs_inode.c prototypes.
|
||||||
|
Loading…
Reference in New Issue
Block a user