public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [GIT PULL] LOCKDEP and Rust locking changes for v6.15
@ 2025-02-26  4:12 Boqun Feng
  2025-02-28 18:57 ` Boqun Feng
                   ` (2 more replies)
  0 siblings, 3 replies; 31+ messages in thread
From: Boqun Feng @ 2025-02-26  4:12 UTC (permalink / raw)
  To: Peter Zijlstra, mingo
  Cc: Will Deacon, Waiman Long, linux-kernel, Miguel Ojeda, Alex Gaynor,
	Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux

Hi Peter & Ingo,

Please pull the changes of lockdep and Rust locking for v6.15 into tip.

The following changes since commit 337369f8ce9e20226402cf139c4f0d3ada7d1705:

  locking/mutex: Add MUTEX_WARN_ON() into fast path (2025-02-21 20:19:12 +0100)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/boqun/linux.git tags/lockdep-for-tip.2025.02.25

for you to fetch changes up to 3b5b307cf84ca3a73abe797df31e0efe897411a9:

  rust: lockdep: Use Pin for all LockClassKey usages (2025-02-25 08:53:08 -0800)


Regards,
Boqun

----------------------------------------------------------------
Lockdep changes for v6.15:

- Fix kernel-doc for rtmutex.
- Fix lock wait context check on softirq for PREEMPT_RT.
- Disable KASAN for lockdep to improve debug kernel performance.

Miscellaneous locking changes for v6.15:

- Use wake_q for semaphore to avoid wake-up in lock critical sections.

Rust locking changes for v6.15:

- Fix the soundness issue around dynamically allocated lock class keys.
- Add CondVar::wait_interruptible_freezable() to allow freezable waits.
- Add Guard::lock_ref() to access the lock reference behind a lock
  guard.

----------------------------------------------------------------
Alice Ryhl (2):
      rust: sync: Add accessor for the lock behind a given guard
      rust: sync: condvar: Add wait_interruptible_freezable()

Boqun Feng (1):
      rust: sync: lock: Add an example for Guard::lock_ref()

Mitchell Levy (2):
      rust: lockdep: Remove support for dynamically allocated LockClassKeys
      rust: lockdep: Use Pin for all LockClassKey usages

Randy Dunlap (1):
      locking/rtmutex: Use struct keyword in kernel-doc comment

Ryo Takakura (1):
      lockdep: Fix wait context check on softirq for PREEMPT_RT

Waiman Long (5):
      locking/semaphore: Use wake_q to wake up processes outside lock critical section
      locking/lock_events: Add locking events for rtmutex slow paths
      locking/lock_events: Add locking events for lockdep
      locking/lockdep: Disable KASAN instrumentation of lockdep.c
      locking/lockdep: Add kasan_check_byte() check in lock_acquire()

 include/linux/bottom_half.h       |  8 +++++
 kernel/locking/Makefile           |  3 +-
 kernel/locking/lock_events_list.h | 28 +++++++++++++++++
 kernel/locking/lockdep.c          | 17 ++++++++++-
 kernel/locking/rtmutex.c          | 29 ++++++++++++++----
 kernel/locking/rtmutex_common.h   |  4 +--
 kernel/locking/semaphore.c        | 13 +++++---
 kernel/softirq.c                  | 12 ++++++++
 rust/helpers/helpers.c            |  1 +
 rust/helpers/sync.c               | 13 ++++++++
 rust/kernel/sync.rs               | 63 ++++++++++++++++++++++++++++++++-------
 rust/kernel/sync/condvar.rs       | 28 ++++++++++++++---
 rust/kernel/sync/lock.rs          | 35 ++++++++++++++++++++--
 rust/kernel/sync/lock/global.rs   |  5 ++--
 rust/kernel/sync/poll.rs          |  2 +-
 rust/kernel/task.rs               |  2 ++
 rust/kernel/workqueue.rs          |  2 +-
 17 files changed, 231 insertions(+), 34 deletions(-)
 create mode 100644 rust/helpers/sync.c

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [GIT PULL] LOCKDEP and Rust locking changes for v6.15
  2025-02-26  4:12 [GIT PULL] LOCKDEP and Rust locking changes for v6.15 Boqun Feng
@ 2025-02-28 18:57 ` Boqun Feng
  2025-03-03 16:52   ` Waiman Long
  2025-03-03 18:42 ` Peter Zijlstra
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
  2 siblings, 1 reply; 31+ messages in thread
From: Boqun Feng @ 2025-02-28 18:57 UTC (permalink / raw)
  To: Peter Zijlstra, mingo
  Cc: Will Deacon, Waiman Long, linux-kernel, Miguel Ojeda, Alex Gaynor,
	Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Alice Ryhl, Trevor Gross, Danilo Krummrich, rust-for-linux

On Tue, Feb 25, 2025 at 08:12:03PM -0800, Boqun Feng wrote:
> Hi Peter & Ingo,
> 

Ping ;-)

Regards,
Boqun

> Please pull the changes of lockdep and Rust locking for v6.15 into tip.
> 
> The following changes since commit 337369f8ce9e20226402cf139c4f0d3ada7d1705:
> 
>   locking/mutex: Add MUTEX_WARN_ON() into fast path (2025-02-21 20:19:12 +0100)
> 
> are available in the Git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/boqun/linux.git tags/lockdep-for-tip.2025.02.25
> 
> for you to fetch changes up to 3b5b307cf84ca3a73abe797df31e0efe897411a9:
> 
>   rust: lockdep: Use Pin for all LockClassKey usages (2025-02-25 08:53:08 -0800)
> 
> 
> Regards,
> Boqun
> 
> ----------------------------------------------------------------
> Lockdep changes for v6.15:
> 
> - Fix kernel-doc for rtmutex.
> - Fix lock wait context check on softirq for PREEMPT_RT.
> - Disable KASAN for lockdep to improve debug kernel performance.
> 
> Miscellaneous locking changes for v6.15:
> 
> - Use wake_q for semaphore to avoid wake-up in lock critical sections.
> 
> Rust locking changes for v6.15:
> 
> - Fix the soundness issue around dynamically allocated lock class keys.
> - Add CondVar::wait_interruptible_freezable() to allow freezable waits.
> - Add Guard::lock_ref() to access the lock reference behind a lock
>   guard.
> 
> ----------------------------------------------------------------
> Alice Ryhl (2):
>       rust: sync: Add accessor for the lock behind a given guard
>       rust: sync: condvar: Add wait_interruptible_freezable()
> 
> Boqun Feng (1):
>       rust: sync: lock: Add an example for Guard::lock_ref()
> 
> Mitchell Levy (2):
>       rust: lockdep: Remove support for dynamically allocated LockClassKeys
>       rust: lockdep: Use Pin for all LockClassKey usages
> 
> Randy Dunlap (1):
>       locking/rtmutex: Use struct keyword in kernel-doc comment
> 
> Ryo Takakura (1):
>       lockdep: Fix wait context check on softirq for PREEMPT_RT
> 
> Waiman Long (5):
>       locking/semaphore: Use wake_q to wake up processes outside lock critical section
>       locking/lock_events: Add locking events for rtmutex slow paths
>       locking/lock_events: Add locking events for lockdep
>       locking/lockdep: Disable KASAN instrumentation of lockdep.c
>       locking/lockdep: Add kasan_check_byte() check in lock_acquire()
> 
>  include/linux/bottom_half.h       |  8 +++++
>  kernel/locking/Makefile           |  3 +-
>  kernel/locking/lock_events_list.h | 28 +++++++++++++++++
>  kernel/locking/lockdep.c          | 17 ++++++++++-
>  kernel/locking/rtmutex.c          | 29 ++++++++++++++----
>  kernel/locking/rtmutex_common.h   |  4 +--
>  kernel/locking/semaphore.c        | 13 +++++---
>  kernel/softirq.c                  | 12 ++++++++
>  rust/helpers/helpers.c            |  1 +
>  rust/helpers/sync.c               | 13 ++++++++
>  rust/kernel/sync.rs               | 63 ++++++++++++++++++++++++++++++++-------
>  rust/kernel/sync/condvar.rs       | 28 ++++++++++++++---
>  rust/kernel/sync/lock.rs          | 35 ++++++++++++++++++++--
>  rust/kernel/sync/lock/global.rs   |  5 ++--
>  rust/kernel/sync/poll.rs          |  2 +-
>  rust/kernel/task.rs               |  2 ++
>  rust/kernel/workqueue.rs          |  2 +-
>  17 files changed, 231 insertions(+), 34 deletions(-)
>  create mode 100644 rust/helpers/sync.c

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [GIT PULL] LOCKDEP and Rust locking changes for v6.15
  2025-02-28 18:57 ` Boqun Feng
@ 2025-03-03 16:52   ` Waiman Long
  0 siblings, 0 replies; 31+ messages in thread
From: Waiman Long @ 2025-03-03 16:52 UTC (permalink / raw)
  To: Peter Zijlstra, mingo
  Cc: Will Deacon, linux-kernel, Miguel Ojeda, Alex Gaynor, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
	Trevor Gross, Danilo Krummrich, rust-for-linux, Boqun Feng


On 2/28/25 1:57 PM, Boqun Feng wrote:
> On Tue, Feb 25, 2025 at 08:12:03PM -0800, Boqun Feng wrote:
>> Hi Peter & Ingo,
>>
> Ping ;-)

Hi Peter, are you going to pull this lockep branch into tip?

Thanks,
Longman


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [GIT PULL] LOCKDEP and Rust locking changes for v6.15
  2025-02-26  4:12 [GIT PULL] LOCKDEP and Rust locking changes for v6.15 Boqun Feng
  2025-02-28 18:57 ` Boqun Feng
@ 2025-03-03 18:42 ` Peter Zijlstra
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
  2 siblings, 0 replies; 31+ messages in thread
From: Peter Zijlstra @ 2025-03-03 18:42 UTC (permalink / raw)
  To: Boqun Feng
  Cc: mingo, Will Deacon, Waiman Long, linux-kernel, Miguel Ojeda,
	Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	rust-for-linux

On Tue, Feb 25, 2025 at 08:12:03PM -0800, Boqun Feng wrote:

> Alice Ryhl (2):
>       rust: sync: Add accessor for the lock behind a given guard
>       rust: sync: condvar: Add wait_interruptible_freezable()
> 
> Boqun Feng (1):
>       rust: sync: lock: Add an example for Guard::lock_ref()
> 
> Mitchell Levy (2):
>       rust: lockdep: Remove support for dynamically allocated LockClassKeys
>       rust: lockdep: Use Pin for all LockClassKey usages
> 
> Randy Dunlap (1):
>       locking/rtmutex: Use struct keyword in kernel-doc comment
> 
> Ryo Takakura (1):
>       lockdep: Fix wait context check on softirq for PREEMPT_RT
> 
> Waiman Long (5):
>       locking/semaphore: Use wake_q to wake up processes outside lock critical section
>       locking/lock_events: Add locking events for rtmutex slow paths
>       locking/lock_events: Add locking events for lockdep
>       locking/lockdep: Disable KASAN instrumentation of lockdep.c
>       locking/lockdep: Add kasan_check_byte() check in lock_acquire()

OK, done!

Thanks, and sorry for being tardy, somehow time got away from me :/

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH locking 00/11] LOCKDEP and Rust locking changes for v6.15
  2025-02-26  4:12 [GIT PULL] LOCKDEP and Rust locking changes for v6.15 Boqun Feng
  2025-02-28 18:57 ` Boqun Feng
  2025-03-03 18:42 ` Peter Zijlstra
@ 2025-03-07 23:26 ` Boqun Feng
  2025-03-07 23:26   ` [PATCH locking 01/11] locking/rtmutex: Use struct keyword in kernel-doc comment Boqun Feng
                     ` (11 more replies)
  2 siblings, 12 replies; 31+ messages in thread
From: Boqun Feng @ 2025-03-07 23:26 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Will Deacon, Waiman Long, linux-kernel, Boqun Feng, Miguel Ojeda,
	Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross,
	open list:RUST:Keyword:b(?i:rust)b

Hi Ingo & Peter,

As discussed, I'm resending the pull request for lockdep and Rust
locking for v6.15 in the format of email patches. I dropped one patch
and will postpone it for v6.16 because of a bug [1], and I think the fix
[2] needs more reviews.

[1]: https://lore.kernel.org/lkml/20250306122413.GBZ8mT7Z61Tmgnh5Y9@fat_crate.local/
[2]: https://lore.kernel.org/lkml/Z8t8imzJVhWyDvhC@boqun-archlinux/

Regards,
Boqun

Alice Ryhl (2):
  rust: sync: Add accessor for the lock behind a given guard
  rust: sync: condvar: Add wait_interruptible_freezable()

Boqun Feng (1):
  rust: sync: lock: Add an example for Guard::lock_ref()

Mitchell Levy (2):
  rust: lockdep: Remove support for dynamically allocated LockClassKeys
  rust: lockdep: Use Pin for all LockClassKey usages

Randy Dunlap (1):
  locking/rtmutex: Use struct keyword in kernel-doc comment

Waiman Long (5):
  locking/semaphore: Use wake_q to wake up processes outside lock
    critical section
  locking/lock_events: Add locking events for rtmutex slow paths
  locking/lock_events: Add locking events for lockdep
  locking/lockdep: Disable KASAN instrumentation of lockdep.c
  locking/lockdep: Add kasan_check_byte() check in lock_acquire()

 kernel/locking/Makefile           |  3 +-
 kernel/locking/lock_events_list.h | 28 ++++++++++++++
 kernel/locking/lockdep.c          | 17 ++++++++-
 kernel/locking/rtmutex.c          | 29 +++++++++++---
 kernel/locking/rtmutex_common.h   |  4 +-
 kernel/locking/semaphore.c        | 13 +++++--
 rust/helpers/helpers.c            |  1 +
 rust/helpers/sync.c               | 13 +++++++
 rust/kernel/sync.rs               | 63 ++++++++++++++++++++++++++-----
 rust/kernel/sync/condvar.rs       | 28 ++++++++++++--
 rust/kernel/sync/lock.rs          | 35 +++++++++++++++--
 rust/kernel/sync/lock/global.rs   |  5 ++-
 rust/kernel/sync/poll.rs          |  2 +-
 rust/kernel/task.rs               |  2 +
 rust/kernel/workqueue.rs          |  2 +-
 15 files changed, 211 insertions(+), 34 deletions(-)
 create mode 100644 rust/helpers/sync.c

-- 
2.47.1


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH locking 01/11] locking/rtmutex: Use struct keyword in kernel-doc comment
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
@ 2025-03-07 23:26   ` Boqun Feng
  2025-03-08  0:08     ` [tip: locking/core] locking/rtmutex: Use the 'struct' " tip-bot2 for Randy Dunlap
  2025-03-07 23:26   ` [PATCH locking 02/11] locking/semaphore: Use wake_q to wake up processes outside lock critical section Boqun Feng
                     ` (10 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: Boqun Feng @ 2025-03-07 23:26 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Will Deacon, Waiman Long, linux-kernel, Randy Dunlap, Ingo Molnar,
	Boqun Feng

From: Randy Dunlap <rdunlap@infradead.org>

Add the "struct" keyword to prevent a kernel-doc warning:

rtmutex_common.h:67: warning: cannot understand function prototype: 'struct rt_wake_q_head '

Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Will Deacon <will@kernel.org>
Cc: Waiman Long <longman@redhat.com>
Cc: Boqun Feng <boqun.feng@gmail.com>
Acked-by: Waiman Long <longman@redhat.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Link: https://lore.kernel.org/r/20250111063040.910763-1-rdunlap@infradead.org
---
 kernel/locking/rtmutex_common.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h
index c38a2d2d4a7e..78dd3d8c6554 100644
--- a/kernel/locking/rtmutex_common.h
+++ b/kernel/locking/rtmutex_common.h
@@ -59,8 +59,8 @@ struct rt_mutex_waiter {
 };
 
 /**
- * rt_wake_q_head - Wrapper around regular wake_q_head to support
- *		    "sleeping" spinlocks on RT
+ * struct rt_wake_q_head - Wrapper around regular wake_q_head to support
+ *			   "sleeping" spinlocks on RT
  * @head:		The regular wake_q_head for sleeping lock variants
  * @rtlock_task:	Task pointer for RT lock (spin/rwlock) wakeups
  */
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH locking 02/11] locking/semaphore: Use wake_q to wake up processes outside lock critical section
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
  2025-03-07 23:26   ` [PATCH locking 01/11] locking/rtmutex: Use struct keyword in kernel-doc comment Boqun Feng
@ 2025-03-07 23:26   ` Boqun Feng
  2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Waiman Long
  2025-03-07 23:26   ` [PATCH locking 03/11] locking/lock_events: Add locking events for rtmutex slow paths Boqun Feng
                     ` (9 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: Boqun Feng @ 2025-03-07 23:26 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Will Deacon, Waiman Long, linux-kernel, Boqun Feng, Ingo Molnar,
	Sebastian Andrzej Siewior, Clark Williams, Steven Rostedt,
	open list:Real-time Linux (PREEMPT_RT):Keyword:PREEMPT_RT

From: Waiman Long <longman@redhat.com>

A circular lock dependency splat has been seen involving down_trylock().

[ 4011.795602] ======================================================
[ 4011.795603] WARNING: possible circular locking dependency detected
[ 4011.795607] 6.12.0-41.el10.s390x+debug
[ 4011.795612] ------------------------------------------------------
[ 4011.795613] dd/32479 is trying to acquire lock:
[ 4011.795617] 0015a20accd0d4f8 ((console_sem).lock){-.-.}-{2:2}, at: down_trylock+0x26/0x90
[ 4011.795636]
[ 4011.795636] but task is already holding lock:
[ 4011.795637] 000000017e461698 (&zone->lock){-.-.}-{2:2}, at: rmqueue_bulk+0xac/0x8f0

  the existing dependency chain (in reverse order) is:
  -> #4 (&zone->lock){-.-.}-{2:2}:
  -> #3 (hrtimer_bases.lock){-.-.}-{2:2}:
  -> #2 (&rq->__lock){-.-.}-{2:2}:
  -> #1 (&p->pi_lock){-.-.}-{2:2}:
  -> #0 ((console_sem).lock){-.-.}-{2:2}:

The console_sem -> pi_lock dependency is due to calling try_to_wake_up()
while holding the console.sem raw_spinlock. This dependency can be broken
by using wake_q to do the wakeup instead of calling try_to_wake_up()
under the console_sem lock. This will also make the semaphore's
raw_spinlock become a terminal lock without taking any further locks
underneath it.

The hrtimer_bases.lock is a raw_spinlock while zone->lock is a
spinlock. The hrtimer_bases.lock -> zone->lock dependency happens via
the debug_objects_fill_pool() helper function in the debugobjects code.

[ 4011.795646] -> #4 (&zone->lock){-.-.}-{2:2}:
[ 4011.795650]        __lock_acquire+0xe86/0x1cc0
[ 4011.795655]        lock_acquire.part.0+0x258/0x630
[ 4011.795657]        lock_acquire+0xb8/0xe0
[ 4011.795659]        _raw_spin_lock_irqsave+0xb4/0x120
[ 4011.795663]        rmqueue_bulk+0xac/0x8f0
[ 4011.795665]        __rmqueue_pcplist+0x580/0x830
[ 4011.795667]        rmqueue_pcplist+0xfc/0x470
[ 4011.795669]        rmqueue.isra.0+0xdec/0x11b0
[ 4011.795671]        get_page_from_freelist+0x2ee/0xeb0
[ 4011.795673]        __alloc_pages_noprof+0x2c2/0x520
[ 4011.795676]        alloc_pages_mpol_noprof+0x1fc/0x4d0
[ 4011.795681]        alloc_pages_noprof+0x8c/0xe0
[ 4011.795684]        allocate_slab+0x320/0x460
[ 4011.795686]        ___slab_alloc+0xa58/0x12b0
[ 4011.795688]        __slab_alloc.isra.0+0x42/0x60
[ 4011.795690]        kmem_cache_alloc_noprof+0x304/0x350
[ 4011.795692]        fill_pool+0xf6/0x450
[ 4011.795697]        debug_object_activate+0xfe/0x360
[ 4011.795700]        enqueue_hrtimer+0x34/0x190
[ 4011.795703]        __run_hrtimer+0x3c8/0x4c0
[ 4011.795705]        __hrtimer_run_queues+0x1b2/0x260
[ 4011.795707]        hrtimer_interrupt+0x316/0x760
[ 4011.795709]        do_IRQ+0x9a/0xe0
[ 4011.795712]        do_irq_async+0xf6/0x160

Normally raw_spinlock to spinlock dependency is not legit
and will be warned if PROVE_RAW_LOCK_NESTING is enabled,
but debug_objects_fill_pool() is an exception as it explicitly
allows this dependency for non-PREEMPT_RT kernel without causing
PROVE_RAW_LOCK_NESTING lockdep splat. As a result, this dependency is
legit and not a bug.

Anyway, semaphore is the only locking primitive left that is still
using try_to_wake_up() to do wakeup inside critical section, all the
other locking primitives had been migrated to use wake_q to do wakeup
outside of the critical section. It is also possible that there are
other circular locking dependencies involving printk/console_sem or
other existing/new semaphores lurking somewhere which may show up in
the future. Let just do the migration now to wake_q to avoid headache
like this.

Reported-by:syzbot+ed801a886dfdbfe7136d@syzkaller.appspotmail.com
Signed-off-by: Waiman Long <longman@redhat.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Link: https://lore.kernel.org/r/20250127013127.3913153-1-longman@redhat.com
---
 kernel/locking/semaphore.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/kernel/locking/semaphore.c b/kernel/locking/semaphore.c
index 34bfae72f295..de9117c0e671 100644
--- a/kernel/locking/semaphore.c
+++ b/kernel/locking/semaphore.c
@@ -29,6 +29,7 @@
 #include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/sched/debug.h>
+#include <linux/sched/wake_q.h>
 #include <linux/semaphore.h>
 #include <linux/spinlock.h>
 #include <linux/ftrace.h>
@@ -38,7 +39,7 @@ static noinline void __down(struct semaphore *sem);
 static noinline int __down_interruptible(struct semaphore *sem);
 static noinline int __down_killable(struct semaphore *sem);
 static noinline int __down_timeout(struct semaphore *sem, long timeout);
-static noinline void __up(struct semaphore *sem);
+static noinline void __up(struct semaphore *sem, struct wake_q_head *wake_q);
 
 /**
  * down - acquire the semaphore
@@ -183,13 +184,16 @@ EXPORT_SYMBOL(down_timeout);
 void __sched up(struct semaphore *sem)
 {
 	unsigned long flags;
+	DEFINE_WAKE_Q(wake_q);
 
 	raw_spin_lock_irqsave(&sem->lock, flags);
 	if (likely(list_empty(&sem->wait_list)))
 		sem->count++;
 	else
-		__up(sem);
+		__up(sem, &wake_q);
 	raw_spin_unlock_irqrestore(&sem->lock, flags);
+	if (!wake_q_empty(&wake_q))
+		wake_up_q(&wake_q);
 }
 EXPORT_SYMBOL(up);
 
@@ -269,11 +273,12 @@ static noinline int __sched __down_timeout(struct semaphore *sem, long timeout)
 	return __down_common(sem, TASK_UNINTERRUPTIBLE, timeout);
 }
 
-static noinline void __sched __up(struct semaphore *sem)
+static noinline void __sched __up(struct semaphore *sem,
+				  struct wake_q_head *wake_q)
 {
 	struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list,
 						struct semaphore_waiter, list);
 	list_del(&waiter->list);
 	waiter->up = true;
-	wake_up_process(waiter->task);
+	wake_q_add(wake_q, waiter->task);
 }
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH locking 03/11] locking/lock_events: Add locking events for rtmutex slow paths
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
  2025-03-07 23:26   ` [PATCH locking 01/11] locking/rtmutex: Use struct keyword in kernel-doc comment Boqun Feng
  2025-03-07 23:26   ` [PATCH locking 02/11] locking/semaphore: Use wake_q to wake up processes outside lock critical section Boqun Feng
@ 2025-03-07 23:26   ` Boqun Feng
  2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Waiman Long
  2025-03-07 23:26   ` [PATCH locking 04/11] locking/lock_events: Add locking events for lockdep Boqun Feng
                     ` (8 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: Boqun Feng @ 2025-03-07 23:26 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Will Deacon, Waiman Long, linux-kernel, Boqun Feng, Ingo Molnar

From: Waiman Long <longman@redhat.com>

Add locking events for rtlock_slowlock() and rt_mutex_slowlock() for
profiling the slow path behavior of rt_spin_lock() and rt_mutex_lock().

Signed-off-by: Waiman Long <longman@redhat.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Link: https://lore.kernel.org/r/20250213200228.1993588-2-longman@redhat.com
---
 kernel/locking/lock_events_list.h | 21 +++++++++++++++++++++
 kernel/locking/rtmutex.c          | 29 ++++++++++++++++++++++++-----
 2 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/kernel/locking/lock_events_list.h b/kernel/locking/lock_events_list.h
index 97fb6f3f840a..80b11f194c9f 100644
--- a/kernel/locking/lock_events_list.h
+++ b/kernel/locking/lock_events_list.h
@@ -67,3 +67,24 @@ LOCK_EVENT(rwsem_rlock_handoff)	/* # of read lock handoffs		*/
 LOCK_EVENT(rwsem_wlock)		/* # of write locks acquired		*/
 LOCK_EVENT(rwsem_wlock_fail)	/* # of failed write lock acquisitions	*/
 LOCK_EVENT(rwsem_wlock_handoff)	/* # of write lock handoffs		*/
+
+/*
+ * Locking events for rtlock_slowlock()
+ */
+LOCK_EVENT(rtlock_slowlock)	/* # of rtlock_slowlock() calls		*/
+LOCK_EVENT(rtlock_slow_acq1)	/* # of locks acquired after wait_lock	*/
+LOCK_EVENT(rtlock_slow_acq2)	/* # of locks acquired in for loop	*/
+LOCK_EVENT(rtlock_slow_sleep)	/* # of sleeps				*/
+LOCK_EVENT(rtlock_slow_wake)	/* # of wakeup's			*/
+
+/*
+ * Locking events for rt_mutex_slowlock()
+ */
+LOCK_EVENT(rtmutex_slowlock)	/* # of rt_mutex_slowlock() calls	*/
+LOCK_EVENT(rtmutex_slow_block)	/* # of rt_mutex_slowlock_block() calls	*/
+LOCK_EVENT(rtmutex_slow_acq1)	/* # of locks acquired after wait_lock	*/
+LOCK_EVENT(rtmutex_slow_acq2)	/* # of locks acquired at the end	*/
+LOCK_EVENT(rtmutex_slow_acq3)	/* # of locks acquired in *block()	*/
+LOCK_EVENT(rtmutex_slow_sleep)	/* # of sleeps				*/
+LOCK_EVENT(rtmutex_slow_wake)	/* # of wakeup's			*/
+LOCK_EVENT(rtmutex_deadlock)	/* # of rt_mutex_handle_deadlock()'s	*/
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index 4a8df1800cbb..c80902eacd79 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -27,6 +27,7 @@
 #include <trace/events/lock.h>
 
 #include "rtmutex_common.h"
+#include "lock_events.h"
 
 #ifndef WW_RT
 # define build_ww_mutex()	(false)
@@ -1612,10 +1613,13 @@ static int __sched rt_mutex_slowlock_block(struct rt_mutex_base *lock,
 	struct task_struct *owner;
 	int ret = 0;
 
+	lockevent_inc(rtmutex_slow_block);
 	for (;;) {
 		/* Try to acquire the lock: */
-		if (try_to_take_rt_mutex(lock, current, waiter))
+		if (try_to_take_rt_mutex(lock, current, waiter)) {
+			lockevent_inc(rtmutex_slow_acq3);
 			break;
+		}
 
 		if (timeout && !timeout->task) {
 			ret = -ETIMEDOUT;
@@ -1638,8 +1642,10 @@ static int __sched rt_mutex_slowlock_block(struct rt_mutex_base *lock,
 			owner = NULL;
 		raw_spin_unlock_irq_wake(&lock->wait_lock, wake_q);
 
-		if (!owner || !rtmutex_spin_on_owner(lock, waiter, owner))
+		if (!owner || !rtmutex_spin_on_owner(lock, waiter, owner)) {
+			lockevent_inc(rtmutex_slow_sleep);
 			rt_mutex_schedule();
+		}
 
 		raw_spin_lock_irq(&lock->wait_lock);
 		set_current_state(state);
@@ -1694,6 +1700,7 @@ static int __sched __rt_mutex_slowlock(struct rt_mutex_base *lock,
 	int ret;
 
 	lockdep_assert_held(&lock->wait_lock);
+	lockevent_inc(rtmutex_slowlock);
 
 	/* Try to acquire the lock again: */
 	if (try_to_take_rt_mutex(lock, current, NULL)) {
@@ -1701,6 +1708,7 @@ static int __sched __rt_mutex_slowlock(struct rt_mutex_base *lock,
 			__ww_mutex_check_waiters(rtm, ww_ctx, wake_q);
 			ww_mutex_lock_acquired(ww, ww_ctx);
 		}
+		lockevent_inc(rtmutex_slow_acq1);
 		return 0;
 	}
 
@@ -1719,10 +1727,12 @@ static int __sched __rt_mutex_slowlock(struct rt_mutex_base *lock,
 				__ww_mutex_check_waiters(rtm, ww_ctx, wake_q);
 			ww_mutex_lock_acquired(ww, ww_ctx);
 		}
+		lockevent_inc(rtmutex_slow_acq2);
 	} else {
 		__set_current_state(TASK_RUNNING);
 		remove_waiter(lock, waiter);
 		rt_mutex_handle_deadlock(ret, chwalk, lock, waiter);
+		lockevent_inc(rtmutex_deadlock);
 	}
 
 	/*
@@ -1751,6 +1761,7 @@ static inline int __rt_mutex_slowlock_locked(struct rt_mutex_base *lock,
 				  &waiter, wake_q);
 
 	debug_rt_mutex_free_waiter(&waiter);
+	lockevent_cond_inc(rtmutex_slow_wake, !wake_q_empty(wake_q));
 	return ret;
 }
 
@@ -1823,9 +1834,12 @@ static void __sched rtlock_slowlock_locked(struct rt_mutex_base *lock,
 	struct task_struct *owner;
 
 	lockdep_assert_held(&lock->wait_lock);
+	lockevent_inc(rtlock_slowlock);
 
-	if (try_to_take_rt_mutex(lock, current, NULL))
+	if (try_to_take_rt_mutex(lock, current, NULL)) {
+		lockevent_inc(rtlock_slow_acq1);
 		return;
+	}
 
 	rt_mutex_init_rtlock_waiter(&waiter);
 
@@ -1838,8 +1852,10 @@ static void __sched rtlock_slowlock_locked(struct rt_mutex_base *lock,
 
 	for (;;) {
 		/* Try to acquire the lock again */
-		if (try_to_take_rt_mutex(lock, current, &waiter))
+		if (try_to_take_rt_mutex(lock, current, &waiter)) {
+			lockevent_inc(rtlock_slow_acq2);
 			break;
+		}
 
 		if (&waiter == rt_mutex_top_waiter(lock))
 			owner = rt_mutex_owner(lock);
@@ -1847,8 +1863,10 @@ static void __sched rtlock_slowlock_locked(struct rt_mutex_base *lock,
 			owner = NULL;
 		raw_spin_unlock_irq_wake(&lock->wait_lock, wake_q);
 
-		if (!owner || !rtmutex_spin_on_owner(lock, &waiter, owner))
+		if (!owner || !rtmutex_spin_on_owner(lock, &waiter, owner)) {
+			lockevent_inc(rtlock_slow_sleep);
 			schedule_rtlock();
+		}
 
 		raw_spin_lock_irq(&lock->wait_lock);
 		set_current_state(TASK_RTLOCK_WAIT);
@@ -1865,6 +1883,7 @@ static void __sched rtlock_slowlock_locked(struct rt_mutex_base *lock,
 	debug_rt_mutex_free_waiter(&waiter);
 
 	trace_contention_end(lock, 0);
+	lockevent_cond_inc(rtlock_slow_wake, !wake_q_empty(wake_q));
 }
 
 static __always_inline void __sched rtlock_slowlock(struct rt_mutex_base *lock)
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH locking 04/11] locking/lock_events: Add locking events for lockdep
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
                     ` (2 preceding siblings ...)
  2025-03-07 23:26   ` [PATCH locking 03/11] locking/lock_events: Add locking events for rtmutex slow paths Boqun Feng
@ 2025-03-07 23:26   ` Boqun Feng
  2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Waiman Long
  2025-03-07 23:26   ` [PATCH locking 05/11] locking/lockdep: Disable KASAN instrumentation of lockdep.c Boqun Feng
                     ` (7 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: Boqun Feng @ 2025-03-07 23:26 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Will Deacon, Waiman Long, linux-kernel, Boqun Feng, Ingo Molnar

From: Waiman Long <longman@redhat.com>

Add some lock events to the lockdep for profiling its behavior.

Signed-off-by: Waiman Long <longman@redhat.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Link: https://lore.kernel.org/r/20250213200228.1993588-3-longman@redhat.com
---
 kernel/locking/lock_events_list.h | 7 +++++++
 kernel/locking/lockdep.c          | 8 +++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/kernel/locking/lock_events_list.h b/kernel/locking/lock_events_list.h
index 80b11f194c9f..9ef9850aeebe 100644
--- a/kernel/locking/lock_events_list.h
+++ b/kernel/locking/lock_events_list.h
@@ -88,3 +88,10 @@ LOCK_EVENT(rtmutex_slow_acq3)	/* # of locks acquired in *block()	*/
 LOCK_EVENT(rtmutex_slow_sleep)	/* # of sleeps				*/
 LOCK_EVENT(rtmutex_slow_wake)	/* # of wakeup's			*/
 LOCK_EVENT(rtmutex_deadlock)	/* # of rt_mutex_handle_deadlock()'s	*/
+
+/*
+ * Locking events for lockdep
+ */
+LOCK_EVENT(lockdep_acquire)
+LOCK_EVENT(lockdep_lock)
+LOCK_EVENT(lockdep_nocheck)
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 4470680f0226..8436f017c74d 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -61,6 +61,7 @@
 #include <asm/sections.h>
 
 #include "lockdep_internals.h"
+#include "lock_events.h"
 
 #include <trace/events/lock.h>
 
@@ -170,6 +171,7 @@ static struct task_struct *lockdep_selftest_task_struct;
 static int graph_lock(void)
 {
 	lockdep_lock();
+	lockevent_inc(lockdep_lock);
 	/*
 	 * Make sure that if another CPU detected a bug while
 	 * walking the graph we dont change it (while the other
@@ -5091,8 +5093,12 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
 	if (unlikely(lock->key == &__lockdep_no_track__))
 		return 0;
 
-	if (!prove_locking || lock->key == &__lockdep_no_validate__)
+	lockevent_inc(lockdep_acquire);
+
+	if (!prove_locking || lock->key == &__lockdep_no_validate__) {
 		check = 0;
+		lockevent_inc(lockdep_nocheck);
+	}
 
 	if (subclass < NR_LOCKDEP_CACHING_CLASSES)
 		class = lock->class_cache[subclass];
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH locking 05/11] locking/lockdep: Disable KASAN instrumentation of lockdep.c
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
                     ` (3 preceding siblings ...)
  2025-03-07 23:26   ` [PATCH locking 04/11] locking/lock_events: Add locking events for lockdep Boqun Feng
@ 2025-03-07 23:26   ` Boqun Feng
  2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Waiman Long
  2025-03-07 23:26   ` [PATCH locking 06/11] locking/lockdep: Add kasan_check_byte() check in lock_acquire() Boqun Feng
                     ` (6 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: Boqun Feng @ 2025-03-07 23:26 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Will Deacon, Waiman Long, linux-kernel, Marco Elver,
	Andrey Konovalov, Boqun Feng, Ingo Molnar,
	Sebastian Andrzej Siewior, Clark Williams, Steven Rostedt,
	open list:Real-time Linux (PREEMPT_RT):Keyword:PREEMPT_RT

From: Waiman Long <longman@redhat.com>

Both KASAN and LOCKDEP are commonly enabled in building a debug kernel.
Each of them can significantly slow down the speed of a debug kernel.
Enabling KASAN instrumentation of the LOCKDEP code will further slow
thing down.

Since LOCKDEP is a high overhead debugging tool, it will never get
enabled in a production kernel. The LOCKDEP code is also pretty mature
and is unlikely to get major changes. There is also a possibility of
recursion similar to KCSAN.

To evaluate the performance impact of disabling KASAN instrumentation
of lockdep.c, the time to do a parallel build of the Linux defconfig
kernel was used as the benchmark. Two x86-64 systems (Skylake & Zen 2)
and an arm64 system were used as test beds. Two sets of non-RT and RT
kernels with similar configurations except mainly CONFIG_PREEMPT_RT
were used for evaulation.

For the Skylake system:

  Kernel			Run time	    Sys time
  ------			--------	    --------
  Non-debug kernel (baseline)	0m47.642s	      4m19.811s

  [CONFIG_KASAN_INLINE=y]
  Debug kernel			2m11.108s (x2.8)     38m20.467s (x8.9)
  Debug kernel (patched)	1m49.602s (x2.3)     31m28.501s (x7.3)
  Debug kernel
  (patched + mitigations=off) 	1m30.988s (x1.9)     26m41.993s (x6.2)

  RT kernel (baseline)		0m54.871s	      7m15.340s

  [CONFIG_KASAN_INLINE=n]
  RT debug kernel		6m07.151s (x6.7)    135m47.428s (x18.7)
  RT debug kernel (patched)	3m42.434s (x4.1)     74m51.636s (x10.3)
  RT debug kernel
  (patched + mitigations=off) 	2m40.383s (x2.9)     57m54.369s (x8.0)

  [CONFIG_KASAN_INLINE=y]
  RT debug kernel		3m22.155s (x3.7)     77m53.018s (x10.7)
  RT debug kernel (patched)	2m36.700s (x2.9)     54m31.195s (x7.5)
  RT debug kernel
  (patched + mitigations=off) 	2m06.110s (x2.3)     45m49.493s (x6.3)

For the Zen 2 system:

  Kernel			Run time	    Sys time
  ------			--------	    --------
  Non-debug kernel (baseline)	1m42.806s	     39m48.714s

  [CONFIG_KASAN_INLINE=y]
  Debug kernel			4m04.524s (x2.4)    125m35.904s (x3.2)
  Debug kernel (patched)	3m56.241s (x2.3)    127m22.378s (x3.2)
  Debug kernel
  (patched + mitigations=off) 	2m38.157s (x1.5)     92m35.680s (x2.3)

  RT kernel (baseline)		 1m51.500s	     14m56.322s

  [CONFIG_KASAN_INLINE=n]
  RT debug kernel		16m04.962s (x8.7)   244m36.463s (x16.4)
  RT debug kernel (patched)	 9m09.073s (x4.9)   129m28.439s (x8.7)
  RT debug kernel
  (patched + mitigations=off) 	 3m31.662s (x1.9)    51m01.391s (x3.4)

For the arm64 system:

  Kernel			Run time	    Sys time
  ------			--------	    --------
  Non-debug kernel (baseline)	1m56.844s	      8m47.150s
  Debug kernel			3m54.774s (x2.0)     92m30.098s (x10.5)
  Debug kernel (patched)	3m32.429s (x1.8)     77m40.779s (x8.8)

  RT kernel (baseline)		 4m01.641s	     18m16.777s

  [CONFIG_KASAN_INLINE=n]
  RT debug kernel		19m32.977s (x4.9)   304m23.965s (x16.7)
  RT debug kernel (patched)	16m28.354s (x4.1)   234m18.149s (x12.8)

Turning the mitigations off doesn't seems to have any noticeable impact
on the performance of the arm64 system. So the mitigation=off entries
aren't included.

For the x86 CPUs, cpu mitigations has a much bigger
impact on performance, especially the RT debug kernel with
CONFIG_KASAN_INLINE=n. The SRSO mitigation in Zen 2 has an especially
big impact on the debug kernel. It is also the majority of the slowdown
with mitigations on. It is because the patched ret instruction slows
down function returns. A lot of helper functions that are normally
compiled out or inlined may become real function calls in the debug
kernel.

With CONFIG_KASAN_INLINE=n, the KASAN instrumentation inserts a
lot of __asan_loadX*() and __kasan_check_read() function calls to memory
access portion of the code. The lockdep's __lock_acquire() function,
for instance, has 66 __asan_loadX*() and 6 __kasan_check_read() calls
added with KASAN instrumentation. Of course, the actual numbers may vary
depending on the compiler used and the exact version of the lockdep code.

With the Skylake test system, the parallel kernel build times reduction
of the RT debug kernel with this patch are:

 CONFIG_KASAN_INLINE=n: -37%
 CONFIG_KASAN_INLINE=y: -22%

The time reduction is less with CONFIG_KASAN_INLINE=y, but it is still
significant.

Setting CONFIG_KASAN_INLINE=y can result in a significant performance
improvement. The major drawback is a significant increase in the size
of kernel text. In the case of vmlinux, its text size increases from
45997948 to 67606807. That is a 47% size increase (about 21 Mbytes). The
size increase of other kernel modules should be similar.

With the newly added rtmutex and lockdep lock events, the relevant
event counts for the test runs with the Skylake system were:

  Event type		Debug kernel	RT debug kernel
  ----------		------------	---------------
  lockdep_acquire	1,968,663,277	5,425,313,953
  rtlock_slowlock	     -		  401,701,156
  rtmutex_slowlock	     -		      139,672

The __lock_acquire() calls in the RT debug kernel are x2.8 times of the
non-RT debug kernel with the same workload. Since the __lock_acquire()
function is a big hitter in term of performance slowdown, this makes
the RT debug kernel much slower than the non-RT one. The average lock
nesting depth is likely to be higher in the RT debug kernel too leading
to longer execution time in the __lock_acquire() function.

As the small advantage of enabling KASAN instrumentation to catch
potential memory access error in the lockdep debugging tool is probably
not worth the drawback of further slowing down a debug kernel, disable
KASAN instrumentation in the lockdep code to allow the debug kernels
to regain some performance back, especially for the RT debug kernels.

Signed-off-by: Waiman Long <longman@redhat.com>
Reviewed-by: Marco Elver <elver@google.com>
Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Link: https://lore.kernel.org/r/20250213200228.1993588-4-longman@redhat.com
---
 kernel/locking/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/locking/Makefile b/kernel/locking/Makefile
index 0db4093d17b8..a114949eeed5 100644
--- a/kernel/locking/Makefile
+++ b/kernel/locking/Makefile
@@ -5,7 +5,8 @@ KCOV_INSTRUMENT		:= n
 
 obj-y += mutex.o semaphore.o rwsem.o percpu-rwsem.o
 
-# Avoid recursion lockdep -> sanitizer -> ... -> lockdep.
+# Avoid recursion lockdep -> sanitizer -> ... -> lockdep & improve performance.
+KASAN_SANITIZE_lockdep.o := n
 KCSAN_SANITIZE_lockdep.o := n
 
 ifdef CONFIG_FUNCTION_TRACER
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH locking 06/11] locking/lockdep: Add kasan_check_byte() check in lock_acquire()
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
                     ` (4 preceding siblings ...)
  2025-03-07 23:26   ` [PATCH locking 05/11] locking/lockdep: Disable KASAN instrumentation of lockdep.c Boqun Feng
@ 2025-03-07 23:26   ` Boqun Feng
  2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Waiman Long
  2025-03-07 23:26   ` [PATCH locking 07/11] rust: sync: Add accessor for the lock behind a given guard Boqun Feng
                     ` (5 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: Boqun Feng @ 2025-03-07 23:26 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Will Deacon, Waiman Long, linux-kernel, Marco Elver,
	Andrey Konovalov, Boqun Feng, Ingo Molnar

From: Waiman Long <longman@redhat.com>

KASAN instrumentation of lockdep has been disabled as we don't need
KASAN to check the validity of lockdep internal data structures and
incur unnecessary performance overhead. However, the lockdep_map pointer
passed in externally may not be valid (e.g. use-after-free) and we run
the risk of using garbage data resulting in false lockdep reports.

Add kasan_check_byte() call in lock_acquire() for non kernel core data
object to catch invalid lockdep_map and print out a KASAN report before
any lockdep splat, if any.

Suggested-by: Marco Elver <elver@google.com>
Signed-off-by: Waiman Long <longman@redhat.com>
Reviewed-by: Marco Elver <elver@google.com>
Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Link: https://lore.kernel.org/r/20250214195242.2480920-1-longman@redhat.com
---
 kernel/locking/lockdep.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 8436f017c74d..b15757e63626 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -57,6 +57,7 @@
 #include <linux/lockdep.h>
 #include <linux/context_tracking.h>
 #include <linux/console.h>
+#include <linux/kasan.h>
 
 #include <asm/sections.h>
 
@@ -5830,6 +5831,14 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
 	if (!debug_locks)
 		return;
 
+	/*
+	 * As KASAN instrumentation is disabled and lock_acquire() is usually
+	 * the first lockdep call when a task tries to acquire a lock, add
+	 * kasan_check_byte() here to check for use-after-free and other
+	 * memory errors.
+	 */
+	kasan_check_byte(lock);
+
 	if (unlikely(!lockdep_enabled())) {
 		/* XXX allow trylock from NMI ?!? */
 		if (lockdep_nmi() && !trylock) {
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH locking 07/11] rust: sync: Add accessor for the lock behind a given guard
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
                     ` (5 preceding siblings ...)
  2025-03-07 23:26   ` [PATCH locking 06/11] locking/lockdep: Add kasan_check_byte() check in lock_acquire() Boqun Feng
@ 2025-03-07 23:26   ` Boqun Feng
  2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Alice Ryhl
  2025-03-07 23:26   ` [PATCH locking 08/11] rust: sync: lock: Add an example for Guard::lock_ref() Boqun Feng
                     ` (4 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: Boqun Feng @ 2025-03-07 23:26 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Will Deacon, Waiman Long, linux-kernel, Alice Ryhl, Fiona Behrens,
	Boqun Feng, Ingo Molnar, Miguel Ojeda, Alex Gaynor, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, open list:RUST

From: Alice Ryhl <aliceryhl@google.com>

In order to assert a particular `Guard` is associated with a particular
`Lock`, add an accessor to obtain a reference to the underlying `Lock`
of a `Guard`.

Binder needs this assertion to ensure unsafe list operations are done
with the correct lock held.

[Boqun: Capitalize the title and reword the commit log]

Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Fiona Behrens <me@kloenk.dev>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Link: https://lore.kernel.org/r/20250205-guard-get-lock-v2-1-ba32a8c1d5b7@google.com
---
 rust/kernel/sync/lock.rs | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
index eb80048e0110..8e7e6d5f61e4 100644
--- a/rust/kernel/sync/lock.rs
+++ b/rust/kernel/sync/lock.rs
@@ -199,7 +199,12 @@ pub struct Guard<'a, T: ?Sized, B: Backend> {
 // SAFETY: `Guard` is sync when the data protected by the lock is also sync.
 unsafe impl<T: Sync + ?Sized, B: Backend> Sync for Guard<'_, T, B> {}
 
-impl<T: ?Sized, B: Backend> Guard<'_, T, B> {
+impl<'a, T: ?Sized, B: Backend> Guard<'a, T, B> {
+    /// Returns the lock that this guard originates from.
+    pub fn lock_ref(&self) -> &'a Lock<T, B> {
+        self.lock
+    }
+
     pub(crate) fn do_unlocked<U>(&mut self, cb: impl FnOnce() -> U) -> U {
         // SAFETY: The caller owns the lock, so it is safe to unlock it.
         unsafe { B::unlock(self.lock.state.get(), &self.state) };
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH locking 08/11] rust: sync: lock: Add an example for Guard::lock_ref()
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
                     ` (6 preceding siblings ...)
  2025-03-07 23:26   ` [PATCH locking 07/11] rust: sync: Add accessor for the lock behind a given guard Boqun Feng
@ 2025-03-07 23:26   ` Boqun Feng
  2025-03-08  0:08     ` [tip: locking/core] rust: sync: lock: Add an example for Guard:: Lock_ref() tip-bot2 for Boqun Feng
  2025-03-07 23:26   ` [PATCH locking 09/11] rust: sync: condvar: Add wait_interruptible_freezable() Boqun Feng
                     ` (3 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: Boqun Feng @ 2025-03-07 23:26 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Will Deacon, Waiman Long, linux-kernel, Boqun Feng, Benno Lossin,
	Alice Ryhl, Ingo Molnar, Miguel Ojeda, Alex Gaynor, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Trevor Gross,
	open list:RUST

To provide examples on usage of `Guard::lock_ref()` along with the unit
test, an "assert a lock is held by a guard" example is added.

[boqun: Apply feedback from Benno]

Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20250223072114.3715-1-boqun.feng@gmail.com
---
 rust/kernel/sync/lock.rs | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
index 8e7e6d5f61e4..f53e87d04cd2 100644
--- a/rust/kernel/sync/lock.rs
+++ b/rust/kernel/sync/lock.rs
@@ -201,6 +201,30 @@ unsafe impl<T: Sync + ?Sized, B: Backend> Sync for Guard<'_, T, B> {}
 
 impl<'a, T: ?Sized, B: Backend> Guard<'a, T, B> {
     /// Returns the lock that this guard originates from.
+    ///
+    /// # Examples
+    ///
+    /// The following example shows how to use [`Guard::lock_ref()`] to assert the corresponding
+    /// lock is held.
+    ///
+    /// ```
+    /// # use kernel::{new_spinlock, stack_pin_init, sync::lock::{Backend, Guard, Lock}};
+    ///
+    /// fn assert_held<T, B: Backend>(guard: &Guard<'_, T, B>, lock: &Lock<T, B>) {
+    ///     // Address-equal means the same lock.
+    ///     assert!(core::ptr::eq(guard.lock_ref(), lock));
+    /// }
+    ///
+    /// // Creates a new lock on the stack.
+    /// stack_pin_init!{
+    ///     let l = new_spinlock!(42)
+    /// }
+    ///
+    /// let g = l.lock();
+    ///
+    /// // `g` originates from `l`.
+    /// assert_held(&g, &l);
+    /// ```
     pub fn lock_ref(&self) -> &'a Lock<T, B> {
         self.lock
     }
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH locking 09/11] rust: sync: condvar: Add wait_interruptible_freezable()
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
                     ` (7 preceding siblings ...)
  2025-03-07 23:26   ` [PATCH locking 08/11] rust: sync: lock: Add an example for Guard::lock_ref() Boqun Feng
@ 2025-03-07 23:26   ` Boqun Feng
  2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Alice Ryhl
  2025-03-07 23:27   ` [PATCH locking 10/11] rust: lockdep: Remove support for dynamically allocated LockClassKeys Boqun Feng
                     ` (2 subsequent siblings)
  11 siblings, 1 reply; 31+ messages in thread
From: Boqun Feng @ 2025-03-07 23:26 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Will Deacon, Waiman Long, linux-kernel, Alice Ryhl, Boqun Feng,
	Miguel Ojeda, Alex Gaynor, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Trevor Gross, Mitchell Levy,
	Danilo Krummrich, Christian Brauner, Martin Rodriguez Reboredo,
	open list:RUST

From: Alice Ryhl <aliceryhl@google.com>

To support waiting for a `CondVar` as a freezable process, add a
wait_interruptible_freezable() function.

Binder needs this function in the appropriate places to freeze a process
where some of its threads are blocked on the Binder driver.

[Boqun: Capitalize the title, reword the commit log and rephrase the
function doc comment with the impersonal style to align with rest of the
file]

Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Link: https://lore.kernel.org/r/20250204-condvar-freeze-v2-1-804483096260@google.com
---
 rust/kernel/sync/condvar.rs | 23 ++++++++++++++++++++++-
 rust/kernel/task.rs         |  2 ++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
index 7df565038d7d..5c1e546a26c3 100644
--- a/rust/kernel/sync/condvar.rs
+++ b/rust/kernel/sync/condvar.rs
@@ -11,7 +11,9 @@
     init::PinInit,
     pin_init,
     str::CStr,
-    task::{MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE, TASK_NORMAL, TASK_UNINTERRUPTIBLE},
+    task::{
+        MAX_SCHEDULE_TIMEOUT, TASK_FREEZABLE, TASK_INTERRUPTIBLE, TASK_NORMAL, TASK_UNINTERRUPTIBLE,
+    },
     time::Jiffies,
     types::Opaque,
 };
@@ -159,6 +161,25 @@ pub fn wait_interruptible<T: ?Sized, B: Backend>(&self, guard: &mut Guard<'_, T,
         crate::current!().signal_pending()
     }
 
+    /// Releases the lock and waits for a notification in interruptible and freezable mode.
+    ///
+    /// The process is allowed to be frozen during this sleep. No lock should be held when calling
+    /// this function, and there is a lockdep assertion for this. Freezing a task that holds a lock
+    /// can trivially deadlock vs another task that needs that lock to complete before it too can
+    /// hit freezable.
+    #[must_use = "wait_interruptible_freezable returns if a signal is pending, so the caller must check the return value"]
+    pub fn wait_interruptible_freezable<T: ?Sized, B: Backend>(
+        &self,
+        guard: &mut Guard<'_, T, B>,
+    ) -> bool {
+        self.wait_internal(
+            TASK_INTERRUPTIBLE | TASK_FREEZABLE,
+            guard,
+            MAX_SCHEDULE_TIMEOUT,
+        );
+        crate::current!().signal_pending()
+    }
+
     /// Releases the lock and waits for a notification in interruptible mode.
     ///
     /// Atomically releases the given lock (whose ownership is proven by the guard) and puts the
diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
index 07bc22a7645c..ea43a3b8d9c5 100644
--- a/rust/kernel/task.rs
+++ b/rust/kernel/task.rs
@@ -23,6 +23,8 @@
 pub const TASK_INTERRUPTIBLE: c_int = bindings::TASK_INTERRUPTIBLE as c_int;
 /// Bitmask for tasks that are sleeping in an uninterruptible state.
 pub const TASK_UNINTERRUPTIBLE: c_int = bindings::TASK_UNINTERRUPTIBLE as c_int;
+/// Bitmask for tasks that are sleeping in a freezable state.
+pub const TASK_FREEZABLE: c_int = bindings::TASK_FREEZABLE as c_int;
 /// Convenience constant for waking up tasks regardless of whether they are in interruptible or
 /// uninterruptible sleep.
 pub const TASK_NORMAL: c_uint = bindings::TASK_NORMAL as c_uint;
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH locking 10/11] rust: lockdep: Remove support for dynamically allocated LockClassKeys
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
                     ` (8 preceding siblings ...)
  2025-03-07 23:26   ` [PATCH locking 09/11] rust: sync: condvar: Add wait_interruptible_freezable() Boqun Feng
@ 2025-03-07 23:27   ` Boqun Feng
  2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Mitchell Levy
  2025-03-07 23:27   ` [PATCH locking 11/11] rust: lockdep: Use Pin for all LockClassKey usages Boqun Feng
  2025-03-08  0:01   ` [PATCH locking 00/11] LOCKDEP and Rust locking changes for v6.15 Ingo Molnar
  11 siblings, 1 reply; 31+ messages in thread
From: Boqun Feng @ 2025-03-07 23:27 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Will Deacon, Waiman Long, linux-kernel, Mitchell Levy, Alice Ryhl,
	stable, Benno Lossin, Boqun Feng, Miguel Ojeda, Alex Gaynor,
	Gary Guo, Björn Roy Baron, Andreas Hindborg, Trevor Gross,
	Lyude Paul, Wedson Almeida Filho, Martin Rodriguez Reboredo,
	open list:RUST

From: Mitchell Levy <levymitchell0@gmail.com>

Currently, dynamically allocated LockCLassKeys can be used from the Rust
side without having them registered. This is a soundness issue, so
remove them.

Suggested-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/rust-for-linux/20240815074519.2684107-3-nmi@metaspace.dk/
Cc: stable@vger.kernel.org
Fixes: 6ea5aa08857a ("rust: sync: introduce `LockClassKey`")
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Signed-off-by: Mitchell Levy <levymitchell0@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Link: https://lore.kernel.org/r/20250207-rust-lockdep-v4-1-7a50a7e88656@gmail.com
---
 rust/kernel/sync.rs | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs
index 3498fb344dc9..16eab9138b2b 100644
--- a/rust/kernel/sync.rs
+++ b/rust/kernel/sync.rs
@@ -30,28 +30,20 @@
 unsafe impl Sync for LockClassKey {}
 
 impl LockClassKey {
-    /// Creates a new lock class key.
-    pub const fn new() -> Self {
-        Self(Opaque::uninit())
-    }
-
     pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key {
         self.0.get()
     }
 }
 
-impl Default for LockClassKey {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
 /// Defines a new static lock class and returns a pointer to it.
 #[doc(hidden)]
 #[macro_export]
 macro_rules! static_lock_class {
     () => {{
-        static CLASS: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
+        static CLASS: $crate::sync::LockClassKey =
+            // SAFETY: lockdep expects uninitialized memory when it's handed a statically allocated
+            // lock_class_key
+            unsafe { ::core::mem::MaybeUninit::uninit().assume_init() };
         &CLASS
     }};
 }
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [PATCH locking 11/11] rust: lockdep: Use Pin for all LockClassKey usages
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
                     ` (9 preceding siblings ...)
  2025-03-07 23:27   ` [PATCH locking 10/11] rust: lockdep: Remove support for dynamically allocated LockClassKeys Boqun Feng
@ 2025-03-07 23:27   ` Boqun Feng
  2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Mitchell Levy
  2025-03-08  0:01   ` [PATCH locking 00/11] LOCKDEP and Rust locking changes for v6.15 Ingo Molnar
  11 siblings, 1 reply; 31+ messages in thread
From: Boqun Feng @ 2025-03-07 23:27 UTC (permalink / raw)
  To: Ingo Molnar, Peter Zijlstra
  Cc: Will Deacon, Waiman Long, linux-kernel, Mitchell Levy,
	Benno Lossin, Boqun Feng, Miguel Ojeda, Alex Gaynor, Gary Guo,
	Björn Roy Baron, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	Ingo Molnar, Danilo Krummrich, Wedson Almeida Filho,
	Christian Brauner, Lyude Paul, Martin Rodriguez Reboredo,
	Konstantin Andrikopoulos, Roland Xu, open list:RUST

From: Mitchell Levy <levymitchell0@gmail.com>

Reintroduce dynamically-allocated LockClassKeys such that they are
automatically (de)registered. Require that all usages of LockClassKeys
ensure that they are Pin'd.

Currently, only `'static` LockClassKeys are supported, so Pin is
redundant. However, it is intended that dynamically-allocated
LockClassKeys will eventually be supported, so using Pin from the outset
will make that change simpler.

Closes: https://github.com/Rust-for-Linux/linux/issues/1102
Suggested-by: Benno Lossin <benno.lossin@proton.me>
Suggested-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Mitchell Levy <levymitchell0@gmail.com>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Link: https://lore.kernel.org/r/20250207-rust-lockdep-v4-2-7a50a7e88656@gmail.com
---
 rust/helpers/helpers.c          |  1 +
 rust/helpers/sync.c             | 13 ++++++++
 rust/kernel/sync.rs             | 57 +++++++++++++++++++++++++++++++--
 rust/kernel/sync/condvar.rs     |  5 ++-
 rust/kernel/sync/lock.rs        |  4 +--
 rust/kernel/sync/lock/global.rs |  5 +--
 rust/kernel/sync/poll.rs        |  2 +-
 rust/kernel/workqueue.rs        |  2 +-
 8 files changed, 77 insertions(+), 12 deletions(-)
 create mode 100644 rust/helpers/sync.c

diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
index 0640b7e115be..4c1a10a419cf 100644
--- a/rust/helpers/helpers.c
+++ b/rust/helpers/helpers.c
@@ -30,6 +30,7 @@
 #include "signal.c"
 #include "slab.c"
 #include "spinlock.c"
+#include "sync.c"
 #include "task.c"
 #include "uaccess.c"
 #include "vmalloc.c"
diff --git a/rust/helpers/sync.c b/rust/helpers/sync.c
new file mode 100644
index 000000000000..ff7e68b48810
--- /dev/null
+++ b/rust/helpers/sync.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/lockdep.h>
+
+void rust_helper_lockdep_register_key(struct lock_class_key *k)
+{
+	lockdep_register_key(k);
+}
+
+void rust_helper_lockdep_unregister_key(struct lock_class_key *k)
+{
+	lockdep_unregister_key(k);
+}
diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs
index 16eab9138b2b..4104bc26471a 100644
--- a/rust/kernel/sync.rs
+++ b/rust/kernel/sync.rs
@@ -5,6 +5,8 @@
 //! This module contains the kernel APIs related to synchronisation that have been ported or
 //! wrapped for usage by Rust code in the kernel.
 
+use crate::pin_init;
+use crate::prelude::*;
 use crate::types::Opaque;
 
 mod arc;
@@ -23,15 +25,64 @@
 
 /// Represents a lockdep class. It's a wrapper around C's `lock_class_key`.
 #[repr(transparent)]
-pub struct LockClassKey(Opaque<bindings::lock_class_key>);
+#[pin_data(PinnedDrop)]
+pub struct LockClassKey {
+    #[pin]
+    inner: Opaque<bindings::lock_class_key>,
+}
 
 // SAFETY: `bindings::lock_class_key` is designed to be used concurrently from multiple threads and
 // provides its own synchronization.
 unsafe impl Sync for LockClassKey {}
 
 impl LockClassKey {
+    /// Initializes a dynamically allocated lock class key. In the common case of using a
+    /// statically allocated lock class key, the static_lock_class! macro should be used instead.
+    ///
+    /// # Example
+    /// ```
+    /// # use kernel::{c_str, stack_pin_init};
+    /// # use kernel::alloc::KBox;
+    /// # use kernel::types::ForeignOwnable;
+    /// # use kernel::sync::{LockClassKey, SpinLock};
+    ///
+    /// let key = KBox::pin_init(LockClassKey::new_dynamic(), GFP_KERNEL)?;
+    /// let key_ptr = key.into_foreign();
+    ///
+    /// {
+    ///     stack_pin_init!(let num: SpinLock<u32> = SpinLock::new(
+    ///         0,
+    ///         c_str!("my_spinlock"),
+    ///         // SAFETY: `key_ptr` is returned by the above `into_foreign()`, whose
+    ///         // `from_foreign()` has not yet been called.
+    ///         unsafe { <Pin<KBox<LockClassKey>> as ForeignOwnable>::borrow(key_ptr) }
+    ///     ));
+    /// }
+    ///
+    /// // SAFETY: We dropped `num`, the only use of the key, so the result of the previous
+    /// // `borrow` has also been dropped. Thus, it's safe to use from_foreign.
+    /// unsafe { drop(<Pin<KBox<LockClassKey>> as ForeignOwnable>::from_foreign(key_ptr)) };
+    ///
+    /// # Ok::<(), Error>(())
+    /// ```
+    pub fn new_dynamic() -> impl PinInit<Self> {
+        pin_init!(Self {
+            // SAFETY: lockdep_register_key expects an uninitialized block of memory
+            inner <- Opaque::ffi_init(|slot| unsafe { bindings::lockdep_register_key(slot) })
+        })
+    }
+
     pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key {
-        self.0.get()
+        self.inner.get()
+    }
+}
+
+#[pinned_drop]
+impl PinnedDrop for LockClassKey {
+    fn drop(self: Pin<&mut Self>) {
+        // SAFETY: self.as_ptr was registered with lockdep and self is pinned, so the address
+        // hasn't changed. Thus, it's safe to pass to unregister.
+        unsafe { bindings::lockdep_unregister_key(self.as_ptr()) }
     }
 }
 
@@ -44,7 +95,7 @@ macro_rules! static_lock_class {
             // SAFETY: lockdep expects uninitialized memory when it's handed a statically allocated
             // lock_class_key
             unsafe { ::core::mem::MaybeUninit::uninit().assume_init() };
-        &CLASS
+        $crate::prelude::Pin::static_ref(&CLASS)
     }};
 }
 
diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
index 5c1e546a26c3..fbf68ada582f 100644
--- a/rust/kernel/sync/condvar.rs
+++ b/rust/kernel/sync/condvar.rs
@@ -17,8 +17,7 @@
     time::Jiffies,
     types::Opaque,
 };
-use core::marker::PhantomPinned;
-use core::ptr;
+use core::{marker::PhantomPinned, pin::Pin, ptr};
 use macros::pin_data;
 
 /// Creates a [`CondVar`] initialiser with the given name and a newly-created lock class.
@@ -103,7 +102,7 @@ unsafe impl Sync for CondVar {}
 
 impl CondVar {
     /// Constructs a new condvar initialiser.
-    pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self> {
+    pub fn new(name: &'static CStr, key: Pin<&'static LockClassKey>) -> impl PinInit<Self> {
         pin_init!(Self {
             _pin: PhantomPinned,
             // SAFETY: `slot` is valid while the closure is called and both `name` and `key` have
diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
index f53e87d04cd2..360a10a9216d 100644
--- a/rust/kernel/sync/lock.rs
+++ b/rust/kernel/sync/lock.rs
@@ -12,7 +12,7 @@
     str::CStr,
     types::{NotThreadSafe, Opaque, ScopeGuard},
 };
-use core::{cell::UnsafeCell, marker::PhantomPinned};
+use core::{cell::UnsafeCell, marker::PhantomPinned, pin::Pin};
 use macros::pin_data;
 
 pub mod mutex;
@@ -129,7 +129,7 @@ unsafe impl<T: ?Sized + Send, B: Backend> Sync for Lock<T, B> {}
 
 impl<T, B: Backend> Lock<T, B> {
     /// Constructs a new lock initialiser.
-    pub fn new(t: T, name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self> {
+    pub fn new(t: T, name: &'static CStr, key: Pin<&'static LockClassKey>) -> impl PinInit<Self> {
         pin_init!(Self {
             data: UnsafeCell::new(t),
             _pin: PhantomPinned,
diff --git a/rust/kernel/sync/lock/global.rs b/rust/kernel/sync/lock/global.rs
index 480ee724e3cc..d65f94b5caf2 100644
--- a/rust/kernel/sync/lock/global.rs
+++ b/rust/kernel/sync/lock/global.rs
@@ -13,6 +13,7 @@
 use core::{
     cell::UnsafeCell,
     marker::{PhantomData, PhantomPinned},
+    pin::Pin,
 };
 
 /// Trait implemented for marker types for global locks.
@@ -26,7 +27,7 @@ pub trait GlobalLockBackend {
     /// The backend used for this global lock.
     type Backend: Backend + 'static;
     /// The class for this global lock.
-    fn get_lock_class() -> &'static LockClassKey;
+    fn get_lock_class() -> Pin<&'static LockClassKey>;
 }
 
 /// Type used for global locks.
@@ -270,7 +271,7 @@ impl $crate::sync::lock::GlobalLockBackend for $name {
             type Item = $valuety;
             type Backend = $crate::global_lock_inner!(backend $kind);
 
-            fn get_lock_class() -> &'static $crate::sync::LockClassKey {
+            fn get_lock_class() -> Pin<&'static $crate::sync::LockClassKey> {
                 $crate::static_lock_class!()
             }
         }
diff --git a/rust/kernel/sync/poll.rs b/rust/kernel/sync/poll.rs
index d5f17153b424..c4934f82d68b 100644
--- a/rust/kernel/sync/poll.rs
+++ b/rust/kernel/sync/poll.rs
@@ -89,7 +89,7 @@ pub struct PollCondVar {
 
 impl PollCondVar {
     /// Constructs a new condvar initialiser.
-    pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self> {
+    pub fn new(name: &'static CStr, key: Pin<&'static LockClassKey>) -> impl PinInit<Self> {
         pin_init!(Self {
             inner <- CondVar::new(name, key),
         })
diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index 0cd100d2aefb..6b6f3ad08951 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -369,7 +369,7 @@ unsafe impl<T: ?Sized, const ID: u64> Sync for Work<T, ID> {}
 impl<T: ?Sized, const ID: u64> Work<T, ID> {
     /// Creates a new instance of [`Work`].
     #[inline]
-    pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self>
+    pub fn new(name: &'static CStr, key: Pin<&'static LockClassKey>) -> impl PinInit<Self>
     where
         T: WorkItem<ID>,
     {
-- 
2.47.1


^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH locking 00/11] LOCKDEP and Rust locking changes for v6.15
  2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
                     ` (10 preceding siblings ...)
  2025-03-07 23:27   ` [PATCH locking 11/11] rust: lockdep: Use Pin for all LockClassKey usages Boqun Feng
@ 2025-03-08  0:01   ` Ingo Molnar
  2025-03-08  0:04     ` Boqun Feng
  11 siblings, 1 reply; 31+ messages in thread
From: Ingo Molnar @ 2025-03-08  0:01 UTC (permalink / raw)
  To: Boqun Feng
  Cc: Peter Zijlstra, Will Deacon, Waiman Long, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	open list:RUST:Keyword:b(?i:rust)b


* Boqun Feng <boqun.feng@gmail.com> wrote:

> Hi Ingo & Peter,
> 
> As discussed, I'm resending the pull request for lockdep and Rust
> locking for v6.15 in the format of email patches. I dropped one patch
> and will postpone it for v6.16 because of a bug [1], and I think the fix
> [2] needs more reviews.
> 
> [1]: https://lore.kernel.org/lkml/20250306122413.GBZ8mT7Z61Tmgnh5Y9@fat_crate.local/
> [2]: https://lore.kernel.org/lkml/Z8t8imzJVhWyDvhC@boqun-archlinux/
> 
> Regards,
> Boqun
> 
> Alice Ryhl (2):
>   rust: sync: Add accessor for the lock behind a given guard
>   rust: sync: condvar: Add wait_interruptible_freezable()
> 
> Boqun Feng (1):
>   rust: sync: lock: Add an example for Guard::lock_ref()
> 
> Mitchell Levy (2):
>   rust: lockdep: Remove support for dynamically allocated LockClassKeys
>   rust: lockdep: Use Pin for all LockClassKey usages
> 
> Randy Dunlap (1):
>   locking/rtmutex: Use struct keyword in kernel-doc comment
> 
> Waiman Long (5):
>   locking/semaphore: Use wake_q to wake up processes outside lock
>     critical section
>   locking/lock_events: Add locking events for rtmutex slow paths
>   locking/lock_events: Add locking events for lockdep
>   locking/lockdep: Disable KASAN instrumentation of lockdep.c
>   locking/lockdep: Add kasan_check_byte() check in lock_acquire()

Thanks Boqun!

I've applied these 3 patches to the tip:locking/urgent tree:

  locking/semaphore: Use wake_q to wake up processes outside lock critical section
  locking/rtmutex: Use the 'struct' keyword in kernel-doc comment
  rust: lockdep: Remove support for dynamically allocated LockClassKeys

As a general rule, if a patch is marked Cc: stable, it must also be 
applied to current upstream.

I have applied the others to tip:locking/core:

  locking/lock_events: Add locking events for rtmutex slow pathsa94d32446ab5 locking/lock_events: Add locking events for lockdep
  locking/lockdep: Disable KASAN instrumentation of lockdep.c
  locking/lockdep: Add kasan_check_byte() check in lock_acquire()
  rust: sync: Add accessor for the lock behind a given guard
  rust: sync: lock: Add an example for Guard:: Lock_ref()
  rust: sync: condvar: Add wait_interruptible_freezable()
  rust: lockdep: Use Pin for all LockClassKey usages

I cleaned up changelogs where necessary - for example we generally 
don't include printk timestamps in changelogs, unless it's relevant, 
plus there were a number of typos and grammar mistakes left in some of 
the changelogs.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH locking 00/11] LOCKDEP and Rust locking changes for v6.15
  2025-03-08  0:01   ` [PATCH locking 00/11] LOCKDEP and Rust locking changes for v6.15 Ingo Molnar
@ 2025-03-08  0:04     ` Boqun Feng
  2025-03-08  0:11       ` Ingo Molnar
  0 siblings, 1 reply; 31+ messages in thread
From: Boqun Feng @ 2025-03-08  0:04 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Peter Zijlstra, Will Deacon, Waiman Long, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	open list:RUST:Keyword:b(?i:rust)b

On Sat, Mar 08, 2025 at 01:01:45AM +0100, Ingo Molnar wrote:
> 
> * Boqun Feng <boqun.feng@gmail.com> wrote:
> 
> > Hi Ingo & Peter,
> > 
> > As discussed, I'm resending the pull request for lockdep and Rust
> > locking for v6.15 in the format of email patches. I dropped one patch
> > and will postpone it for v6.16 because of a bug [1], and I think the fix
> > [2] needs more reviews.
> > 
> > [1]: https://lore.kernel.org/lkml/20250306122413.GBZ8mT7Z61Tmgnh5Y9@fat_crate.local/
> > [2]: https://lore.kernel.org/lkml/Z8t8imzJVhWyDvhC@boqun-archlinux/
> > 
> > Regards,
> > Boqun
> > 
> > Alice Ryhl (2):
> >   rust: sync: Add accessor for the lock behind a given guard
> >   rust: sync: condvar: Add wait_interruptible_freezable()
> > 
> > Boqun Feng (1):
> >   rust: sync: lock: Add an example for Guard::lock_ref()
> > 
> > Mitchell Levy (2):
> >   rust: lockdep: Remove support for dynamically allocated LockClassKeys
> >   rust: lockdep: Use Pin for all LockClassKey usages
> > 
> > Randy Dunlap (1):
> >   locking/rtmutex: Use struct keyword in kernel-doc comment
> > 
> > Waiman Long (5):
> >   locking/semaphore: Use wake_q to wake up processes outside lock
> >     critical section
> >   locking/lock_events: Add locking events for rtmutex slow paths
> >   locking/lock_events: Add locking events for lockdep
> >   locking/lockdep: Disable KASAN instrumentation of lockdep.c
> >   locking/lockdep: Add kasan_check_byte() check in lock_acquire()
> 
> Thanks Boqun!
> 

Thanks.

> I've applied these 3 patches to the tip:locking/urgent tree:
> 
>   locking/semaphore: Use wake_q to wake up processes outside lock critical section
>   locking/rtmutex: Use the 'struct' keyword in kernel-doc comment
>   rust: lockdep: Remove support for dynamically allocated LockClassKeys
> 
> As a general rule, if a patch is marked Cc: stable, it must also be 
> applied to current upstream.
> 

Do you prefer a separate pull request for the future? I can send one for
urgent and one for locking/core.

> I have applied the others to tip:locking/core:
> 
>   locking/lock_events: Add locking events for rtmutex slow pathsa94d32446ab5 locking/lock_events: Add locking events for lockdep
>   locking/lockdep: Disable KASAN instrumentation of lockdep.c
>   locking/lockdep: Add kasan_check_byte() check in lock_acquire()
>   rust: sync: Add accessor for the lock behind a given guard
>   rust: sync: lock: Add an example for Guard:: Lock_ref()
>   rust: sync: condvar: Add wait_interruptible_freezable()
>   rust: lockdep: Use Pin for all LockClassKey usages
> 
> I cleaned up changelogs where necessary - for example we generally 
> don't include printk timestamps in changelogs, unless it's relevant, 

Got it, I will avoid them in the future.

> plus there were a number of typos and grammar mistakes left in some of 
> the changelogs.
> 

Will take a look at your updates and keep working on improve them,
thanks!

Regards,
Boqun

> Thanks,
> 
> 	Ingo

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [tip: locking/core] rust: lockdep: Use Pin for all LockClassKey usages
  2025-03-07 23:27   ` [PATCH locking 11/11] rust: lockdep: Use Pin for all LockClassKey usages Boqun Feng
@ 2025-03-08  0:08     ` tip-bot2 for Mitchell Levy
  0 siblings, 0 replies; 31+ messages in thread
From: tip-bot2 for Mitchell Levy @ 2025-03-08  0:08 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Benno Lossin, Boqun Feng, Mitchell Levy, Ingo Molnar, x86,
	linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     f73ca66f0d7f4371d172d6f5b1f9a00e367ba921
Gitweb:        https://git.kernel.org/tip/f73ca66f0d7f4371d172d6f5b1f9a00e367ba921
Author:        Mitchell Levy <levymitchell0@gmail.com>
AuthorDate:    Fri, 07 Mar 2025 15:27:01 -08:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 08 Mar 2025 00:55:04 +01:00

rust: lockdep: Use Pin for all LockClassKey usages

Reintroduce dynamically-allocated LockClassKeys such that they are
automatically (de)registered. Require that all usages of LockClassKeys
ensure that they are Pin'd.

Currently, only `'static` LockClassKeys are supported, so Pin is
redundant. However, it is intended that dynamically-allocated
LockClassKeys will eventually be supported, so using Pin from the outset
will make that change simpler.

Closes: https://github.com/Rust-for-Linux/linux/issues/1102
Suggested-by: Benno Lossin <benno.lossin@proton.me>
Suggested-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Mitchell Levy <levymitchell0@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Link: https://lore.kernel.org/r/20250307232717.1759087-12-boqun.feng@gmail.com
---
 rust/helpers/helpers.c          |  1 +-
 rust/helpers/sync.c             | 13 +++++++-
 rust/kernel/sync.rs             | 57 ++++++++++++++++++++++++++++++--
 rust/kernel/sync/condvar.rs     |  5 +--
 rust/kernel/sync/lock.rs        |  4 +-
 rust/kernel/sync/lock/global.rs |  5 +--
 rust/kernel/sync/poll.rs        |  2 +-
 rust/kernel/workqueue.rs        |  2 +-
 8 files changed, 77 insertions(+), 12 deletions(-)
 create mode 100644 rust/helpers/sync.c

diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
index 0640b7e..4c1a10a 100644
--- a/rust/helpers/helpers.c
+++ b/rust/helpers/helpers.c
@@ -30,6 +30,7 @@
 #include "signal.c"
 #include "slab.c"
 #include "spinlock.c"
+#include "sync.c"
 #include "task.c"
 #include "uaccess.c"
 #include "vmalloc.c"
diff --git a/rust/helpers/sync.c b/rust/helpers/sync.c
new file mode 100644
index 0000000..ff7e68b
--- /dev/null
+++ b/rust/helpers/sync.c
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/lockdep.h>
+
+void rust_helper_lockdep_register_key(struct lock_class_key *k)
+{
+	lockdep_register_key(k);
+}
+
+void rust_helper_lockdep_unregister_key(struct lock_class_key *k)
+{
+	lockdep_unregister_key(k);
+}
diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs
index 16eab91..4104bc2 100644
--- a/rust/kernel/sync.rs
+++ b/rust/kernel/sync.rs
@@ -5,6 +5,8 @@
 //! This module contains the kernel APIs related to synchronisation that have been ported or
 //! wrapped for usage by Rust code in the kernel.
 
+use crate::pin_init;
+use crate::prelude::*;
 use crate::types::Opaque;
 
 mod arc;
@@ -23,15 +25,64 @@ pub use locked_by::LockedBy;
 
 /// Represents a lockdep class. It's a wrapper around C's `lock_class_key`.
 #[repr(transparent)]
-pub struct LockClassKey(Opaque<bindings::lock_class_key>);
+#[pin_data(PinnedDrop)]
+pub struct LockClassKey {
+    #[pin]
+    inner: Opaque<bindings::lock_class_key>,
+}
 
 // SAFETY: `bindings::lock_class_key` is designed to be used concurrently from multiple threads and
 // provides its own synchronization.
 unsafe impl Sync for LockClassKey {}
 
 impl LockClassKey {
+    /// Initializes a dynamically allocated lock class key. In the common case of using a
+    /// statically allocated lock class key, the static_lock_class! macro should be used instead.
+    ///
+    /// # Example
+    /// ```
+    /// # use kernel::{c_str, stack_pin_init};
+    /// # use kernel::alloc::KBox;
+    /// # use kernel::types::ForeignOwnable;
+    /// # use kernel::sync::{LockClassKey, SpinLock};
+    ///
+    /// let key = KBox::pin_init(LockClassKey::new_dynamic(), GFP_KERNEL)?;
+    /// let key_ptr = key.into_foreign();
+    ///
+    /// {
+    ///     stack_pin_init!(let num: SpinLock<u32> = SpinLock::new(
+    ///         0,
+    ///         c_str!("my_spinlock"),
+    ///         // SAFETY: `key_ptr` is returned by the above `into_foreign()`, whose
+    ///         // `from_foreign()` has not yet been called.
+    ///         unsafe { <Pin<KBox<LockClassKey>> as ForeignOwnable>::borrow(key_ptr) }
+    ///     ));
+    /// }
+    ///
+    /// // SAFETY: We dropped `num`, the only use of the key, so the result of the previous
+    /// // `borrow` has also been dropped. Thus, it's safe to use from_foreign.
+    /// unsafe { drop(<Pin<KBox<LockClassKey>> as ForeignOwnable>::from_foreign(key_ptr)) };
+    ///
+    /// # Ok::<(), Error>(())
+    /// ```
+    pub fn new_dynamic() -> impl PinInit<Self> {
+        pin_init!(Self {
+            // SAFETY: lockdep_register_key expects an uninitialized block of memory
+            inner <- Opaque::ffi_init(|slot| unsafe { bindings::lockdep_register_key(slot) })
+        })
+    }
+
     pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key {
-        self.0.get()
+        self.inner.get()
+    }
+}
+
+#[pinned_drop]
+impl PinnedDrop for LockClassKey {
+    fn drop(self: Pin<&mut Self>) {
+        // SAFETY: self.as_ptr was registered with lockdep and self is pinned, so the address
+        // hasn't changed. Thus, it's safe to pass to unregister.
+        unsafe { bindings::lockdep_unregister_key(self.as_ptr()) }
     }
 }
 
@@ -44,7 +95,7 @@ macro_rules! static_lock_class {
             // SAFETY: lockdep expects uninitialized memory when it's handed a statically allocated
             // lock_class_key
             unsafe { ::core::mem::MaybeUninit::uninit().assume_init() };
-        &CLASS
+        $crate::prelude::Pin::static_ref(&CLASS)
     }};
 }
 
diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
index 5c1e546..fbf68ad 100644
--- a/rust/kernel/sync/condvar.rs
+++ b/rust/kernel/sync/condvar.rs
@@ -17,8 +17,7 @@ use crate::{
     time::Jiffies,
     types::Opaque,
 };
-use core::marker::PhantomPinned;
-use core::ptr;
+use core::{marker::PhantomPinned, pin::Pin, ptr};
 use macros::pin_data;
 
 /// Creates a [`CondVar`] initialiser with the given name and a newly-created lock class.
@@ -103,7 +102,7 @@ unsafe impl Sync for CondVar {}
 
 impl CondVar {
     /// Constructs a new condvar initialiser.
-    pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self> {
+    pub fn new(name: &'static CStr, key: Pin<&'static LockClassKey>) -> impl PinInit<Self> {
         pin_init!(Self {
             _pin: PhantomPinned,
             // SAFETY: `slot` is valid while the closure is called and both `name` and `key` have
diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
index f53e87d..360a10a 100644
--- a/rust/kernel/sync/lock.rs
+++ b/rust/kernel/sync/lock.rs
@@ -12,7 +12,7 @@ use crate::{
     str::CStr,
     types::{NotThreadSafe, Opaque, ScopeGuard},
 };
-use core::{cell::UnsafeCell, marker::PhantomPinned};
+use core::{cell::UnsafeCell, marker::PhantomPinned, pin::Pin};
 use macros::pin_data;
 
 pub mod mutex;
@@ -129,7 +129,7 @@ unsafe impl<T: ?Sized + Send, B: Backend> Sync for Lock<T, B> {}
 
 impl<T, B: Backend> Lock<T, B> {
     /// Constructs a new lock initialiser.
-    pub fn new(t: T, name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self> {
+    pub fn new(t: T, name: &'static CStr, key: Pin<&'static LockClassKey>) -> impl PinInit<Self> {
         pin_init!(Self {
             data: UnsafeCell::new(t),
             _pin: PhantomPinned,
diff --git a/rust/kernel/sync/lock/global.rs b/rust/kernel/sync/lock/global.rs
index 480ee72..d65f94b 100644
--- a/rust/kernel/sync/lock/global.rs
+++ b/rust/kernel/sync/lock/global.rs
@@ -13,6 +13,7 @@ use crate::{
 use core::{
     cell::UnsafeCell,
     marker::{PhantomData, PhantomPinned},
+    pin::Pin,
 };
 
 /// Trait implemented for marker types for global locks.
@@ -26,7 +27,7 @@ pub trait GlobalLockBackend {
     /// The backend used for this global lock.
     type Backend: Backend + 'static;
     /// The class for this global lock.
-    fn get_lock_class() -> &'static LockClassKey;
+    fn get_lock_class() -> Pin<&'static LockClassKey>;
 }
 
 /// Type used for global locks.
@@ -270,7 +271,7 @@ macro_rules! global_lock {
             type Item = $valuety;
             type Backend = $crate::global_lock_inner!(backend $kind);
 
-            fn get_lock_class() -> &'static $crate::sync::LockClassKey {
+            fn get_lock_class() -> Pin<&'static $crate::sync::LockClassKey> {
                 $crate::static_lock_class!()
             }
         }
diff --git a/rust/kernel/sync/poll.rs b/rust/kernel/sync/poll.rs
index d5f1715..c4934f8 100644
--- a/rust/kernel/sync/poll.rs
+++ b/rust/kernel/sync/poll.rs
@@ -89,7 +89,7 @@ pub struct PollCondVar {
 
 impl PollCondVar {
     /// Constructs a new condvar initialiser.
-    pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self> {
+    pub fn new(name: &'static CStr, key: Pin<&'static LockClassKey>) -> impl PinInit<Self> {
         pin_init!(Self {
             inner <- CondVar::new(name, key),
         })
diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index 0cd100d..6b6f3ad 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -369,7 +369,7 @@ unsafe impl<T: ?Sized, const ID: u64> Sync for Work<T, ID> {}
 impl<T: ?Sized, const ID: u64> Work<T, ID> {
     /// Creates a new instance of [`Work`].
     #[inline]
-    pub fn new(name: &'static CStr, key: &'static LockClassKey) -> impl PinInit<Self>
+    pub fn new(name: &'static CStr, key: Pin<&'static LockClassKey>) -> impl PinInit<Self>
     where
         T: WorkItem<ID>,
     {

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [tip: locking/core] rust: sync: condvar: Add wait_interruptible_freezable()
  2025-03-07 23:26   ` [PATCH locking 09/11] rust: sync: condvar: Add wait_interruptible_freezable() Boqun Feng
@ 2025-03-08  0:08     ` tip-bot2 for Alice Ryhl
  0 siblings, 0 replies; 31+ messages in thread
From: tip-bot2 for Alice Ryhl @ 2025-03-08  0:08 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Alice Ryhl, Boqun Feng, Ingo Molnar, x86, linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     70b9c8563c9c29102a785d4822f0d77d33fee808
Gitweb:        https://git.kernel.org/tip/70b9c8563c9c29102a785d4822f0d77d33fee808
Author:        Alice Ryhl <aliceryhl@google.com>
AuthorDate:    Fri, 07 Mar 2025 15:26:59 -08:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 08 Mar 2025 00:55:04 +01:00

rust: sync: condvar: Add wait_interruptible_freezable()

To support waiting for a `CondVar` as a freezable process, add a
wait_interruptible_freezable() function.

Binder needs this function in the appropriate places to freeze a process
where some of its threads are blocked on the Binder driver.

[ Boqun: Cleaned up the changelog and documentation. ]

Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Link: https://lore.kernel.org/r/20250307232717.1759087-10-boqun.feng@gmail.com
---
 rust/kernel/sync/condvar.rs | 23 ++++++++++++++++++++++-
 rust/kernel/task.rs         |  2 ++
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
index 7df5650..5c1e546 100644
--- a/rust/kernel/sync/condvar.rs
+++ b/rust/kernel/sync/condvar.rs
@@ -11,7 +11,9 @@ use crate::{
     init::PinInit,
     pin_init,
     str::CStr,
-    task::{MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE, TASK_NORMAL, TASK_UNINTERRUPTIBLE},
+    task::{
+        MAX_SCHEDULE_TIMEOUT, TASK_FREEZABLE, TASK_INTERRUPTIBLE, TASK_NORMAL, TASK_UNINTERRUPTIBLE,
+    },
     time::Jiffies,
     types::Opaque,
 };
@@ -159,6 +161,25 @@ impl CondVar {
         crate::current!().signal_pending()
     }
 
+    /// Releases the lock and waits for a notification in interruptible and freezable mode.
+    ///
+    /// The process is allowed to be frozen during this sleep. No lock should be held when calling
+    /// this function, and there is a lockdep assertion for this. Freezing a task that holds a lock
+    /// can trivially deadlock vs another task that needs that lock to complete before it too can
+    /// hit freezable.
+    #[must_use = "wait_interruptible_freezable returns if a signal is pending, so the caller must check the return value"]
+    pub fn wait_interruptible_freezable<T: ?Sized, B: Backend>(
+        &self,
+        guard: &mut Guard<'_, T, B>,
+    ) -> bool {
+        self.wait_internal(
+            TASK_INTERRUPTIBLE | TASK_FREEZABLE,
+            guard,
+            MAX_SCHEDULE_TIMEOUT,
+        );
+        crate::current!().signal_pending()
+    }
+
     /// Releases the lock and waits for a notification in interruptible mode.
     ///
     /// Atomically releases the given lock (whose ownership is proven by the guard) and puts the
diff --git a/rust/kernel/task.rs b/rust/kernel/task.rs
index 07bc22a..ea43a3b 100644
--- a/rust/kernel/task.rs
+++ b/rust/kernel/task.rs
@@ -23,6 +23,8 @@ pub const MAX_SCHEDULE_TIMEOUT: c_long = c_long::MAX;
 pub const TASK_INTERRUPTIBLE: c_int = bindings::TASK_INTERRUPTIBLE as c_int;
 /// Bitmask for tasks that are sleeping in an uninterruptible state.
 pub const TASK_UNINTERRUPTIBLE: c_int = bindings::TASK_UNINTERRUPTIBLE as c_int;
+/// Bitmask for tasks that are sleeping in a freezable state.
+pub const TASK_FREEZABLE: c_int = bindings::TASK_FREEZABLE as c_int;
 /// Convenience constant for waking up tasks regardless of whether they are in interruptible or
 /// uninterruptible sleep.
 pub const TASK_NORMAL: c_uint = bindings::TASK_NORMAL as c_uint;

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [tip: locking/core] rust: sync: lock: Add an example for Guard:: Lock_ref()
  2025-03-07 23:26   ` [PATCH locking 08/11] rust: sync: lock: Add an example for Guard::lock_ref() Boqun Feng
@ 2025-03-08  0:08     ` tip-bot2 for Boqun Feng
  0 siblings, 0 replies; 31+ messages in thread
From: tip-bot2 for Boqun Feng @ 2025-03-08  0:08 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Boqun Feng, Ingo Molnar, Benno Lossin, Alice Ryhl, x86,
	linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     c2849afafd08a1c3ad881129de48ebe1642f7675
Gitweb:        https://git.kernel.org/tip/c2849afafd08a1c3ad881129de48ebe1642f7675
Author:        Boqun Feng <boqun.feng@gmail.com>
AuthorDate:    Fri, 07 Mar 2025 15:26:58 -08:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 08 Mar 2025 00:55:04 +01:00

rust: sync: lock: Add an example for Guard:: Lock_ref()

To provide examples on usage of `Guard::lock_ref()` along with the unit
test, an "assert a lock is held by a guard" example is added.

(Also apply feedback from Benno.)

Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://lore.kernel.org/r/20250223072114.3715-1-boqun.feng@gmail.com
Link: https://lore.kernel.org/r/20250307232717.1759087-9-boqun.feng@gmail.com
---
 rust/kernel/sync/lock.rs | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
index 8e7e6d5..f53e87d 100644
--- a/rust/kernel/sync/lock.rs
+++ b/rust/kernel/sync/lock.rs
@@ -201,6 +201,30 @@ unsafe impl<T: Sync + ?Sized, B: Backend> Sync for Guard<'_, T, B> {}
 
 impl<'a, T: ?Sized, B: Backend> Guard<'a, T, B> {
     /// Returns the lock that this guard originates from.
+    ///
+    /// # Examples
+    ///
+    /// The following example shows how to use [`Guard::lock_ref()`] to assert the corresponding
+    /// lock is held.
+    ///
+    /// ```
+    /// # use kernel::{new_spinlock, stack_pin_init, sync::lock::{Backend, Guard, Lock}};
+    ///
+    /// fn assert_held<T, B: Backend>(guard: &Guard<'_, T, B>, lock: &Lock<T, B>) {
+    ///     // Address-equal means the same lock.
+    ///     assert!(core::ptr::eq(guard.lock_ref(), lock));
+    /// }
+    ///
+    /// // Creates a new lock on the stack.
+    /// stack_pin_init!{
+    ///     let l = new_spinlock!(42)
+    /// }
+    ///
+    /// let g = l.lock();
+    ///
+    /// // `g` originates from `l`.
+    /// assert_held(&g, &l);
+    /// ```
     pub fn lock_ref(&self) -> &'a Lock<T, B> {
         self.lock
     }

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [tip: locking/core] rust: sync: Add accessor for the lock behind a given guard
  2025-03-07 23:26   ` [PATCH locking 07/11] rust: sync: Add accessor for the lock behind a given guard Boqun Feng
@ 2025-03-08  0:08     ` tip-bot2 for Alice Ryhl
  0 siblings, 0 replies; 31+ messages in thread
From: tip-bot2 for Alice Ryhl @ 2025-03-08  0:08 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Alice Ryhl, Boqun Feng, Ingo Molnar, Fiona Behrens, x86,
	linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     8f65291dae0e75941cf76e427088e5612c4d692e
Gitweb:        https://git.kernel.org/tip/8f65291dae0e75941cf76e427088e5612c4d692e
Author:        Alice Ryhl <aliceryhl@google.com>
AuthorDate:    Fri, 07 Mar 2025 15:26:57 -08:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 08 Mar 2025 00:55:04 +01:00

rust: sync: Add accessor for the lock behind a given guard

In order to assert a particular `Guard` is associated with a particular
`Lock`, add an accessor to obtain a reference to the underlying `Lock`
of a `Guard`.

Binder needs this assertion to ensure unsafe list operations are done
with the correct lock held.

[Boqun: Capitalize the title and reword the commit log]

Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Fiona Behrens <me@kloenk.dev>
Link: https://lore.kernel.org/r/20250205-guard-get-lock-v2-1-ba32a8c1d5b7@google.com
Link: https://lore.kernel.org/r/20250307232717.1759087-8-boqun.feng@gmail.com
---
 rust/kernel/sync/lock.rs | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/sync/lock.rs b/rust/kernel/sync/lock.rs
index eb80048..8e7e6d5 100644
--- a/rust/kernel/sync/lock.rs
+++ b/rust/kernel/sync/lock.rs
@@ -199,7 +199,12 @@ pub struct Guard<'a, T: ?Sized, B: Backend> {
 // SAFETY: `Guard` is sync when the data protected by the lock is also sync.
 unsafe impl<T: Sync + ?Sized, B: Backend> Sync for Guard<'_, T, B> {}
 
-impl<T: ?Sized, B: Backend> Guard<'_, T, B> {
+impl<'a, T: ?Sized, B: Backend> Guard<'a, T, B> {
+    /// Returns the lock that this guard originates from.
+    pub fn lock_ref(&self) -> &'a Lock<T, B> {
+        self.lock
+    }
+
     pub(crate) fn do_unlocked<U>(&mut self, cb: impl FnOnce() -> U) -> U {
         // SAFETY: The caller owns the lock, so it is safe to unlock it.
         unsafe { B::unlock(self.lock.state.get(), &self.state) };

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [tip: locking/core] locking/lockdep: Add kasan_check_byte() check in lock_acquire()
  2025-03-07 23:26   ` [PATCH locking 06/11] locking/lockdep: Add kasan_check_byte() check in lock_acquire() Boqun Feng
@ 2025-03-08  0:08     ` tip-bot2 for Waiman Long
  0 siblings, 0 replies; 31+ messages in thread
From: tip-bot2 for Waiman Long @ 2025-03-08  0:08 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Marco Elver, Waiman Long, Boqun Feng, Ingo Molnar,
	Andrey Konovalov, x86, linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     de4b59d652646cf00cf632174348ca2266099edc
Gitweb:        https://git.kernel.org/tip/de4b59d652646cf00cf632174348ca2266099edc
Author:        Waiman Long <longman@redhat.com>
AuthorDate:    Fri, 07 Mar 2025 15:26:56 -08:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 08 Mar 2025 00:55:04 +01:00

locking/lockdep: Add kasan_check_byte() check in lock_acquire()

KASAN instrumentation of lockdep has been disabled, as we don't need
KASAN to check the validity of lockdep internal data structures and
incur unnecessary performance overhead. However, the lockdep_map pointer
passed in externally may not be valid (e.g. use-after-free) and we run
the risk of using garbage data resulting in false lockdep reports.

Add kasan_check_byte() call in lock_acquire() for non kernel core data
object to catch invalid lockdep_map and print out a KASAN report before
any lockdep splat, if any.

Suggested-by: Marco Elver <elver@google.com>
Signed-off-by: Waiman Long <longman@redhat.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Marco Elver <elver@google.com>
Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
Link: https://lore.kernel.org/r/20250214195242.2480920-1-longman@redhat.com
Link: https://lore.kernel.org/r/20250307232717.1759087-7-boqun.feng@gmail.com
---
 kernel/locking/lockdep.c |  9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 8436f01..b15757e 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -57,6 +57,7 @@
 #include <linux/lockdep.h>
 #include <linux/context_tracking.h>
 #include <linux/console.h>
+#include <linux/kasan.h>
 
 #include <asm/sections.h>
 
@@ -5830,6 +5831,14 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
 	if (!debug_locks)
 		return;
 
+	/*
+	 * As KASAN instrumentation is disabled and lock_acquire() is usually
+	 * the first lockdep call when a task tries to acquire a lock, add
+	 * kasan_check_byte() here to check for use-after-free and other
+	 * memory errors.
+	 */
+	kasan_check_byte(lock);
+
 	if (unlikely(!lockdep_enabled())) {
 		/* XXX allow trylock from NMI ?!? */
 		if (lockdep_nmi() && !trylock) {

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [tip: locking/core] locking/lockdep: Disable KASAN instrumentation of lockdep.c
  2025-03-07 23:26   ` [PATCH locking 05/11] locking/lockdep: Disable KASAN instrumentation of lockdep.c Boqun Feng
@ 2025-03-08  0:08     ` tip-bot2 for Waiman Long
  0 siblings, 0 replies; 31+ messages in thread
From: tip-bot2 for Waiman Long @ 2025-03-08  0:08 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Waiman Long, Boqun Feng, Ingo Molnar, Marco Elver,
	Andrey Konovalov, Linus Torvalds, x86, linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     ee57ab5a32129f599ee1d358548dbebcb5e45953
Gitweb:        https://git.kernel.org/tip/ee57ab5a32129f599ee1d358548dbebcb5e45953
Author:        Waiman Long <longman@redhat.com>
AuthorDate:    Fri, 07 Mar 2025 15:26:55 -08:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 08 Mar 2025 00:55:03 +01:00

locking/lockdep: Disable KASAN instrumentation of lockdep.c

Both KASAN and LOCKDEP are commonly enabled in building a debug kernel.
Each of them can significantly slow down the speed of a debug kernel.
Enabling KASAN instrumentation of the LOCKDEP code will further slow
things down.

Since LOCKDEP is a high overhead debugging tool, it will never get
enabled in a production kernel. The LOCKDEP code is also pretty mature
and is unlikely to get major changes. There is also a possibility of
recursion similar to KCSAN.

To evaluate the performance impact of disabling KASAN instrumentation
of lockdep.c, the time to do a parallel build of the Linux defconfig
kernel was used as the benchmark. Two x86-64 systems (Skylake & Zen 2)
and an arm64 system were used as test beds. Two sets of non-RT and RT
kernels with similar configurations except mainly CONFIG_PREEMPT_RT
were used for evaluation.

For the Skylake system:

  Kernel			Run time	    Sys time
  ------			--------	    --------
  Non-debug kernel (baseline)	0m47.642s	      4m19.811s

  [CONFIG_KASAN_INLINE=y]
  Debug kernel			2m11.108s (x2.8)     38m20.467s (x8.9)
  Debug kernel (patched)	1m49.602s (x2.3)     31m28.501s (x7.3)
  Debug kernel
  (patched + mitigations=off)	1m30.988s (x1.9)     26m41.993s (x6.2)

  RT kernel (baseline)		0m54.871s	      7m15.340s

  [CONFIG_KASAN_INLINE=n]
  RT debug kernel		6m07.151s (x6.7)    135m47.428s (x18.7)
  RT debug kernel (patched)	3m42.434s (x4.1)     74m51.636s (x10.3)
  RT debug kernel
  (patched + mitigations=off)	2m40.383s (x2.9)     57m54.369s (x8.0)

  [CONFIG_KASAN_INLINE=y]
  RT debug kernel		3m22.155s (x3.7)     77m53.018s (x10.7)
  RT debug kernel (patched)	2m36.700s (x2.9)     54m31.195s (x7.5)
  RT debug kernel
  (patched + mitigations=off)	2m06.110s (x2.3)     45m49.493s (x6.3)

For the Zen 2 system:

  Kernel			Run time	    Sys time
  ------			--------	    --------
  Non-debug kernel (baseline)	1m42.806s	     39m48.714s

  [CONFIG_KASAN_INLINE=y]
  Debug kernel			4m04.524s (x2.4)    125m35.904s (x3.2)
  Debug kernel (patched)	3m56.241s (x2.3)    127m22.378s (x3.2)
  Debug kernel
  (patched + mitigations=off)	2m38.157s (x1.5)     92m35.680s (x2.3)

  RT kernel (baseline)		 1m51.500s	     14m56.322s

  [CONFIG_KASAN_INLINE=n]
  RT debug kernel		16m04.962s (x8.7)   244m36.463s (x16.4)
  RT debug kernel (patched)	 9m09.073s (x4.9)   129m28.439s (x8.7)
  RT debug kernel
  (patched + mitigations=off)	 3m31.662s (x1.9)    51m01.391s (x3.4)

For the arm64 system:

  Kernel			Run time	    Sys time
  ------			--------	    --------
  Non-debug kernel (baseline)	1m56.844s	      8m47.150s
  Debug kernel			3m54.774s (x2.0)     92m30.098s (x10.5)
  Debug kernel (patched)	3m32.429s (x1.8)     77m40.779s (x8.8)

  RT kernel (baseline)		 4m01.641s	     18m16.777s

  [CONFIG_KASAN_INLINE=n]
  RT debug kernel		19m32.977s (x4.9)   304m23.965s (x16.7)
  RT debug kernel (patched)	16m28.354s (x4.1)   234m18.149s (x12.8)

Turning the mitigations off doesn't seems to have any noticeable impact
on the performance of the arm64 system. So the mitigation=off entries
aren't included.

For the x86 CPUs, CPU mitigations has a much bigger
impact on performance, especially the RT debug kernel with
CONFIG_KASAN_INLINE=n. The SRSO mitigation in Zen 2 has an especially
big impact on the debug kernel. It is also the majority of the slowdown
with mitigations on. It is because the patched RET instruction slows
down function returns. A lot of helper functions that are normally
compiled out or inlined may become real function calls in the debug
kernel.

With !CONFIG_KASAN_INLINE, the KASAN instrumentation inserts a
lot of __asan_loadX*() and __kasan_check_read() function calls to memory
access portion of the code. The lockdep's __lock_acquire() function,
for instance, has 66 __asan_loadX*() and 6 __kasan_check_read() calls
added with KASAN instrumentation. Of course, the actual numbers may vary
depending on the compiler used and the exact version of the lockdep code.

With the Skylake test system, the parallel kernel build times reduction
of the RT debug kernel with this patch are:

 CONFIG_KASAN_INLINE=n: -37%
 CONFIG_KASAN_INLINE=y: -22%

The time reduction is less with CONFIG_KASAN_INLINE=y, but it is still
significant.

Setting CONFIG_KASAN_INLINE=y can result in a significant performance
improvement. The major drawback is a significant increase in the size
of kernel text. In the case of vmlinux, its text size increases from
45997948 to 67606807. That is a 47% size increase (about 21 Mbytes). The
size increase of other kernel modules should be similar.

With the newly added rtmutex and lockdep lock events, the relevant
event counts for the test runs with the Skylake system were:

  Event type		Debug kernel	RT debug kernel
  ----------		------------	---------------
  lockdep_acquire	1,968,663,277	5,425,313,953
  rtlock_slowlock	     -		  401,701,156
  rtmutex_slowlock	     -		      139,672

The __lock_acquire() calls in the RT debug kernel are x2.8 times of the
non-RT debug kernel with the same workload. Since the __lock_acquire()
function is a big hitter in term of performance slowdown, this makes
the RT debug kernel much slower than the non-RT one. The average lock
nesting depth is likely to be higher in the RT debug kernel too leading
to longer execution time in the __lock_acquire() function.

As the small advantage of enabling KASAN instrumentation to catch
potential memory access error in the lockdep debugging tool is probably
not worth the drawback of further slowing down a debug kernel, disable
KASAN instrumentation in the lockdep code to allow the debug kernels
to regain some performance back, especially for the RT debug kernels.

Signed-off-by: Waiman Long <longman@redhat.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Marco Elver <elver@google.com>
Reviewed-by: Andrey Konovalov <andreyknvl@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: https://lore.kernel.org/r/20250307232717.1759087-6-boqun.feng@gmail.com
---
 kernel/locking/Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/locking/Makefile b/kernel/locking/Makefile
index 0db4093..a114949 100644
--- a/kernel/locking/Makefile
+++ b/kernel/locking/Makefile
@@ -5,7 +5,8 @@ KCOV_INSTRUMENT		:= n
 
 obj-y += mutex.o semaphore.o rwsem.o percpu-rwsem.o
 
-# Avoid recursion lockdep -> sanitizer -> ... -> lockdep.
+# Avoid recursion lockdep -> sanitizer -> ... -> lockdep & improve performance.
+KASAN_SANITIZE_lockdep.o := n
 KCSAN_SANITIZE_lockdep.o := n
 
 ifdef CONFIG_FUNCTION_TRACER

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [tip: locking/core] locking/lock_events: Add locking events for lockdep
  2025-03-07 23:26   ` [PATCH locking 04/11] locking/lock_events: Add locking events for lockdep Boqun Feng
@ 2025-03-08  0:08     ` tip-bot2 for Waiman Long
  0 siblings, 0 replies; 31+ messages in thread
From: tip-bot2 for Waiman Long @ 2025-03-08  0:08 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Waiman Long, Boqun Feng, Ingo Molnar, x86, linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     a94d32446ab5e85c7ba97e48a8c9bd85be4fe889
Gitweb:        https://git.kernel.org/tip/a94d32446ab5e85c7ba97e48a8c9bd85be4fe889
Author:        Waiman Long <longman@redhat.com>
AuthorDate:    Fri, 07 Mar 2025 15:26:54 -08:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 08 Mar 2025 00:55:03 +01:00

locking/lock_events: Add locking events for lockdep

Add some lock events to lockdep to profile its behavior.

Signed-off-by: Waiman Long <longman@redhat.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Link: https://lore.kernel.org/r/20250307232717.1759087-5-boqun.feng@gmail.com
---
 kernel/locking/lock_events_list.h | 7 +++++++
 kernel/locking/lockdep.c          | 8 +++++++-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/kernel/locking/lock_events_list.h b/kernel/locking/lock_events_list.h
index 80b11f1..9ef9850 100644
--- a/kernel/locking/lock_events_list.h
+++ b/kernel/locking/lock_events_list.h
@@ -88,3 +88,10 @@ LOCK_EVENT(rtmutex_slow_acq3)	/* # of locks acquired in *block()	*/
 LOCK_EVENT(rtmutex_slow_sleep)	/* # of sleeps				*/
 LOCK_EVENT(rtmutex_slow_wake)	/* # of wakeup's			*/
 LOCK_EVENT(rtmutex_deadlock)	/* # of rt_mutex_handle_deadlock()'s	*/
+
+/*
+ * Locking events for lockdep
+ */
+LOCK_EVENT(lockdep_acquire)
+LOCK_EVENT(lockdep_lock)
+LOCK_EVENT(lockdep_nocheck)
diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c
index 4470680..8436f01 100644
--- a/kernel/locking/lockdep.c
+++ b/kernel/locking/lockdep.c
@@ -61,6 +61,7 @@
 #include <asm/sections.h>
 
 #include "lockdep_internals.h"
+#include "lock_events.h"
 
 #include <trace/events/lock.h>
 
@@ -170,6 +171,7 @@ static struct task_struct *lockdep_selftest_task_struct;
 static int graph_lock(void)
 {
 	lockdep_lock();
+	lockevent_inc(lockdep_lock);
 	/*
 	 * Make sure that if another CPU detected a bug while
 	 * walking the graph we dont change it (while the other
@@ -5091,8 +5093,12 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
 	if (unlikely(lock->key == &__lockdep_no_track__))
 		return 0;
 
-	if (!prove_locking || lock->key == &__lockdep_no_validate__)
+	lockevent_inc(lockdep_acquire);
+
+	if (!prove_locking || lock->key == &__lockdep_no_validate__) {
 		check = 0;
+		lockevent_inc(lockdep_nocheck);
+	}
 
 	if (subclass < NR_LOCKDEP_CACHING_CLASSES)
 		class = lock->class_cache[subclass];

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [tip: locking/core] locking/lock_events: Add locking events for rtmutex slow paths
  2025-03-07 23:26   ` [PATCH locking 03/11] locking/lock_events: Add locking events for rtmutex slow paths Boqun Feng
@ 2025-03-08  0:08     ` tip-bot2 for Waiman Long
  0 siblings, 0 replies; 31+ messages in thread
From: tip-bot2 for Waiman Long @ 2025-03-08  0:08 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Waiman Long, Boqun Feng, Ingo Molnar, x86, linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     b76b44fb656100fcd8482d9102d35d1b6a5129e9
Gitweb:        https://git.kernel.org/tip/b76b44fb656100fcd8482d9102d35d1b6a5129e9
Author:        Waiman Long <longman@redhat.com>
AuthorDate:    Fri, 07 Mar 2025 15:26:53 -08:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 08 Mar 2025 00:55:03 +01:00

locking/lock_events: Add locking events for rtmutex slow paths

Add locking events for rtlock_slowlock() and rt_mutex_slowlock() for
profiling the slow path behavior of rt_spin_lock() and rt_mutex_lock().

Signed-off-by: Waiman Long <longman@redhat.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Link: https://lore.kernel.org/r/20250307232717.1759087-4-boqun.feng@gmail.com
---
 kernel/locking/lock_events_list.h | 21 +++++++++++++++++++++
 kernel/locking/rtmutex.c          | 29 ++++++++++++++++++++++++-----
 2 files changed, 45 insertions(+), 5 deletions(-)

diff --git a/kernel/locking/lock_events_list.h b/kernel/locking/lock_events_list.h
index 97fb6f3..80b11f1 100644
--- a/kernel/locking/lock_events_list.h
+++ b/kernel/locking/lock_events_list.h
@@ -67,3 +67,24 @@ LOCK_EVENT(rwsem_rlock_handoff)	/* # of read lock handoffs		*/
 LOCK_EVENT(rwsem_wlock)		/* # of write locks acquired		*/
 LOCK_EVENT(rwsem_wlock_fail)	/* # of failed write lock acquisitions	*/
 LOCK_EVENT(rwsem_wlock_handoff)	/* # of write lock handoffs		*/
+
+/*
+ * Locking events for rtlock_slowlock()
+ */
+LOCK_EVENT(rtlock_slowlock)	/* # of rtlock_slowlock() calls		*/
+LOCK_EVENT(rtlock_slow_acq1)	/* # of locks acquired after wait_lock	*/
+LOCK_EVENT(rtlock_slow_acq2)	/* # of locks acquired in for loop	*/
+LOCK_EVENT(rtlock_slow_sleep)	/* # of sleeps				*/
+LOCK_EVENT(rtlock_slow_wake)	/* # of wakeup's			*/
+
+/*
+ * Locking events for rt_mutex_slowlock()
+ */
+LOCK_EVENT(rtmutex_slowlock)	/* # of rt_mutex_slowlock() calls	*/
+LOCK_EVENT(rtmutex_slow_block)	/* # of rt_mutex_slowlock_block() calls	*/
+LOCK_EVENT(rtmutex_slow_acq1)	/* # of locks acquired after wait_lock	*/
+LOCK_EVENT(rtmutex_slow_acq2)	/* # of locks acquired at the end	*/
+LOCK_EVENT(rtmutex_slow_acq3)	/* # of locks acquired in *block()	*/
+LOCK_EVENT(rtmutex_slow_sleep)	/* # of sleeps				*/
+LOCK_EVENT(rtmutex_slow_wake)	/* # of wakeup's			*/
+LOCK_EVENT(rtmutex_deadlock)	/* # of rt_mutex_handle_deadlock()'s	*/
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index 4a8df18..c80902e 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -27,6 +27,7 @@
 #include <trace/events/lock.h>
 
 #include "rtmutex_common.h"
+#include "lock_events.h"
 
 #ifndef WW_RT
 # define build_ww_mutex()	(false)
@@ -1612,10 +1613,13 @@ static int __sched rt_mutex_slowlock_block(struct rt_mutex_base *lock,
 	struct task_struct *owner;
 	int ret = 0;
 
+	lockevent_inc(rtmutex_slow_block);
 	for (;;) {
 		/* Try to acquire the lock: */
-		if (try_to_take_rt_mutex(lock, current, waiter))
+		if (try_to_take_rt_mutex(lock, current, waiter)) {
+			lockevent_inc(rtmutex_slow_acq3);
 			break;
+		}
 
 		if (timeout && !timeout->task) {
 			ret = -ETIMEDOUT;
@@ -1638,8 +1642,10 @@ static int __sched rt_mutex_slowlock_block(struct rt_mutex_base *lock,
 			owner = NULL;
 		raw_spin_unlock_irq_wake(&lock->wait_lock, wake_q);
 
-		if (!owner || !rtmutex_spin_on_owner(lock, waiter, owner))
+		if (!owner || !rtmutex_spin_on_owner(lock, waiter, owner)) {
+			lockevent_inc(rtmutex_slow_sleep);
 			rt_mutex_schedule();
+		}
 
 		raw_spin_lock_irq(&lock->wait_lock);
 		set_current_state(state);
@@ -1694,6 +1700,7 @@ static int __sched __rt_mutex_slowlock(struct rt_mutex_base *lock,
 	int ret;
 
 	lockdep_assert_held(&lock->wait_lock);
+	lockevent_inc(rtmutex_slowlock);
 
 	/* Try to acquire the lock again: */
 	if (try_to_take_rt_mutex(lock, current, NULL)) {
@@ -1701,6 +1708,7 @@ static int __sched __rt_mutex_slowlock(struct rt_mutex_base *lock,
 			__ww_mutex_check_waiters(rtm, ww_ctx, wake_q);
 			ww_mutex_lock_acquired(ww, ww_ctx);
 		}
+		lockevent_inc(rtmutex_slow_acq1);
 		return 0;
 	}
 
@@ -1719,10 +1727,12 @@ static int __sched __rt_mutex_slowlock(struct rt_mutex_base *lock,
 				__ww_mutex_check_waiters(rtm, ww_ctx, wake_q);
 			ww_mutex_lock_acquired(ww, ww_ctx);
 		}
+		lockevent_inc(rtmutex_slow_acq2);
 	} else {
 		__set_current_state(TASK_RUNNING);
 		remove_waiter(lock, waiter);
 		rt_mutex_handle_deadlock(ret, chwalk, lock, waiter);
+		lockevent_inc(rtmutex_deadlock);
 	}
 
 	/*
@@ -1751,6 +1761,7 @@ static inline int __rt_mutex_slowlock_locked(struct rt_mutex_base *lock,
 				  &waiter, wake_q);
 
 	debug_rt_mutex_free_waiter(&waiter);
+	lockevent_cond_inc(rtmutex_slow_wake, !wake_q_empty(wake_q));
 	return ret;
 }
 
@@ -1823,9 +1834,12 @@ static void __sched rtlock_slowlock_locked(struct rt_mutex_base *lock,
 	struct task_struct *owner;
 
 	lockdep_assert_held(&lock->wait_lock);
+	lockevent_inc(rtlock_slowlock);
 
-	if (try_to_take_rt_mutex(lock, current, NULL))
+	if (try_to_take_rt_mutex(lock, current, NULL)) {
+		lockevent_inc(rtlock_slow_acq1);
 		return;
+	}
 
 	rt_mutex_init_rtlock_waiter(&waiter);
 
@@ -1838,8 +1852,10 @@ static void __sched rtlock_slowlock_locked(struct rt_mutex_base *lock,
 
 	for (;;) {
 		/* Try to acquire the lock again */
-		if (try_to_take_rt_mutex(lock, current, &waiter))
+		if (try_to_take_rt_mutex(lock, current, &waiter)) {
+			lockevent_inc(rtlock_slow_acq2);
 			break;
+		}
 
 		if (&waiter == rt_mutex_top_waiter(lock))
 			owner = rt_mutex_owner(lock);
@@ -1847,8 +1863,10 @@ static void __sched rtlock_slowlock_locked(struct rt_mutex_base *lock,
 			owner = NULL;
 		raw_spin_unlock_irq_wake(&lock->wait_lock, wake_q);
 
-		if (!owner || !rtmutex_spin_on_owner(lock, &waiter, owner))
+		if (!owner || !rtmutex_spin_on_owner(lock, &waiter, owner)) {
+			lockevent_inc(rtlock_slow_sleep);
 			schedule_rtlock();
+		}
 
 		raw_spin_lock_irq(&lock->wait_lock);
 		set_current_state(TASK_RTLOCK_WAIT);
@@ -1865,6 +1883,7 @@ static void __sched rtlock_slowlock_locked(struct rt_mutex_base *lock,
 	debug_rt_mutex_free_waiter(&waiter);
 
 	trace_contention_end(lock, 0);
+	lockevent_cond_inc(rtlock_slow_wake, !wake_q_empty(wake_q));
 }
 
 static __always_inline void __sched rtlock_slowlock(struct rt_mutex_base *lock)

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [tip: locking/core] locking/rtmutex: Use the 'struct' keyword in kernel-doc comment
  2025-03-07 23:26   ` [PATCH locking 01/11] locking/rtmutex: Use struct keyword in kernel-doc comment Boqun Feng
@ 2025-03-08  0:08     ` tip-bot2 for Randy Dunlap
  0 siblings, 0 replies; 31+ messages in thread
From: tip-bot2 for Randy Dunlap @ 2025-03-08  0:08 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Randy Dunlap, Boqun Feng, Ingo Molnar, Waiman Long, x86,
	linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     b3c5ec8b79bf6bc49cc4850d0949d712830283d7
Gitweb:        https://git.kernel.org/tip/b3c5ec8b79bf6bc49cc4850d0949d712830283d7
Author:        Randy Dunlap <rdunlap@infradead.org>
AuthorDate:    Fri, 07 Mar 2025 15:26:51 -08:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 08 Mar 2025 00:52:01 +01:00

locking/rtmutex: Use the 'struct' keyword in kernel-doc comment

Add the "struct" keyword to prevent a kernel-doc warning:

  rtmutex_common.h:67: warning: cannot understand function prototype: 'struct rt_wake_q_head '

Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: Waiman Long <longman@redhat.com>
Link: https://lore.kernel.org/r/20250307232717.1759087-2-boqun.feng@gmail.com
---
 kernel/locking/rtmutex_common.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/locking/rtmutex_common.h b/kernel/locking/rtmutex_common.h
index c38a2d2..78dd3d8 100644
--- a/kernel/locking/rtmutex_common.h
+++ b/kernel/locking/rtmutex_common.h
@@ -59,8 +59,8 @@ struct rt_mutex_waiter {
 };
 
 /**
- * rt_wake_q_head - Wrapper around regular wake_q_head to support
- *		    "sleeping" spinlocks on RT
+ * struct rt_wake_q_head - Wrapper around regular wake_q_head to support
+ *			   "sleeping" spinlocks on RT
  * @head:		The regular wake_q_head for sleeping lock variants
  * @rtlock_task:	Task pointer for RT lock (spin/rwlock) wakeups
  */

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [tip: locking/core] locking/semaphore: Use wake_q to wake up processes outside lock critical section
  2025-03-07 23:26   ` [PATCH locking 02/11] locking/semaphore: Use wake_q to wake up processes outside lock critical section Boqun Feng
@ 2025-03-08  0:08     ` tip-bot2 for Waiman Long
  0 siblings, 0 replies; 31+ messages in thread
From: tip-bot2 for Waiman Long @ 2025-03-08  0:08 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: yzbot+ed801a886dfdbfe7136d, Waiman Long, Boqun Feng, Ingo Molnar,
	Linus Torvalds, x86, linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     85b2b9c16d053364e2004883140538e73b333cdb
Gitweb:        https://git.kernel.org/tip/85b2b9c16d053364e2004883140538e73b333cdb
Author:        Waiman Long <longman@redhat.com>
AuthorDate:    Fri, 07 Mar 2025 15:26:52 -08:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 08 Mar 2025 00:52:01 +01:00

locking/semaphore: Use wake_q to wake up processes outside lock critical section

A circular lock dependency splat has been seen involving down_trylock():

  ======================================================
  WARNING: possible circular locking dependency detected
  6.12.0-41.el10.s390x+debug
  ------------------------------------------------------
  dd/32479 is trying to acquire lock:
  0015a20accd0d4f8 ((console_sem).lock){-.-.}-{2:2}, at: down_trylock+0x26/0x90

  but task is already holding lock:
  000000017e461698 (&zone->lock){-.-.}-{2:2}, at: rmqueue_bulk+0xac/0x8f0

  the existing dependency chain (in reverse order) is:
  -> #4 (&zone->lock){-.-.}-{2:2}:
  -> #3 (hrtimer_bases.lock){-.-.}-{2:2}:
  -> #2 (&rq->__lock){-.-.}-{2:2}:
  -> #1 (&p->pi_lock){-.-.}-{2:2}:
  -> #0 ((console_sem).lock){-.-.}-{2:2}:

The console_sem -> pi_lock dependency is due to calling try_to_wake_up()
while holding the console_sem raw_spinlock. This dependency can be broken
by using wake_q to do the wakeup instead of calling try_to_wake_up()
under the console_sem lock. This will also make the semaphore's
raw_spinlock become a terminal lock without taking any further locks
underneath it.

The hrtimer_bases.lock is a raw_spinlock while zone->lock is a
spinlock. The hrtimer_bases.lock -> zone->lock dependency happens via
the debug_objects_fill_pool() helper function in the debugobjects code.

  -> #4 (&zone->lock){-.-.}-{2:2}:
         __lock_acquire+0xe86/0x1cc0
         lock_acquire.part.0+0x258/0x630
         lock_acquire+0xb8/0xe0
         _raw_spin_lock_irqsave+0xb4/0x120
         rmqueue_bulk+0xac/0x8f0
         __rmqueue_pcplist+0x580/0x830
         rmqueue_pcplist+0xfc/0x470
         rmqueue.isra.0+0xdec/0x11b0
         get_page_from_freelist+0x2ee/0xeb0
         __alloc_pages_noprof+0x2c2/0x520
         alloc_pages_mpol_noprof+0x1fc/0x4d0
         alloc_pages_noprof+0x8c/0xe0
         allocate_slab+0x320/0x460
         ___slab_alloc+0xa58/0x12b0
         __slab_alloc.isra.0+0x42/0x60
         kmem_cache_alloc_noprof+0x304/0x350
         fill_pool+0xf6/0x450
         debug_object_activate+0xfe/0x360
         enqueue_hrtimer+0x34/0x190
         __run_hrtimer+0x3c8/0x4c0
         __hrtimer_run_queues+0x1b2/0x260
         hrtimer_interrupt+0x316/0x760
         do_IRQ+0x9a/0xe0
         do_irq_async+0xf6/0x160

Normally a raw_spinlock to spinlock dependency is not legitimate
and will be warned if CONFIG_PROVE_RAW_LOCK_NESTING is enabled,
but debug_objects_fill_pool() is an exception as it explicitly
allows this dependency for non-PREEMPT_RT kernel without causing
PROVE_RAW_LOCK_NESTING lockdep splat. As a result, this dependency is
legitimate and not a bug.

Anyway, semaphore is the only locking primitive left that is still
using try_to_wake_up() to do wakeup inside critical section, all the
other locking primitives had been migrated to use wake_q to do wakeup
outside of the critical section. It is also possible that there are
other circular locking dependencies involving printk/console_sem or
other existing/new semaphores lurking somewhere which may show up in
the future. Let just do the migration now to wake_q to avoid headache
like this.

Reported-by: yzbot+ed801a886dfdbfe7136d@syzkaller.appspotmail.com
Signed-off-by: Waiman Long <longman@redhat.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: https://lore.kernel.org/r/20250307232717.1759087-3-boqun.feng@gmail.com
---
 kernel/locking/semaphore.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/kernel/locking/semaphore.c b/kernel/locking/semaphore.c
index 34bfae7..de9117c 100644
--- a/kernel/locking/semaphore.c
+++ b/kernel/locking/semaphore.c
@@ -29,6 +29,7 @@
 #include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/sched/debug.h>
+#include <linux/sched/wake_q.h>
 #include <linux/semaphore.h>
 #include <linux/spinlock.h>
 #include <linux/ftrace.h>
@@ -38,7 +39,7 @@ static noinline void __down(struct semaphore *sem);
 static noinline int __down_interruptible(struct semaphore *sem);
 static noinline int __down_killable(struct semaphore *sem);
 static noinline int __down_timeout(struct semaphore *sem, long timeout);
-static noinline void __up(struct semaphore *sem);
+static noinline void __up(struct semaphore *sem, struct wake_q_head *wake_q);
 
 /**
  * down - acquire the semaphore
@@ -183,13 +184,16 @@ EXPORT_SYMBOL(down_timeout);
 void __sched up(struct semaphore *sem)
 {
 	unsigned long flags;
+	DEFINE_WAKE_Q(wake_q);
 
 	raw_spin_lock_irqsave(&sem->lock, flags);
 	if (likely(list_empty(&sem->wait_list)))
 		sem->count++;
 	else
-		__up(sem);
+		__up(sem, &wake_q);
 	raw_spin_unlock_irqrestore(&sem->lock, flags);
+	if (!wake_q_empty(&wake_q))
+		wake_up_q(&wake_q);
 }
 EXPORT_SYMBOL(up);
 
@@ -269,11 +273,12 @@ static noinline int __sched __down_timeout(struct semaphore *sem, long timeout)
 	return __down_common(sem, TASK_UNINTERRUPTIBLE, timeout);
 }
 
-static noinline void __sched __up(struct semaphore *sem)
+static noinline void __sched __up(struct semaphore *sem,
+				  struct wake_q_head *wake_q)
 {
 	struct semaphore_waiter *waiter = list_first_entry(&sem->wait_list,
 						struct semaphore_waiter, list);
 	list_del(&waiter->list);
 	waiter->up = true;
-	wake_up_process(waiter->task);
+	wake_q_add(wake_q, waiter->task);
 }

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [tip: locking/core] rust: lockdep: Remove support for dynamically allocated LockClassKeys
  2025-03-07 23:27   ` [PATCH locking 10/11] rust: lockdep: Remove support for dynamically allocated LockClassKeys Boqun Feng
@ 2025-03-08  0:08     ` tip-bot2 for Mitchell Levy
  0 siblings, 0 replies; 31+ messages in thread
From: tip-bot2 for Mitchell Levy @ 2025-03-08  0:08 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Alice Ryhl, Mitchell Levy, Boqun Feng, Ingo Molnar, Benno Lossin,
	stable, x86, linux-kernel

The following commit has been merged into the locking/core branch of tip:

Commit-ID:     966944f3711665db13e214fef6d02982c49bb972
Gitweb:        https://git.kernel.org/tip/966944f3711665db13e214fef6d02982c49bb972
Author:        Mitchell Levy <levymitchell0@gmail.com>
AuthorDate:    Fri, 07 Mar 2025 15:27:00 -08:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Sat, 08 Mar 2025 00:52:00 +01:00

rust: lockdep: Remove support for dynamically allocated LockClassKeys

Currently, dynamically allocated LockCLassKeys can be used from the Rust
side without having them registered. This is a soundness issue, so
remove them.

Fixes: 6ea5aa08857a ("rust: sync: introduce `LockClassKey`")
Suggested-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Mitchell Levy <levymitchell0@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20250307232717.1759087-11-boqun.feng@gmail.com
---
 rust/kernel/sync.rs | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/rust/kernel/sync.rs b/rust/kernel/sync.rs
index 3498fb3..16eab91 100644
--- a/rust/kernel/sync.rs
+++ b/rust/kernel/sync.rs
@@ -30,28 +30,20 @@ pub struct LockClassKey(Opaque<bindings::lock_class_key>);
 unsafe impl Sync for LockClassKey {}
 
 impl LockClassKey {
-    /// Creates a new lock class key.
-    pub const fn new() -> Self {
-        Self(Opaque::uninit())
-    }
-
     pub(crate) fn as_ptr(&self) -> *mut bindings::lock_class_key {
         self.0.get()
     }
 }
 
-impl Default for LockClassKey {
-    fn default() -> Self {
-        Self::new()
-    }
-}
-
 /// Defines a new static lock class and returns a pointer to it.
 #[doc(hidden)]
 #[macro_export]
 macro_rules! static_lock_class {
     () => {{
-        static CLASS: $crate::sync::LockClassKey = $crate::sync::LockClassKey::new();
+        static CLASS: $crate::sync::LockClassKey =
+            // SAFETY: lockdep expects uninitialized memory when it's handed a statically allocated
+            // lock_class_key
+            unsafe { ::core::mem::MaybeUninit::uninit().assume_init() };
         &CLASS
     }};
 }

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [PATCH locking 00/11] LOCKDEP and Rust locking changes for v6.15
  2025-03-08  0:11       ` Ingo Molnar
@ 2025-03-08  0:11         ` Boqun Feng
  0 siblings, 0 replies; 31+ messages in thread
From: Boqun Feng @ 2025-03-08  0:11 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Peter Zijlstra, Will Deacon, Waiman Long, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	open list:RUST:Keyword:b(?i:rust)b

On Sat, Mar 08, 2025 at 01:11:36AM +0100, Ingo Molnar wrote:
[...]
> > > I've applied these 3 patches to the tip:locking/urgent tree:
> > > 
> > >   locking/semaphore: Use wake_q to wake up processes outside lock critical section
> > >   locking/rtmutex: Use the 'struct' keyword in kernel-doc comment
> > >   rust: lockdep: Remove support for dynamically allocated LockClassKeys
> > > 
> > > As a general rule, if a patch is marked Cc: stable, it must also be 
> > > applied to current upstream.
> > > 
> > 
> > Do you prefer a separate pull request for the future? I can send one for
> > urgent and one for locking/core.
> 
> One tree is fine - maybe indicate which ones are urgent material and 
> keep them at the head of the tree?
> 

Sounds good to me, will do.

Regards,
Boqun

> Thanks,
> 
> 	Ingo

^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH locking 00/11] LOCKDEP and Rust locking changes for v6.15
  2025-03-08  0:04     ` Boqun Feng
@ 2025-03-08  0:11       ` Ingo Molnar
  2025-03-08  0:11         ` Boqun Feng
  0 siblings, 1 reply; 31+ messages in thread
From: Ingo Molnar @ 2025-03-08  0:11 UTC (permalink / raw)
  To: Boqun Feng
  Cc: Peter Zijlstra, Will Deacon, Waiman Long, linux-kernel,
	Miguel Ojeda, Alex Gaynor, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
	open list:RUST:Keyword:b(?i:rust)b


* Boqun Feng <boqun.feng@gmail.com> wrote:

> On Sat, Mar 08, 2025 at 01:01:45AM +0100, Ingo Molnar wrote:
> > 
> > * Boqun Feng <boqun.feng@gmail.com> wrote:
> > 
> > > Hi Ingo & Peter,
> > > 
> > > As discussed, I'm resending the pull request for lockdep and Rust
> > > locking for v6.15 in the format of email patches. I dropped one patch
> > > and will postpone it for v6.16 because of a bug [1], and I think the fix
> > > [2] needs more reviews.
> > > 
> > > [1]: https://lore.kernel.org/lkml/20250306122413.GBZ8mT7Z61Tmgnh5Y9@fat_crate.local/
> > > [2]: https://lore.kernel.org/lkml/Z8t8imzJVhWyDvhC@boqun-archlinux/
> > > 
> > > Regards,
> > > Boqun
> > > 
> > > Alice Ryhl (2):
> > >   rust: sync: Add accessor for the lock behind a given guard
> > >   rust: sync: condvar: Add wait_interruptible_freezable()
> > > 
> > > Boqun Feng (1):
> > >   rust: sync: lock: Add an example for Guard::lock_ref()
> > > 
> > > Mitchell Levy (2):
> > >   rust: lockdep: Remove support for dynamically allocated LockClassKeys
> > >   rust: lockdep: Use Pin for all LockClassKey usages
> > > 
> > > Randy Dunlap (1):
> > >   locking/rtmutex: Use struct keyword in kernel-doc comment
> > > 
> > > Waiman Long (5):
> > >   locking/semaphore: Use wake_q to wake up processes outside lock
> > >     critical section
> > >   locking/lock_events: Add locking events for rtmutex slow paths
> > >   locking/lock_events: Add locking events for lockdep
> > >   locking/lockdep: Disable KASAN instrumentation of lockdep.c
> > >   locking/lockdep: Add kasan_check_byte() check in lock_acquire()
> > 
> > Thanks Boqun!
> > 
> 
> Thanks.
> 
> > I've applied these 3 patches to the tip:locking/urgent tree:
> > 
> >   locking/semaphore: Use wake_q to wake up processes outside lock critical section
> >   locking/rtmutex: Use the 'struct' keyword in kernel-doc comment
> >   rust: lockdep: Remove support for dynamically allocated LockClassKeys
> > 
> > As a general rule, if a patch is marked Cc: stable, it must also be 
> > applied to current upstream.
> > 
> 
> Do you prefer a separate pull request for the future? I can send one for
> urgent and one for locking/core.

One tree is fine - maybe indicate which ones are urgent material and 
keep them at the head of the tree?

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2025-03-08  0:12 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-26  4:12 [GIT PULL] LOCKDEP and Rust locking changes for v6.15 Boqun Feng
2025-02-28 18:57 ` Boqun Feng
2025-03-03 16:52   ` Waiman Long
2025-03-03 18:42 ` Peter Zijlstra
2025-03-07 23:26 ` [PATCH locking 00/11] " Boqun Feng
2025-03-07 23:26   ` [PATCH locking 01/11] locking/rtmutex: Use struct keyword in kernel-doc comment Boqun Feng
2025-03-08  0:08     ` [tip: locking/core] locking/rtmutex: Use the 'struct' " tip-bot2 for Randy Dunlap
2025-03-07 23:26   ` [PATCH locking 02/11] locking/semaphore: Use wake_q to wake up processes outside lock critical section Boqun Feng
2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Waiman Long
2025-03-07 23:26   ` [PATCH locking 03/11] locking/lock_events: Add locking events for rtmutex slow paths Boqun Feng
2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Waiman Long
2025-03-07 23:26   ` [PATCH locking 04/11] locking/lock_events: Add locking events for lockdep Boqun Feng
2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Waiman Long
2025-03-07 23:26   ` [PATCH locking 05/11] locking/lockdep: Disable KASAN instrumentation of lockdep.c Boqun Feng
2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Waiman Long
2025-03-07 23:26   ` [PATCH locking 06/11] locking/lockdep: Add kasan_check_byte() check in lock_acquire() Boqun Feng
2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Waiman Long
2025-03-07 23:26   ` [PATCH locking 07/11] rust: sync: Add accessor for the lock behind a given guard Boqun Feng
2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Alice Ryhl
2025-03-07 23:26   ` [PATCH locking 08/11] rust: sync: lock: Add an example for Guard::lock_ref() Boqun Feng
2025-03-08  0:08     ` [tip: locking/core] rust: sync: lock: Add an example for Guard:: Lock_ref() tip-bot2 for Boqun Feng
2025-03-07 23:26   ` [PATCH locking 09/11] rust: sync: condvar: Add wait_interruptible_freezable() Boqun Feng
2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Alice Ryhl
2025-03-07 23:27   ` [PATCH locking 10/11] rust: lockdep: Remove support for dynamically allocated LockClassKeys Boqun Feng
2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Mitchell Levy
2025-03-07 23:27   ` [PATCH locking 11/11] rust: lockdep: Use Pin for all LockClassKey usages Boqun Feng
2025-03-08  0:08     ` [tip: locking/core] " tip-bot2 for Mitchell Levy
2025-03-08  0:01   ` [PATCH locking 00/11] LOCKDEP and Rust locking changes for v6.15 Ingo Molnar
2025-03-08  0:04     ` Boqun Feng
2025-03-08  0:11       ` Ingo Molnar
2025-03-08  0:11         ` Boqun Feng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox