locking, percpu counters: introduce separate lock classes

Impact: fix lockdep false positives

Classify percpu_counter instances similar to regular lock objects --
that is, per instantiation site.

The networking code has increased its use of percpu_counters, which
leads to false positives if they are treated as a single class.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
Peter Zijlstra 2008-12-26 15:08:55 +01:00 committed by Ingo Molnar
parent 00ef9f7348
commit ea319518ba
4 changed files with 18 additions and 22 deletions

View File

@ -30,8 +30,16 @@ struct percpu_counter {
#define FBC_BATCH (NR_CPUS*4) #define FBC_BATCH (NR_CPUS*4)
#endif #endif
int percpu_counter_init(struct percpu_counter *fbc, s64 amount); int __percpu_counter_init(struct percpu_counter *fbc, s64 amount,
int percpu_counter_init_irq(struct percpu_counter *fbc, s64 amount); struct lock_class_key *key);
#define percpu_counter_init(fbc, value) \
({ \
static struct lock_class_key __key; \
\
__percpu_counter_init(fbc, value, &__key); \
})
void percpu_counter_destroy(struct percpu_counter *fbc); void percpu_counter_destroy(struct percpu_counter *fbc);
void percpu_counter_set(struct percpu_counter *fbc, s64 amount); void percpu_counter_set(struct percpu_counter *fbc, s64 amount);
void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch); void __percpu_counter_add(struct percpu_counter *fbc, s64 amount, s32 batch);
@ -85,8 +93,6 @@ static inline int percpu_counter_init(struct percpu_counter *fbc, s64 amount)
return 0; return 0;
} }
#define percpu_counter_init_irq percpu_counter_init
static inline void percpu_counter_destroy(struct percpu_counter *fbc) static inline void percpu_counter_destroy(struct percpu_counter *fbc)
{ {
} }

View File

@ -71,11 +71,11 @@ s64 __percpu_counter_sum(struct percpu_counter *fbc)
} }
EXPORT_SYMBOL(__percpu_counter_sum); EXPORT_SYMBOL(__percpu_counter_sum);
static struct lock_class_key percpu_counter_irqsafe; int __percpu_counter_init(struct percpu_counter *fbc, s64 amount,
struct lock_class_key *key)
int percpu_counter_init(struct percpu_counter *fbc, s64 amount)
{ {
spin_lock_init(&fbc->lock); spin_lock_init(&fbc->lock);
lockdep_set_class(&fbc->lock, key);
fbc->count = amount; fbc->count = amount;
fbc->counters = alloc_percpu(s32); fbc->counters = alloc_percpu(s32);
if (!fbc->counters) if (!fbc->counters)
@ -87,17 +87,7 @@ int percpu_counter_init(struct percpu_counter *fbc, s64 amount)
#endif #endif
return 0; return 0;
} }
EXPORT_SYMBOL(percpu_counter_init); EXPORT_SYMBOL(__percpu_counter_init);
int percpu_counter_init_irq(struct percpu_counter *fbc, s64 amount)
{
int err;
err = percpu_counter_init(fbc, amount);
if (!err)
lockdep_set_class(&fbc->lock, &percpu_counter_irqsafe);
return err;
}
void percpu_counter_destroy(struct percpu_counter *fbc) void percpu_counter_destroy(struct percpu_counter *fbc)
{ {

View File

@ -83,11 +83,11 @@ int prop_descriptor_init(struct prop_descriptor *pd, int shift)
pd->index = 0; pd->index = 0;
pd->pg[0].shift = shift; pd->pg[0].shift = shift;
mutex_init(&pd->mutex); mutex_init(&pd->mutex);
err = percpu_counter_init_irq(&pd->pg[0].events, 0); err = percpu_counter_init(&pd->pg[0].events, 0);
if (err) if (err)
goto out; goto out;
err = percpu_counter_init_irq(&pd->pg[1].events, 0); err = percpu_counter_init(&pd->pg[1].events, 0);
if (err) if (err)
percpu_counter_destroy(&pd->pg[0].events); percpu_counter_destroy(&pd->pg[0].events);
@ -191,7 +191,7 @@ int prop_local_init_percpu(struct prop_local_percpu *pl)
spin_lock_init(&pl->lock); spin_lock_init(&pl->lock);
pl->shift = 0; pl->shift = 0;
pl->period = 0; pl->period = 0;
return percpu_counter_init_irq(&pl->events, 0); return percpu_counter_init(&pl->events, 0);
} }
void prop_local_destroy_percpu(struct prop_local_percpu *pl) void prop_local_destroy_percpu(struct prop_local_percpu *pl)

View File

@ -220,7 +220,7 @@ int bdi_init(struct backing_dev_info *bdi)
bdi->max_prop_frac = PROP_FRAC_BASE; bdi->max_prop_frac = PROP_FRAC_BASE;
for (i = 0; i < NR_BDI_STAT_ITEMS; i++) { for (i = 0; i < NR_BDI_STAT_ITEMS; i++) {
err = percpu_counter_init_irq(&bdi->bdi_stat[i], 0); err = percpu_counter_init(&bdi->bdi_stat[i], 0);
if (err) if (err)
goto err; goto err;
} }