On Wed, Oct 22, 2008 at 06:58:38PM +1100, Dave Chinner wrote: > On Tue, Oct 21, 2008 at 03:42:16PM +0400, Alexander Beregalov wrote: > > Bisected to: > > dd509097cb0b76d3836385f80d6b2d6fd3b97757 is first bad commit > > commit dd509097cb0b76d3836385f80d6b2d6fd3b97757 > > Author: Lachlan McIlroy <lachlan@xxxxxxx> > > Date: Mon Sep 29 14:56:40 2008 +1000 > > > > [XFS] Unlock inode before calling xfs_idestroy() > > > > Lock debugging reported the ilock was being destroyed without being > > unlocked. We don't need to lock the inode until we are going to insert it > > into the radix tree. > > Ah, OK, I see the problem, though I don't understand why I'm not > seeing the might_sleep() triggering all the time given that I always > build with: > > $ grep SLEEP .config > CONFIG_DEBUG_SPINLOCK_SLEEP=y > > Basically the above commit moved xfs_ilock() inside > radix_tree_preload()/radix_tree_preload_end(), which means we are > taking a rwsem() while we have an elevated preempt count. I'll > get a patch out to fix it. Patch below (against the xfs master/linux-next branch) should fix the regression. I've just started QA on it. Can you please check that it works for you, Alexander? Cheers, Dave. -- Dave Chinner david@xxxxxxxxxxxxx XFS: Can't lock inodes in radix tree preload region When we are inside a radix tree preload region, we cannot sleep. Recently we moved the inode locking inside the preload region for the inode radix tree. Fix that, and fix a missed unlock in another error path in the same code at the same time. Signed-off-by: Dave Chinner <david@xxxxxxxxxxxxx> --- fs/xfs/xfs_iget.c | 18 +++++++++++------- 1 files changed, 11 insertions(+), 7 deletions(-) diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index fbc6088..837cae7 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c @@ -159,18 +159,19 @@ xfs_iget_cache_miss( goto out_destroy; } + if (lock_flags) + xfs_ilock(ip, lock_flags); + /* * Preload the radix tree so we can insert safely under the - * write spinlock. + * write spinlock. Note that we cannot sleep inside the preload + * region. */ if (radix_tree_preload(GFP_KERNEL)) { error = EAGAIN; - goto out_destroy; + goto out_unlock; } - if (lock_flags) - xfs_ilock(ip, lock_flags); - mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1); first_index = agino & mask; write_lock(&pag->pag_ici_lock); @@ -181,7 +182,7 @@ xfs_iget_cache_miss( WARN_ON(error != -EEXIST); XFS_STATS_INC(xs_ig_dup); error = EAGAIN; - goto out_unlock; + goto out_preload_end; } /* These values _must_ be set before releasing the radix tree lock! */ @@ -193,9 +194,12 @@ xfs_iget_cache_miss( *ipp = ip; return 0; -out_unlock: +out_preload_end: write_unlock(&pag->pag_ici_lock); radix_tree_preload_end(); +out_unlock: + if (lock_flags) + xfs_iunlock(ip, lock_flags); out_destroy: xfs_destroy_inode(ip); return error; -- To unsubscribe from this list: send the line "unsubscribe linux-next" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html