diff options
Diffstat (limited to 'fs/xfs/xfs_inode.c')
| -rw-r--r-- | fs/xfs/xfs_inode.c | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 48146bdc6bdd..94b60dd03801 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
| @@ -2732,16 +2732,29 @@ xfs_iunpin( | |||
| 2732 | ASSERT(atomic_read(&ip->i_pincount) > 0); | 2732 | ASSERT(atomic_read(&ip->i_pincount) > 0); |
| 2733 | 2733 | ||
| 2734 | if (atomic_dec_and_test(&ip->i_pincount)) { | 2734 | if (atomic_dec_and_test(&ip->i_pincount)) { |
| 2735 | vnode_t *vp = XFS_ITOV_NULL(ip); | 2735 | /* |
| 2736 | * If the inode is currently being reclaimed, the | ||
| 2737 | * linux inode _and_ the xfs vnode may have been | ||
| 2738 | * freed so we cannot reference either of them safely. | ||
| 2739 | * Hence we should not try to do anything to them | ||
| 2740 | * if the xfs inode is currently in the reclaim | ||
| 2741 | * path. | ||
| 2742 | * | ||
| 2743 | * However, we still need to issue the unpin wakeup | ||
| 2744 | * call as the inode reclaim may be blocked waiting for | ||
| 2745 | * the inode to become unpinned. | ||
| 2746 | */ | ||
| 2747 | if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) { | ||
| 2748 | vnode_t *vp = XFS_ITOV_NULL(ip); | ||
| 2736 | 2749 | ||
| 2737 | /* make sync come back and flush this inode */ | 2750 | /* make sync come back and flush this inode */ |
| 2738 | if (vp) { | 2751 | if (vp) { |
| 2739 | struct inode *inode = vn_to_inode(vp); | 2752 | struct inode *inode = vn_to_inode(vp); |
| 2740 | 2753 | ||
| 2741 | if (!(inode->i_state & I_NEW)) | 2754 | if (!(inode->i_state & I_NEW)) |
| 2742 | mark_inode_dirty_sync(inode); | 2755 | mark_inode_dirty_sync(inode); |
| 2756 | } | ||
| 2743 | } | 2757 | } |
| 2744 | |||
| 2745 | wake_up(&ip->i_ipin_wait); | 2758 | wake_up(&ip->i_ipin_wait); |
| 2746 | } | 2759 | } |
| 2747 | } | 2760 | } |
