aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_iget.c
diff options
context:
space:
mode:
authorDavid Chinner <dgc@sgi.com>2008-03-05 21:43:49 -0500
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>2008-04-17 21:37:41 -0400
commitbad5584332e888ac40ca13584e8c114149ddb01e (patch)
treef66ff83686cd28967d8b9fc0a8b8d6411a081071 /fs/xfs/xfs_iget.c
parenta3f74ffb6d1448d9a8f482e593b80ec15f1695d4 (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.c49
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);