From: "Andreas Hindborg (Samsung)" <nmi@metaspace.dk>
To: Benno Lossin <benno.lossin@proton.me>
Cc: "Jens Axboe" <axboe@kernel.dk>, "Christoph Hellwig" <hch@lst.de>,
"Keith Busch" <kbusch@kernel.org>,
"Damien Le Moal" <Damien.LeMoal@wdc.com>,
"Hannes Reinecke" <hare@suse.de>,
lsf-pc@lists.linux-foundation.org,
rust-for-linux@vger.kernel.org, linux-block@vger.kernel.org,
"Matthew Wilcox" <willy@infradead.org>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Wedson Almeida Filho" <wedsonaf@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
linux-kernel@vger.kernel.org, gost.dev@samsung.com
Subject: Re: [RFC PATCH 04/11] rust: block: introduce `kernel::block::bio` module
Date: Thu, 11 Jan 2024 13:49:53 +0100 [thread overview]
Message-ID: <87a5pcyqf8.fsf@metaspace.dk> (raw)
In-Reply-To: <-SiJ5paRDIUkH1WEWhGhEjhIgFbSo5PJAvac53bTnBZ5o41DR-kNWZEQBsnKeW1FRJh35siVFRrx54L0M6ebSzl0rzecgcDjqZFGRa9uypE=@proton.me>
Benno Lossin <benno.lossin@proton.me> writes:
>> +/// A wrapper around a `struct bio` pointer
>> +///
>> +/// # Invariants
>> +///
>> +/// First field must alwyas be a valid pointer to a valid `struct bio`.
>> +pub struct Bio<'a>(
>> + NonNull<crate::bindings::bio>,
>> + core::marker::PhantomData<&'a ()>,
>
> Please make this a struct with named fields. Also this is rather a
> `BioRef`, right? Why can't `&Bio` be used and `Bio` embeds
> `bindings::bio`?
Yes, it feels better with a &Bio reference, thanks.
>> +);
>> +
>> +impl<'a> Bio<'a> {
>> + /// Returns an iterator over segments in this `Bio`. Does not consider
>> + /// segments of other bios in this bio chain.
>> + #[inline(always)]
>
> Why are these `inline(always)`? The compiler should inline them
> automatically?
No, the compiler would not inline into modules without them. I'll check
again if that is still the case.
>
>> + pub fn segment_iter(&'a self) -> BioSegmentIterator<'a> {
>> + BioSegmentIterator::new(self)
>> + }
>> +
>> + /// Get a pointer to the `bio_vec` off this bio
>> + #[inline(always)]
>> + fn io_vec(&self) -> *const bindings::bio_vec {
>> + // SAFETY: By type invariant, get_raw() returns a valid pointer to a
>> + // valid `struct bio`
>> + unsafe { (*self.get_raw()).bi_io_vec }
>> + }
>> +
>> + /// Return a copy of the `bvec_iter` for this `Bio`
>> + #[inline(always)]
>> + fn iter(&self) -> bindings::bvec_iter {
>
> Why does this return the bindings iter? Maybe rename to `raw_iter`?
Makes sense to rename it, thanks.
>> + // SAFETY: self.0 is always a valid pointer
>> + unsafe { (*self.get_raw()).bi_iter }
>> + }
>> +
>> + /// Get the next `Bio` in the chain
>> + #[inline(always)]
>> + fn next(&self) -> Option<Bio<'a>> {
>> + // SAFETY: self.0 is always a valid pointer
>> + let next = unsafe { (*self.get_raw()).bi_next };
>> + Some(Self(NonNull::new(next)?, core::marker::PhantomData))
>
> Missing `INVARIANT` explaining why `next` is valid or null. Also why not
> use `Self::from_raw` here?
Thanks, will change that.
>
>> + }
>> +
>> + /// Return the raw pointer of the wrapped `struct bio`
>> + #[inline(always)]
>> + fn get_raw(&self) -> *const bindings::bio {
>> + self.0.as_ptr()
>> + }
>> +
>> + /// Create an instance of `Bio` from a raw pointer. Does check that the
>> + /// pointer is not null.
>> + #[inline(always)]
>> + pub(crate) unsafe fn from_raw(ptr: *mut bindings::bio) -> Option<Bio<'a>> {
>> + Some(Self(NonNull::new(ptr)?, core::marker::PhantomData))
>> + }
>> +}
>> +
>> +impl core::fmt::Display for Bio<'_> {
>> + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
>> + write!(f, "Bio {:?}", self.0.as_ptr())
>
> this will display as `Bio 0x7ff0654..` I think there should be some
> symbol wrapping the pointer like `Bio(0x7ff0654)` or `Bio { ptr: 0x7ff0654 }`.
>
Sure 👍
>> + }
>> +}
>> +
>> +/// An iterator over `Bio`
>> +pub struct BioIterator<'a> {
>> + pub(crate) bio: Option<Bio<'a>>,
>> +}
>> +
>> +impl<'a> core::iter::Iterator for BioIterator<'a> {
>> + type Item = Bio<'a>;
>> +
>> + #[inline(always)]
>> + fn next(&mut self) -> Option<Bio<'a>> {
>> + if let Some(current) = self.bio.take() {
>> + self.bio = current.next();
>> + Some(current)
>> + } else {
>> + None
>> + }
>
> Can be rewritten as:
> let current = self.bio.take()?;
> self.bio = current.next();
> Some(cur)
>
Thanks 👍
>> + }
>> +}
>> diff --git a/rust/kernel/block/bio/vec.rs b/rust/kernel/block/bio/vec.rs
>> new file mode 100644
>> index 000000000000..acd328a6fe54
>> --- /dev/null
>> +++ b/rust/kernel/block/bio/vec.rs
>> @@ -0,0 +1,181 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +
>> +//! Types for working with `struct bio_vec` IO vectors
>> +//!
>> +//! C header: [`include/linux/bvec.h`](../../include/linux/bvec.h)
>> +
>> +use super::Bio;
>> +use crate::error::Result;
>> +use crate::pages::Pages;
>> +use core::fmt;
>> +use core::mem::ManuallyDrop;
>> +
>> +#[inline(always)]
>> +fn mp_bvec_iter_offset(bvec: *const bindings::bio_vec, iter: &bindings::bvec_iter) -> u32 {
>> + (unsafe { (*bvec_iter_bvec(bvec, iter)).bv_offset }) + iter.bi_bvec_done
>> +}
>> +
>> +#[inline(always)]
>> +fn mp_bvec_iter_page(
>> + bvec: *const bindings::bio_vec,
>> + iter: &bindings::bvec_iter,
>> +) -> *mut bindings::page {
>> + unsafe { (*bvec_iter_bvec(bvec, iter)).bv_page }
>> +}
>> +
>> +#[inline(always)]
>> +fn mp_bvec_iter_page_idx(bvec: *const bindings::bio_vec, iter: &bindings::bvec_iter) -> usize {
>> + (mp_bvec_iter_offset(bvec, iter) / crate::PAGE_SIZE) as usize
>> +}
>> +
>> +#[inline(always)]
>> +fn mp_bvec_iter_len(bvec: *const bindings::bio_vec, iter: &bindings::bvec_iter) -> u32 {
>> + iter.bi_size
>> + .min(unsafe { (*bvec_iter_bvec(bvec, iter)).bv_len } - iter.bi_bvec_done)
>> +}
>> +
>> +#[inline(always)]
>> +fn bvec_iter_bvec(
>> + bvec: *const bindings::bio_vec,
>> + iter: &bindings::bvec_iter,
>> +) -> *const bindings::bio_vec {
>> + unsafe { bvec.add(iter.bi_idx as usize) }
>> +}
>> +
>> +#[inline(always)]
>> +fn bvec_iter_page(
>> + bvec: *const bindings::bio_vec,
>> + iter: &bindings::bvec_iter,
>> +) -> *mut bindings::page {
>> + unsafe { mp_bvec_iter_page(bvec, iter).add(mp_bvec_iter_page_idx(bvec, iter)) }
>> +}
>> +
>> +#[inline(always)]
>> +fn bvec_iter_len(bvec: *const bindings::bio_vec, iter: &bindings::bvec_iter) -> u32 {
>> + mp_bvec_iter_len(bvec, iter).min(crate::PAGE_SIZE - bvec_iter_offset(bvec, iter))
>> +}
>> +
>> +#[inline(always)]
>> +fn bvec_iter_offset(bvec: *const bindings::bio_vec, iter: &bindings::bvec_iter) -> u32 {
>> + mp_bvec_iter_offset(bvec, iter) % crate::PAGE_SIZE
>> +}
>
> Why are these functions:
> - not marked as `unsafe`?
> - undocumented,
> - free functions.
>
> Can't these be directly implemented on `Segment<'_>`? If not,
> I think we should find some better way or make them `unsafe`.
Yes, you are right. I will move them to `Segment` and document them
better. They definitely need to be unsafe because they rely on C API
contract that the iterator is not indexing out of bounds.
[...]
>> +impl<'a> core::iter::Iterator for BioSegmentIterator<'a> {
>> + type Item = Segment<'a>;
>> +
>> + #[inline(always)]
>> + fn next(&mut self) -> Option<Self::Item> {
>> + if self.iter.bi_size == 0 {
>> + return None;
>> + }
>> +
>> + // Macro
>> + // bio_vec = bio_iter_iovec(bio, self.iter)
>> + // bio_vec = bvec_iter_bvec(bio.bi_io_vec, self.iter);
>
> Weird comment?
Yes, will fix, thanks.
Thanks for the comments!
BR Andreas
next prev parent reply other threads:[~2024-01-11 13:04 UTC|newest]
Thread overview: 67+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-03 9:06 [RFC PATCH 00/11] Rust null block driver Andreas Hindborg
2023-05-03 9:06 ` [RFC PATCH 01/11] rust: add radix tree abstraction Andreas Hindborg
2023-05-03 10:34 ` Benno Lossin
2023-05-05 4:04 ` Matthew Wilcox
2023-05-05 4:49 ` Andreas Hindborg
2023-05-05 5:28 ` Matthew Wilcox
2023-05-05 6:09 ` Christoph Hellwig
2023-05-05 8:33 ` Chaitanya Kulkarni
2023-05-03 9:06 ` [RFC PATCH 02/11] rust: add `pages` module for handling page allocation Andreas Hindborg
2023-05-03 12:31 ` Benno Lossin
2023-05-03 12:38 ` Benno Lossin
2023-05-05 4:09 ` Matthew Wilcox
2023-05-05 4:42 ` Andreas Hindborg
2023-05-05 5:29 ` Matthew Wilcox
2023-05-03 9:07 ` [RFC PATCH 03/11] rust: block: introduce `kernel::block::mq` module Andreas Hindborg
2023-05-08 12:29 ` Benno Lossin
2023-05-11 6:52 ` Sergio González Collado
2024-01-23 14:03 ` Andreas Hindborg (Samsung)
2024-01-12 9:18 ` Andreas Hindborg (Samsung)
2024-01-23 16:14 ` Benno Lossin
2024-01-23 18:39 ` Andreas Hindborg (Samsung)
2024-01-25 9:26 ` Benno Lossin
2024-01-29 14:14 ` Andreas Hindborg (Samsung)
2023-05-03 9:07 ` [RFC PATCH 04/11] rust: block: introduce `kernel::block::bio` module Andreas Hindborg
2023-05-08 12:58 ` Benno Lossin
2024-01-11 12:49 ` Andreas Hindborg (Samsung) [this message]
2024-02-28 14:31 ` Andreas Hindborg
2024-03-09 12:30 ` Benno Lossin
2023-05-03 9:07 ` [RFC PATCH 05/11] RUST: add `module_params` macro Andreas Hindborg
2023-05-03 9:07 ` [RFC PATCH 06/11] rust: apply cache line padding for `SpinLock` Andreas Hindborg
2023-05-03 12:03 ` Alice Ryhl
2024-02-23 11:29 ` Andreas Hindborg (Samsung)
2024-02-26 9:15 ` Alice Ryhl
2023-05-03 9:07 ` [RFC PATCH 07/11] rust: lock: add support for `Lock::lock_irqsave` Andreas Hindborg
2023-05-03 9:07 ` [RFC PATCH 08/11] rust: lock: implement `IrqSaveBackend` for `SpinLock` Andreas Hindborg
2023-05-03 9:07 ` [RFC PATCH 09/11] RUST: implement `ForeignOwnable` for `Pin` Andreas Hindborg
2023-05-03 9:07 ` [RFC PATCH 10/11] rust: add null block driver Andreas Hindborg
2023-05-03 9:07 ` [RFC PATCH 11/11] rust: inline a number of short functions Andreas Hindborg
2023-05-03 11:32 ` [RFC PATCH 00/11] Rust null block driver Niklas Cassel
2023-05-03 12:29 ` Andreas Hindborg
2023-05-03 13:54 ` Niklas Cassel
2023-05-03 16:47 ` Bart Van Assche
2023-05-04 18:15 ` Andreas Hindborg
2023-05-04 18:36 ` Bart Van Assche
2023-05-04 18:46 ` Andreas Hindborg
2023-05-04 18:52 ` Keith Busch
2023-05-04 19:02 ` Jens Axboe
2023-05-04 19:59 ` Andreas Hindborg
2023-05-04 20:55 ` Jens Axboe
2023-05-05 5:06 ` Andreas Hindborg
2023-05-05 11:14 ` Miguel Ojeda
2023-05-04 20:11 ` Miguel Ojeda
2023-05-04 20:22 ` Jens Axboe
2023-05-05 10:53 ` Miguel Ojeda
2023-05-05 12:24 ` Boqun Feng
2023-05-05 13:52 ` Boqun Feng
2023-05-05 19:42 ` Keith Busch
2023-05-05 21:46 ` Boqun Feng
2023-05-05 19:38 ` Bart Van Assche
2023-05-05 3:52 ` Christoph Hellwig
2023-06-06 13:33 ` Andreas Hindborg (Samsung)
2023-06-06 14:46 ` Miguel Ojeda
2023-05-05 5:28 ` Hannes Reinecke
2023-05-07 23:31 ` Luis Chamberlain
2023-05-07 23:37 ` Andreas Hindborg
[not found] ` <2B3CA5F1CCCFEAB2+20230727034517.GB126117@1182282462>
2023-07-28 6:49 ` Andreas Hindborg (Samsung)
2023-07-31 14:14 ` Andreas Hindborg (Samsung)
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=87a5pcyqf8.fsf@metaspace.dk \
--to=nmi@metaspace.dk \
--cc=Damien.LeMoal@wdc.com \
--cc=alex.gaynor@gmail.com \
--cc=axboe@kernel.dk \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=gary@garyguo.net \
--cc=gost.dev@samsung.com \
--cc=hare@suse.de \
--cc=hch@lst.de \
--cc=kbusch@kernel.org \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lsf-pc@lists.linux-foundation.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=wedsonaf@gmail.com \
--cc=willy@infradead.org \
/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