[XFS] Retry linux inode cacech lookup if we found a stale inode. This
authorChristoph Hellwig <hch@sgi.com>
Sun, 4 Sep 2005 22:33:00 +0000 (08:33 +1000)
committerNathan Scott <nathans@sgi.com>
Sun, 4 Sep 2005 22:33:00 +0000 (08:33 +1000)
fixes crashes under high nfs load

SGI-PV: 941429
SGI-Modid: xfs-linux:xfs-kern:197929a

Signed-off-by: Christoph Hellwig <hch@sgi.com>
Signed-off-by: Nathan Scott <nathans@sgi.com>
fs/xfs/xfs_iget.c

index fa79691..0d9ae8f 100644 (file)
@@ -30,6 +30,8 @@
  * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
  */
 
+#include <linux/delay.h>
+
 #include "xfs.h"
 
 #include "xfs_macros.h"
@@ -507,14 +509,13 @@ xfs_iget(
 
        XFS_STATS_INC(xs_ig_attempts);
 
+retry:
        if ((inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino))) {
                bhv_desc_t      *bdp;
                xfs_inode_t     *ip;
-               int             newnode;
 
                vp = LINVFS_GET_VP(inode);
                if (inode->i_state & I_NEW) {
-inode_allocate:
                        vn_initialize(inode);
                        error = xfs_iget_core(vp, mp, tp, ino, flags,
                                        lock_flags, ipp, bno);
@@ -525,22 +526,25 @@ inode_allocate:
                                iput(inode);
                        }
                } else {
-                       if (is_bad_inode(inode)) {
+                       /*
+                        * If the inode is not fully constructed due to
+                        * filehandle mistmatches wait for the inode to go
+                        * away and try again.
+                        *
+                        * iget_locked will call __wait_on_freeing_inode
+                        * to wait for the inode to go away.
+                        */
+                       if (is_bad_inode(inode) ||
+                           ((bdp = vn_bhv_lookup(VN_BHV_HEAD(vp),
+                                                 &xfs_vnodeops)) == NULL)) {
                                iput(inode);
-                               return EIO;
+                               delay(1);
+                               goto retry;
                        }
 
-                       bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops);
-                       if (bdp == NULL) {
-                               XFS_STATS_INC(xs_ig_dup);
-                               goto inode_allocate;
-                       }
                        ip = XFS_BHVTOI(bdp);
                        if (lock_flags != 0)
                                xfs_ilock(ip, lock_flags);
-                       newnode = (ip->i_d.di_mode == 0);
-                       if (newnode)
-                               xfs_iocore_inode_reinit(ip);
                        XFS_STATS_INC(xs_ig_found);
                        *ipp = ip;
                        error = 0;