aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorAlex Elder <elder@dreamhost.com>2012-02-16 17:01:00 -0500
committerBen Myers <bpm@sgi.com>2012-02-25 14:55:49 -0500
commitad637a10f444fc66b1f6d4a28fe30d4c61ed0161 (patch)
treec4512d9553696d9d5e36e40a909c3f7dabdcb1fb /fs/xfs
parent9006fb91cfdf22812923f0536c7531c429c1aeab (diff)
xfs: only take the ILOCK in xfs_reclaim_inode()
At the end of xfs_reclaim_inode(), the inode is locked in order to we wait for a possible concurrent lookup to complete before the inode is freed. This synchronization step was taking both the ILOCK and the IOLOCK, but the latter was causing lockdep to produce reports of the possibility of deadlock. It turns out that there's no need to acquire the IOLOCK at this point anyway. It may have been required in some earlier version of the code, but there should be no need to take the IOLOCK in xfs_iget(), so there's no (longer) any need to get it here for synchronization. Add an assertion in xfs_iget() as a reminder of this assumption. Dave Chinner diagnosed this on IRC, and Christoph Hellwig suggested no longer including the IOLOCK. I just put together the patch. Signed-off-by: Alex Elder <elder@dreamhost.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_iget.c9
-rw-r--r--fs/xfs/xfs_sync.c10
2 files changed, 13 insertions, 6 deletions
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 19dcfb2aac9a..37f22dad5f59 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -418,6 +418,15 @@ xfs_iget(
418 xfs_perag_t *pag; 418 xfs_perag_t *pag;
419 xfs_agino_t agino; 419 xfs_agino_t agino;
420 420
421 /*
422 * xfs_reclaim_inode() uses the ILOCK to ensure an inode
423 * doesn't get freed while it's being referenced during a
424 * radix tree traversal here. It assumes this function
425 * aqcuires only the ILOCK (and therefore it has no need to
426 * involve the IOLOCK in this synchronization).
427 */
428 ASSERT((lock_flags & (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED)) == 0);
429
421 /* reject inode numbers outside existing AGs */ 430 /* reject inode numbers outside existing AGs */
422 if (!ino || XFS_INO_TO_AGNO(mp, ino) >= mp->m_sb.sb_agcount) 431 if (!ino || XFS_INO_TO_AGNO(mp, ino) >= mp->m_sb.sb_agcount)
423 return EINVAL; 432 return EINVAL;
diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c
index 40b75eecd2b4..71bf846b7280 100644
--- a/fs/xfs/xfs_sync.c
+++ b/fs/xfs/xfs_sync.c
@@ -913,17 +913,15 @@ reclaim:
913 * can reference the inodes in the cache without taking references. 913 * can reference the inodes in the cache without taking references.
914 * 914 *
915 * We make that OK here by ensuring that we wait until the inode is 915 * We make that OK here by ensuring that we wait until the inode is
916 * unlocked after the lookup before we go ahead and free it. We get 916 * unlocked after the lookup before we go ahead and free it.
917 * both the ilock and the iolock because the code may need to drop the
918 * ilock one but will still hold the iolock.
919 */ 917 */
920 xfs_ilock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 918 xfs_ilock(ip, XFS_ILOCK_EXCL);
921 xfs_qm_dqdetach(ip); 919 xfs_qm_dqdetach(ip);
922 xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); 920 xfs_iunlock(ip, XFS_ILOCK_EXCL);
923 921
924 xfs_inode_free(ip); 922 xfs_inode_free(ip);
925 return error;
926 923
924 return error;
927} 925}
928 926
929/* 927/*