diff options
author | David Chinner <dgc@sgi.com> | 2008-03-05 21:43:49 -0500 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-04-17 21:37:41 -0400 |
commit | bad5584332e888ac40ca13584e8c114149ddb01e (patch) | |
tree | f66ff83686cd28967d8b9fc0a8b8d6411a081071 /fs/xfs/xfs_iget.c | |
parent | a3f74ffb6d1448d9a8f482e593b80ec15f1695d4 (diff) |
[XFS] Remove the xfs_icluster structure
Remove the xfs_icluster structure and replace with a radix tree lookup.
We don't need to keep a list of inodes in each cluster around anymore as
we can look them up quickly when we need to. The only time we need to do
this now is during inode writeback.
Factor the inode cluster writeback code out of xfs_iflush and convert it
to use radix_tree_gang_lookup() instead of walking a list of inodes built
when we first read in the inodes.
This remove 3 pointers from each xfs_inode structure and the xfs_icluster
structure per inode cluster. Hence we reduce the cache footprint of the
xfs_inodes by between 5-10% depending on cluster sparseness.
To be truly efficient we need a radix_tree_gang_lookup_range() call to
stop searching once we are past the end of the cluster instead of trying
to find a full cluster's worth of inodes.
Before (ia64):
$ cat /sys/slab/xfs_inode/object_size 536
After:
$ cat /sys/slab/xfs_inode/object_size 512
SGI-PV: 977460
SGI-Modid: xfs-linux-melb:xfs-kern:30502a
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_iget.c')
-rw-r--r-- | fs/xfs/xfs_iget.c | 49 |
1 files changed, 3 insertions, 46 deletions
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 8e09b71f4104..e657c5128460 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -78,7 +78,6 @@ xfs_iget_core( | |||
78 | xfs_inode_t *ip; | 78 | xfs_inode_t *ip; |
79 | xfs_inode_t *iq; | 79 | xfs_inode_t *iq; |
80 | int error; | 80 | int error; |
81 | xfs_icluster_t *icl, *new_icl = NULL; | ||
82 | unsigned long first_index, mask; | 81 | unsigned long first_index, mask; |
83 | xfs_perag_t *pag; | 82 | xfs_perag_t *pag; |
84 | xfs_agino_t agino; | 83 | xfs_agino_t agino; |
@@ -229,11 +228,9 @@ finish_inode: | |||
229 | } | 228 | } |
230 | 229 | ||
231 | /* | 230 | /* |
232 | * This is a bit messy - we preallocate everything we _might_ | 231 | * Preload the radix tree so we can insert safely under the |
233 | * need before we pick up the ici lock. That way we don't have to | 232 | * write spinlock. |
234 | * juggle locks and go all the way back to the start. | ||
235 | */ | 233 | */ |
236 | new_icl = kmem_zone_alloc(xfs_icluster_zone, KM_SLEEP); | ||
237 | if (radix_tree_preload(GFP_KERNEL)) { | 234 | if (radix_tree_preload(GFP_KERNEL)) { |
238 | xfs_idestroy(ip); | 235 | xfs_idestroy(ip); |
239 | delay(1); | 236 | delay(1); |
@@ -242,17 +239,6 @@ finish_inode: | |||
242 | mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1); | 239 | mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1); |
243 | first_index = agino & mask; | 240 | first_index = agino & mask; |
244 | write_lock(&pag->pag_ici_lock); | 241 | write_lock(&pag->pag_ici_lock); |
245 | |||
246 | /* | ||
247 | * Find the cluster if it exists | ||
248 | */ | ||
249 | icl = NULL; | ||
250 | if (radix_tree_gang_lookup(&pag->pag_ici_root, (void**)&iq, | ||
251 | first_index, 1)) { | ||
252 | if ((XFS_INO_TO_AGINO(mp, iq->i_ino) & mask) == first_index) | ||
253 | icl = iq->i_cluster; | ||
254 | } | ||
255 | |||
256 | /* | 242 | /* |
257 | * insert the new inode | 243 | * insert the new inode |
258 | */ | 244 | */ |
@@ -267,30 +253,13 @@ finish_inode: | |||
267 | } | 253 | } |
268 | 254 | ||
269 | /* | 255 | /* |
270 | * These values _must_ be set before releasing ihlock! | 256 | * These values _must_ be set before releasing the radix tree lock! |
271 | */ | 257 | */ |
272 | ip->i_udquot = ip->i_gdquot = NULL; | 258 | ip->i_udquot = ip->i_gdquot = NULL; |
273 | xfs_iflags_set(ip, XFS_INEW); | 259 | xfs_iflags_set(ip, XFS_INEW); |
274 | 260 | ||
275 | ASSERT(ip->i_cluster == NULL); | ||
276 | |||
277 | if (!icl) { | ||
278 | spin_lock_init(&new_icl->icl_lock); | ||
279 | INIT_HLIST_HEAD(&new_icl->icl_inodes); | ||
280 | icl = new_icl; | ||
281 | new_icl = NULL; | ||
282 | } else { | ||
283 | ASSERT(!hlist_empty(&icl->icl_inodes)); | ||
284 | } | ||
285 | spin_lock(&icl->icl_lock); | ||
286 | hlist_add_head(&ip->i_cnode, &icl->icl_inodes); | ||
287 | ip->i_cluster = icl; | ||
288 | spin_unlock(&icl->icl_lock); | ||
289 | |||
290 | write_unlock(&pag->pag_ici_lock); | 261 | write_unlock(&pag->pag_ici_lock); |
291 | radix_tree_preload_end(); | 262 | radix_tree_preload_end(); |
292 | if (new_icl) | ||
293 | kmem_zone_free(xfs_icluster_zone, new_icl); | ||
294 | 263 | ||
295 | /* | 264 | /* |
296 | * Link ip to its mount and thread it on the mount's inode list. | 265 | * Link ip to its mount and thread it on the mount's inode list. |
@@ -529,18 +498,6 @@ xfs_iextract( | |||
529 | xfs_put_perag(mp, pag); | 498 | xfs_put_perag(mp, pag); |
530 | 499 | ||
531 | /* | 500 | /* |
532 | * Remove from cluster list | ||
533 | */ | ||
534 | mp = ip->i_mount; | ||
535 | spin_lock(&ip->i_cluster->icl_lock); | ||
536 | hlist_del(&ip->i_cnode); | ||
537 | spin_unlock(&ip->i_cluster->icl_lock); | ||
538 | |||
539 | /* was last inode in cluster? */ | ||
540 | if (hlist_empty(&ip->i_cluster->icl_inodes)) | ||
541 | kmem_zone_free(xfs_icluster_zone, ip->i_cluster); | ||
542 | |||
543 | /* | ||
544 | * Remove from mount's inode list. | 501 | * Remove from mount's inode list. |
545 | */ | 502 | */ |
546 | XFS_MOUNT_ILOCK(mp); | 503 | XFS_MOUNT_ILOCK(mp); |