diff options
author | Dave Chinner <dchinner@redhat.com> | 2010-12-22 19:57:13 -0500 |
---|---|---|
committer | Dave Chinner <david@fromorbit.com> | 2010-12-22 19:57:13 -0500 |
commit | dcfcf20512cb517ac18b9433b676183fa1257911 (patch) | |
tree | fd5551251e63f47dbb804e36cfd4cb3f15f5c322 | |
parent | 489a150f6454e2cd93d9e0ee6d7c5a361844f62a (diff) |
xfs: provide a inode iolock lockdep class
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>
-rw-r--r-- | fs/xfs/linux-2.6/xfs_super.c | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_iget.c | 19 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.h | 2 |
3 files changed, 23 insertions, 0 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 064f964d4f3c..c45b3233d486 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -1118,6 +1118,8 @@ xfs_fs_evict_inode( | |||
1118 | */ | 1118 | */ |
1119 | ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock)); | 1119 | ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock)); |
1120 | mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); | 1120 | mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); |
1121 | lockdep_set_class_and_name(&ip->i_iolock.mr_lock, | ||
1122 | &xfs_iolock_reclaimable, "xfs_iolock_reclaimable"); | ||
1121 | 1123 | ||
1122 | xfs_inactive(ip); | 1124 | xfs_inactive(ip); |
1123 | } | 1125 | } |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index 0cdd26932d8e..cdb1c2505fc6 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -43,6 +43,17 @@ | |||
43 | 43 | ||
44 | 44 | ||
45 | /* | 45 | /* |
46 | * Define xfs inode iolock lockdep classes. We need to ensure that all active | ||
47 | * inodes are considered the same for lockdep purposes, including inodes that | ||
48 | * are recycled through the XFS_IRECLAIMABLE state. This is the the only way to | ||
49 | * guarantee the locks are considered the same when there are multiple lock | ||
50 | * initialisation siteѕ. Also, define a reclaimable inode class so it is | ||
51 | * obvious in lockdep reports which class the report is against. | ||
52 | */ | ||
53 | static struct lock_class_key xfs_iolock_active; | ||
54 | struct lock_class_key xfs_iolock_reclaimable; | ||
55 | |||
56 | /* | ||
46 | * Allocate and initialise an xfs_inode. | 57 | * Allocate and initialise an xfs_inode. |
47 | */ | 58 | */ |
48 | STATIC struct xfs_inode * | 59 | STATIC struct xfs_inode * |
@@ -71,6 +82,8 @@ xfs_inode_alloc( | |||
71 | ASSERT(completion_done(&ip->i_flush)); | 82 | ASSERT(completion_done(&ip->i_flush)); |
72 | 83 | ||
73 | mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); | 84 | mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); |
85 | lockdep_set_class_and_name(&ip->i_iolock.mr_lock, | ||
86 | &xfs_iolock_active, "xfs_iolock_active"); | ||
74 | 87 | ||
75 | /* initialise the xfs inode */ | 88 | /* initialise the xfs inode */ |
76 | ip->i_ino = ino; | 89 | ip->i_ino = ino; |
@@ -218,6 +231,12 @@ xfs_iget_cache_hit( | |||
218 | ip->i_flags |= XFS_INEW; | 231 | ip->i_flags |= XFS_INEW; |
219 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); | 232 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); |
220 | inode->i_state = I_NEW; | 233 | inode->i_state = I_NEW; |
234 | |||
235 | ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock)); | ||
236 | mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); | ||
237 | lockdep_set_class_and_name(&ip->i_iolock.mr_lock, | ||
238 | &xfs_iolock_active, "xfs_iolock_active"); | ||
239 | |||
221 | spin_unlock(&ip->i_flags_lock); | 240 | spin_unlock(&ip->i_flags_lock); |
222 | write_unlock(&pag->pag_ici_lock); | 241 | write_unlock(&pag->pag_ici_lock); |
223 | } else { | 242 | } else { |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index fb2ca2e4cdc9..1c6514d73dc8 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -438,6 +438,8 @@ static inline void xfs_ifunlock(xfs_inode_t *ip) | |||
438 | #define XFS_IOLOCK_DEP(flags) (((flags) & XFS_IOLOCK_DEP_MASK) >> XFS_IOLOCK_SHIFT) | 438 | #define XFS_IOLOCK_DEP(flags) (((flags) & XFS_IOLOCK_DEP_MASK) >> XFS_IOLOCK_SHIFT) |
439 | #define XFS_ILOCK_DEP(flags) (((flags) & XFS_ILOCK_DEP_MASK) >> XFS_ILOCK_SHIFT) | 439 | #define XFS_ILOCK_DEP(flags) (((flags) & XFS_ILOCK_DEP_MASK) >> XFS_ILOCK_SHIFT) |
440 | 440 | ||
441 | extern struct lock_class_key xfs_iolock_reclaimable; | ||
442 | |||
441 | /* | 443 | /* |
442 | * Flags for xfs_itruncate_start(). | 444 | * Flags for xfs_itruncate_start(). |
443 | */ | 445 | */ |