Re: [PATCH 2/2] rust: block: fix wrong usage of lockdep API

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

 



On Thu, Aug 15, 2024 at 08:07:38PM +0100, Gary Guo wrote:
> On Thu, 15 Aug 2024 10:04:56 +0200
> Alice Ryhl <aliceryhl@xxxxxxxxxx> wrote:
> 
> > On Thu, Aug 15, 2024 at 9:49 AM Andreas Hindborg <nmi@xxxxxxxxxxxx> wrote:
> > >
> > > From: Andreas Hindborg <a.hindborg@xxxxxxxxxxx>
> > >
> > > When allocating `struct gendisk`, `GenDiskBuilder` is using a dynamic lock
> > > class key without registering the key. This is incorrect use of the API,
> > > which causes a `WARN` trace. This patch fixes the issue by using a static
> > > lock class key, which is more appropriate for the situation anyway.
> > >
> > > Fixes: 3253aba3408a ("rust: block: introduce `kernel::block::mq` module")
> > > Reported-by: "Behme Dirk (XC-CP/ESB5)" <Dirk.Behme@xxxxxxxxxxxx>
> > > Closes: https://rust-for-linux.zulipchat.com/#narrow/stream/288089-General/topic/6.2E11.2E0-rc1.3A.20rust.2Fkernel.2Fblock.2Fmq.2Ers.3A.20doctest.20lock.20warning
> > > Signed-off-by: Andreas Hindborg <a.hindborg@xxxxxxxxxxx>  
> > 
> > LGTM. This makes me wonder if there's some design mistake in how we
> > handle lock classes in Rust.
> > 
> > Reviewed-by: Alice Ryhl <aliceryhl@xxxxxxxxxx>
> 
> I agree. The API that we current have is designed without much
> consideration into dynamically allocated keys, and we use `&'static
> LockClassKey` in a lot of kernel crate APIs.
> 
> This arguably is wrong, because presence of `&'static LockClassKey`
> doesn't mean the key is static. If we do a
> `Box::leak(Box::new(LockClassKey::new()))`, then this is a `&'static
> LockClassKey`, but lockdep wouldn't consider this as a static object.
> 
> Maybe we should make the `new` function unsafe.
> 

I think a more proper fix is to make LockClassKey pin-init, for
dynamically allocated LockClassKey, we just use lockdep_register_key()
as the initializer and lockdep_unregister_key() as the desconstructor.
And instead of a `&'static LockClassKey`, we should use `Pin<&'static
LockClassKey>` to pass a lock class key. Of course we will need some
special treatment on static allocated keys (e.g. assume they are
initialized since lockdep doesn't require initialization for them).


Pin initializer:

	impl LockClassKey {
	    pub fn new() -> impl PinInit<Self> {
		pin_init!(Self {
		    inner <- Opaque::ffi_init(|slot| { lockdep_register_key(slot) })
		})
	    }
	}

LockClassKey::new_uninit() for `static_lock_class!`:


	impl LockClassKey {
	    pub const fn new_uninit() -> MaybeUninit<Self> {
	        ....
	    }
	}

and the new `static_lock_class!`:

	macro_rules! static_lock_class {
	    () => {{
		static CLASS: MaybeUninit<$crate::sync::LockClassKey> = $crate::sync::LockClassKey::new_uninit();

	        // SAFETY: `CLASS` is pinned because it's static
		// allocated. And it's OK to assume it's initialized
		// because lockdep support uninitialized static
		// allocated key.
		unsafe { Pin::new_unchecked(CLASS.assume_init_ref()) }
	    }};
	}

Thoughts?

Regards,
Boqun

> For the patch itself:
> 
> Reviewed-by: Gary Guo <gary@xxxxxxxxxxx>




[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux