All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ming Lei <ming.lei@redhat.com>
To: Benno Lossin <lossin@kernel.org>
Cc: Sidong Yang <sidong.yang@furiosa.ai>,
	Jens Axboe <axboe@kernel.dk>,
	Daniel Almeida <daniel.almeida@collabora.com>,
	Caleb Sander Mateos <csander@purestorage.com>,
	Miguel Ojeda <ojeda@kernel.org>, Arnd Bergmann <arnd@arndb.de>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
	io-uring@vger.kernel.org
Subject: Re: [RFC PATCH v3 3/5] rust: io_uring: introduce rust abstraction for io-uring cmd
Date: Thu, 28 Aug 2025 18:05:16 +0800	[thread overview]
Message-ID: <aLAp3OUhsxUEsEWT@fedora> (raw)
In-Reply-To: <DCDVRPJKZBC3.31KGTGS90WUUA@kernel.org>

On Thu, Aug 28, 2025 at 09:25:56AM +0200, Benno Lossin wrote:
> On Thu Aug 28, 2025 at 2:36 AM CEST, Ming Lei wrote:
> > On Fri, Aug 22, 2025 at 12:55:53PM +0000, Sidong Yang wrote:
> >> +    /// Reads protocol data unit as `T` that impl `FromBytes` from uring cmd
> >> +    ///
> >> +    /// Fails with [`EFAULT`] if size of `T` is bigger than pdu size.
> >> +    #[inline]
> >> +    pub fn read_pdu<T: FromBytes>(&self) -> Result<T> {
> >> +        // SAFETY: `self.inner` is guaranteed by the type invariant to point
> >> +        // to a live `io_uring_cmd`, so dereferencing is safe.
> >> +        let inner = unsafe { &mut *self.inner.get() };
> >> +
> >> +        let len = size_of::<T>();
> >> +        if len > inner.pdu.len() {
> >> +            return Err(EFAULT);
> >> +        }
> >> +
> >> +        let mut out: MaybeUninit<T> = MaybeUninit::uninit();
> >> +        let ptr = &raw mut inner.pdu as *const c_void;
> >> +
> >> +        // SAFETY:
> >> +        // * The `ptr` is valid pointer from `self.inner` that is guaranteed by type invariant.
> >> +        // * The `out` is valid pointer that points `T` which impls `FromBytes` and checked
> >> +        //   size of `T` is smaller than pdu size.
> >> +        unsafe {
> >> +            core::ptr::copy_nonoverlapping(ptr, out.as_mut_ptr().cast::<c_void>(), len);
> >> +        }
> >> +
> >> +        // SAFETY: The read above has initialized all bytes in `out`, and since `T` implements
> >> +        // `FromBytes`, any bit-pattern is a valid value for this type.
> >> +        Ok(unsafe { out.assume_init() })
> >> +    }
> >> +
> >> +    /// Writes the provided `value` to `pdu` in uring_cmd `self`
> >> +    ///
> >> +    /// Fails with [`EFAULT`] if size of `T` is bigger than pdu size.
> >> +    #[inline]
> >> +    pub fn write_pdu<T: AsBytes>(&mut self, value: &T) -> Result<()> {
> >> +        // SAFETY: `self.inner` is guaranteed by the type invariant to point
> >> +        // to a live `io_uring_cmd`, so dereferencing is safe.
> >> +        let inner = unsafe { &mut *self.inner.get() };
> >> +
> >> +        let len = size_of::<T>();
> >> +        if len > inner.pdu.len() {
> >> +            return Err(EFAULT);
> >> +        }
> >> +
> >> +        let src = (value as *const T).cast::<c_void>();
> >> +        let dst = &raw mut inner.pdu as *mut c_void;
> >> +
> >> +        // SAFETY:
> >> +        // * The `src` is points valid memory that is guaranteed by `T` impls `AsBytes`
> >> +        // * The `dst` is valid. It's from `self.inner` that is guaranteed by type invariant.
> >> +        // * It's safe to copy because size of `T` is no more than len of pdu.
> >> +        unsafe {
> >> +            core::ptr::copy_nonoverlapping(src, dst, len);
> >> +        }
> >> +
> >> +        Ok(())
> >> +    }
> >
> > pdu is part of IoUringCmd, which is live in the whole uring_cmd lifetime. But
> > both read_pdu()/write_pdu() needs copy to read or write any byte in the pdu, which
> > is slow and hard to use, it could be more efficient to add two methods to return
> > Result<&T> and Result<mut &T> for user to manipulate uring_cmd's pdu.
> 
> That can also be useful, but you do need to ensure that the pdu is
> aligned to at least the required alignment of `T` for this to be sound.

