Merge tag 'rcu.6.4.april5.2023.3' of git://git.kernel.org/pub/scm/linux/kernel/git/jfern/linux
Pull RCU updates from Joel Fernandes:
- Updates and additions to MAINTAINERS files, with Boqun being added to
the RCU entry and Zqiang being added as an RCU reviewer.
I have also transitioned from reviewer to maintainer; however, Paul
will be taking over sending RCU pull-requests for the next merge
window.
- Resolution of hotplug warning in nohz code, achieved by fixing
cpu_is_hotpluggable() through interaction with the nohz subsystem.
Tick dependency modifications by Zqiang, focusing on fixing usage of
the TICK_DEP_BIT_RCU_EXP bitmask.
- Avoid needless calls to the rcu-lazy shrinker for CONFIG_RCU_LAZY=n
kernels, fixed by Zqiang.
- Improvements to rcu-tasks stall reporting by Neeraj.
- Initial renaming of k[v]free_rcu() to k[v]free_rcu_mightsleep() for
increased robustness, affecting several components like mac802154,
drbd, vmw_vmci, tracing, and more.
A report by Eric Dumazet showed that the API could be unknowingly
used in an atomic context, so we'd rather make sure they know what
they're asking for by being explicit:
https://lore.kernel.org/all/20221202052847.2623997-1-edumazet@google.com/
- Documentation updates, including corrections to spelling,
clarifications in comments, and improvements to the srcu_size_state
comments.
- Better srcu_struct cache locality for readers, by adjusting the size
of srcu_struct in support of SRCU usage by Christoph Hellwig.
- Teach lockdep to detect deadlocks between srcu_read_lock() vs
synchronize_srcu() contributed by Boqun.
Previously lockdep could not detect such deadlocks, now it can.
- Integration of rcutorture and rcu-related tools, targeted for v6.4
from Boqun's tree, featuring new SRCU deadlock scenarios, test_nmis
module parameter, and more
- Miscellaneous changes, various code cleanups and comment improvements
* tag 'rcu.6.4.april5.2023.3' of git://git.kernel.org/pub/scm/linux/kernel/git/jfern/linux: (71 commits)
checkpatch: Error out if deprecated RCU API used
mac802154: Rename kfree_rcu() to kvfree_rcu_mightsleep()
rcuscale: Rename kfree_rcu() to kfree_rcu_mightsleep()
ext4/super: Rename kfree_rcu() to kfree_rcu_mightsleep()
net/mlx5: Rename kfree_rcu() to kfree_rcu_mightsleep()
net/sysctl: Rename kvfree_rcu() to kvfree_rcu_mightsleep()
lib/test_vmalloc.c: Rename kvfree_rcu() to kvfree_rcu_mightsleep()
tracing: Rename kvfree_rcu() to kvfree_rcu_mightsleep()
misc: vmw_vmci: Rename kvfree_rcu() to kvfree_rcu_mightsleep()
drbd: Rename kvfree_rcu() to kvfree_rcu_mightsleep()
rcu: Protect rcu_print_task_exp_stall() ->exp_tasks access
rcu: Avoid stack overflow due to __rcu_irq_enter_check_tick() being kprobe-ed
rcu-tasks: Report stalls during synchronize_srcu() in rcu_tasks_postscan()
rcu: Permit start_poll_synchronize_rcu_expedited() to be invoked early
rcu: Remove never-set needwake assignment from rcu_report_qs_rdp()
rcu: Register rcu-lazy shrinker only for CONFIG_RCU_LAZY=y kernels
rcu: Fix missing TICK_DEP_MASK_RCU_EXP dependency check
rcu: Fix set/clear TICK_DEP_BIT_RCU_EXP bitmask race
rcu/trace: use strscpy() to instead of strncpy()
tick/nohz: Fix cpu_is_hotpluggable() by checking with nohz subsystem
...
This commit is contained in:
@@ -1881,6 +1881,8 @@ print_circular_lock_scenario(struct held_lock *src,
|
||||
struct lock_class *source = hlock_class(src);
|
||||
struct lock_class *target = hlock_class(tgt);
|
||||
struct lock_class *parent = prt->class;
|
||||
int src_read = src->read;
|
||||
int tgt_read = tgt->read;
|
||||
|
||||
/*
|
||||
* A direct locking problem where unsafe_class lock is taken
|
||||
@@ -1908,7 +1910,10 @@ print_circular_lock_scenario(struct held_lock *src,
|
||||
printk(" Possible unsafe locking scenario:\n\n");
|
||||
printk(" CPU0 CPU1\n");
|
||||
printk(" ---- ----\n");
|
||||
printk(" lock(");
|
||||
if (tgt_read != 0)
|
||||
printk(" rlock(");
|
||||
else
|
||||
printk(" lock(");
|
||||
__print_lock_name(target);
|
||||
printk(KERN_CONT ");\n");
|
||||
printk(" lock(");
|
||||
@@ -1917,7 +1922,12 @@ print_circular_lock_scenario(struct held_lock *src,
|
||||
printk(" lock(");
|
||||
__print_lock_name(target);
|
||||
printk(KERN_CONT ");\n");
|
||||
printk(" lock(");
|
||||
if (src_read != 0)
|
||||
printk(" rlock(");
|
||||
else if (src->sync)
|
||||
printk(" sync(");
|
||||
else
|
||||
printk(" lock(");
|
||||
__print_lock_name(source);
|
||||
printk(KERN_CONT ");\n");
|
||||
printk("\n *** DEADLOCK ***\n\n");
|
||||
@@ -4531,7 +4541,13 @@ mark_usage(struct task_struct *curr, struct held_lock *hlock, int check)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (!hlock->hardirqs_off) {
|
||||
|
||||
/*
|
||||
* For lock_sync(), don't mark the ENABLED usage, since lock_sync()
|
||||
* creates no critical section and no extra dependency can be introduced
|
||||
* by interrupts
|
||||
*/
|
||||
if (!hlock->hardirqs_off && !hlock->sync) {
|
||||
if (hlock->read) {
|
||||
if (!mark_lock(curr, hlock,
|
||||
LOCK_ENABLED_HARDIRQ_READ))
|
||||
@@ -4910,7 +4926,7 @@ static int __lock_is_held(const struct lockdep_map *lock, int read);
|
||||
static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
|
||||
int trylock, int read, int check, int hardirqs_off,
|
||||
struct lockdep_map *nest_lock, unsigned long ip,
|
||||
int references, int pin_count)
|
||||
int references, int pin_count, int sync)
|
||||
{
|
||||
struct task_struct *curr = current;
|
||||
struct lock_class *class = NULL;
|
||||
@@ -4961,7 +4977,8 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
|
||||
|
||||
class_idx = class - lock_classes;
|
||||
|
||||
if (depth) { /* we're holding locks */
|
||||
if (depth && !sync) {
|
||||
/* we're holding locks and the new held lock is not a sync */
|
||||
hlock = curr->held_locks + depth - 1;
|
||||
if (hlock->class_idx == class_idx && nest_lock) {
|
||||
if (!references)
|
||||
@@ -4995,6 +5012,7 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
|
||||
hlock->trylock = trylock;
|
||||
hlock->read = read;
|
||||
hlock->check = check;
|
||||
hlock->sync = !!sync;
|
||||
hlock->hardirqs_off = !!hardirqs_off;
|
||||
hlock->references = references;
|
||||
#ifdef CONFIG_LOCK_STAT
|
||||
@@ -5056,6 +5074,10 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
|
||||
if (!validate_chain(curr, hlock, chain_head, chain_key))
|
||||
return 0;
|
||||
|
||||
/* For lock_sync(), we are done here since no actual critical section */
|
||||
if (hlock->sync)
|
||||
return 1;
|
||||
|
||||
curr->curr_chain_key = chain_key;
|
||||
curr->lockdep_depth++;
|
||||
check_chain_key(curr);
|
||||
@@ -5197,7 +5219,7 @@ static int reacquire_held_locks(struct task_struct *curr, unsigned int depth,
|
||||
hlock->read, hlock->check,
|
||||
hlock->hardirqs_off,
|
||||
hlock->nest_lock, hlock->acquire_ip,
|
||||
hlock->references, hlock->pin_count)) {
|
||||
hlock->references, hlock->pin_count, 0)) {
|
||||
case 0:
|
||||
return 1;
|
||||
case 1:
|
||||
@@ -5667,7 +5689,7 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
|
||||
|
||||
lockdep_recursion_inc();
|
||||
__lock_acquire(lock, subclass, trylock, read, check,
|
||||
irqs_disabled_flags(flags), nest_lock, ip, 0, 0);
|
||||
irqs_disabled_flags(flags), nest_lock, ip, 0, 0, 0);
|
||||
lockdep_recursion_finish();
|
||||
raw_local_irq_restore(flags);
|
||||
}
|
||||
@@ -5693,6 +5715,34 @@ void lock_release(struct lockdep_map *lock, unsigned long ip)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lock_release);
|
||||
|
||||
/*
|
||||
* lock_sync() - A special annotation for synchronize_{s,}rcu()-like API.
|
||||
*
|
||||
* No actual critical section is created by the APIs annotated with this: these
|
||||
* APIs are used to wait for one or multiple critical sections (on other CPUs
|
||||
* or threads), and it means that calling these APIs inside these critical
|
||||
* sections is potential deadlock.
|
||||
*/
|
||||
void lock_sync(struct lockdep_map *lock, unsigned subclass, int read,
|
||||
int check, struct lockdep_map *nest_lock, unsigned long ip)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (unlikely(!lockdep_enabled()))
|
||||
return;
|
||||
|
||||
raw_local_irq_save(flags);
|
||||
check_flags(flags);
|
||||
|
||||
lockdep_recursion_inc();
|
||||
__lock_acquire(lock, subclass, 0, read, check,
|
||||
irqs_disabled_flags(flags), nest_lock, ip, 0, 0, 1);
|
||||
check_chain_key(current);
|
||||
lockdep_recursion_finish();
|
||||
raw_local_irq_restore(flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(lock_sync);
|
||||
|
||||
noinstr int lock_is_held_type(const struct lockdep_map *lock, int read)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
@@ -659,7 +659,7 @@ static int __init test_ww_mutex_init(void)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = stress(4095, hweight32(STRESS_ALL)*ncpus, STRESS_ALL);
|
||||
ret = stress(2047, hweight32(STRESS_ALL)*ncpus, STRESS_ALL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user