155 lines
5.0 KiB
Diff
155 lines
5.0 KiB
Diff
From 5e6c711142fbc276226847de1abd988bfd367e88 Mon Sep 17 00:00:00 2001
|
|
From: Dave Chinner <dchinner@redhat.com>
|
|
Date: Tue, 20 Jul 2010 17:53:25 +1000
|
|
Subject: 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>
|
|
---
|
|
fs/xfs/linux-2.6/xfs_sync.c | 31 ++++++++++++++++++++++++-
|
|
fs/xfs/xfs_iget.c | 53 +------------------------------------------
|
|
fs/xfs/xfs_inode.h | 2 +-
|
|
3 files changed, 32 insertions(+), 54 deletions(-)
|
|
|
|
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
|
|
index b927a54..97275c5 100644
|
|
--- a/fs/xfs/linux-2.6/xfs_sync.c
|
|
+++ b/fs/xfs/linux-2.6/xfs_sync.c
|
|
@@ -908,7 +908,36 @@ out:
|
|
reclaim:
|
|
xfs_ifunlock(ip);
|
|
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;
|
|
|
|
}
|
|
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
|
|
index 6845db9..e4da0e1 100644
|
|
--- a/fs/xfs/xfs_iget.c
|
|
+++ b/fs/xfs/xfs_iget.c
|
|
@@ -95,7 +95,7 @@ xfs_inode_alloc(
|
|
return ip;
|
|
}
|
|
|
|
-STATIC void
|
|
+void
|
|
xfs_inode_free(
|
|
struct xfs_inode *ip)
|
|
{
|
|
@@ -469,57 +469,6 @@ xfs_iput_new(
|
|
}
|
|
|
|
/*
|
|
- * 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
|
|
* used to centralize some grungy code. It is used in places
|
|
* that wish to lock the inode solely for reading the extents.
|
|
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
|
|
index 9965e40..b418992 100644
|
|
--- a/fs/xfs/xfs_inode.h
|
|
+++ b/fs/xfs/xfs_inode.h
|
|
@@ -452,7 +452,7 @@ void xfs_ilock_demote(xfs_inode_t *, uint);
|
|
int xfs_isilocked(xfs_inode_t *, uint);
|
|
uint xfs_ilock_map_shared(xfs_inode_t *);
|
|
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.
|
|
--
|
|
1.7.3.2
|
|
|