diff options
Diffstat (limited to 'fs/xfs/xfs_inode.c')
-rw-r--r-- | fs/xfs/xfs_inode.c | 64 |
1 files changed, 27 insertions, 37 deletions
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index c27d7d495aa0..44dfac521285 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -2193,7 +2193,7 @@ xfs_ifree_cluster( | |||
2193 | /* Inode not in memory or we found it already, | 2193 | /* Inode not in memory or we found it already, |
2194 | * nothing to do | 2194 | * nothing to do |
2195 | */ | 2195 | */ |
2196 | if (!ip || (ip->i_flags & XFS_ISTALE)) { | 2196 | if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) { |
2197 | read_unlock(&ih->ih_lock); | 2197 | read_unlock(&ih->ih_lock); |
2198 | continue; | 2198 | continue; |
2199 | } | 2199 | } |
@@ -2215,10 +2215,7 @@ xfs_ifree_cluster( | |||
2215 | 2215 | ||
2216 | if (ip == free_ip) { | 2216 | if (ip == free_ip) { |
2217 | if (xfs_iflock_nowait(ip)) { | 2217 | if (xfs_iflock_nowait(ip)) { |
2218 | spin_lock(&ip->i_flags_lock); | 2218 | xfs_iflags_set(ip, XFS_ISTALE); |
2219 | ip->i_flags |= XFS_ISTALE; | ||
2220 | spin_unlock(&ip->i_flags_lock); | ||
2221 | |||
2222 | if (xfs_inode_clean(ip)) { | 2219 | if (xfs_inode_clean(ip)) { |
2223 | xfs_ifunlock(ip); | 2220 | xfs_ifunlock(ip); |
2224 | } else { | 2221 | } else { |
@@ -2231,9 +2228,7 @@ xfs_ifree_cluster( | |||
2231 | 2228 | ||
2232 | if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { | 2229 | if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { |
2233 | if (xfs_iflock_nowait(ip)) { | 2230 | if (xfs_iflock_nowait(ip)) { |
2234 | spin_lock(&ip->i_flags_lock); | 2231 | xfs_iflags_set(ip, XFS_ISTALE); |
2235 | ip->i_flags |= XFS_ISTALE; | ||
2236 | spin_unlock(&ip->i_flags_lock); | ||
2237 | 2232 | ||
2238 | if (xfs_inode_clean(ip)) { | 2233 | if (xfs_inode_clean(ip)) { |
2239 | xfs_ifunlock(ip); | 2234 | xfs_ifunlock(ip); |
@@ -2263,9 +2258,7 @@ xfs_ifree_cluster( | |||
2263 | AIL_LOCK(mp,s); | 2258 | AIL_LOCK(mp,s); |
2264 | iip->ili_flush_lsn = iip->ili_item.li_lsn; | 2259 | iip->ili_flush_lsn = iip->ili_item.li_lsn; |
2265 | AIL_UNLOCK(mp, s); | 2260 | AIL_UNLOCK(mp, s); |
2266 | spin_lock(&iip->ili_inode->i_flags_lock); | 2261 | xfs_iflags_set(iip->ili_inode, XFS_ISTALE); |
2267 | iip->ili_inode->i_flags |= XFS_ISTALE; | ||
2268 | spin_unlock(&iip->ili_inode->i_flags_lock); | ||
2269 | pre_flushed++; | 2262 | pre_flushed++; |
2270 | } | 2263 | } |
2271 | lip = lip->li_bio_list; | 2264 | lip = lip->li_bio_list; |
@@ -2748,42 +2741,39 @@ xfs_iunpin( | |||
2748 | { | 2741 | { |
2749 | ASSERT(atomic_read(&ip->i_pincount) > 0); | 2742 | ASSERT(atomic_read(&ip->i_pincount) > 0); |
2750 | 2743 | ||
2751 | if (atomic_dec_and_test(&ip->i_pincount)) { | 2744 | if (atomic_dec_and_lock(&ip->i_pincount, &ip->i_flags_lock)) { |
2745 | |||
2752 | /* | 2746 | /* |
2753 | * If the inode is currently being reclaimed, the | 2747 | * If the inode is currently being reclaimed, the link between |
2754 | * linux inode _and_ the xfs vnode may have been | 2748 | * the bhv_vnode and the xfs_inode will be broken after the |
2755 | * freed so we cannot reference either of them safely. | 2749 | * XFS_IRECLAIM* flag is set. Hence, if these flags are not |
2756 | * Hence we should not try to do anything to them | 2750 | * set, then we can move forward and mark the linux inode dirty |
2757 | * if the xfs inode is currently in the reclaim | 2751 | * knowing that it is still valid as it won't freed until after |
2758 | * path. | 2752 | * the bhv_vnode<->xfs_inode link is broken in xfs_reclaim. The |
2753 | * i_flags_lock is used to synchronise the setting of the | ||
2754 | * XFS_IRECLAIM* flags and the breaking of the link, and so we | ||
2755 | * can execute atomically w.r.t to reclaim by holding this lock | ||
2756 | * here. | ||
2759 | * | 2757 | * |
2760 | * However, we still need to issue the unpin wakeup | 2758 | * However, we still need to issue the unpin wakeup call as the |
2761 | * call as the inode reclaim may be blocked waiting for | 2759 | * inode reclaim may be blocked waiting for the inode to become |
2762 | * the inode to become unpinned. | 2760 | * unpinned. |
2763 | */ | 2761 | */ |
2764 | struct inode *inode = NULL; | ||
2765 | 2762 | ||
2766 | spin_lock(&ip->i_flags_lock); | 2763 | if (!__xfs_iflags_test(ip, XFS_IRECLAIM|XFS_IRECLAIMABLE)) { |
2767 | if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) { | ||
2768 | bhv_vnode_t *vp = XFS_ITOV_NULL(ip); | 2764 | bhv_vnode_t *vp = XFS_ITOV_NULL(ip); |
2765 | struct inode *inode = NULL; | ||
2766 | |||
2767 | BUG_ON(vp == NULL); | ||
2768 | inode = vn_to_inode(vp); | ||
2769 | BUG_ON(inode->i_state & I_CLEAR); | ||
2769 | 2770 | ||
2770 | /* make sync come back and flush this inode */ | 2771 | /* make sync come back and flush this inode */ |
2771 | if (vp) { | 2772 | if (!(inode->i_state & (I_NEW|I_FREEING))) |
2772 | inode = vn_to_inode(vp); | 2773 | mark_inode_dirty_sync(inode); |
2773 | |||
2774 | if (!(inode->i_state & | ||
2775 | (I_NEW|I_FREEING|I_CLEAR))) { | ||
2776 | inode = igrab(inode); | ||
2777 | if (inode) | ||
2778 | mark_inode_dirty_sync(inode); | ||
2779 | } else | ||
2780 | inode = NULL; | ||
2781 | } | ||
2782 | } | 2774 | } |
2783 | spin_unlock(&ip->i_flags_lock); | 2775 | spin_unlock(&ip->i_flags_lock); |
2784 | wake_up(&ip->i_ipin_wait); | 2776 | wake_up(&ip->i_ipin_wait); |
2785 | if (inode) | ||
2786 | iput(inode); | ||
2787 | } | 2777 | } |
2788 | } | 2778 | } |
2789 | 2779 | ||