Yes, `IoUringCmd` is actually one C struct, so `T` is supposed to be `#[repr(C)]`
too, and the usage should be just like what io_uring_cmd_to_pdu() provides.

> I also don't follow your argument that reading & writing the pdu is
> slow.

Please look at how pdu is used in existing C users, such as, the tag field of
`pdu` can be read/write directly via:

	`io_uring_cmd_to_pdu(ioucmd, struct ublk_uring_cmd_pdu)->tag`

but read_pdu()/write_pdu() needs whole 32bytes copy for read/write any
single field.

User may only need to store single byte data in pdu...

Thanks,
Ming


  reply	other threads:[~2025-08-28 10:05 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-22 12:55 [RFC PATCH v3 0/5] rust: miscdevice: abstraction for uring_cmd Sidong Yang
2025-08-22 12:55 ` [RFC PATCH v3 1/5] rust: bindings: add io_uring headers in bindings_helper.h Sidong Yang
2025-08-22 12:55 ` [RFC PATCH v3 2/5] io_uring/cmd: zero-init pdu in io_uring_cmd_prep() to avoid UB Sidong Yang
2025-09-02  0:34   ` Caleb Sander Mateos
2025-09-02 10:23     ` Sidong Yang
2025-09-02 15:31       ` Caleb Sander Mateos
2025-09-06 14:28         ` Sidong Yang
2025-09-08 19:45           ` Caleb Sander Mateos
2025-09-09 14:43             ` Sidong Yang
2025-09-09 16:32               ` Caleb Sander Mateos
2025-09-12 16:41                 ` Sidong Yang
2025-09-12 17:56                   ` Caleb Sander Mateos
2025-09-13 12:42                     ` Sidong Yang
2025-09-15 16:54                       ` Caleb Sander Mateos
2025-09-17 14:56                         ` Sidong Yang
2025-09-22 18:09                           ` Caleb Sander Mateos
2025-08-22 12:55 ` [RFC PATCH v3 3/5] rust: io_uring: introduce rust abstraction for io-uring cmd Sidong Yang
2025-08-27 20:41   ` Daniel Almeida
2025-08-28  7:24     ` Benno Lossin
2025-08-29 15:43     ` Sidong Yang
2025-08-29 16:11       ` Daniel Almeida
2025-08-28  0:36   ` Ming Lei
2025-08-28  7:25     ` Benno Lossin
2025-08-28 10:05       ` Ming Lei [this message]
2025-09-02  1:11   ` Caleb Sander Mateos
2025-09-02 11:11     ` Sidong Yang
2025-09-02 15:41       ` Caleb Sander Mateos
2025-08-22 12:55 ` [RFC PATCH v3 4/5] rust: miscdevice: Add `uring_cmd` support Sidong Yang
2025-09-02  1:12   ` Caleb Sander Mateos
2025-09-02 11:18     ` Sidong Yang
2025-09-02 15:53       ` Caleb Sander Mateos
2025-08-22 12:55 ` [RFC PATCH v3 5/5] samples: rust: Add `uring_cmd` example to `rust_misc_device` Sidong Yang
2025-08-28  0:48   ` Ming Lei

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=aLAp3OUhsxUEsEWT@fedora \
    --to=ming.lei@redhat.com \
    --cc=arnd@arndb.de \
    --cc=axboe@kernel.dk \
    --cc=csander@purestorage.com \
    --cc=daniel.almeida@collabora.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=io-uring@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=sidong.yang@furiosa.ai \
    /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.