aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2009-10-19 00:05:26 -0400
committerAlex Elder <aelder@sgi.com>2009-12-11 16:11:20 -0500
commit033da48fda9d56e28b3fe3ef87ef6fd43290f554 (patch)
tree0883ff1fd99a9d9bff00c2694e6b66ae12a39bba
parent80641dc66a2d6dfb22af4413227a92b8ab84c7bb (diff)
xfs: reset the i_iolock lock class in the reclaim path
The iolock is used for protecting reads, writes and block truncates against each other. We have two classes of callers, the first one is induced by a file operation and requires a reference to the inode be held and not dropped after the operation is done: - xfs_vm_vmap, xfs_vn_fallocate, xfs_read, xfs_write, xfs_splice_read, xfs_splice_write and xfs_setattr are all implementations of VFS methods that require a live inode - xfs_getbmap and xfs_swap_extents are ioctl subcommand for which the same is true - xfs_truncate_file is only called on quota inodes just returned from xfs_iget - xfs_sync_inode_data does the lock just after an igrab() - xfs_filestream_associate and xfs_filestream_new_ag take the iolock on the parent inode of an inode which by VFS rules must be referenced And we have various calls to truncate blocks past EOF or the whole file when dropping the last reference to an inode. Unfortunately lockdep complains when we do memory allocations that can recurse into the filesystem in the first class because the second class happens to take the same lock. To avoid this re-init the iolock in the beginning of xfs_fs_clear_inode to get a new lock class. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Alex Elder <aelder@sgi.com> Signed-off-by: Alex Elder <aelder@sgi.com>
-rw-r--r--fs/xfs/linux-2.6/xfs_super.c15
-rw-r--r--fs/xfs/xfs_iget.c3
2 files changed, 17 insertions, 1 deletions
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
index a82a93db67c2..25b6903a3bce 100644
--- a/fs/xfs/linux-2.6/xfs_super.c
+++ b/fs/xfs/linux-2.6/xfs_super.c
@@ -999,7 +999,6 @@ xfs_fs_inode_init_once(
999 999
1000 mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER, 1000 mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER,
1001 "xfsino", ip->i_ino); 1001 "xfsino", ip->i_ino);
1002 mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
1003} 1002}
1004 1003
1005/* 1004/*
@@ -1101,6 +1100,20 @@ xfs_fs_clear_inode(
1101 XFS_STATS_INC(vn_remove); 1100 XFS_STATS_INC(vn_remove);
1102 XFS_STATS_DEC(vn_active); 1101 XFS_STATS_DEC(vn_active);
1103 1102
1103 /*
1104 * The iolock is used by the file system to coordinate reads,
1105 * writes, and block truncates. Up to this point the lock
1106 * protected concurrent accesses by users of the inode. But
1107 * from here forward we're doing some final processing of the
1108 * inode because we're done with it, and although we reuse the
1109 * iolock for protection it is really a distinct lock class
1110 * (in the lockdep sense) from before. To keep lockdep happy
1111 * (and basically indicate what we are doing), we explicitly
1112 * re-init the iolock here.
1113 */
1114 ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock));
1115 mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
1116
1104 xfs_inactive(ip); 1117 xfs_inactive(ip);
1105} 1118}
1106 1119
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 80e526489be5..cc72c561ff52 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -73,6 +73,9 @@ xfs_inode_alloc(
73 ASSERT(atomic_read(&ip->i_pincount) == 0); 73 ASSERT(atomic_read(&ip->i_pincount) == 0);
74 ASSERT(!spin_is_locked(&ip->i_flags_lock)); 74 ASSERT(!spin_is_locked(&ip->i_flags_lock));
75 ASSERT(completion_done(&ip->i_flush)); 75 ASSERT(completion_done(&ip->i_flush));
76 ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock));
77
78 mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino);
76 79
77 /* initialise the xfs inode */ 80 /* initialise the xfs inode */
78 ip->i_ino = ino; 81 ip->i_ino = ino;