diff options
author | Christoph Hellwig <hch@lst.de> | 2009-01-19 02:03:19 +0100 |
---|---|---|
committer | Christoph Hellwig <hch@brick.lst.de> | 2009-01-19 02:03:19 +0100 |
commit | 5bb87a33b2cfb8e7ef3383718274094bdff266a3 (patch) | |
tree | 7917b0354e01dde2fc321a48214f72333aab3073 | |
parent | a4edd1da20af79b2e92efeee3ca94831c8024d61 (diff) |
xfs: lockdep annotations for xfs_dqlock2
xfs_dqlock2 locks two xfs_dquots, which is fine as it always locks the
dquot with the lower id first. Use mutex_lock_nested to tell lockdep
about this fact.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <david@fromorbit.com>
-rw-r--r-- | fs/xfs/quota/xfs_dquot.c | 24 | ||||
-rw-r--r-- | fs/xfs/quota/xfs_dquot.h | 10 |
2 files changed, 24 insertions, 10 deletions
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index d68b4e1cf1d..ebdf3c842dc 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c @@ -1383,6 +1383,12 @@ xfs_dqunlock_nonotify( mutex_unlock(&(dqp->q_qlock)); } +/* + * Lock two xfs_dquot structures. + * + * To avoid deadlocks we always lock the quota structure with + * the lowerd id first. + */ void xfs_dqlock2( xfs_dquot_t *d1, @@ -1392,18 +1398,16 @@ xfs_dqlock2( ASSERT(d1 != d2); if (be32_to_cpu(d1->q_core.d_id) > be32_to_cpu(d2->q_core.d_id)) { - xfs_dqlock(d2); - xfs_dqlock(d1); + mutex_lock(&d2->q_qlock); + mutex_lock_nested(&d1->q_qlock, XFS_QLOCK_NESTED); } else { - xfs_dqlock(d1); - xfs_dqlock(d2); - } - } else { - if (d1) { - xfs_dqlock(d1); - } else if (d2) { - xfs_dqlock(d2); + mutex_lock(&d1->q_qlock); + mutex_lock_nested(&d2->q_qlock, XFS_QLOCK_NESTED); } + } else if (d1) { + mutex_lock(&d1->q_qlock); + } else if (d2) { + mutex_lock(&d2->q_qlock); } } diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h index 7e455337e2b..d443e93b433 100644 --- a/fs/xfs/quota/xfs_dquot.h +++ b/fs/xfs/quota/xfs_dquot.h @@ -97,6 +97,16 @@ typedef struct xfs_dquot { #define dq_hashlist q_lists.dqm_hashlist #define dq_flags q_lists.dqm_flags +/* + * Lock hierachy for q_qlock: + * XFS_QLOCK_NORMAL is the implicit default, + * XFS_QLOCK_NESTED is the dquot with the higher id in xfs_dqlock2 + */ +enum { + XFS_QLOCK_NORMAL = 0, + XFS_QLOCK_NESTED, +}; + #define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++) #ifdef DEBUG |