diff options
Diffstat (limited to 'fs/xfs/xfs_iget.c')
| -rw-r--r-- | fs/xfs/xfs_iget.c | 35 |
1 files changed, 14 insertions, 21 deletions
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index d3da00045f26..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" |
| @@ -505,17 +507,15 @@ xfs_iget( | |||
| 505 | vnode_t *vp = NULL; | 507 | vnode_t *vp = NULL; |
| 506 | int error; | 508 | int error; |
| 507 | 509 | ||
| 508 | retry: | ||
| 509 | XFS_STATS_INC(xs_ig_attempts); | 510 | XFS_STATS_INC(xs_ig_attempts); |
| 510 | 511 | ||
| 512 | retry: | ||
| 511 | if ((inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino))) { | 513 | if ((inode = iget_locked(XFS_MTOVFS(mp)->vfs_super, ino))) { |
| 512 | bhv_desc_t *bdp; | 514 | bhv_desc_t *bdp; |
| 513 | xfs_inode_t *ip; | 515 | xfs_inode_t *ip; |
| 514 | int newnode; | ||
| 515 | 516 | ||
| 516 | vp = LINVFS_GET_VP(inode); | 517 | vp = LINVFS_GET_VP(inode); |
| 517 | if (inode->i_state & I_NEW) { | 518 | if (inode->i_state & I_NEW) { |
| 518 | inode_allocate: | ||
| 519 | vn_initialize(inode); | 519 | vn_initialize(inode); |
| 520 | error = xfs_iget_core(vp, mp, tp, ino, flags, | 520 | error = xfs_iget_core(vp, mp, tp, ino, flags, |
| 521 | lock_flags, ipp, bno); | 521 | lock_flags, ipp, bno); |
| @@ -526,32 +526,25 @@ inode_allocate: | |||
| 526 | iput(inode); | 526 | iput(inode); |
| 527 | } | 527 | } |
| 528 | } else { | 528 | } else { |
| 529 | /* These are true if the inode is in inactive or | 529 | /* |
| 530 | * reclaim. The linux inode is about to go away, | 530 | * If the inode is not fully constructed due to |
| 531 | * wait for that path to finish, and try again. | 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. | ||
| 532 | */ | 536 | */ |
| 533 | if (vp->v_flag & (VINACT | VRECLM)) { | 537 | if (is_bad_inode(inode) || |
| 534 | vn_wait(vp); | 538 | ((bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), |
| 539 | &xfs_vnodeops)) == NULL)) { | ||
| 535 | iput(inode); | 540 | iput(inode); |
| 541 | delay(1); | ||
| 536 | goto retry; | 542 | goto retry; |
| 537 | } | 543 | } |
| 538 | 544 | ||
| 539 | if (is_bad_inode(inode)) { | ||
| 540 | iput(inode); | ||
| 541 | return EIO; | ||
| 542 | } | ||
| 543 | |||
| 544 | bdp = vn_bhv_lookup(VN_BHV_HEAD(vp), &xfs_vnodeops); | ||
| 545 | if (bdp == NULL) { | ||
| 546 | XFS_STATS_INC(xs_ig_dup); | ||
| 547 | goto inode_allocate; | ||
| 548 | } | ||
| 549 | ip = XFS_BHVTOI(bdp); | 545 | ip = XFS_BHVTOI(bdp); |
| 550 | if (lock_flags != 0) | 546 | if (lock_flags != 0) |
| 551 | xfs_ilock(ip, lock_flags); | 547 | xfs_ilock(ip, lock_flags); |
| 552 | newnode = (ip->i_d.di_mode == 0); | ||
| 553 | if (newnode) | ||
| 554 | xfs_iocore_inode_reinit(ip); | ||
| 555 | XFS_STATS_INC(xs_ig_found); | 548 | XFS_STATS_INC(xs_ig_found); |
| 556 | *ipp = ip; | 549 | *ipp = ip; |
| 557 | error = 0; | 550 | error = 0; |
