xfs: provide a inode iolock lockdep class
authorDave Chinner <dchinner@redhat.com>
Thu, 23 Dec 2010 00:57:13 +0000 (11:57 +1100)
committerDave Chinner <david@fromorbit.com>
Thu, 23 Dec 2010 00:57:13 +0000 (11:57 +1100)
The XFS iolock needs to be re-initialised to a new lock class before
it enters reclaim to prevent lockdep false positives. Unfortunately,
this is not sufficient protection as inodes in the XFS_IRECLAIMABLE
state can be recycled and not re-initialised before being reused.

We need to re-initialise the lock state when transfering out of
XFS_IRECLAIMABLE state to XFS_INEW, but we need to keep the same
class as if the inode was just allocated. Hence we need a specific
lockdep class variable for the iolock so that both initialisations
use the same class.

While there, add a specific class for inodes in the reclaim state so
that it is easy to tell from lockdep reports what state the inode
was in that generated the report.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/xfs_iget.c
fs/xfs/xfs_inode.h

index 064f964d4f3c201ce52bf6bb42e7dbbd3c0526bd..c45b3233d486bb97337c61cec90d5d2a9bb70760 100644 (file)
@@ -1118,6 +1118,8 @@ xfs_fs_evict_inode(
         */
        ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock));
        mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
+       lockdep_set_class_and_name(&ip->i_iolock.mr_lock,
+                       &xfs_iolock_reclaimable, "xfs_iolock_reclaimable");
 
        xfs_inactive(ip);
 }
index 0cdd26932d8e8d1c22ac008b4d4d107c69187468..cdb1c2505fc672db69eb1ef9b1ee3519995bbdf9 100644 (file)
 #include "xfs_trace.h"
 
 
+/*
+ * Define xfs inode iolock lockdep classes. We need to ensure that all active
+ * inodes are considered the same for lockdep purposes, including inodes that
+ * are recycled through the XFS_IRECLAIMABLE state. This is the the only way to
+ * guarantee the locks are considered the same when there are multiple lock
+ * initialisation siteŃ•. Also, define a reclaimable inode class so it is
+ * obvious in lockdep reports which class the report is against.
+ */
+static struct lock_class_key xfs_iolock_active;
+struct lock_class_key xfs_iolock_reclaimable;
+
 /*
  * Allocate and initialise an xfs_inode.
  */
@@ -71,6 +82,8 @@ xfs_inode_alloc(
        ASSERT(completion_done(&ip->i_flush));
 
        mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
+       lockdep_set_class_and_name(&ip->i_iolock.mr_lock,
+                       &xfs_iolock_active, "xfs_iolock_active");
 
        /* initialise the xfs inode */
        ip->i_ino = ino;
@@ -218,6 +231,12 @@ xfs_iget_cache_hit(
                ip->i_flags |= XFS_INEW;
                __xfs_inode_clear_reclaim_tag(mp, pag, ip);
                inode->i_state = I_NEW;
+
+               ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock));
+               mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
+               lockdep_set_class_and_name(&ip->i_iolock.mr_lock,
+                               &xfs_iolock_active, "xfs_iolock_active");
+
                spin_unlock(&ip->i_flags_lock);
                write_unlock(&pag->pag_ici_lock);
        } else {
index fb2ca2e4cdc935c112d1504a85aca3130f511179..1c6514d73dc877572a421103f43997c10d2e1b09 100644 (file)
@@ -438,6 +438,8 @@ static inline void xfs_ifunlock(xfs_inode_t *ip)
 #define XFS_IOLOCK_DEP(flags)  (((flags) & XFS_IOLOCK_DEP_MASK) >> XFS_IOLOCK_SHIFT)
 #define XFS_ILOCK_DEP(flags)   (((flags) & XFS_ILOCK_DEP_MASK) >> XFS_ILOCK_SHIFT)
 
+extern struct lock_class_key xfs_iolock_reclaimable;
+
 /*
  * Flags for xfs_itruncate_start().
  */