|
@@ -349,9 +349,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);
|
|
@@ -359,11 +370,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();
|
|
|
|