sh: Define HAVE_FUNCTION_TRACE_MCOUNT_TEST
[safe/jmp/linux-2.6] / fs / xfs / xfs_iget.c
index f58e5e0..5fcec6f 100644 (file)
@@ -18,6 +18,7 @@
 #include "xfs.h"
 #include "xfs_fs.h"
 #include "xfs_types.h"
+#include "xfs_acl.h"
 #include "xfs_bit.h"
 #include "xfs_log.h"
 #include "xfs_inum.h"
@@ -69,15 +70,6 @@ xfs_inode_alloc(
        ASSERT(!spin_is_locked(&ip->i_flags_lock));
        ASSERT(completion_done(&ip->i_flush));
 
-       /*
-        * initialise the VFS inode here to get failures
-        * out of the way early.
-        */
-       if (!inode_init_always(mp->m_super, VFS_I(ip))) {
-               kmem_zone_free(xfs_inode_zone, ip);
-               return NULL;
-       }
-
        /* initialise the xfs inode */
        ip->i_ino = ino;
        ip->i_mount = mp;
@@ -113,6 +105,20 @@ xfs_inode_alloc(
 #ifdef XFS_DIR2_TRACE
        ip->i_dir_trace = ktrace_alloc(XFS_DIR2_KTRACE_SIZE, KM_NOFS);
 #endif
+       /*
+       * Now initialise the VFS inode. We do this after the xfs_inode
+       * initialisation as internal failures will result in ->destroy_inode
+       * being called and that will pass down through the reclaim path and
+       * free the XFS inode. This path requires the XFS inode to already be
+       * initialised. Hence if this call fails, the xfs_inode has already
+       * been freed and we should not reference it at all in the error
+       * handling.
+       */
+       if (!inode_init_always(mp->m_super, VFS_I(ip)))
+               return NULL;
+
+       /* prevent anyone from using this yet */
+       VFS_I(ip)->i_state = I_NEW|I_LOCK;
 
        return ip;
 }
@@ -246,9 +252,6 @@ 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. Note that we cannot sleep inside the preload
@@ -256,7 +259,16 @@ xfs_iget_cache_miss(
         */
        if (radix_tree_preload(GFP_KERNEL)) {
                error = EAGAIN;
-               goto out_unlock;
+               goto out_destroy;
+       }
+
+       /*
+        * Because the inode hasn't been added to the radix-tree yet it can't
+        * be found by another thread, so we can do the non-sleeping lock here.
+        */
+       if (lock_flags) {
+               if (!xfs_ilock_nowait(ip, lock_flags))
+                       BUG();
        }
 
        mask = ~(((XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog)) - 1);
@@ -284,7 +296,6 @@ xfs_iget_cache_miss(
 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:
@@ -362,7 +373,6 @@ again:
        }
        xfs_put_perag(mp, pag);
 
-       xfs_iflags_set(ip, XFS_IMODIFIED);
        *ipp = ip;
 
        ASSERT(ip->i_df.if_ext_max ==
@@ -491,10 +501,7 @@ xfs_ireclaim(
         * ilock one but will still hold the iolock.
         */
        xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
-       /*
-        * Release dquots (and their references) if any.
-        */
-       XFS_QM_DQDETACH(ip->i_mount, ip);
+       xfs_qm_dqdetach(ip);
        xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL);
 
        switch (ip->i_d.di_mode & S_IFMT) {
@@ -806,3 +813,51 @@ xfs_isilocked(
 }
 #endif
 
+#ifdef XFS_INODE_TRACE
+
+#define KTRACE_ENTER(ip, vk, s, line, ra)                      \
+       ktrace_enter((ip)->i_trace,                             \
+/*  0 */               (void *)(__psint_t)(vk),                \
+/*  1 */               (void *)(s),                            \
+/*  2 */               (void *)(__psint_t) line,               \
+/*  3 */               (void *)(__psint_t)atomic_read(&VFS_I(ip)->i_count), \
+/*  4 */               (void *)(ra),                           \
+/*  5 */               NULL,                                   \
+/*  6 */               (void *)(__psint_t)current_cpu(),       \
+/*  7 */               (void *)(__psint_t)current_pid(),       \
+/*  8 */               (void *)__return_address,               \
+/*  9 */               NULL, NULL, NULL, NULL, NULL, NULL, NULL)
+
+/*
+ * Vnode tracing code.
+ */
+void
+_xfs_itrace_entry(xfs_inode_t *ip, const char *func, inst_t *ra)
+{
+       KTRACE_ENTER(ip, INODE_KTRACE_ENTRY, func, 0, ra);
+}
+
+void
+_xfs_itrace_exit(xfs_inode_t *ip, const char *func, inst_t *ra)
+{
+       KTRACE_ENTER(ip, INODE_KTRACE_EXIT, func, 0, ra);
+}
+
+void
+xfs_itrace_hold(xfs_inode_t *ip, char *file, int line, inst_t *ra)
+{
+       KTRACE_ENTER(ip, INODE_KTRACE_HOLD, file, line, ra);
+}
+
+void
+_xfs_itrace_ref(xfs_inode_t *ip, char *file, int line, inst_t *ra)
+{
+       KTRACE_ENTER(ip, INODE_KTRACE_REF, file, line, ra);
+}
+
+void
+xfs_itrace_rele(xfs_inode_t *ip, char *file, int line, inst_t *ra)
+{
+       KTRACE_ENTER(ip, INODE_KTRACE_RELE, file, line, ra);
+}
+#endif /* XFS_INODE_TRACE */