From: "Benno Lossin" <lossin@kernel.org>
To: "Vitaly Wool" <vitaly.wool@konsulko.se>
Cc: "rust-for-linux" <rust-for-linux@vger.kernel.org>,
"LKML" <linux-kernel@vger.kernel.org>,
"Uladzislau Rezki" <urezki@gmail.com>,
"Danilo Krummrich" <dakr@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Vlastimil Babka" <vbabka@suse.cz>,
"Lorenzo Stoakes" <lorenzo.stoakes@oracle.com>,
"Liam R . Howlett" <Liam.Howlett@oracle.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Bjorn Roy Baron" <bjorn3_gh@protonmail.com>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Trevor Gross" <tmgross@umich.edu>,
"Johannes Weiner" <hannes@cmpxchg.org>,
"Yosry Ahmed" <yosry.ahmed@linux.dev>,
"Nhat Pham" <nphamcs@gmail.com>, <linux-mm@kvack.org>
Subject: Re: [PATCH v4 2/2] rust: zpool: add abstraction for zpool drivers
Date: Sat, 06 Sep 2025 09:56:25 +0200 [thread overview]
Message-ID: <DCLK1YG1L5TZ.1VMGX131LII9V@kernel.org> (raw)
In-Reply-To: <9c63dda1-0a4b-4131-a5e7-12ad2e88c6d6@konsulko.se>
On Thu Aug 28, 2025 at 9:22 AM CEST, Vitaly Wool wrote:
>
>
> On 8/27/25 17:59, Benno Lossin wrote:
>> On Wed Aug 27, 2025 at 4:24 PM CEST, Vitaly Wool wrote:
>>>
>>>
>>>> On Aug 26, 2025, at 7:02 PM, Benno Lossin <lossin@kernel.org> wrote:
>>>>
>>>> On Sat Aug 23, 2025 at 3:05 PM CEST, Vitaly Wool wrote:
>>>>> +pub trait ZpoolDriver {
>>>>> + /// Opaque Rust representation of `struct zpool`.
>>>>> + type Pool: ForeignOwnable;
>>>>
>>>> I think this is the same question that Danilo asked a few versions ago,
>>>> but why do we need this? Why can't we just use `Self` instead?
>>>
>>> It’s convenient to use it in the backend implementation, like in the toy example supplied in the documentation part:
>>>
>>> +/// struct MyZpool {
>>> +/// name: &'static CStr,
>>> +/// bytes_used: AtomicU64,
>>> +/// }
>>> …
>>> +/// impl ZpoolDriver for MyZpoolDriver {
>>> +/// type Pool = KBox<MyZpool>;
>>>
>>> Does that make sense?
>>
>> No, why can't it just be like this:
>>
>> struct MyZpool {
>> name: &'static CStr,
>> bytes_used: AtomicU64,
>> }
>>
>> struct MyZpoolDriver;
>>
>> impl ZpoolDriver for MyZpoolDriver {
>> type Error = Infallible;
>>
>> fn create(name: &'static CStr) -> impl PinInit<Self, Self::Error> {
>> MyZpool { name, bytes_used: AtomicU64::new(0) }
>> }
>>
>> fn malloc(&mut self, size: usize, gfp: Flags, _nid: NumaNode) -> Result<usize> {
>> let mut pow: usize = 0;
>> for n in 6..=PAGE_SHIFT {
>> if size <= 1 << n {
>> pow = n;
>> break;
>> }
>> }
>> match pow {
>> 0 => Err(EINVAL),
>> _ => {
>> let vec = KVec::<u64>::with_capacity(1 << (pow - 3), gfp)?;
>> let (ptr, _len, _cap) = vec.into_raw_parts();
>> self.bytes_used.fetch_add(1 << pow, Ordering::Relaxed);
>> Ok(ptr as usize | (pow - 6))
>> }
>> }
>> }
>>
>> unsafe fn free(&self, handle: usize) {
>> let n = (handle & 0x3F) + 3;
>> let uptr = handle & !0x3F;
>>
>> // SAFETY:
>> // - uptr comes from handle which points to the KVec allocation from `alloc`.
>> // - size == capacity and is coming from the first 6 bits of handle.
>> let vec = unsafe { KVec::<u64>::from_raw_parts(uptr as *mut u64, 1 << n, 1 << n) };
>> drop(vec);
>> self.bytes_used.fetch_sub(1 << (n + 3), Ordering::Relaxed);
>> }
>>
>> unsafe fn read_begin(&self, handle: usize) -> NonNull<u8> {
>> let uptr = handle & !0x3F;
>> // SAFETY: uptr points to a memory area allocated by KVec
>> unsafe { NonNull::new_unchecked(uptr as *mut u8) }
>> }
>>
>> unsafe fn read_end(&self, _handle: usize, _handle_mem: NonNull<u8>) {}
>>
>> unsafe fn write(&self, handle: usize, handle_mem: NonNull<u8>, mem_len: usize) {
>> let uptr = handle & !0x3F;
>> // SAFETY: handle_mem is a valid non-null pointer provided by zpool, uptr points to
>> // a KVec allocated in `malloc` and is therefore also valid.
>> unsafe {
>> copy_nonoverlapping(handle_mem.as_ptr().cast(), uptr as *mut c_void, mem_len)
>> };
>> }
>>
>> fn total_pages(&self) -> u64 {
>> self.bytes_used.load(Ordering::Relaxed) >> PAGE_SHIFT
>> }
>> }
>
> It can indeed but then the ZpoolDriver trait will have to be extended
> with functions like into_raw() and from_raw(), because zpool expects
> *mut c_void, so on the Adapter side it will look like
>
> extern "C" fn create_(name: *const c_uchar, gfp: u32) -> *mut c_void {
> // SAFETY: the memory pointed to by name is guaranteed by zpool
> to be a valid string
> let pool = unsafe { T::create(CStr::from_char_ptr(name),
> Flags::from_raw(gfp)) };
> match pool {
> Err(_) => null_mut(),
> Ok(p) => T::into_raw(p).cast(),
> }
> }
>
> The question is, why does this make it better?
No, thanks for sharing that function. Then the question becomes, do you
really need `ForeignOwnable`? Or is `KBox` enough? Do you really want
people to use `Arc<MyZPool>`? Because `BorrowedMut` of `Arc` is the same
as it's `Borrowed` variant (it's read-only after all).
If you can get away with just `Box` (you might want people to choose
their allocator, which is fine IMO), then I'd do so.
---
Cheers,
Benno
next prev parent reply other threads:[~2025-09-06 7:56 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-23 13:04 [PATCH v4 0/2] rust: zpool: add abstraction for zpool drivers Vitaly Wool
2025-08-23 13:05 ` [PATCH v4 1/2] rust: alloc: add from_raw method to Flags Vitaly Wool
2025-08-26 10:57 ` Danilo Krummrich
2025-08-23 13:05 ` [PATCH v4 2/2] rust: zpool: add abstraction for zpool drivers Vitaly Wool
2025-08-26 12:20 ` Danilo Krummrich
2025-08-27 20:43 ` Vitaly Wool
2025-08-28 10:01 ` Vitaly Wool
2025-08-26 17:02 ` Benno Lossin
2025-08-27 14:24 ` Vitaly Wool
2025-08-27 15:59 ` Benno Lossin
2025-08-28 7:22 ` Vitaly Wool
2025-09-06 7:56 ` Benno Lossin [this message]
2025-08-26 10:43 ` [PATCH v4 0/2] " Miguel Ojeda
2025-08-26 11:37 ` Danilo Krummrich
2025-08-27 12:37 ` Alice Ryhl
2025-08-26 12:44 ` Johannes Weiner
2025-08-26 14:56 ` Vitaly Wool
2025-08-27 13:07 ` Johannes Weiner
2025-09-02 15:16 ` Vitaly Wool
2025-09-05 6:58 ` Vlastimil Babka
2025-09-05 12:03 ` Vitaly Wool
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=DCLK1YG1L5TZ.1VMGX131LII9V@kernel.org \
--to=lossin@kernel.org \
--cc=Liam.Howlett@oracle.com \
--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=gary@garyguo.net \
--cc=hannes@cmpxchg.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lorenzo.stoakes@oracle.com \
--cc=nphamcs@gmail.com \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
--cc=urezki@gmail.com \
--cc=vbabka@suse.cz \
--cc=vitaly.wool@konsulko.se \
--cc=yosry.ahmed@linux.dev \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.