From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: Alice Ryhl <aliceryhl@google.com>
Cc: "Benno Lossin" <lossin@kernel.org>,
"Danilo Krummrich" <dakr@kernel.org>,
"Matthew Maurer" <mmaurer@google.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Trevor Gross" <tmgross@umich.edu>,
"Rafael J. Wysocki" <rafael@kernel.org>,
"Sami Tolvanen" <samitolvanen@google.com>,
"Timur Tabi" <ttabi@nvidia.com>,
linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
"Dirk Behme" <dirk.behme@de.bosch.com>
Subject: Re: [PATCH v8 4/6] rust: debugfs: Support arbitrary owned backing for File
Date: Thu, 3 Jul 2025 13:41:53 +0200 [thread overview]
Message-ID: <2025070349-tricky-arguable-5362@gregkh> (raw)
In-Reply-To: <CAH5fLgjaNzOHNxa+XY1c2V5A1H2RhWP9gHAAmHx=9LN9CbHq=Q@mail.gmail.com>
On Thu, Jul 03, 2025 at 12:54:18PM +0200, Alice Ryhl wrote:
> On Thu, Jul 3, 2025 at 12:33 PM Benno Lossin <lossin@kernel.org> wrote:
> >
> > On Thu Jul 3, 2025 at 12:02 PM CEST, Alice Ryhl wrote:
> > > On Tue, Jul 01, 2025 at 05:10:47PM +0200, Danilo Krummrich wrote:
> > >> On Tue, Jul 01, 2025 at 04:21:56PM +0200, Greg Kroah-Hartman wrote:
> > >> > On Tue, Jul 01, 2025 at 04:13:28PM +0200, Danilo Krummrich wrote:
> > >> > > Instead this should just be:
> > >> > >
> > >> > > struct GPU {
> > >> > > fw: debugfs::File<Firmware>,
> > >> > > }
> > >> > >
> > >> > > and then I would initialize it the following way:
> > >> > >
> > >> > > let fw = KBox::new(Firmware::new(), GFP_KERNEL)?;
> > >> > > let file = dir.create_file("firmware", fw);
> > >> > >
> > >> > > // debugfs::File<Firmware> dereferences to Firmware
> > >> > > file.do_something();
> > >> > >
> > >> > > // Access to fw is prevented by the compiler, since it has been moved
> > >> > > // into file.
> > >> > >
> > >> > > This is much better, since now I have the guarantee that my Firmare instance
> > >> > > can't out-live the GPU instance.
> > >> >
> > >> > That's better, yes, but how would multiple files for the same
> > >> > "structure" work here? Like a debugfs-file-per-field of a structure
> > >> > that we often have?
> > >>
> > >> That is a very good question and I thought about this as well, because with only
> > >> the current API this would require us to have more and more dynamic allocations
> > >> if we want to have a more fine grained filesystem representations of structures.
> > >>
> > >> The idea I have for this is to use pin-init, which we do in quite some other
> > >> places as well.
> > >>
> > >> I think we can add an additional API like this:
> > >>
> > >> impl Dir {
> > >> pub fn create_file<T>(&self, data: impl PinInit<T>) -> impl PinInit<Self> {
> > >> pin_init!(Self {
> > >> data <- data,
> > >> ...
> > >> })
> > >> }
> > >> }
> > >>
> > >> This allows us to do things like:
> > >>
> > >> #[pin_data]
> > >> struct Firmware {
> > >> #[pin]
> > >> minor: debugfs::File<u32>,
> > >> #[pin]
> > >> major: debugfs::File<u32>,
> > >> #[pin]
> > >> buffer: debugfs::File<[u8]>,
> > >> }
> > >>
> > >> impl Firmware {
> > >> pub fn new(&dir: debugfs::Dir, buffer: [u8]) -> impl PinInit<Self> {
> > >> pin_init!(Self {
> > >> minor <- dir.create_file("minor", 1),
> > >> major <- dir.create_file("major", 2),
> > >> buffer <- dir.create_file("buffer", buffer),
> > >> })
> > >> }
> > >> }
> > >>
> > >> // This is the only allocation we need.
> > >> let fw = KBox::pin_init(Firmware::new(...), GFP_KERNEL)?;
> > >>
> > >> With this everything is now in a single allocation and since we're using
> > >> pin-init, Dir::create_file() can safely store pointers of the corresponding data
> > >> in debugfs_create_file(), since this structure is guaranteed to be pinned in
> > >> memory.
> > >>
> > >> Actually, we can also implement *only this*, since with this my previous example
> > >> would just become this:
> > >>
> > >> struct GPU {
> > >> fw: debugfs::File<Firmware>,
> > >> }
> > >>
> > >> let file = dir.create_file("firmware", Firmware::new());
> > >> let file = KBox::pin_init(file, GFP_KERNEL)?;
> > >>
> > >> // debugfs::File<Firmware> dereferences to Firmware
> > >> file.do_something();
> > >>
> > >> Given that, I think we should change things to use pin-init right away for the
> > >> debugfs::File API.
> > >
> > > Does this actually work in practice for anything except immutable data?
> > > I mean, let's take Rust Binder as an example and lets say that I want to
> > > expose a directory for each Process object with some of the fields
> > > exposed. Let's just simplify Rust Binder a bit and only include some of
> > > the fields:
> > >
> > > #[pin_data]
> > > struct Process {
> > > task: ARef<Task>,
> > > #[pin]
> > > inner: SpinLock<ProcessInner>,
> > > }
> > >
> > > pub(crate) struct ProcessInner {
> > > threads: RBTree<i32, Arc<Thread>>,
> > > nodes: RBTree<u64, DArc<Node>>,
> > > requested_thread_count: u32,
> > > max_threads: u32,
> > > started_thread_count: u32,
> > > }
> > >
> > > Rust Binder already does expose some debugging data through a file
> > > system, though it doesn't do so using debugfs. It exposes a lot of data,
> > > but among them are the pid, the number of threads and nodes, as well as
> > > the values of requested_thread_count, started_thread_count, and
> > > max_threads.
> > >
> > > Now, we run into problem number one: pinning is not supported inside
> > > mutexes. But let's say we solved that and we could do this:
> > >
> > > #[pin_data]
> > > struct Process {
> > > task: File<ARef<Task>>, // prints the pid
> > > #[pin]
> > > inner: SpinLock<ProcessInner>,
> > > }
> > >
> > > pub(crate) struct ProcessInner {
> > > threads: File<RBTree<i32, Arc<Thread>>>, // prints the count
> > > nodes: File<RBTree<u64, DArc<Node>>>, // prints the count
> > > requested_thread_count: File<u32>,
> > > max_threads: File<u32>,
> > > started_thread_count: File<u32>,
> > > }
> > >
> > > However, this still doesn't work! Debugfs may get triggered at any time
> > > and need to read these fields, and there's no way for it to take the
> > > spinlock with the above design - it doesn't know where the spinlock is.
> > > For the integers I guess we could make them atomic to allow reading them
> > > in parallel with mutation, but that option is not available for the
> > > red/black trees.
> > >
> > > What is the intended solution in this case? If the argument is that this
> > > is a rare case, then keep in mind that this is a real-world example of
> > > debugging information that we actually expose today in a real driver.
> > > With Matt's current approach, it's relatively easy - just store a bunch
> > > of File<Arc<Process>> instances somewhere and define each one to take
> > > the mutex and print the relevant value.
> >
> > How would your example look like with the current approach? IIUC, it
> > also wouldn't work, because the debugfs data can't be mutated?
>
> I would store a bunch of `File<Arc<Process>>` instances somewhere.
> Each one has a closure that takes the spinlock and prints the
> appropriate value.
Ok, I think we need to see some "real" examples here of the api in use
before figuring it out further as I'm totally confused :)
Yes, we need to be able to have a debugfs file callback handle a mutable
structure in order to lock things correctly. We also need to have it be
mutable so that it can MODIFY the value (everyone seems to forget that
debugfs allows that...)
So how about a platform driver that exposes values read from a platform
device (i.e. a soc info driver), that also includes a
local-to-the-device data structure that can be locked and modified?
That should cover all the use cases that I can think of at the moment.
thanks,
greg k-h
next prev parent reply other threads:[~2025-07-03 11:41 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-27 23:18 [PATCH v8 0/6] rust: DebugFS Bindings Matthew Maurer
2025-06-27 23:18 ` [PATCH v8 1/6] rust: debugfs: Bind DebugFS directory creation Matthew Maurer
2025-06-27 23:18 ` [PATCH v8 2/6] rust: debugfs: Bind file creation for long-lived Display Matthew Maurer
2025-06-27 23:18 ` [PATCH v8 3/6] rust: types: Support &'static and &'static mut ForeignOwnable Matthew Maurer
2025-07-01 11:41 ` Dirk Behme
2025-07-01 11:46 ` Danilo Krummrich
2025-06-27 23:18 ` [PATCH v8 4/6] rust: debugfs: Support arbitrary owned backing for File Matthew Maurer
2025-06-30 17:29 ` Danilo Krummrich
2025-06-30 17:34 ` Matthew Maurer
2025-06-30 17:36 ` Matthew Maurer
2025-06-30 17:39 ` Danilo Krummrich
2025-06-30 17:49 ` Matthew Maurer
2025-06-30 18:16 ` Danilo Krummrich
2025-07-01 13:58 ` Greg Kroah-Hartman
2025-07-01 14:13 ` Danilo Krummrich
2025-07-01 14:21 ` Greg Kroah-Hartman
2025-07-01 15:10 ` Danilo Krummrich
2025-07-01 18:11 ` Matthew Maurer
2025-07-01 19:21 ` Danilo Krummrich
2025-07-01 19:46 ` Benno Lossin
2025-07-01 19:58 ` Danilo Krummrich
2025-07-01 20:03 ` Benno Lossin
2025-07-01 20:09 ` Benno Lossin
2025-07-01 20:16 ` Danilo Krummrich
2025-07-01 21:53 ` Matthew Maurer
2025-07-01 22:26 ` Danilo Krummrich
2025-07-01 20:07 ` Benno Lossin
2025-07-03 10:02 ` Alice Ryhl
2025-07-03 10:33 ` Benno Lossin
2025-07-03 10:54 ` Alice Ryhl
2025-07-03 11:41 ` Greg Kroah-Hartman [this message]
2025-07-03 12:29 ` Danilo Krummrich
2025-07-03 12:50 ` Greg Kroah-Hartman
2025-07-03 14:00 ` Danilo Krummrich
2025-07-03 13:34 ` Benno Lossin
2025-07-03 14:04 ` Danilo Krummrich
2025-07-03 13:35 ` Benno Lossin
2025-07-03 13:38 ` Alice Ryhl
2025-07-03 12:34 ` Benno Lossin
2025-07-03 12:45 ` Greg Kroah-Hartman
2025-07-03 11:00 ` Danilo Krummrich
2025-06-27 23:18 ` [PATCH v8 5/6] rust: debugfs: Support format hooks Matthew Maurer
2025-06-27 23:18 ` [PATCH v8 6/6] rust: samples: Add debugfs sample Matthew Maurer
2025-07-01 14:03 ` Greg Kroah-Hartman
2025-07-01 17:24 ` Matthew Maurer
2025-07-01 17:34 ` Danilo Krummrich
2025-07-01 18:32 ` Matthew Maurer
2025-07-01 19:40 ` Danilo Krummrich
2025-07-01 10:57 ` [PATCH v8 0/6] rust: DebugFS Bindings Alice Ryhl
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=2025070349-tricky-arguable-5362@gregkh \
--to=gregkh@linuxfoundation.org \
--cc=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=dirk.behme@de.bosch.com \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=mmaurer@google.com \
--cc=ojeda@kernel.org \
--cc=rafael@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=samitolvanen@google.com \
--cc=tmgross@umich.edu \
--cc=ttabi@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).