aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@sgi.com>2005-09-04 18:33:00 -0400
committerNathan Scott <nathans@sgi.com>2005-09-04 18:33:00 -0400
commitba403ab43e896c57f32995ccba9a6bd6ec8dd1b9 (patch)
tree1262d9ec73d90bd4a73093cdd8afe8d2459dae72
parentefa092f3d4c60be7e81de515db9f06e5f8426afc (diff)
[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>
-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 @@
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ 30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */ 31 */
32 32
33#include <linux/delay.h>
34
33#include "xfs.h" 35#include "xfs.h"
34 36
35#include "xfs_macros.h" 37#include "xfs_macros.h"
@@ -507,14 +509,13 @@ xfs_iget(
507 509
508 XFS_STATS_INC(xs_ig_attempts); 510 XFS_STATS_INC(xs_ig_attempts);
509 511
512retry:
510 if ((inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino))) { 513 if ((inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino))) {
511 bhv_desc_t *bdp; 514 bhv_desc_t *bdp;
512 xfs_inode_t *ip; 515 xfs_inode_t *ip;
513 int newnode;
514 516
515 vp = LINVFS_GET_VP(inode); 517 vp = LINVFS_GET_VP(inode);
516 if (inode->i_state & I_NEW) { 518 if (inode->i_state & I_NEW) {
517inode_allocate:
518 vn_initialize(inode); 519 vn_initialize(inode);
519 error = xfs_iget_core(vp, mp, tp, ino, flags, 520 error = xfs_iget_core(vp, mp, tp, ino, flags,
520 lock_flags, ipp, bno); 521 lock_flags, ipp, bno);
@@ -525,22 +526,25 @@ inode_allocate:
525 iput(inode); 526 iput(inode);
526 } 527 }
527 } else { 528 } else {
528 if (is_bad_inode(inode)) { 529 /*
530 * If the inode is not fully constructed due to
531 * filehandle mistmatches wait for the inode to go
532 * away and try again.
533 *
534 * iget_locked will call __wait_on_freeing_inode
535 * to wait for the inode to go away.
536 */
537 if (is_bad_inode(inode) ||
538 ((bdp = vn_bhv_lookup(VN_BHV_HEAD(vp),
539 &xfs_vnodeops)) == NULL)) {
529 iput(inode); 540 iput(inode);
530 return EIO; 541 delay(1);
542 goto retry;
531 } 543 }
532 544
533 bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops);
534 if (bdp == NULL) {
535 XFS_STATS_INC(xs_ig_dup);
536 goto inode_allocate;
537 }
538 ip = XFS_BHVTOI(bdp); 545 ip = XFS_BHVTOI(bdp);
539 if (lock_flags != 0) 546 if (lock_flags != 0)
540 xfs_ilock(ip, lock_flags); 547 xfs_ilock(ip, lock_flags);
541 newnode = (ip->i_d.di_mode == 0);
542 if (newnode)
543 xfs_iocore_inode_reinit(ip);
544 XFS_STATS_INC(xs_ig_found); 548 XFS_STATS_INC(xs_ig_found);
545 *ipp = ip; 549 *ipp = ip;
546 error = 0; 550 error = 0;