Commit f112a049 authored by Dave Chinner's avatar Dave Chinner Committed by Ben Myers

xfs: lockdep needs to know about 3 dquot-deep nesting

Michael Semon reported that xfs/299 generated this lockdep warning:

=============================================
[ INFO: possible recursive locking detected ]
3.12.0-rc2+ #2 Not tainted
---------------------------------------------
touch/21072 is trying to acquire lock:
 (&xfs_dquot_other_class){+.+...}, at: [<c12902fb>] xfs_trans_dqlockedjoin+0x57/0x64

but task is already holding lock:
 (&xfs_dquot_other_class){+.+...}, at: [<c12902fb>] xfs_trans_dqlockedjoin+0x57/0x64

other info that might help us debug this:
 Possible unsafe locking scenario:

       CPU0
       ----
  lock(&xfs_dquot_other_class);
  lock(&xfs_dquot_other_class);

 *** DEADLOCK ***

 May be due to missing lock nesting notation

7 locks held by touch/21072:
 #0:  (sb_writers#10){++++.+}, at: [<c11185b6>] mnt_want_write+0x1e/0x3e
 #1:  (&type->i_mutex_dir_key#4){+.+.+.}, at: [<c11078ee>] do_last+0x245/0xe40
 #2:  (sb_internal#2){++++.+}, at: [<c122c9e0>] xfs_trans_alloc+0x1f/0x35
 #3:  (&(&ip->i_lock)->mr_lock/1){+.+...}, at: [<c126cd1b>] xfs_ilock+0x100/0x1f1
 #4:  (&(&ip->i_lock)->mr_lock){++++-.}, at: [<c126cf52>] xfs_ilock_nowait+0x105/0x22f
 #5:  (&dqp->q_qlock){+.+...}, at: [<c12902fb>] xfs_trans_dqlockedjoin+0x57/0x64
 #6:  (&xfs_dquot_other_class){+.+...}, at: [<c12902fb>] xfs_trans_dqlockedjoin+0x57/0x64

The lockdep annotation for dquot lock nesting only understands
locking for user and "other" dquots, not user, group and quota
dquots. Fix the annotations to match the locking heirarchy we now
have.
Reported-by: default avatarMichael L. Semon <mlsemon35@gmail.com>
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarBen Myers <bpm@sgi.com>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>
parent 997def25
...@@ -64,7 +64,8 @@ int xfs_dqerror_mod = 33; ...@@ -64,7 +64,8 @@ int xfs_dqerror_mod = 33;
struct kmem_zone *xfs_qm_dqtrxzone; struct kmem_zone *xfs_qm_dqtrxzone;
static struct kmem_zone *xfs_qm_dqzone; static struct kmem_zone *xfs_qm_dqzone;
static struct lock_class_key xfs_dquot_other_class; static struct lock_class_key xfs_dquot_group_class;
static struct lock_class_key xfs_dquot_project_class;
/* /*
* This is called to free all the memory associated with a dquot * This is called to free all the memory associated with a dquot
...@@ -703,8 +704,20 @@ xfs_qm_dqread( ...@@ -703,8 +704,20 @@ xfs_qm_dqread(
* Make sure group quotas have a different lock class than user * Make sure group quotas have a different lock class than user
* quotas. * quotas.
*/ */
if (!(type & XFS_DQ_USER)) switch (type) {
lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class); case XFS_DQ_USER:
/* uses the default lock class */
break;
case XFS_DQ_GROUP:
lockdep_set_class(&dqp->q_qlock, &xfs_dquot_group_class);
break;
case XFS_DQ_PROJ:
lockdep_set_class(&dqp->q_qlock, &xfs_dquot_project_class);
break;
default:
ASSERT(0);
break;
}
XFS_STATS_INC(xs_qm_dquot); XFS_STATS_INC(xs_qm_dquot);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment