summaryrefslogtreecommitdiff
path: root/fs/xfs/xfs_iget.c
diff options
context:
space:
mode:
authorClark Williams <williams@redhat.com>2012-04-04 10:52:26 -0500
committerClark Williams <williams@redhat.com>2012-04-04 10:52:26 -0500
commit2d93eaf2d4ace5853a74a4b0596f601aa62cb840 (patch)
treeb0a2e2083c1749c4e3b8ae23db7bb13a7ca9aafe /fs/xfs/xfs_iget.c
parent003133585fc61d7bd36d3a097d7fde62e64a9550 (diff)
parent23d8c3f8f494c8516c9b4c05529e118e6a485956 (diff)
Merge commit 'v3.2.14' into rt-3.2.14-rt23v3.2.14-rt23
Diffstat (limited to 'fs/xfs/xfs_iget.c')
-rw-r--r--fs/xfs/xfs_iget.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 0fa98b1c70ea..cfc4277ebda3 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -353,9 +353,20 @@ xfs_iget_cache_miss(
BUG();
}
- spin_lock(&pag->pag_ici_lock);
+ /*
+ * These values must be set before inserting the inode into the radix
+ * tree as the moment it is inserted a concurrent lookup (allowed by the
+ * RCU locking mechanism) can find it and that lookup must see that this
+ * is an inode currently under construction (i.e. that XFS_INEW is set).
+ * The ip->i_flags_lock that protects the XFS_INEW flag forms the
+ * memory barrier that ensures this detection works correctly at lookup
+ * time.
+ */
+ ip->i_udquot = ip->i_gdquot = NULL;
+ xfs_iflags_set(ip, XFS_INEW);
/* insert the new inode */
+ spin_lock(&pag->pag_ici_lock);
error = radix_tree_insert(&pag->pag_ici_root, agino, ip);
if (unlikely(error)) {
WARN_ON(error != -EEXIST);
@@ -363,11 +374,6 @@ xfs_iget_cache_miss(
error = EAGAIN;
goto out_preload_end;
}
-
- /* These values _must_ be set before releasing the radix tree lock! */
- ip->i_udquot = ip->i_gdquot = NULL;
- xfs_iflags_set(ip, XFS_INEW);
-
spin_unlock(&pag->pag_ici_lock);
radix_tree_preload_end();