summaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDavid Chinner <david@fromorbit.com>2008-10-30 07:55:27 +0100
committerLachlan McIlroy <lachlan@sgi.com>2008-10-30 07:55:27 +0100
commit56e73ec47d749047f441e6b9d60d964535d31c3b (patch)
tree73423b4b01d760f95c5dcf1cff38ba4b56f6c969 /fs/xfs
parent[XFS] Trivial xfs_remove comment fixup (diff)
downloadlinux-56e73ec47d749047f441e6b9d60d964535d31c3b.tar.xz
linux-56e73ec47d749047f441e6b9d60d964535d31c3b.zip
[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. SGI-PV: 987246 SGI-Modid: xfs-linux-melb:xfs-kern:32385a Signed-off-by: David Chinner <david@fromorbit.com> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com> Signed-off-by: Christoph Hellwig <hch@infradead.org>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_iget.c18
1 files changed, 11 insertions, 7 deletions
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index a1f209b0596f..377c0cd14999 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_idestroy(ip);
return error;