All of lore.kernel.org
 help / color / mirror / Atom feed
From: Bart Van Assche <bvanassche@acm.org>
To: Waiman Long <longman@redhat.com>, mingo@redhat.com
Cc: peterz@infradead.org, tj@kernel.org, johannes.berg@intel.com,
	linux-kernel@vger.kernel.org,
	Johannes Berg <johannes@sipsolutions.net>
Subject: Re: [PATCH v2 17/24] locking/lockdep: Free lock classes that are no longer in use
Date: Tue, 04 Dec 2018 13:42:47 -0800	[thread overview]
Message-ID: <1543959767.185366.217.camel@acm.org> (raw)
In-Reply-To: <46b0ff3c-aa6e-7183-3554-19ed112536aa@redhat.com>

On Tue, 2018-12-04 at 15:27 -0500, Waiman Long wrote:
> On 12/03/2018 07:28 PM, Bart Van Assche wrote:
> > +/* Must be called with the graph lock held. */
> > +static void remove_class_from_lock_chain(struct lock_chain *chain,
> > +					 struct lock_class *class)
> > +{
> > +	u64 chain_key;
> > +	int i;
> > +
> > +#ifdef CONFIG_PROVE_LOCKING
> > +	for (i = chain->base; i < chain->base + chain->depth; i++) {
> > +		if (chain_hlocks[i] != class - lock_classes)
> > +			continue;
> > +		if (--chain->depth == 0)
> > +			break;
> > +		memmove(&chain_hlocks[i], &chain_hlocks[i + 1],
> > +			(chain->base + chain->depth - i) *
> > +			sizeof(chain_hlocks[0]));
> > +		/*
> > +		 * Each lock class occurs at most once in a
> > +		 * lock chain so once we found a match we can
> > +		 * break out of this loop.
> > +		 */
> > +		break;
> > +	}
> > +	/*
> > +	 * Note: calling hlist_del_rcu() from inside a
> > +	 * hlist_for_each_entry_rcu() loop is safe.
> > +	 */
> > +	if (chain->depth == 0) {
> > +		/* To do: decrease chain count. See also inc_chains(). */
> > +		hlist_del_rcu(&chain->entry);
> > +		return;
> > +	}
> > +	chain_key = 0;
> > +	for (i = chain->base; i < chain->base + chain->depth; i++)
> > +		chain_key = iterate_chain_key(chain_key, chain_hlocks[i] + 1);
> 
> Do you need to recompute the chain_key if no entry in the chain is removed?

Thanks for having pointed that out. I will modify this function such that the
chain key is only recalculated if necessary.

> >  
> > @@ -4141,14 +4253,31 @@ static void zap_class(struct lock_class *class)
> >  	for (i = 0, entry = list_entries; i < nr_list_entries; i++, entry++) {
> >  		if (entry->class != class && entry->links_to != class)
> >  			continue;
> > +		links_to = entry->links_to;
> > +		WARN_ON_ONCE(entry->class == links_to);
> >  		list_del_rcu(&entry->entry);
> > +		check_free_class(class);
> 
> Is the check_free_class() call redundant? You are going to call it near
> the end below.

I think so. I will remove the check_free_class() that is inside the for-loop.

> > +static void reinit_class(struct lock_class *class)
> > +{
> > +	void *const p = class;
> > +	const unsigned int offset = offsetof(struct lock_class, key);
> > +
> > +	WARN_ON_ONCE(!class->lock_entry.next);
> > +	WARN_ON_ONCE(!list_empty(&class->locks_after));
> > +	WARN_ON_ONCE(!list_empty(&class->locks_before));
> > +	memset(p + offset, 0, sizeof(*class) - offset);
> > +	WARN_ON_ONCE(!class->lock_entry.next);
> > +	WARN_ON_ONCE(!list_empty(&class->locks_after));
> > +	WARN_ON_ONCE(!list_empty(&class->locks_before));
> >  }
> 
> Is it safer to just reinit those fields before "key" instead of using
> memset()? Lockdep is slow anyway, doing that individually won't
> introduce any noticeable slowdown.

The warning statements will only be hit if the order of the struct lock_class members
would be modified. I don't think that we need to change the approach of this function.

> > @@ -4193,18 +4355,14 @@ void lockdep_free_key_range(void *start, unsigned long size)
> >  	raw_local_irq_restore(flags);
> >  
> >  	/*
> > -	 * Wait for any possible iterators from look_up_lock_class() to pass
> > -	 * before continuing to free the memory they refer to.
> > -	 *
> > -	 * sync_sched() is sufficient because the read-side is IRQ disable.
> > +	 * Do not wait for concurrent look_up_lock_class() calls. If any such
> > +	 * concurrent call would return a pointer to one of the lock classes
> > +	 * freed by this function then that means that there is a race in the
> > +	 * code that calls look_up_lock_class(), namely concurrently accessing
> > +	 * and freeing a synchronization object.
> >  	 */
> > -	synchronize_sched();
> >  
> > -	/*
> > -	 * XXX at this point we could return the resources to the pool;
> > -	 * instead we leak them. We would need to change to bitmap allocators
> > -	 * instead of the linear allocators we have now.
> > -	 */
> > +	schedule_free_zapped_classes();
> 
> Should you move the graph_unlock() and raw_lock_irq_restore() down to
> after this? The schedule_free_zapped_classes must be called with
> graph_lock held. Right?

I will modify this and other patches such that all schedule_free_zapped_classes()
calls are protected by the graph lock.

Bart.

  reply	other threads:[~2018-12-04 21:42 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-04  0:28 [PATCH v2 00/24] locking/lockdep: Add support for dynamic keys Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 01/24] lockdep tests: Display compiler warning and error messages Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 02/24] lockdep tests: Fix shellcheck warnings Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 03/24] lockdep tests: Improve testing accuracy Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 04/24] lockdep tests: Run lockdep tests a second time under Valgrind Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 05/24] liblockdep: Rename "trywlock" into "trywrlock" Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 06/24] liblockdep: Add dummy print_irqtrace_events() implementation Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 07/24] lockdep tests: Test the lockdep_reset_lock() implementation Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 08/24] locking/lockdep: Declare local symbols static Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 09/24] locking/lockdep: Inline __lockdep_init_map() Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 10/24] locking/lockdep: Introduce lock_class_cache_is_registered() Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 11/24] locking/lockdep: Remove a superfluous INIT_LIST_HEAD() statement Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 12/24] locking/lockdep: Make concurrent lockdep_reset_lock() calls safe Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 13/24] locking/lockdep: Stop using RCU primitives to access all_lock_classes Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 14/24] locking/lockdep: Make zap_class() remove all matching lock order entries Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 15/24] locking/lockdep: Reorder struct lock_class members Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 16/24] locking/lockdep: Retain the class key and name while freeing a lock class Bart Van Assche
2018-12-04 18:57   ` Waiman Long
2018-12-04 19:08     ` Bart Van Assche
2018-12-04 20:31       ` Waiman Long
2018-12-04 21:07         ` Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 17/24] locking/lockdep: Free lock classes that are no longer in use Bart Van Assche
2018-12-04 20:27   ` Waiman Long
2018-12-04 21:42     ` Bart Van Assche [this message]
2018-12-04  0:28 ` [PATCH v2 18/24] locking/lockdep: Reuse list entries " Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 19/24] locking/lockdep: Check data structure consistency Bart Van Assche
2018-12-04 20:53   ` Waiman Long
2018-12-04  0:28 ` [PATCH v2 20/24] locking/lockdep: Introduce __lockdep_free_key_range() Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 21/24] locking/lockdep: Verify whether lock objects are small enough to be used as class keys Bart Van Assche
2018-12-04 21:08   ` Waiman Long
2018-12-04 21:39     ` Bart Van Assche
2018-12-04 21:50       ` Waiman Long
2018-12-05  0:06         ` Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 22/24] locking/lockdep: Add support for dynamic keys Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 23/24] kernel/workqueue: Use dynamic lockdep keys for workqueues Bart Van Assche
2018-12-04  0:28 ` [PATCH v2 24/24] lockdep tests: Test dynamic key registration Bart Van Assche

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1543959767.185366.217.camel@acm.org \
    --to=bvanassche@acm.org \
    --cc=johannes.berg@intel.com \
    --cc=johannes@sipsolutions.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=longman@redhat.com \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tj@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.