Commit 56e73ec4 authored by David Chinner's avatar David Chinner Committed by Lachlan McIlroy

[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: default avatarDavid Chinner <david@fromorbit.com>
Signed-off-by: default avatarLachlan McIlroy <lachlan@sgi.com>
Signed-off-by: default avatarChristoph Hellwig <hch@infradead.org>
parent 2b7035fd
...@@ -159,18 +159,19 @@ xfs_iget_cache_miss( ...@@ -159,18 +159,19 @@ xfs_iget_cache_miss(
goto out_destroy; goto out_destroy;
} }
if (lock_flags)
xfs_ilock(ip, lock_flags);
/* /*
* Preload the radix tree so we can insert safely under the * 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)) { if (radix_tree_preload(GFP_KERNEL)) {
error = EAGAIN; 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); mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1);
first_index = agino & mask; first_index = agino & mask;
write_lock(&pag->pag_ici_lock); write_lock(&pag->pag_ici_lock);
...@@ -181,7 +182,7 @@ xfs_iget_cache_miss( ...@@ -181,7 +182,7 @@ xfs_iget_cache_miss(
WARN_ON(error != -EEXIST); WARN_ON(error != -EEXIST);
XFS_STATS_INC(xs_ig_dup); XFS_STATS_INC(xs_ig_dup);
error = EAGAIN; error = EAGAIN;
goto out_unlock; goto out_preload_end;
} }
/* These values _must_ be set before releasing the radix tree lock! */ /* These values _must_ be set before releasing the radix tree lock! */
...@@ -193,9 +194,12 @@ xfs_iget_cache_miss( ...@@ -193,9 +194,12 @@ xfs_iget_cache_miss(
*ipp = ip; *ipp = ip;
return 0; return 0;
out_unlock: out_preload_end:
write_unlock(&pag->pag_ici_lock); write_unlock(&pag->pag_ici_lock);
radix_tree_preload_end(); radix_tree_preload_end();
out_unlock:
if (lock_flags)
xfs_iunlock(ip, lock_flags);
out_destroy: out_destroy:
xfs_idestroy(ip); xfs_idestroy(ip);
return error; return error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment