Re: [RFC] Catch dwmw2's deadlock

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Dec 30, 2022 at 12:30:12PM -0800, Paul E. McKenney wrote:
> On Fri, Dec 30, 2022 at 11:38:21AM +0000, Matthew Wilcox wrote:
> > 
> > <dwmw2> why doesn't lockdep catch us calling synchronize_srcu() with
> >    a lock held, and elsewhere obtaining that lock within an srcu critical
> >    region ("read lock") ?
> > 
> > Because synchronize_srcu() doesn't acquire the lock, merely checks that
> > it isn't held.
> > 
> > Would this work?  Not even compile tested.
> > 
> > You can put my SoB on this if it works.
> > 
> > diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
> > index ca4b5dcec675..e9c2ab8369c0 100644
> > --- a/kernel/rcu/srcutree.c
> > +++ b/kernel/rcu/srcutree.c
> > @@ -1267,11 +1267,11 @@ static void __synchronize_srcu(struct srcu_struct *ssp, bool do_norm)
> >  {
> >  	struct rcu_synchronize rcu;
> >  
> > -	RCU_LOCKDEP_WARN(lockdep_is_held(ssp) ||
> > -			 lock_is_held(&rcu_bh_lock_map) ||
> > +	rcu_lock_acquire(&ssp->dep_map);
> 
> If this does do anything, why doesn't lockdep complain about things
> like this?
> 
> 	i1 = srcu_read_lock(&my_srcu);
> 	i2 = srcu_read_lock(&my_srcu);
> 	srcu_read_unlock(&my_srcu, i2);
> 	srcu_read_unlock(&my_srcu, i1);
> 
> Or does it in fact complain and I have somehow managed to confuse things
> such that rcutorture does not detect such complaints?  I would expect
> rcutorture_extend_mask_max() to make this happen, but then again, RCU
> has confused me in the past.

static inline void rcu_lock_acquire(struct lockdep_map *map)
{
        lock_acquire(map, 0, 0, 2, 0, NULL, _THIS_IP_);
}

That's clear as mud, of course.  The fourth argument, which has value
'2' is documented as 'int read', and that has the meaning:

 * Values for "read":
 *
 *   0: exclusive (write) acquire
 *   1: read-acquire (no recursion allowed)
 *   2: read-acquire with same-instance recursion allowed

But that's enough to establish the locking hierarchy.  ie if you do:

read-lock-A
write-lock-B

in one thread and in the other thread do:

write-lock-B
read-lock-A

lockdep is still going to detect that as a deadly embrace.  Isn't it?

In any case, I was just trying to point out the general outlines of
something I saw as a potential solution.  If we need to turn that into
lock_acquire(map, 0, 0, 0, 0, NULL, _THIS_IP), that's fine.  And Joel
is right, there needs to be a release in that other path.

But I am not an expert in RCU, lockdep, or working while travelling,
so I was rather hoping someone like dwmw2 would pick up the sketch,
make it compile, and then test it.



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux