diff options
Diffstat (limited to 'fs/xfs')
-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 591ca6602bfb..36d1bb6140d1 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c | |||
@@ -1383,6 +1383,12 @@ xfs_dqunlock_nonotify( | |||
1383 | mutex_unlock(&(dqp->q_qlock)); | 1383 | mutex_unlock(&(dqp->q_qlock)); |
1384 | } | 1384 | } |
1385 | 1385 | ||
1386 | /* | ||
1387 | * Lock two xfs_dquot structures. | ||
1388 | * | ||
1389 | * To avoid deadlocks we always lock the quota structure with | ||
1390 | * the lowerd id first. | ||
1391 | */ | ||
1386 | void | 1392 | void |
1387 | xfs_dqlock2( | 1393 | xfs_dqlock2( |
1388 | xfs_dquot_t *d1, | 1394 | xfs_dquot_t *d1, |
@@ -1392,18 +1398,16 @@ xfs_dqlock2( | |||
1392 | ASSERT(d1 != d2); | 1398 | ASSERT(d1 != d2); |
1393 | if (be32_to_cpu(d1->q_core.d_id) > | 1399 | if (be32_to_cpu(d1->q_core.d_id) > |
1394 | be32_to_cpu(d2->q_core.d_id)) { | 1400 | be32_to_cpu(d2->q_core.d_id)) { |
1395 | xfs_dqlock(d2); | 1401 | mutex_lock(&d2->q_qlock); |
1396 | xfs_dqlock(d1); | 1402 | mutex_lock_nested(&d1->q_qlock, XFS_QLOCK_NESTED); |
1397 | } else { | 1403 | } else { |
1398 | xfs_dqlock(d1); | 1404 | mutex_lock(&d1->q_qlock); |
1399 | xfs_dqlock(d2); | 1405 | mutex_lock_nested(&d2->q_qlock, XFS_QLOCK_NESTED); |
1400 | } | ||
1401 | } else { | ||
1402 | if (d1) { | ||
1403 | xfs_dqlock(d1); | ||
1404 | } else if (d2) { | ||
1405 | xfs_dqlock(d2); | ||
1406 | } | 1406 | } |
1407 | } else if (d1) { | ||
1408 | mutex_lock(&d1->q_qlock); | ||
1409 | } else if (d2) { | ||
1410 | mutex_lock(&d2->q_qlock); | ||
1407 | } | 1411 | } |
1408 | } | 1412 | } |
1409 | 1413 | ||
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h index 7e455337e2ba..d443e93b4331 100644 --- a/fs/xfs/quota/xfs_dquot.h +++ b/fs/xfs/quota/xfs_dquot.h | |||
@@ -97,6 +97,16 @@ typedef struct xfs_dquot { | |||
97 | #define dq_hashlist q_lists.dqm_hashlist | 97 | #define dq_hashlist q_lists.dqm_hashlist |
98 | #define dq_flags q_lists.dqm_flags | 98 | #define dq_flags q_lists.dqm_flags |
99 | 99 | ||
100 | /* | ||
101 | * Lock hierachy for q_qlock: | ||
102 | * XFS_QLOCK_NORMAL is the implicit default, | ||
103 | * XFS_QLOCK_NESTED is the dquot with the higher id in xfs_dqlock2 | ||
104 | */ | ||
105 | enum { | ||
106 | XFS_QLOCK_NORMAL = 0, | ||
107 | XFS_QLOCK_NESTED, | ||
108 | }; | ||
109 | |||
100 | #define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++) | 110 | #define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++) |
101 | 111 | ||
102 | #ifdef DEBUG | 112 | #ifdef DEBUG |