--- zzzz-none-000/linux-2.6.19.2/fs/xfs/xfs_inode.c 2007-01-10 19:10:37.000000000 +0000 +++ davinci-8020-5505/linux-2.6.19.2/fs/xfs/xfs_inode.c 2007-01-11 07:38:19.000000000 +0000 @@ -2193,7 +2193,7 @@ /* Inode not in memory or we found it already, * nothing to do */ - if (!ip || xfs_iflags_test(ip, XFS_ISTALE)) { + if (!ip || (ip->i_flags & XFS_ISTALE)) { read_unlock(&ih->ih_lock); continue; } @@ -2215,7 +2215,10 @@ if (ip == free_ip) { if (xfs_iflock_nowait(ip)) { - xfs_iflags_set(ip, XFS_ISTALE); + spin_lock(&ip->i_flags_lock); + ip->i_flags |= XFS_ISTALE; + spin_unlock(&ip->i_flags_lock); + if (xfs_inode_clean(ip)) { xfs_ifunlock(ip); } else { @@ -2228,7 +2231,9 @@ if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL)) { if (xfs_iflock_nowait(ip)) { - xfs_iflags_set(ip, XFS_ISTALE); + spin_lock(&ip->i_flags_lock); + ip->i_flags |= XFS_ISTALE; + spin_unlock(&ip->i_flags_lock); if (xfs_inode_clean(ip)) { xfs_ifunlock(ip); @@ -2258,7 +2263,9 @@ AIL_LOCK(mp,s); iip->ili_flush_lsn = iip->ili_item.li_lsn; AIL_UNLOCK(mp, s); - xfs_iflags_set(iip->ili_inode, XFS_ISTALE); + spin_lock(&iip->ili_inode->i_flags_lock); + iip->ili_inode->i_flags |= XFS_ISTALE; + spin_unlock(&iip->ili_inode->i_flags_lock); pre_flushed++; } lip = lip->li_bio_list; @@ -2741,39 +2748,42 @@ { ASSERT(atomic_read(&ip->i_pincount) > 0); - if (atomic_dec_and_lock(&ip->i_pincount, &ip->i_flags_lock)) { - + if (atomic_dec_and_test(&ip->i_pincount)) { /* - * If the inode is currently being reclaimed, the link between - * the bhv_vnode and the xfs_inode will be broken after the - * XFS_IRECLAIM* flag is set. Hence, if these flags are not - * set, then we can move forward and mark the linux inode dirty - * knowing that it is still valid as it won't freed until after - * the bhv_vnode<->xfs_inode link is broken in xfs_reclaim. The - * i_flags_lock is used to synchronise the setting of the - * XFS_IRECLAIM* flags and the breaking of the link, and so we - * can execute atomically w.r.t to reclaim by holding this lock - * here. + * If the inode is currently being reclaimed, the + * linux inode _and_ the xfs vnode may have been + * freed so we cannot reference either of them safely. + * Hence we should not try to do anything to them + * if the xfs inode is currently in the reclaim + * path. * - * However, we still need to issue the unpin wakeup call as the - * inode reclaim may be blocked waiting for the inode to become - * unpinned. + * However, we still need to issue the unpin wakeup + * call as the inode reclaim may be blocked waiting for + * the inode to become unpinned. */ + struct inode *inode = NULL; - if (!__xfs_iflags_test(ip, XFS_IRECLAIM|XFS_IRECLAIMABLE)) { + spin_lock(&ip->i_flags_lock); + if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) { bhv_vnode_t *vp = XFS_ITOV_NULL(ip); - struct inode *inode = NULL; - - BUG_ON(vp == NULL); - inode = vn_to_inode(vp); - BUG_ON(inode->i_state & I_CLEAR); /* make sync come back and flush this inode */ - if (!(inode->i_state & (I_NEW|I_FREEING))) - mark_inode_dirty_sync(inode); + if (vp) { + inode = vn_to_inode(vp); + + if (!(inode->i_state & + (I_NEW|I_FREEING|I_CLEAR))) { + inode = igrab(inode); + if (inode) + mark_inode_dirty_sync(inode); + } else + inode = NULL; + } } spin_unlock(&ip->i_flags_lock); wake_up(&ip->i_ipin_wait); + if (inode) + iput(inode); } }