summaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@sgi.com>2005-09-05 08:33:00 +1000
committerNathan Scott <nathans@sgi.com>2005-09-05 08:33:00 +1000
commitba403ab43e896c57f32995ccba9a6bd6ec8dd1b9 (patch)
tree1262d9ec73d90bd4a73093cdd8afe8d2459dae72 /fs/xfs
parentefa092f3d4c60be7e81de515db9f06e5f8426afc (diff)
downloadlinux-ba403ab43e896c57f32995ccba9a6bd6ec8dd1b9.tar.gz
linux-ba403ab43e896c57f32995ccba9a6bd6ec8dd1b9.tar.bz2
linux-ba403ab43e896c57f32995ccba9a6bd6ec8dd1b9.zip
[XFS] Retry linux inode cacech lookup if we found a stale inode. This
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>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_iget.c28
1 files changed, 16 insertions, 12 deletions
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index fa796910f3aa..0d9ae8fb4138 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -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;