Commit 71bce256bf2e2aaddf54a2f4ac216329c74be3ad

Authored by Nathan Scott
Committed by Christoph Hellwig
1 parent bfd4bda097

[XFS] Move the XFS inode to the front of its hash list on a cache hit

SGI Modid: xfs-linux:xfs-kern:21915a

Signed-off-by: Nathan Scott <nathans@sgi.com>
Signed-off-by: Christoph Hellwig <hch@sgi.com>

Showing 1 changed file with 50 additions and 1 deletions Side-by-side Diff

... ... @@ -136,6 +136,40 @@
136 136 }
137 137  
138 138 /*
  139 + * Try to move an inode to the front of its hash list if possible
  140 + * (and if its not there already). Called right after obtaining
  141 + * the list version number and then dropping the read_lock on the
  142 + * hash list in question (which is done right after looking up the
  143 + * inode in question...).
  144 + */
  145 +STATIC void
  146 +xfs_ihash_promote(
  147 + xfs_ihash_t *ih,
  148 + xfs_inode_t *ip,
  149 + ulong version)
  150 +{
  151 + xfs_inode_t *iq;
  152 +
  153 + if ((ip->i_prevp != &ih->ih_next) && write_trylock(&ih->ih_lock)) {
  154 + if (likely(version == ih->ih_version)) {
  155 + /* remove from list */
  156 + if ((iq = ip->i_next)) {
  157 + iq->i_prevp = ip->i_prevp;
  158 + }
  159 + *ip->i_prevp = iq;
  160 +
  161 + /* insert at list head */
  162 + iq = ih->ih_next;
  163 + iq->i_prevp = &ip->i_next;
  164 + ip->i_next = iq;
  165 + ip->i_prevp = &ih->ih_next;
  166 + ih->ih_next = ip;
  167 + }
  168 + write_unlock(&ih->ih_lock);
  169 + }
  170 +}
  171 +
  172 +/*
139 173 * Look up an inode by number in the given file system.
140 174 * The inode is looked up in the hash table for the file system
141 175 * represented by the mount point parameter mp. Each bucket of
142 176  
... ... @@ -229,7 +263,9 @@
229 263 XFS_STATS_INC(xs_ig_found);
230 264  
231 265 ip->i_flags &= ~XFS_IRECLAIMABLE;
  266 + version = ih->ih_version;
232 267 read_unlock(&ih->ih_lock);
  268 + xfs_ihash_promote(ih, ip, version);
233 269  
234 270 XFS_MOUNT_ILOCK(mp);
235 271 list_del_init(&ip->i_reclaim);
236 272  
... ... @@ -259,8 +295,15 @@
259 295 inode_vp, vp);
260 296 }
261 297  
  298 + /*
  299 + * Inode cache hit: if ip is not at the front of
  300 + * its hash chain, move it there now.
  301 + * Do this with the lock held for update, but
  302 + * do statistics after releasing the lock.
  303 + */
  304 + version = ih->ih_version;
262 305 read_unlock(&ih->ih_lock);
263   -
  306 + xfs_ihash_promote(ih, ip, version);
264 307 XFS_STATS_INC(xs_ig_found);
265 308  
266 309 finish_inode:
... ... @@ -547,6 +590,7 @@
547 590 {
548 591 xfs_ihash_t *ih;
549 592 xfs_inode_t *ip;
  593 + ulong version;
550 594  
551 595 ih = XFS_IHASH(mp, ino);
552 596 read_lock(&ih->ih_lock);
553 597  
554 598  
... ... @@ -554,11 +598,15 @@
554 598 if (ip->i_ino == ino) {
555 599 /*
556 600 * If we find it and tp matches, return it.
  601 + * Also move it to the front of the hash list
  602 + * if we find it and it is not already there.
557 603 * Otherwise break from the loop and return
558 604 * NULL.
559 605 */
560 606 if (ip->i_transp == tp) {
  607 + version = ih->ih_version;
561 608 read_unlock(&ih->ih_lock);
  609 + xfs_ihash_promote(ih, ip, version);
562 610 return (ip);
563 611 }
564 612 break;
... ... @@ -685,6 +733,7 @@
685 733 iq->i_prevp = ip->i_prevp;
686 734 }
687 735 *ip->i_prevp = iq;
  736 + ih->ih_version++;
688 737 write_unlock(&ih->ih_lock);
689 738  
690 739 /*