Merge branch 'master' into for-linus
[pandora-kernel.git] / fs / xfs / xfs_iget.c
index 155e798..75df75f 100644 (file)
@@ -190,13 +190,12 @@ xfs_iget_cache_hit(
                trace_xfs_iget_reclaim(ip);
 
                /*
-                * We need to set XFS_INEW atomically with clearing the
-                * reclaimable tag so that we do have an indicator of the
-                * inode still being initialized.
+                * We need to set XFS_IRECLAIM to prevent xfs_reclaim_inode
+                * from stomping over us while we recycle the inode.  We can't
+                * clear the radix tree reclaimable tag yet as it requires
+                * pag_ici_lock to be held exclusive.
                 */
-               ip->i_flags |= XFS_INEW;
-               ip->i_flags &= ~XFS_IRECLAIMABLE;
-               __xfs_inode_clear_reclaim_tag(mp, pag, ip);
+               ip->i_flags |= XFS_IRECLAIM;
 
                spin_unlock(&ip->i_flags_lock);
                read_unlock(&pag->pag_ici_lock);
@@ -216,7 +215,15 @@ xfs_iget_cache_hit(
                        trace_xfs_iget_reclaim(ip);
                        goto out_error;
                }
+
+               write_lock(&pag->pag_ici_lock);
+               spin_lock(&ip->i_flags_lock);
+               ip->i_flags &= ~(XFS_IRECLAIMABLE | XFS_IRECLAIM);
+               ip->i_flags |= XFS_INEW;
+               __xfs_inode_clear_reclaim_tag(mp, pag, ip);
                inode->i_state = I_NEW;
+               spin_unlock(&ip->i_flags_lock);
+               write_unlock(&pag->pag_ici_lock);
        } else {
                /* If the VFS inode is being torn down, pause and try again. */
                if (!igrab(inode)) {
@@ -374,10 +381,7 @@ xfs_iget(
                return EINVAL;
 
        /* get the perag structure and ensure that it's inode capable */
-       pag = xfs_get_perag(mp, ino);
-       if (!pag->pagi_inodeok)
-               return EINVAL;
-       ASSERT(pag->pag_ici_init);
+       pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ino));
        agino = XFS_INO_TO_AGINO(mp, ino);
 
 again:
@@ -398,7 +402,7 @@ again:
                if (error)
                        goto out_error_or_again;
        }
-       xfs_put_perag(mp, pag);
+       xfs_perag_put(pag);
 
        *ipp = ip;
 
@@ -417,7 +421,7 @@ out_error_or_again:
                delay(1);
                goto again;
        }
-       xfs_put_perag(mp, pag);
+       xfs_perag_put(pag);
        return error;
 }
 
@@ -488,12 +492,12 @@ xfs_ireclaim(
         * added to the tree assert that it's been there before to catch
         * problems with the inode life time early on.
         */
-       pag = xfs_get_perag(mp, ip->i_ino);
+       pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino));
        write_lock(&pag->pag_ici_lock);
        if (!radix_tree_delete(&pag->pag_ici_root, agino))
                ASSERT(0);
        write_unlock(&pag->pag_ici_lock);
-       xfs_put_perag(mp, pag);
+       xfs_perag_put(pag);
 
        /*
         * Here we do an (almost) spurious inode lock in order to coordinate
@@ -737,30 +741,24 @@ xfs_ilock_demote(
 }
 
 #ifdef DEBUG
-/*
- * Debug-only routine, without additional rw_semaphore APIs, we can
- * now only answer requests regarding whether we hold the lock for write
- * (reader state is outside our visibility, we only track writer state).
- *
- * Note: this means !xfs_isilocked would give false positives, so don't do that.
- */
 int
 xfs_isilocked(
        xfs_inode_t             *ip,
        uint                    lock_flags)
 {
-       if ((lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) ==
-                       XFS_ILOCK_EXCL) {
-               if (!ip->i_lock.mr_writer)
-                       return 0;
+       if (lock_flags & (XFS_ILOCK_EXCL|XFS_ILOCK_SHARED)) {
+               if (!(lock_flags & XFS_ILOCK_SHARED))
+                       return !!ip->i_lock.mr_writer;
+               return rwsem_is_locked(&ip->i_lock.mr_lock);
        }
 
-       if ((lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) ==
-                       XFS_IOLOCK_EXCL) {
-               if (!ip->i_iolock.mr_writer)
-                       return 0;
+       if (lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) {
+               if (!(lock_flags & XFS_IOLOCK_SHARED))
+                       return !!ip->i_iolock.mr_writer;
+               return rwsem_is_locked(&ip->i_iolock.mr_lock);
        }
 
-       return 1;
+       ASSERT(0);
+       return 0;
 }
 #endif