public inbox for io-uring@vger.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd
@ 2025-07-27 15:03 Sidong Yang
  2025-07-27 15:03 ` [RFC PATCH v2 1/4] rust: bindings: add io_uring headers in bindings_helper.h Sidong Yang
                   ` (5 more replies)
  0 siblings, 6 replies; 41+ messages in thread
From: Sidong Yang @ 2025-07-27 15:03 UTC (permalink / raw)
  To: Caleb Sander Mateos, Benno Lossin
  Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, Greg Kroah-Hartman,
	rust-for-linux, linux-kernel, io-uring, Sidong Yang

This patch series implemens an abstraction for io-uring sqe and cmd and
adds uring_cmd callback for miscdevice. Also there is an example that use
uring_cmd in rust-miscdevice sample.

I received a email from kernel bot that `io_tw_state` is not FFI-safe.
It seems that the struct has no field how can I fix this?

Changelog:
v2:
* use pinned &mut for IoUringCmd
* add missing safety comments
* use write_volatile for read uring_cmd in sample

Sidong Yang (4):
  rust: bindings: add io_uring headers in bindings_helper.h
  rust: io_uring: introduce rust abstraction for io-uring cmd
  rust: miscdevice: add uring_cmd() for MiscDevice trait
  samples: rust: rust_misc_device: add uring_cmd example

 rust/bindings/bindings_helper.h  |   2 +
 rust/kernel/io_uring.rs          | 183 +++++++++++++++++++++++++++++++
 rust/kernel/lib.rs               |   1 +
 rust/kernel/miscdevice.rs        |  41 +++++++
 samples/rust/rust_misc_device.rs |  34 ++++++
 5 files changed, 261 insertions(+)
 create mode 100644 rust/kernel/io_uring.rs

-- 
2.43.0


^ permalink raw reply	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 1/4] rust: bindings: add io_uring headers in bindings_helper.h
  2025-07-27 15:03 [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
@ 2025-07-27 15:03 ` Sidong Yang
  2025-07-27 15:03 ` [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd Sidong Yang
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 41+ messages in thread
From: Sidong Yang @ 2025-07-27 15:03 UTC (permalink / raw)
  To: Caleb Sander Mateos, Benno Lossin
  Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, Greg Kroah-Hartman,
	rust-for-linux, linux-kernel, io-uring, Sidong Yang

This patch adds two headers io_uring.h io_uring/cmd.h in bindings_helper
for implementing rust io_uring abstraction.

Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
---
 rust/bindings/bindings_helper.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 8cbb660e2ec2..a41205e2b8b8 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -72,6 +72,8 @@
 #include <linux/wait.h>
 #include <linux/workqueue.h>
 #include <linux/xarray.h>
+#include <linux/io_uring.h>
+#include <linux/io_uring/cmd.h>
 #include <trace/events/rust_sample.h>
 
 #if defined(CONFIG_DRM_PANIC_SCREEN_QR_CODE)
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-07-27 15:03 [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
  2025-07-27 15:03 ` [RFC PATCH v2 1/4] rust: bindings: add io_uring headers in bindings_helper.h Sidong Yang
@ 2025-07-27 15:03 ` Sidong Yang
  2025-08-01 13:48   ` Daniel Almeida
  2025-07-27 15:03 ` [RFC PATCH v2 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait Sidong Yang
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 41+ messages in thread
From: Sidong Yang @ 2025-07-27 15:03 UTC (permalink / raw)
  To: Caleb Sander Mateos, Benno Lossin
  Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, Greg Kroah-Hartman,
	rust-for-linux, linux-kernel, io-uring, Sidong Yang

This patch introduces rust abstraction for io-uring sqe, cmd. IoUringSqe
abstracts io_uring_sqe and it has cmd_data(). and IoUringCmd is
abstraction for io_uring_cmd. From this, user can get cmd_op, flags,
pdu and also sqe.

Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
---
 rust/kernel/io_uring.rs | 183 ++++++++++++++++++++++++++++++++++++++++
 rust/kernel/lib.rs      |   1 +
 2 files changed, 184 insertions(+)
 create mode 100644 rust/kernel/io_uring.rs

diff --git a/rust/kernel/io_uring.rs b/rust/kernel/io_uring.rs
new file mode 100644
index 000000000000..0acdf3878247
--- /dev/null
+++ b/rust/kernel/io_uring.rs
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2025 Furiosa AI.
+
+//! IoUring command and submission queue entry abstractions.
+//!
+//! C headers: [`include/linux/io_uring/cmd.h`](srctree/include/linux/io_uring/cmd.h) and
+//! [`include/linux/io_uring/io_uring.h`](srctree/include/linux/io_uring/io_uring.h)
+
+use core::{mem::MaybeUninit, pin::Pin, ptr::addr_of_mut};
+
+use crate::{fs::File, types::Opaque};
+
+/// A Rust abstraction for the Linux kernel's `io_uring_cmd` structure.
+///
+/// This structure is a safe, opaque wrapper around the raw C `io_uring_cmd`
+/// binding from the Linux kernel. It represents a command structure used
+/// in io_uring operations within the kernel.
+///
+/// # Type Safety
+///
+/// The `#[repr(transparent)]` attribute ensures that this wrapper has
+/// the same memory layout as the underlying `io_uring_cmd` structure,
+/// allowing it to be safely transmuted between the two representations.
+///
+/// # Fields
+///
+/// * `inner` - An opaque wrapper containing the actual `io_uring_cmd` data.
+///             The `Opaque` type prevents direct access to the internal
+///             structure fields, ensuring memory safety and encapsulation.
+///
+/// # Usage
+///
+/// This type is used internally by the io_uring subsystem to manage
+/// asynchronous I/O commands. It is typically accessed through a pinned
+/// mutable reference: `Pin<&mut IoUringCmd>`. The pinning ensures that
+/// the structure remains at a fixed memory location, which is required
+/// for safe interaction with the kernel's io_uring infrastructure.
+///
+/// Users typically receive this type as an argument in the `file_operations::uring_cmd()`
+/// callback function, where they can access and manipulate the io_uring command
+/// data for custom file operations.
+///
+/// This type should not be constructed or manipulated directly by
+/// kernel module developers.
+#[repr(transparent)]
+pub struct IoUringCmd {
+    inner: Opaque<bindings::io_uring_cmd>,
+}
+
+impl IoUringCmd {
+    /// Returns the cmd_op with associated with the io_uring_cmd.
+    #[inline]
+    pub fn cmd_op(&self) -> u32 {
+        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
+        unsafe { (*self.inner.get()).cmd_op }
+    }
+
+    /// Returns the flags with associated with the io_uring_cmd.
+    #[inline]
+    pub fn flags(&self) -> u32 {
+        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
+        unsafe { (*self.inner.get()).flags }
+    }
+
+    /// Returns the ref pdu for free use.
+    #[inline]
+    pub fn pdu(&mut self) -> &mut MaybeUninit<[u8; 32]> {
+        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
+        let inner = unsafe { &mut *self.inner.get() };
+        let ptr = addr_of_mut!(inner.pdu) as *mut MaybeUninit<[u8; 32]>;
+
+        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
+        unsafe { &mut *ptr }
+    }
+
+    /// Constructs a new `IoUringCmd` from a raw `io_uring_cmd`
+    ///
+    /// # Safety
+    ///
+    /// The caller must guarantee that:
+    /// - The pointer `ptr` is not null and points to a valid `bindings::io_uring_cmd`.
+    /// - The memory pointed to by `ptr` remains valid for the duration of the returned reference's lifetime `'a`.
+    /// - The memory will not be moved or freed while the returned `Pin<&mut IoUringCmd>` is alive.
+    #[inline]
+    pub unsafe fn from_raw<'a>(ptr: *mut bindings::io_uring_cmd) -> Pin<&'a mut IoUringCmd> {
+        // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
+        // duration of 'a. The cast is okay because `IoUringCmd` is `repr(transparent)` and has the
+        // same memory layout as `bindings::io_uring_cmd`. The returned `Pin` ensures that the object
+        // cannot be moved, which is required because the kernel may hold pointers to this memory
+        // location and moving it would invalidate those pointers.
+        unsafe { Pin::new_unchecked(&mut *ptr.cast()) }
+    }
+
+    /// Returns the file that referenced by uring cmd self.
+    #[inline]
+    pub fn file(&self) -> &File {
+        // SAFETY: The call guarantees that the `self.inner` is not dangling and stays valid
+        let file = unsafe { (*self.inner.get()).file };
+        // SAFETY: The call guarantees that `file` points valid file.
+        unsafe { File::from_raw_file(file) }
+    }
+
+    /// Returns a reference to the uring cmd's SQE.
+    #[inline]
+    pub fn sqe(&self) -> &IoUringSqe {
+        // SAFETY: The call guarantees that the `self.inner` is not dangling and stays valid
+        let sqe = unsafe { (*self.inner.get()).sqe };
+        // SAFETY: The call guarantees that the `sqe` points valid io_uring_sqe.
+        unsafe { IoUringSqe::from_raw(sqe) }
+    }
+
+    /// Called by consumers of io_uring_cmd, if they originally returned -EIOCBQUEUED upon receiving the command
+    #[inline]
+    pub fn done(self: Pin<&mut IoUringCmd>, ret: isize, res2: u64, issue_flags: u32) {
+        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
+        unsafe {
+            bindings::io_uring_cmd_done(self.inner.get(), ret, res2, issue_flags);
+        }
+    }
+}
+
+/// A Rust abstraction for the Linux kernel's `io_uring_sqe` structure.
+///
+/// This structure is a safe, opaque wrapper around the raw C `io_uring_sqe`
+/// binding from the Linux kernel. It represents a Submission Queue Entry
+/// used in io_uring operations within the kernel.
+///
+/// # Type Safety
+///
+/// The `#[repr(transparent)]` attribute ensures that this wrapper has
+/// the same memory layout as the underlying `io_uring_sqe` structure,
+/// allowing it to be safely transmuted between the two representations.
+///
+/// # Fields
+///
+/// * `inner` - An opaque wrapper containing the actual `io_uring_sqe` data.
+///             The `Opaque` type prevents direct access to the internal
+///             structure fields, ensuring memory safety and encapsulation.
+///
+/// # Usage
+///
+/// This type represents a submission queue entry that describes an I/O
+/// operation to be executed by the io_uring subsystem. It contains
+/// information such as the operation type, file descriptor, buffer
+/// pointers, and other operation-specific data.
+///
+/// Users can obtain this type from `IoUringCmd::sqe()` method, which
+/// extracts the submission queue entry associated with a command.
+///
+/// This type should not be constructed or manipulated directly by
+/// kernel module developers.
+#[repr(transparent)]
+pub struct IoUringSqe {
+    inner: Opaque<bindings::io_uring_sqe>,
+}
+
+impl<'a> IoUringSqe {
+    /// Returns the cmd_data with associated with the io_uring_sqe.
+    /// This function returns 16 byte array. We don't support IORING_SETUP_SQE128 for now.
+    pub fn cmd_data(&'a self) -> &'a [Opaque<u8>] {
+        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
+        let cmd = unsafe { (*self.inner.get()).__bindgen_anon_6.cmd.as_ref() };
+
+        // SAFETY: The call guarantees that `cmd` is not dangling and stays valid
+        unsafe { core::slice::from_raw_parts(cmd.as_ptr() as *const Opaque<u8>, 16) }
+    }
+
+    /// Constructs a new `IoUringSqe` from a raw `io_uring_sqe`
+    ///
+    /// # Safety
+    ///
+    /// The caller must guarantee that:
+    /// - The pointer `ptr` is not null and points to a valid `bindings::io_uring_sqe`.
+    /// - The memory pointed to by `ptr` remains valid for the duration of the returned reference's lifetime `'a`.
+    #[inline]
+    pub unsafe fn from_raw(ptr: *const bindings::io_uring_sqe) -> &'a IoUringSqe {
+        // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
+        // duration of 'a. The cast is okay because `IoUringSqe` is `repr(transparent)` and has the
+        // same memory layout as `bindings::io_uring_sqe`.
+        unsafe { &*ptr.cast() }
+    }
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 6b4774b2b1c3..fb310e78d51d 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -80,6 +80,7 @@
 pub mod fs;
 pub mod init;
 pub mod io;
+pub mod io_uring;
 pub mod ioctl;
 pub mod jump_label;
 #[cfg(CONFIG_KUNIT)]
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait
  2025-07-27 15:03 [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
  2025-07-27 15:03 ` [RFC PATCH v2 1/4] rust: bindings: add io_uring headers in bindings_helper.h Sidong Yang
  2025-07-27 15:03 ` [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd Sidong Yang
@ 2025-07-27 15:03 ` Sidong Yang
  2025-08-01 14:04   ` Daniel Almeida
  2025-07-27 15:03 ` [RFC PATCH v2 4/4] samples: rust: rust_misc_device: add uring_cmd example Sidong Yang
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 41+ messages in thread
From: Sidong Yang @ 2025-07-27 15:03 UTC (permalink / raw)
  To: Caleb Sander Mateos, Benno Lossin
  Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, Greg Kroah-Hartman,
	rust-for-linux, linux-kernel, io-uring, Sidong Yang

This patch adds uring_cmd() function for MiscDevice trait and its
callback implementation. It uses IoUringCmd that io_uring_cmd rust
abstraction.

Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
---
 rust/kernel/miscdevice.rs | 41 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
index 288f40e79906..54be866ea7ff 100644
--- a/rust/kernel/miscdevice.rs
+++ b/rust/kernel/miscdevice.rs
@@ -14,6 +14,7 @@
     error::{to_result, Error, Result, VTABLE_DEFAULT_ERROR},
     ffi::{c_int, c_long, c_uint, c_ulong},
     fs::File,
+    io_uring::IoUringCmd,
     mm::virt::VmaNew,
     prelude::*,
     seq_file::SeqFile,
@@ -175,6 +176,19 @@ fn show_fdinfo(
     ) {
         build_error!(VTABLE_DEFAULT_ERROR)
     }
+
+    /// Handler for uring_cmd.
+    ///
+    /// This function is invoked when userspace process submits the uring_cmd op
+    /// on io_uring submission queue. The `io_uring_cmd` would be used for get
+    /// arguments cmd_op, sqe, cmd_data.
+    fn uring_cmd(
+        _device: <Self::Ptr as ForeignOwnable>::Borrowed<'_>,
+        _io_uring_cmd: Pin<&mut IoUringCmd>,
+        _issue_flags: u32,
+    ) -> Result<i32> {
+        build_error!(VTABLE_DEFAULT_ERROR)
+    }
 }
 
 /// A vtable for the file operations of a Rust miscdevice.
@@ -332,6 +346,28 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
         T::show_fdinfo(device, m, file);
     }
 
+    /// # Safety
+    ///
+    /// `ioucmd` is not null and points to a valid `bindings::io_uring_cmd`.
+    unsafe extern "C" fn uring_cmd(
+        ioucmd: *mut bindings::io_uring_cmd,
+        issue_flags: ffi::c_uint,
+    ) -> ffi::c_int {
+        // SAFETY: The file is valid for the duration of this call.
+        let ioucmd = unsafe { IoUringCmd::from_raw(ioucmd) };
+        let file = ioucmd.file();
+
+        // SAFETY: The file is valid for the duration of this call.
+        let private = unsafe { (*file.as_ptr()).private_data }.cast();
+        // SAFETY: uring_cmd calls can borrow the private data of the file.
+        let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
+
+        match T::uring_cmd(device, ioucmd, issue_flags) {
+            Ok(ret) => ret as ffi::c_int,
+            Err(err) => err.to_errno() as ffi::c_int,
+        }
+    }
+
     const VTABLE: bindings::file_operations = bindings::file_operations {
         open: Some(Self::open),
         release: Some(Self::release),
@@ -354,6 +390,11 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
         } else {
             None
         },
+        uring_cmd: if T::HAS_URING_CMD {
+            Some(Self::uring_cmd)
+        } else {
+            None
+        },
         // SAFETY: All zeros is a valid value for `bindings::file_operations`.
         ..unsafe { MaybeUninit::zeroed().assume_init() }
     };
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* [RFC PATCH v2 4/4] samples: rust: rust_misc_device: add uring_cmd example
  2025-07-27 15:03 [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
                   ` (2 preceding siblings ...)
  2025-07-27 15:03 ` [RFC PATCH v2 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait Sidong Yang
@ 2025-07-27 15:03 ` Sidong Yang
  2025-08-01 14:11   ` Daniel Almeida
  2025-07-27 17:17 ` [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd Daniel Almeida
  2025-08-01 14:13 ` Daniel Almeida
  5 siblings, 1 reply; 41+ messages in thread
From: Sidong Yang @ 2025-07-27 15:03 UTC (permalink / raw)
  To: Caleb Sander Mateos, Benno Lossin
  Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, Greg Kroah-Hartman,
	rust-for-linux, linux-kernel, io-uring, Sidong Yang

This patch makes rust_misc_device handle uring_cmd. Command ops are like
ioctl that set or get values in simple way.

Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
---
 samples/rust/rust_misc_device.rs | 34 ++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs
index c881fd6dbd08..1044bde86e8d 100644
--- a/samples/rust/rust_misc_device.rs
+++ b/samples/rust/rust_misc_device.rs
@@ -101,6 +101,7 @@
     c_str,
     device::Device,
     fs::File,
+    io_uring::IoUringCmd,
     ioctl::{_IO, _IOC_SIZE, _IOR, _IOW},
     miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration},
     new_mutex,
@@ -114,6 +115,9 @@
 const RUST_MISC_DEV_GET_VALUE: u32 = _IOR::<i32>('|' as u32, 0x81);
 const RUST_MISC_DEV_SET_VALUE: u32 = _IOW::<i32>('|' as u32, 0x82);
 
+const RUST_MISC_DEV_URING_CMD_SET_VALUE: u32 = _IOR::<i32>('|' as u32, 0x83);
+const RUST_MISC_DEV_URING_CMD_GET_VALUE: u32 = _IOW::<i32>('|' as u32, 0x84);
+
 module! {
     type: RustMiscDeviceModule,
     name: "rust_misc_device",
@@ -190,6 +194,36 @@ fn ioctl(me: Pin<&RustMiscDevice>, _file: &File, cmd: u32, arg: usize) -> Result
 
         Ok(0)
     }
+
+    fn uring_cmd(
+        me: Pin<&RustMiscDevice>,
+        io_uring_cmd: Pin<&mut IoUringCmd>,
+        _issue_flags: u32,
+    ) -> Result<i32> {
+        dev_info!(me.dev, "UringCmd Rust Misc Device Sample\n");
+
+        let cmd = io_uring_cmd.cmd_op();
+        let cmd_data = io_uring_cmd.sqe().cmd_data().as_ptr() as *const usize;
+
+        // SAFETY: `cmd_data` is guaranteed to be a valid pointer to the command data
+        // within the SQE structure.
+        // FIXME: switch to read_once() when it's available.
+        let addr = unsafe { core::ptr::read_volatile(cmd_data) };
+
+        match cmd {
+            RUST_MISC_DEV_URING_CMD_SET_VALUE => {
+                me.set_value(UserSlice::new(addr, 8).reader())?;
+            }
+            RUST_MISC_DEV_URING_CMD_GET_VALUE => {
+                me.get_value(UserSlice::new(addr, 8).writer())?;
+            }
+            _ => {
+                dev_err!(me.dev, "-> uring_cmd not recognised: {}\n", cmd);
+                return Err(ENOTTY);
+            }
+        }
+        Ok(0)
+    }
 }
 
 #[pinned_drop]
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd
  2025-07-27 15:03 [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
                   ` (3 preceding siblings ...)
  2025-07-27 15:03 ` [RFC PATCH v2 4/4] samples: rust: rust_misc_device: add uring_cmd example Sidong Yang
@ 2025-07-27 17:17 ` Daniel Almeida
  2025-08-01 14:13 ` Daniel Almeida
  5 siblings, 0 replies; 41+ messages in thread
From: Daniel Almeida @ 2025-07-27 17:17 UTC (permalink / raw)
  To: Sidong Yang
  Cc: Caleb Sander Mateos, Benno Lossin, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

Hi Sidong,

> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> 
> This patch series implemens an abstraction for io-uring sqe and cmd and
> adds uring_cmd callback for miscdevice. Also there is an example that use
> uring_cmd in rust-miscdevice sample.
> 
> I received a email from kernel bot that `io_tw_state` is not FFI-safe.
> It seems that the struct has no field how can I fix this?

It’s not something that you introduced. Empty structs are problematic when
used in FFI, because  ZSTs are not defined in the C standard AFAIK, although
they are supported in some compilers. For example, this is not illegal nor UB
in GCC [0]. The docs say:

> The structure has size zero.

This aligns with Rust's treatment of ZSTs, which are also zero-sized, so I
don't think this will be a problem, but lets wait for others to chime in.

I'll review this tomorrow.

> 
> Changelog:
> v2:
> * use pinned &mut for IoUringCmd
> * add missing safety comments
> * use write_volatile for read uring_cmd in sample
> 
> Sidong Yang (4):
>  rust: bindings: add io_uring headers in bindings_helper.h
>  rust: io_uring: introduce rust abstraction for io-uring cmd
>  rust: miscdevice: add uring_cmd() for MiscDevice trait
>  samples: rust: rust_misc_device: add uring_cmd example
> 
> rust/bindings/bindings_helper.h  |   2 +
> rust/kernel/io_uring.rs          | 183 +++++++++++++++++++++++++++++++
> rust/kernel/lib.rs               |   1 +
> rust/kernel/miscdevice.rs        |  41 +++++++
> samples/rust/rust_misc_device.rs |  34 ++++++
> 5 files changed, 261 insertions(+)
> create mode 100644 rust/kernel/io_uring.rs
> 
> -- 
> 2.43.0
> 
> 


— Daniel

[0]: https://gcc.gnu.org/onlinedocs/gcc/Empty-Structures.html



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-07-27 15:03 ` [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd Sidong Yang
@ 2025-08-01 13:48   ` Daniel Almeida
  2025-08-02 10:52     ` Benno Lossin
  2025-08-05  3:39     ` Sidong Yang
  0 siblings, 2 replies; 41+ messages in thread
From: Daniel Almeida @ 2025-08-01 13:48 UTC (permalink / raw)
  To: Sidong Yang
  Cc: Caleb Sander Mateos, Benno Lossin, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

Hi Sidong,

> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> 
> This patch introduces rust abstraction for io-uring sqe, cmd. IoUringSqe
> abstracts io_uring_sqe and it has cmd_data(). and IoUringCmd is
> abstraction for io_uring_cmd. From this, user can get cmd_op, flags,
> pdu and also sqe.

IMHO you need to expand this substantially.

Instead of a very brief discussion of *what* you're doing, you need to explain
*why* you're doing this and how this patch fits with the overall plan that you
have in mind.

Also, for the sake of reviewers, try to at least describe the role of all the
types you've mentioned.

> 
> Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> ---
> rust/kernel/io_uring.rs | 183 ++++++++++++++++++++++++++++++++++++++++
> rust/kernel/lib.rs      |   1 +
> 2 files changed, 184 insertions(+)
> create mode 100644 rust/kernel/io_uring.rs
> 
> diff --git a/rust/kernel/io_uring.rs b/rust/kernel/io_uring.rs
> new file mode 100644
> index 000000000000..0acdf3878247
> --- /dev/null
> +++ b/rust/kernel/io_uring.rs
> @@ -0,0 +1,183 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +// Copyright (C) 2025 Furiosa AI.
> +

Perhaps this instead [0].


> +//! IoUring command and submission queue entry abstractions.

Maybe expand this just a little bit as well.

> +//!
> +//! C headers: [`include/linux/io_uring/cmd.h`](srctree/include/linux/io_uring/cmd.h) and
> +//! [`include/linux/io_uring/io_uring.h`](srctree/include/linux/io_uring/io_uring.h)
> +
> +use core::{mem::MaybeUninit, pin::Pin, ptr::addr_of_mut};
> +
> +use crate::{fs::File, types::Opaque};
> +
> +/// A Rust abstraction for the Linux kernel's `io_uring_cmd` structure.

Is there a link for io_uring_cmd that you can use here?

> +///
> +/// This structure is a safe, opaque wrapper around the raw C `io_uring_cmd`
> +/// binding from the Linux kernel. It represents a command structure used
> +/// in io_uring operations within the kernel.

Perhaps backticks on “io_uring” ?

> +///
> +/// # Type Safety
> +///
> +/// The `#[repr(transparent)]` attribute ensures that this wrapper has
> +/// the same memory layout as the underlying `io_uring_cmd` structure,
> +/// allowing it to be safely transmuted between the two representations.
> +///
> +/// # Fields
> +///
> +/// * `inner` - An opaque wrapper containing the actual `io_uring_cmd` data.
> +///             The `Opaque` type prevents direct access to the internal
> +///             structure fields, ensuring memory safety and encapsulation.

Place this on top of the field itself please. Also, I don’t think you need
this at all because you don't need to explain the Opaque type, as it's
extensively used in the kernel crate.

> +///
> +/// # Usage

I don’t think you need this.

> +///
> +/// This type is used internally by the io_uring subsystem to manage
> +/// asynchronous I/O commands. It is typically accessed through a pinned
> +/// mutable reference: `Pin<&mut IoUringCmd>`. The pinning ensures that
> +/// the structure remains at a fixed memory location, which is required
> +/// for safe interaction with the kernel's io_uring infrastructure.

I don’t think you need anything other than:

> +/// This type is used internally by the io_uring subsystem to manage
> +/// asynchronous I/O commands.

Specifically, you don’t need to say this:

>  The pinning ensures that
> +/// the structure remains at a fixed memory location,



> +///
> +/// Users typically receive this type as an argument in the `file_operations::uring_cmd()`
> +/// callback function, where they can access and manipulate the io_uring command
> +/// data for custom file operations.
> +///
> +/// This type should not be constructed or manipulated directly by
> +/// kernel module developers.

Well, this is pub, so the reality is that it can be manipulated directly
through whatever public API it offers.

> +#[repr(transparent)]
> +pub struct IoUringCmd {
> +    inner: Opaque<bindings::io_uring_cmd>,
> +}
> +
> +impl IoUringCmd {
> +    /// Returns the cmd_op with associated with the io_uring_cmd.

Backticks

> +    #[inline]
> +    pub fn cmd_op(&self) -> u32 {
> +        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid

Not sure I understand what you’re trying to say here. Perhaps add an
invariant saying that `self.inner` always points to a valid
`bindings::io_uring_cmd` and mention that here instead.

> +        unsafe { (*self.inner.get()).cmd_op }
> +    }
> +
> +    /// Returns the flags with associated with the io_uring_cmd.
> +    #[inline]
> +    pub fn flags(&self) -> u32 {
> +        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
> +        unsafe { (*self.inner.get()).flags }
> +    }
> +
> +    /// Returns the ref pdu for free use.

I have no idea what “ref pdu” is. You need to describe these acronyms.

> +    #[inline]
> +    pub fn pdu(&mut self) -> &mut MaybeUninit<[u8; 32]> {

Why MaybeUninit? Also, this is a question for others, but I don’t think
that `u8`s can ever be uninitialized as all byte values are valid for `u8`.

> +        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
> +        let inner = unsafe { &mut *self.inner.get() };
> +        let ptr = addr_of_mut!(inner.pdu) as *mut MaybeUninit<[u8; 32]>;

&raw mut

> +
> +        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
> +        unsafe { &mut *ptr }
> +    }
> +
> +    /// Constructs a new `IoUringCmd` from a raw `io_uring_cmd`

[`IoUringCmd`]

By the way, always build the docs and see if they look nice.

> +    ///
> +    /// # Safety
> +    ///
> +    /// The caller must guarantee that:
> +    /// - The pointer `ptr` is not null and points to a valid `bindings::io_uring_cmd`.
> +    /// - The memory pointed to by `ptr` remains valid for the duration of the returned reference's lifetime `'a`.
> +    /// - The memory will not be moved or freed while the returned `Pin<&mut IoUringCmd>` is alive.

This returns a wrapper over a mutable reference. You must mention Rust’s aliasing rules here.

> +    #[inline]
> +    pub unsafe fn from_raw<'a>(ptr: *mut bindings::io_uring_cmd) -> Pin<&'a mut IoUringCmd> {
> +        // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
> +        // duration of 'a. The cast is okay because `IoUringCmd` is `repr(transparent)` and has the
> +        // same memory layout as `bindings::io_uring_cmd`. The returned `Pin` ensures that the object
> +        // cannot be moved, which is required because the kernel may hold pointers to this memory
> +        // location and moving it would invalidate those pointers.

Please break this into multiple paragraphs.

> +        unsafe { Pin::new_unchecked(&mut *ptr.cast()) }
> +    }
> +
> +    /// Returns the file that referenced by uring cmd self.
> +    #[inline]
> +    pub fn file(&self) -> &File {
> +        // SAFETY: The call guarantees that the `self.inner` is not dangling and stays valid
> +        let file = unsafe { (*self.inner.get()).file };
> +        // SAFETY: The call guarantees that `file` points valid file.
> +        unsafe { File::from_raw_file(file) }
> +    }
> +
> +    /// Returns a reference to the uring cmd's SQE.

Please define what `SQE` means. Add links if possible.

> +    #[inline]
> +    pub fn sqe(&self) -> &IoUringSqe {
> +        // SAFETY: The call guarantees that the `self.inner` is not dangling and stays valid
> +        let sqe = unsafe { (*self.inner.get()).sqe };
> +        // SAFETY: The call guarantees that the `sqe` points valid io_uring_sqe.

Backticks

> +        unsafe { IoUringSqe::from_raw(sqe) }
> +    }
> +
> +    /// Called by consumers of io_uring_cmd, if they originally returned -EIOCBQUEUED upon receiving the command

Backticks

> +    #[inline]
> +    pub fn done(self: Pin<&mut IoUringCmd>, ret: isize, res2: u64, issue_flags: u32) {

The arguments are cryptic here. Please let us know what they do.

> +        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
> +        unsafe {
> +            bindings::io_uring_cmd_done(self.inner.get(), ret, res2, issue_flags);
> +        }
> +    }
> +}
> +
> +/// A Rust abstraction for the Linux kernel's `io_uring_sqe` structure.
> +///
> +/// This structure is a safe, opaque wrapper around the raw C `io_uring_sqe`
> +/// binding from the Linux kernel. It represents a Submission Queue Entry

Ah, SQE == Submission Queue Entry. Is there a link for this?

> +/// used in io_uring operations within the kernel.
> +///
> +/// # Type Safety
> +///
> +/// The `#[repr(transparent)]` attribute ensures that this wrapper has
> +/// the same memory layout as the underlying `io_uring_sqe` structure,
> +/// allowing it to be safely transmuted between the two representations.
> +///
> +/// # Fields
> +///
> +/// * `inner` - An opaque wrapper containing the actual `io_uring_sqe` data.
> +///             The `Opaque` type prevents direct access to the internal
> +///             structure fields, ensuring memory safety and encapsulation.
> +///
> +/// # Usage
> +///
> +/// This type represents a submission queue entry that describes an I/O
> +/// operation to be executed by the io_uring subsystem. It contains
> +/// information such as the operation type, file descriptor, buffer
> +/// pointers, and other operation-specific data.

This description is very good :)

> +///
> +/// Users can obtain this type from `IoUringCmd::sqe()` method, which
> +/// extracts the submission queue entry associated with a command.

[`IoUringCmd::sqe`]

> +///
> +/// This type should not be constructed or manipulated directly by
> +/// kernel module developers.

Again, this is pub and can be freely manipulated through whatever
public API it offers.

> +#[repr(transparent)]
> +pub struct IoUringSqe {
> +    inner: Opaque<bindings::io_uring_sqe>,
> +}
> +
> +impl<'a> IoUringSqe {

Why is this ‘a here?

> +    /// Returns the cmd_data with associated with the io_uring_sqe.
> +    /// This function returns 16 byte array. We don't support IORING_SETUP_SQE128 for now.
> +    pub fn cmd_data(&'a self) -> &'a [Opaque<u8>] {

This is automatically placed by the compiler. See the lifetime elision rules
[1].

Also why does this return a reference to an array of Opaque<u8>?

You can return a &[u8] here if you can prove that this reference is legal given
Rust's aliasing rules. If you can't, then you have to look at what the DMA
allocator code is doing and use that as an example, i.e.: have a look at the
dma_read and dma_write macros and mark the function that returns the slice as
"unsafe".

> +        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
> +        let cmd = unsafe { (*self.inner.get()).__bindgen_anon_6.cmd.as_ref() };

What do you mean by “the call” ? Same in all other places where this sentence is used.
> +
> +        // SAFETY: The call guarantees that `cmd` is not dangling and stays valid
> +        unsafe { core::slice::from_raw_parts(cmd.as_ptr() as *const Opaque<u8>, 16) }
> +    }
> +
> +    /// Constructs a new `IoUringSqe` from a raw `io_uring_sqe`
> +    ///
> +    /// # Safety
> +    ///
> +    /// The caller must guarantee that:
> +    /// - The pointer `ptr` is not null and points to a valid `bindings::io_uring_sqe`.
> +    /// - The memory pointed to by `ptr` remains valid for the duration of the returned reference's lifetime `'a`.

Must mention Rust’s aliasing rules here.

> +    #[inline]
> +    pub unsafe fn from_raw(ptr: *const bindings::io_uring_sqe) -> &'a IoUringSqe {
> +        // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
> +        // duration of 'a. The cast is okay because `IoUringSqe` is `repr(transparent)` and has the
> +        // same memory layout as `bindings::io_uring_sqe`.
> +        unsafe { &*ptr.cast() }
> +    }
> +}
> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> index 6b4774b2b1c3..fb310e78d51d 100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -80,6 +80,7 @@
> pub mod fs;
> pub mod init;
> pub mod io;
> +pub mod io_uring;
> pub mod ioctl;
> pub mod jump_label;
> #[cfg(CONFIG_KUNIT)]
> -- 
> 2.43.0
> 
> 

[0] https://spdx.github.io/spdx-spec/v3.0.1/model/Software/Properties/copyrightText/
[1] https://doc.rust-lang.org/reference/lifetime-elision.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait
  2025-07-27 15:03 ` [RFC PATCH v2 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait Sidong Yang
@ 2025-08-01 14:04   ` Daniel Almeida
  2025-08-07  7:46     ` Sidong Yang
  0 siblings, 1 reply; 41+ messages in thread
From: Daniel Almeida @ 2025-08-01 14:04 UTC (permalink / raw)
  To: Sidong Yang
  Cc: Caleb Sander Mateos, Benno Lossin, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

Hi Sidong,

> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> 
> This patch adds uring_cmd() function for MiscDevice trait and its
> callback implementation. It uses IoUringCmd that io_uring_cmd rust
> abstraction.

I can’t parse this.

> 
> Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> ---
> rust/kernel/miscdevice.rs | 41 +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 41 insertions(+)
> 
> diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
> index 288f40e79906..54be866ea7ff 100644
> --- a/rust/kernel/miscdevice.rs
> +++ b/rust/kernel/miscdevice.rs
> @@ -14,6 +14,7 @@
>     error::{to_result, Error, Result, VTABLE_DEFAULT_ERROR},
>     ffi::{c_int, c_long, c_uint, c_ulong},
>     fs::File,
> +    io_uring::IoUringCmd,
>     mm::virt::VmaNew,
>     prelude::*,
>     seq_file::SeqFile,
> @@ -175,6 +176,19 @@ fn show_fdinfo(
>     ) {
>         build_error!(VTABLE_DEFAULT_ERROR)
>     }
> +
> +    /// Handler for uring_cmd.
> +    ///
> +    /// This function is invoked when userspace process submits the uring_cmd op
> +    /// on io_uring submission queue. The `io_uring_cmd` would be used for get
> +    /// arguments cmd_op, sqe, cmd_data.

Please improve this. I don’t think that anyone reading this can really get
a good grasp on what this function does.

What does `issue_flags` do?

> +    fn uring_cmd(
> +        _device: <Self::Ptr as ForeignOwnable>::Borrowed<'_>,
> +        _io_uring_cmd: Pin<&mut IoUringCmd>,
> +        _issue_flags: u32,
> +    ) -> Result<i32> {
> +        build_error!(VTABLE_DEFAULT_ERROR)
> +    }
> }
> 
> /// A vtable for the file operations of a Rust miscdevice.
> @@ -332,6 +346,28 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
>         T::show_fdinfo(device, m, file);
>     }
> 
> +    /// # Safety
> +    ///
> +    /// `ioucmd` is not null and points to a valid `bindings::io_uring_cmd`.

Please rewrite this as “the caller must ensure that  `ioucmd` points to a
valid `bindings::io_uring_cmd`” or some variation thereof.

> +    unsafe extern "C" fn uring_cmd(
> +        ioucmd: *mut bindings::io_uring_cmd,
> +        issue_flags: ffi::c_uint,
> +    ) -> ffi::c_int {
> +        // SAFETY: The file is valid for the duration of this call.
> +        let ioucmd = unsafe { IoUringCmd::from_raw(ioucmd) };

What file?

Also, this is what you wrote for IoUringCmd::from_raw:

+
+ /// Constructs a new `IoUringCmd` from a raw `io_uring_cmd`
+ ///
+ /// # Safety
+ ///
+ /// The caller must guarantee that:
+ /// - The pointer `ptr` is not null and points to a valid `bindings::io_uring_cmd`.
+ /// - The memory pointed to by `ptr` remains valid for the duration of the returned reference's lifetime `'a`.
+ /// - The memory will not be moved or freed while the returned `Pin<&mut IoUringCmd>` is alive.
+ #[inline]
+ pub unsafe fn from_raw<'a>(ptr: *mut bindings::io_uring_cmd) -> Pin<&'a mut IoUringCmd> {

Here, you have to mention how the safety requirements above are fulfilled in this call site.

> +        let file = ioucmd.file();
> +
> +        // SAFETY: The file is valid for the duration of this call.

Same here.

> +        let private = unsafe { (*file.as_ptr()).private_data }.cast();

Perhaps this can be hidden away in an accessor?

> +        // SAFETY: uring_cmd calls can borrow the private data of the file.
> +        let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };

This is ForeignOwnable::borrow():

    /// Borrows a foreign-owned object immutably.
    ///
    /// This method provides a way to access a foreign-owned value from Rust immutably. It provides
    /// you with exactly the same abilities as an `&Self` when the value is Rust-owned.
    ///
    /// # Safety
    ///
    /// The provided pointer must have been returned by a previous call to [`into_foreign`], and if
    /// the pointer is ever passed to [`from_foreign`], then that call must happen after the end of
    /// the lifetime `'a`.
    ///
    /// [`into_foreign`]: Self::into_foreign
    /// [`from_foreign`]: Self::from_foreign
    unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> Self::Borrowed<'a>;

You must say how the safety requirements above are fulfilled in this call site
as well. In particular, are you sure that this is true? i.e.:

> The provided pointer must have been returned by a previous call to
> [`into_foreign`],


> +
> +        match T::uring_cmd(device, ioucmd, issue_flags) {
> +            Ok(ret) => ret as ffi::c_int,
> +            Err(err) => err.to_errno() as ffi::c_int,

c_int is in the prelude. Also, please have a look at error::from_result().

> +        }
> +    }
> +
>     const VTABLE: bindings::file_operations = bindings::file_operations {
>         open: Some(Self::open),
>         release: Some(Self::release),
> @@ -354,6 +390,11 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
>         } else {
>             None
>         },
> +        uring_cmd: if T::HAS_URING_CMD {
> +            Some(Self::uring_cmd)
> +        } else {
> +            None
> +        },
>         // SAFETY: All zeros is a valid value for `bindings::file_operations`.
>         ..unsafe { MaybeUninit::zeroed().assume_init() }
>     };
> -- 
> 2.43.0
> 
> 

— Daniel


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 4/4] samples: rust: rust_misc_device: add uring_cmd example
  2025-07-27 15:03 ` [RFC PATCH v2 4/4] samples: rust: rust_misc_device: add uring_cmd example Sidong Yang
@ 2025-08-01 14:11   ` Daniel Almeida
  2025-08-07  6:30     ` Sidong Yang
  0 siblings, 1 reply; 41+ messages in thread
From: Daniel Almeida @ 2025-08-01 14:11 UTC (permalink / raw)
  To: Sidong Yang
  Cc: Caleb Sander Mateos, Benno Lossin, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

Hi Sidong,

> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> 
> This patch makes rust_misc_device handle uring_cmd. Command ops are like
> ioctl that set or get values in simple way.
> 
> Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> ---
> samples/rust/rust_misc_device.rs | 34 ++++++++++++++++++++++++++++++++
> 1 file changed, 34 insertions(+)
> 
> diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs
> index c881fd6dbd08..1044bde86e8d 100644
> --- a/samples/rust/rust_misc_device.rs
> +++ b/samples/rust/rust_misc_device.rs
> @@ -101,6 +101,7 @@
>     c_str,
>     device::Device,
>     fs::File,
> +    io_uring::IoUringCmd,
>     ioctl::{_IO, _IOC_SIZE, _IOR, _IOW},
>     miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration},
>     new_mutex,
> @@ -114,6 +115,9 @@
> const RUST_MISC_DEV_GET_VALUE: u32 = _IOR::<i32>('|' as u32, 0x81);
> const RUST_MISC_DEV_SET_VALUE: u32 = _IOW::<i32>('|' as u32, 0x82);
> 
> +const RUST_MISC_DEV_URING_CMD_SET_VALUE: u32 = _IOR::<i32>('|' as u32, 0x83);
> +const RUST_MISC_DEV_URING_CMD_GET_VALUE: u32 = _IOW::<i32>('|' as u32, 0x84);
> +
> module! {
>     type: RustMiscDeviceModule,
>     name: "rust_misc_device",
> @@ -190,6 +194,36 @@ fn ioctl(me: Pin<&RustMiscDevice>, _file: &File, cmd: u32, arg: usize) -> Result
> 
>         Ok(0)
>     }
> +
> +    fn uring_cmd(
> +        me: Pin<&RustMiscDevice>,

“me” ?

> +        io_uring_cmd: Pin<&mut IoUringCmd>,
> +        _issue_flags: u32,
> +    ) -> Result<i32> {
> +        dev_info!(me.dev, "UringCmd Rust Misc Device Sample\n");
> +
> +        let cmd = io_uring_cmd.cmd_op();
> +        let cmd_data = io_uring_cmd.sqe().cmd_data().as_ptr() as *const usize;
> +
> +        // SAFETY: `cmd_data` is guaranteed to be a valid pointer to the command data
> +        // within the SQE structure.

This is what core::ptr::read_volatile says:

Safety
Behavior is undefined if any of the following conditions are violated:
    • src must be valid for reads.
    • src must be properly aligned.
    • src must point to a properly initialized value of type T.

You must prove that the pre-conditions above are fulfilled here.

> +        // FIXME: switch to read_once() when it's available.
> +        let addr = unsafe { core::ptr::read_volatile(cmd_data) };

So drivers have to write “unsafe” directly? It isn’t forbidden, but
we should try our best to avoid it.

> +
> +        match cmd {
> +            RUST_MISC_DEV_URING_CMD_SET_VALUE => {
> +                me.set_value(UserSlice::new(addr, 8).reader())?;
> +            }
> +            RUST_MISC_DEV_URING_CMD_GET_VALUE => {
> +                me.get_value(UserSlice::new(addr, 8).writer())?;
> +            }
> +            _ => {
> +                dev_err!(me.dev, "-> uring_cmd not recognised: {}\n", cmd);
> +                return Err(ENOTTY);
> +            }
> +        }
> +        Ok(0)
> +    }
> }
> 

Who calls this function?

> #[pinned_drop]
> -- 
> 2.43.0
> 
> 

— Daniel


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd
  2025-07-27 15:03 [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
                   ` (4 preceding siblings ...)
  2025-07-27 17:17 ` [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd Daniel Almeida
@ 2025-08-01 14:13 ` Daniel Almeida
  2025-08-07  6:17   ` Sidong Yang
  5 siblings, 1 reply; 41+ messages in thread
From: Daniel Almeida @ 2025-08-01 14:13 UTC (permalink / raw)
  To: Sidong Yang
  Cc: Caleb Sander Mateos, Benno Lossin, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

Hi Sidong,

> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> 
> This patch series implemens an abstraction for io-uring sqe and cmd and
> adds uring_cmd callback for miscdevice. Also there is an example that use
> uring_cmd in rust-miscdevice sample.
> 
> I received a email from kernel bot that `io_tw_state` is not FFI-safe.
> It seems that the struct has no field how can I fix this?
> 
> Changelog:
> v2:
> * use pinned &mut for IoUringCmd
> * add missing safety comments
> * use write_volatile for read uring_cmd in sample

Why is v2 an RFC when v1 wasn’t? Can you mention it on the changelog?

> 
> Sidong Yang (4):
>  rust: bindings: add io_uring headers in bindings_helper.h
>  rust: io_uring: introduce rust abstraction for io-uring cmd
>  rust: miscdevice: add uring_cmd() for MiscDevice trait
>  samples: rust: rust_misc_device: add uring_cmd example
> 
> rust/bindings/bindings_helper.h  |   2 +
> rust/kernel/io_uring.rs          | 183 +++++++++++++++++++++++++++++++
> rust/kernel/lib.rs               |   1 +
> rust/kernel/miscdevice.rs        |  41 +++++++
> samples/rust/rust_misc_device.rs |  34 ++++++
> 5 files changed, 261 insertions(+)
> create mode 100644 rust/kernel/io_uring.rs
> 
> -- 
> 2.43.0
> 
> 

— Daniel

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-01 13:48   ` Daniel Almeida
@ 2025-08-02 10:52     ` Benno Lossin
  2025-08-06 12:38       ` Daniel Almeida
  2025-08-05  3:39     ` Sidong Yang
  1 sibling, 1 reply; 41+ messages in thread
From: Benno Lossin @ 2025-08-02 10:52 UTC (permalink / raw)
  To: Daniel Almeida, Sidong Yang
  Cc: Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann, Jens Axboe,
	Greg Kroah-Hartman, rust-for-linux, linux-kernel, io-uring

On Fri Aug 1, 2025 at 3:48 PM CEST, Daniel Almeida wrote:
>> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
>> +    #[inline]
>> +    pub fn pdu(&mut self) -> &mut MaybeUninit<[u8; 32]> {
>
> Why MaybeUninit? Also, this is a question for others, but I don’t think
> that `u8`s can ever be uninitialized as all byte values are valid for `u8`.

`u8` can be uninitialized. Uninitialized doesn't just mean "can take any
bit pattern", but also "is known to the compiler as being
uninitialized". The docs of `MaybeUninit` explain it like this:

    Moreover, uninitialized memory is special in that it does not have a
    fixed value (“fixed” meaning “it won’t change without being written
    to”). Reading the same uninitialized byte multiple times can give
    different results.

But the return type probably should be `&mut [MaybeUninit<u8>; 32]`
instead.

>> +    #[inline]
>> +    pub unsafe fn from_raw<'a>(ptr: *mut bindings::io_uring_cmd) -> Pin<&'a mut IoUringCmd> {
>> +        // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
>> +        // duration of 'a. The cast is okay because `IoUringCmd` is `repr(transparent)` and has the
>> +        // same memory layout as `bindings::io_uring_cmd`. The returned `Pin` ensures that the object
>> +        // cannot be moved, which is required because the kernel may hold pointers to this memory
>> +        // location and moving it would invalidate those pointers.
>
> Please break this into multiple paragraphs.

We usually use bullet point lists for this. 

---
Cheers,
Benno

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-01 13:48   ` Daniel Almeida
  2025-08-02 10:52     ` Benno Lossin
@ 2025-08-05  3:39     ` Sidong Yang
  2025-08-05 13:02       ` Daniel Almeida
  1 sibling, 1 reply; 41+ messages in thread
From: Sidong Yang @ 2025-08-05  3:39 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Caleb Sander Mateos, Benno Lossin, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Fri, Aug 01, 2025 at 10:48:40AM -0300, Daniel Almeida wrote:

Hi Daniel,

> Hi Sidong,
> 
> > On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> > 
> > This patch introduces rust abstraction for io-uring sqe, cmd. IoUringSqe
> > abstracts io_uring_sqe and it has cmd_data(). and IoUringCmd is
> > abstraction for io_uring_cmd. From this, user can get cmd_op, flags,
> > pdu and also sqe.
> 
> IMHO you need to expand this substantially.
> 
> Instead of a very brief discussion of *what* you're doing, you need to explain
> *why* you're doing this and how this patch fits with the overall plan that you
> have in mind.

It seems that it's hard to explain *why* deeply. But I'll try it.

> 
> Also, for the sake of reviewers, try to at least describe the role of all the
> types you've mentioned.

Okay, I'll add some detailed descrption for all types like IoUringCmd.
> 
> > 
> > Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> > ---
> > rust/kernel/io_uring.rs | 183 ++++++++++++++++++++++++++++++++++++++++
> > rust/kernel/lib.rs      |   1 +
> > 2 files changed, 184 insertions(+)
> > create mode 100644 rust/kernel/io_uring.rs
> > 
> > diff --git a/rust/kernel/io_uring.rs b/rust/kernel/io_uring.rs
> > new file mode 100644
> > index 000000000000..0acdf3878247
> > --- /dev/null
> > +++ b/rust/kernel/io_uring.rs
> > @@ -0,0 +1,183 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +// Copyright (C) 2025 Furiosa AI.
> > +
> 
> Perhaps this instead [0].

Thanks, I'll change it with the format.
> 
> 
> > +//! IoUring command and submission queue entry abstractions.
> 
> Maybe expand this just a little bit as well.

Okay.
> 
> > +//!
> > +//! C headers: [`include/linux/io_uring/cmd.h`](srctree/include/linux/io_uring/cmd.h) and
> > +//! [`include/linux/io_uring/io_uring.h`](srctree/include/linux/io_uring/io_uring.h)
> > +
> > +use core::{mem::MaybeUninit, pin::Pin, ptr::addr_of_mut};
> > +
> > +use crate::{fs::File, types::Opaque};
> > +
> > +/// A Rust abstraction for the Linux kernel's `io_uring_cmd` structure.
> 
> Is there a link for io_uring_cmd that you can use here?

Yes, I'll add a link for the struct.
> 
> > +///
> > +/// This structure is a safe, opaque wrapper around the raw C `io_uring_cmd`
> > +/// binding from the Linux kernel. It represents a command structure used
> > +/// in io_uring operations within the kernel.
> 
> Perhaps backticks on "io_uring" ?

Thanks.
> 
> > +///
> > +/// # Type Safety
> > +///
> > +/// The `#[repr(transparent)]` attribute ensures that this wrapper has
> > +/// the same memory layout as the underlying `io_uring_cmd` structure,
> > +/// allowing it to be safely transmuted between the two representations.
> > +///
> > +/// # Fields
> > +///
> > +/// * `inner` - An opaque wrapper containing the actual `io_uring_cmd` data.
> > +///             The `Opaque` type prevents direct access to the internal
> > +///             structure fields, ensuring memory safety and encapsulation.
> 
> Place this on top of the field itself please. Also, I don´t think you need
> this at all because you don't need to explain the Opaque type, as it's
> extensively used in the kernel crate.

Okay, I'll move this comments to code with the field.
> 
> > +///
> > +/// # Usage
> 
> I don´t think you need this.

Okay.
> 
> > +///
> > +/// This type is used internally by the io_uring subsystem to manage
> > +/// asynchronous I/O commands. It is typically accessed through a pinned
> > +/// mutable reference: `Pin<&mut IoUringCmd>`. The pinning ensures that
> > +/// the structure remains at a fixed memory location, which is required
> > +/// for safe interaction with the kernel's io_uring infrastructure.
> 
> I don´t think you need anything other than:

Thanks, It's too verbose. I'll rewrite this.
> 
> > +/// This type is used internally by the io_uring subsystem to manage
> > +/// asynchronous I/O commands.
> 
> Specifically, you don´t need to say this:
> 
> >  The pinning ensures that
> > +/// the structure remains at a fixed memory location,
> 
> 
> 
> > +///
> > +/// Users typically receive this type as an argument in the `file_operations::uring_cmd()`
> > +/// callback function, where they can access and manipulate the io_uring command
> > +/// data for custom file operations.
> > +///
> > +/// This type should not be constructed or manipulated directly by
> > +/// kernel module developers.
> 
> Well, this is pub, so the reality is that it can be manipulated directly
> through whatever public API it offers.
> 

Agreed, We should provide safe pub fns that it doesn't corrupt the inner state.

> > +#[repr(transparent)]
> > +pub struct IoUringCmd {
> > +    inner: Opaque<bindings::io_uring_cmd>,
> > +}
> > +
> > +impl IoUringCmd {
> > +    /// Returns the cmd_op with associated with the io_uring_cmd.
> 
> Backticks
Thanks.
> 
> > +    #[inline]
> > +    pub fn cmd_op(&self) -> u32 {
> > +        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
> 
> Not sure I understand what you´re trying to say here. Perhaps add an
> invariant saying that `self.inner` always points to a valid
> `bindings::io_uring_cmd` and mention that here instead.

Thanks, I'll add INVARIANT comment for self.inner and reference it in this comment.
> 
> > +        unsafe { (*self.inner.get()).cmd_op }
> > +    }
> > +
> > +    /// Returns the flags with associated with the io_uring_cmd.
> > +    #[inline]
> > +    pub fn flags(&self) -> u32 {
> > +        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
> > +        unsafe { (*self.inner.get()).flags }
> > +    }
> > +
> > +    /// Returns the ref pdu for free use.
> 
> I have no idea what "ref pdu" is. You need to describe these acronyms.

Okay. Thanks.
> 
> > +    #[inline]
> > +    pub fn pdu(&mut self) -> &mut MaybeUninit<[u8; 32]> {
> 
> Why MaybeUninit? Also, this is a question for others, but I don´t think
> that `u8`s can ever be uninitialized as all byte values are valid for `u8`.
> 
> > +        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
> > +        let inner = unsafe { &mut *self.inner.get() };
> > +        let ptr = addr_of_mut!(inner.pdu) as *mut MaybeUninit<[u8; 32]>;
> 
> &raw mut

I didn't know about this. Thanks.
> 
> > +
> > +        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
> > +        unsafe { &mut *ptr }
> > +    }
> > +
> > +    /// Constructs a new `IoUringCmd` from a raw `io_uring_cmd`
> 
> [`IoUringCmd`]
> 
> By the way, always build the docs and see if they look nice.

Thanks.
> 
> > +    ///
> > +    /// # Safety
> > +    ///
> > +    /// The caller must guarantee that:
> > +    /// - The pointer `ptr` is not null and points to a valid `bindings::io_uring_cmd`.
> > +    /// - The memory pointed to by `ptr` remains valid for the duration of the returned reference's lifetime `'a`.
> > +    /// - The memory will not be moved or freed while the returned `Pin<&mut IoUringCmd>` is alive.
> 
> This returns a wrapper over a mutable reference. You must mention Rust´s aliasing rules here.

Okay. Thanks.
> 
> > +    #[inline]
> > +    pub unsafe fn from_raw<'a>(ptr: *mut bindings::io_uring_cmd) -> Pin<&'a mut IoUringCmd> {
> > +        // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
> > +        // duration of 'a. The cast is okay because `IoUringCmd` is `repr(transparent)` and has the
> > +        // same memory layout as `bindings::io_uring_cmd`. The returned `Pin` ensures that the object
> > +        // cannot be moved, which is required because the kernel may hold pointers to this memory
> > +        // location and moving it would invalidate those pointers.
> 
> Please break this into multiple paragraphs.

Thanks.
> 
> > +        unsafe { Pin::new_unchecked(&mut *ptr.cast()) }
> > +    }
> > +
> > +    /// Returns the file that referenced by uring cmd self.
> > +    #[inline]
> > +    pub fn file(&self) -> &File {
> > +        // SAFETY: The call guarantees that the `self.inner` is not dangling and stays valid
> > +        let file = unsafe { (*self.inner.get()).file };
> > +        // SAFETY: The call guarantees that `file` points valid file.
> > +        unsafe { File::from_raw_file(file) }
> > +    }
> > +
> > +    /// Returns a reference to the uring cmd's SQE.
> 
> Please define what `SQE` means. Add links if possible.

Okay. Thanks.
> 
> > +    #[inline]
> > +    pub fn sqe(&self) -> &IoUringSqe {
> > +        // SAFETY: The call guarantees that the `self.inner` is not dangling and stays valid
> > +        let sqe = unsafe { (*self.inner.get()).sqe };
> > +        // SAFETY: The call guarantees that the `sqe` points valid io_uring_sqe.
> 
> Backticks

Thanks.
> 
> > +        unsafe { IoUringSqe::from_raw(sqe) }
> > +    }
> > +
> > +    /// Called by consumers of io_uring_cmd, if they originally returned -EIOCBQUEUED upon receiving the command
> 
> Backticks

Thanks.
> 
> > +    #[inline]
> > +    pub fn done(self: Pin<&mut IoUringCmd>, ret: isize, res2: u64, issue_flags: u32) {
> 
> The arguments are cryptic here. Please let us know what they do.

Thanks I'll add description for each arguments.
> 
> > +        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
> > +        unsafe {
> > +            bindings::io_uring_cmd_done(self.inner.get(), ret, res2, issue_flags);
> > +        }
> > +    }
> > +}
> > +
> > +/// A Rust abstraction for the Linux kernel's `io_uring_sqe` structure.
> > +///
> > +/// This structure is a safe, opaque wrapper around the raw C `io_uring_sqe`
> > +/// binding from the Linux kernel. It represents a Submission Queue Entry
> 
> Ah, SQE == Submission Queue Entry. Is there a link for this?

I'll add a link for this.
> 
> > +/// used in io_uring operations within the kernel.
> > +///
> > +/// # Type Safety
> > +///
> > +/// The `#[repr(transparent)]` attribute ensures that this wrapper has
> > +/// the same memory layout as the underlying `io_uring_sqe` structure,
> > +/// allowing it to be safely transmuted between the two representations.
> > +///
> > +/// # Fields
> > +///
> > +/// * `inner` - An opaque wrapper containing the actual `io_uring_sqe` data.
> > +///             The `Opaque` type prevents direct access to the internal
> > +///             structure fields, ensuring memory safety and encapsulation.
> > +///
> > +/// # Usage
> > +///
> > +/// This type represents a submission queue entry that describes an I/O
> > +/// operation to be executed by the io_uring subsystem. It contains
> > +/// information such as the operation type, file descriptor, buffer
> > +/// pointers, and other operation-specific data.
> 
> This description is very good :)

Thanks. :)
> 
> > +///
> > +/// Users can obtain this type from `IoUringCmd::sqe()` method, which
> > +/// extracts the submission queue entry associated with a command.
> 
> [`IoUringCmd::sqe`]

Thanks.
> 
> > +///
> > +/// This type should not be constructed or manipulated directly by
> > +/// kernel module developers.
> 
> Again, this is pub and can be freely manipulated through whatever
> public API it offers.

Okay.
> 
> > +#[repr(transparent)]
> > +pub struct IoUringSqe {
> > +    inner: Opaque<bindings::io_uring_sqe>,
> > +}
> > +
> > +impl<'a> IoUringSqe {
> 
> Why is this `a here?

It seems that I can delete 'a here. 
> 
> > +    /// Returns the cmd_data with associated with the io_uring_sqe.
> > +    /// This function returns 16 byte array. We don't support IORING_SETUP_SQE128 for now.
> > +    pub fn cmd_data(&'a self) -> &'a [Opaque<u8>] {
> 
> This is automatically placed by the compiler. See the lifetime elision rules
> [1].
> 
Thanks.

> Also why does this return a reference to an array of Opaque<u8>?
> 
> You can return a &[u8] here if you can prove that this reference is legal given
> Rust's aliasing rules. If you can't, then you have to look at what the DMA
> allocator code is doing and use that as an example, i.e.: have a look at the
> dma_read and dma_write macros and mark the function that returns the slice as
> "unsafe".
> 

Okay. It's better to use &[u8].

> > +        // SAFETY: The call guarantees that `self.inner` is not dangling and stays valid
> > +        let cmd = unsafe { (*self.inner.get()).__bindgen_anon_6.cmd.as_ref() };
> 
> What do you mean by "the call" ? Same in all other places where this sentence is used.
Thanks, it should be dereferecing than call.

> > +
> > +        // SAFETY: The call guarantees that `cmd` is not dangling and stays valid
> > +        unsafe { core::slice::from_raw_parts(cmd.as_ptr() as *const Opaque<u8>, 16) }
> > +    }
> > +
> > +    /// Constructs a new `IoUringSqe` from a raw `io_uring_sqe`
> > +    ///
> > +    /// # Safety
> > +    ///
> > +    /// The caller must guarantee that:
> > +    /// - The pointer `ptr` is not null and points to a valid `bindings::io_uring_sqe`.
> > +    /// - The memory pointed to by `ptr` remains valid for the duration of the returned reference's lifetime `'a`.
> 
> Must mention Rust´s aliasing rules here.

Okay. Thanks.
> 
> > +    #[inline]
> > +    pub unsafe fn from_raw(ptr: *const bindings::io_uring_sqe) -> &'a IoUringSqe {
> > +        // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
> > +        // duration of 'a. The cast is okay because `IoUringSqe` is `repr(transparent)` and has the
> > +        // same memory layout as `bindings::io_uring_sqe`.
> > +        unsafe { &*ptr.cast() }
> > +    }
> > +}
> > diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> > index 6b4774b2b1c3..fb310e78d51d 100644
> > --- a/rust/kernel/lib.rs
> > +++ b/rust/kernel/lib.rs
> > @@ -80,6 +80,7 @@
> > pub mod fs;
> > pub mod init;
> > pub mod io;
> > +pub mod io_uring;
> > pub mod ioctl;
> > pub mod jump_label;
> > #[cfg(CONFIG_KUNIT)]
> > -- 
> > 2.43.0
> > 
> > 
> 
> [0] https://spdx.github.io/spdx-spec/v3.0.1/model/Software/Properties/copyrightText/
> [1] https://doc.rust-lang.org/reference/lifetime-elision.html

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-05  3:39     ` Sidong Yang
@ 2025-08-05 13:02       ` Daniel Almeida
  2025-08-06  9:11         ` Sidong Yang
  0 siblings, 1 reply; 41+ messages in thread
From: Daniel Almeida @ 2025-08-05 13:02 UTC (permalink / raw)
  To: Sidong Yang
  Cc: Caleb Sander Mateos, Benno Lossin, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

Hi Sidon,

> On 5 Aug 2025, at 00:39, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> 
> On Fri, Aug 01, 2025 at 10:48:40AM -0300, Daniel Almeida wrote:
> 
> Hi Daniel,
> 
>> Hi Sidong,
>> 
>>> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
>>> 
>>> This patch introduces rust abstraction for io-uring sqe, cmd. IoUringSqe
>>> abstracts io_uring_sqe and it has cmd_data(). and IoUringCmd is
>>> abstraction for io_uring_cmd. From this, user can get cmd_op, flags,
>>> pdu and also sqe.
>> 
>> IMHO you need to expand this substantially.
>> 
>> Instead of a very brief discussion of *what* you're doing, you need to explain
>> *why* you're doing this and how this patch fits with the overall plan that you
>> have in mind.
> 
> It seems that it's hard to explain *why* deeply. But I'll try it.

Just to be clear, you don’t need to go deep enough in the sense that
you’re basically rewriting the documentation that is already available in
C, but you do need to provide an overview of how things fit together, otherwise
we're left to connect the dots.

Have a look at the I2C series [0]. That is all you need to do IMHO.

I’d use that as an example.
 
[0]: https://lore.kernel.org/rust-for-linux/2D1DE1BC-13FB-4563-BE11-232C755B5117@collabora.com/T/#t

— Daniel

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-05 13:02       ` Daniel Almeida
@ 2025-08-06  9:11         ` Sidong Yang
  0 siblings, 0 replies; 41+ messages in thread
From: Sidong Yang @ 2025-08-06  9:11 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Caleb Sander Mateos, Benno Lossin, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Tue, Aug 05, 2025 at 10:02:18AM -0300, Daniel Almeida wrote:
> Hi Sidon,
> 
> > On 5 Aug 2025, at 00:39, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> > 
> > On Fri, Aug 01, 2025 at 10:48:40AM -0300, Daniel Almeida wrote:
> > 
> > Hi Daniel,
> > 
> >> Hi Sidong,
> >> 
> >>> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> >>> 
> >>> This patch introduces rust abstraction for io-uring sqe, cmd. IoUringSqe
> >>> abstracts io_uring_sqe and it has cmd_data(). and IoUringCmd is
> >>> abstraction for io_uring_cmd. From this, user can get cmd_op, flags,
> >>> pdu and also sqe.
> >> 
> >> IMHO you need to expand this substantially.
> >> 
> >> Instead of a very brief discussion of *what* you're doing, you need to explain
> >> *why* you're doing this and how this patch fits with the overall plan that you
> >> have in mind.
> > 
> > It seems that it's hard to explain *why* deeply. But I'll try it.
> 
> Just to be clear, you don´t need to go deep enough in the sense that
> you´re basically rewriting the documentation that is already available in
> C, but you do need to provide an overview of how things fit together, otherwise
> we're left to connect the dots.
> 
> Have a look at the I2C series [0]. That is all you need to do IMHO.
> 
> I´d use that as an example.
>  
> [0]: https://lore.kernel.org/rust-for-linux/2D1DE1BC-13FB-4563-BE11-232C755B5117@collabora.com/T/#t

Thanks, 
I'll rewrite the cover letter and commit messages that reference the example. 

Thanks,
Sidong
> 
> - Daniel

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-02 10:52     ` Benno Lossin
@ 2025-08-06 12:38       ` Daniel Almeida
  2025-08-06 13:38         ` Benno Lossin
  0 siblings, 1 reply; 41+ messages in thread
From: Daniel Almeida @ 2025-08-06 12:38 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Sidong Yang, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

Hi Benno,

> On 2 Aug 2025, at 07:52, Benno Lossin <lossin@kernel.org> wrote:
> 
> On Fri Aug 1, 2025 at 3:48 PM CEST, Daniel Almeida wrote:
>>> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
>>> +    #[inline]
>>> +    pub fn pdu(&mut self) -> &mut MaybeUninit<[u8; 32]> {
>> 
>> Why MaybeUninit? Also, this is a question for others, but I don’t think
>> that `u8`s can ever be uninitialized as all byte values are valid for `u8`.
> 
> `u8` can be uninitialized. Uninitialized doesn't just mean "can take any
> bit pattern", but also "is known to the compiler as being
> uninitialized". The docs of `MaybeUninit` explain it like this:
> 
>    Moreover, uninitialized memory is special in that it does not have a
>    fixed value (“fixed” meaning “it won’t change without being written
>    to”). Reading the same uninitialized byte multiple times can give
>    different results.
> 
> But the return type probably should be `&mut [MaybeUninit<u8>; 32]`
> instead.


Right, but I guess the question then is why would we ever need to use
MaybeUninit here anyways.

It's a reference to a C array. Just treat that as initialized.

— Daniel

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-06 12:38       ` Daniel Almeida
@ 2025-08-06 13:38         ` Benno Lossin
  2025-08-08  6:56           ` Sidong Yang
  0 siblings, 1 reply; 41+ messages in thread
From: Benno Lossin @ 2025-08-06 13:38 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Sidong Yang, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Wed Aug 6, 2025 at 2:38 PM CEST, Daniel Almeida wrote:
> Hi Benno,
>
>> On 2 Aug 2025, at 07:52, Benno Lossin <lossin@kernel.org> wrote:
>> 
>> On Fri Aug 1, 2025 at 3:48 PM CEST, Daniel Almeida wrote:
>>>> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
>>>> +    #[inline]
>>>> +    pub fn pdu(&mut self) -> &mut MaybeUninit<[u8; 32]> {
>>> 
>>> Why MaybeUninit? Also, this is a question for others, but I don’t think
>>> that `u8`s can ever be uninitialized as all byte values are valid for `u8`.
>> 
>> `u8` can be uninitialized. Uninitialized doesn't just mean "can take any
>> bit pattern", but also "is known to the compiler as being
>> uninitialized". The docs of `MaybeUninit` explain it like this:
>> 
>>    Moreover, uninitialized memory is special in that it does not have a
>>    fixed value (“fixed” meaning “it won’t change without being written
>>    to”). Reading the same uninitialized byte multiple times can give
>>    different results.
>> 
>> But the return type probably should be `&mut [MaybeUninit<u8>; 32]`
>> instead.
>
>
> Right, but I guess the question then is why would we ever need to use
> MaybeUninit here anyways.
>
> It's a reference to a C array. Just treat that as initialized.

AFAIK C uninitialized memory also is considered uninitialized in Rust.
So if this array is not properly initialized on the C side, this would
be the correct type. If it is initialized, then just use `&mut [u8; 32]`.

---
Cheers,
Benno

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd
  2025-08-01 14:13 ` Daniel Almeida
@ 2025-08-07  6:17   ` Sidong Yang
  0 siblings, 0 replies; 41+ messages in thread
From: Sidong Yang @ 2025-08-07  6:17 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Caleb Sander Mateos, Benno Lossin, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Fri, Aug 01, 2025 at 11:13:29AM -0300, Daniel Almeida wrote:
> Hi Sidong,
> 
> > On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> > 
> > This patch series implemens an abstraction for io-uring sqe and cmd and
> > adds uring_cmd callback for miscdevice. Also there is an example that use
> > uring_cmd in rust-miscdevice sample.
> > 
> > I received a email from kernel bot that `io_tw_state` is not FFI-safe.
> > It seems that the struct has no field how can I fix this?
> > 
> > Changelog:
> > v2:
> > * use pinned &mut for IoUringCmd
> > * add missing safety comments
> > * use write_volatile for read uring_cmd in sample
> 
> Why is v2 an RFC when v1 wasn´t? Can you mention it on the changelog?

It was just miss. v1 should be also RFC. I'll mention it for next v3.

Thanks,
Sidong
> 
> > 
> > Sidong Yang (4):
> >  rust: bindings: add io_uring headers in bindings_helper.h
> >  rust: io_uring: introduce rust abstraction for io-uring cmd
> >  rust: miscdevice: add uring_cmd() for MiscDevice trait
> >  samples: rust: rust_misc_device: add uring_cmd example
> > 
> > rust/bindings/bindings_helper.h  |   2 +
> > rust/kernel/io_uring.rs          | 183 +++++++++++++++++++++++++++++++
> > rust/kernel/lib.rs               |   1 +
> > rust/kernel/miscdevice.rs        |  41 +++++++
> > samples/rust/rust_misc_device.rs |  34 ++++++
> > 5 files changed, 261 insertions(+)
> > create mode 100644 rust/kernel/io_uring.rs
> > 
> > -- 
> > 2.43.0
> > 
> > 
> 
> - Daniel

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 4/4] samples: rust: rust_misc_device: add uring_cmd example
  2025-08-01 14:11   ` Daniel Almeida
@ 2025-08-07  6:30     ` Sidong Yang
  0 siblings, 0 replies; 41+ messages in thread
From: Sidong Yang @ 2025-08-07  6:30 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Caleb Sander Mateos, Benno Lossin, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Fri, Aug 01, 2025 at 11:11:44AM -0300, Daniel Almeida wrote:
> Hi Sidong,
> 
> > On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> > 
> > This patch makes rust_misc_device handle uring_cmd. Command ops are like
> > ioctl that set or get values in simple way.
> > 
> > Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> > ---
> > samples/rust/rust_misc_device.rs | 34 ++++++++++++++++++++++++++++++++
> > 1 file changed, 34 insertions(+)
> > 
> > diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs
> > index c881fd6dbd08..1044bde86e8d 100644
> > --- a/samples/rust/rust_misc_device.rs
> > +++ b/samples/rust/rust_misc_device.rs
> > @@ -101,6 +101,7 @@
> >     c_str,
> >     device::Device,
> >     fs::File,
> > +    io_uring::IoUringCmd,
> >     ioctl::{_IO, _IOC_SIZE, _IOR, _IOW},
> >     miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration},
> >     new_mutex,
> > @@ -114,6 +115,9 @@
> > const RUST_MISC_DEV_GET_VALUE: u32 = _IOR::<i32>('|' as u32, 0x81);
> > const RUST_MISC_DEV_SET_VALUE: u32 = _IOW::<i32>('|' as u32, 0x82);
> > 
> > +const RUST_MISC_DEV_URING_CMD_SET_VALUE: u32 = _IOR::<i32>('|' as u32, 0x83);
> > +const RUST_MISC_DEV_URING_CMD_GET_VALUE: u32 = _IOW::<i32>('|' as u32, 0x84);
> > +
> > module! {
> >     type: RustMiscDeviceModule,
> >     name: "rust_misc_device",
> > @@ -190,6 +194,36 @@ fn ioctl(me: Pin<&RustMiscDevice>, _file: &File, cmd: u32, arg: usize) -> Result
> > 
> >         Ok(0)
> >     }
> > +
> > +    fn uring_cmd(
> > +        me: Pin<&RustMiscDevice>,
> 
> "me" ?

ioctl() uses the args name with "me".

> 
> > +        io_uring_cmd: Pin<&mut IoUringCmd>,
> > +        _issue_flags: u32,
> > +    ) -> Result<i32> {
> > +        dev_info!(me.dev, "UringCmd Rust Misc Device Sample\n");
> > +
> > +        let cmd = io_uring_cmd.cmd_op();
> > +        let cmd_data = io_uring_cmd.sqe().cmd_data().as_ptr() as *const usize;
> > +
> > +        // SAFETY: `cmd_data` is guaranteed to be a valid pointer to the command data
> > +        // within the SQE structure.
> 
> This is what core::ptr::read_volatile says:
> 
> Safety
> Behavior is undefined if any of the following conditions are violated:
>     o src must be valid for reads.
>     o src must be properly aligned.
>     o src must point to a properly initialized value of type T.
> 
> You must prove that the pre-conditions above are fulfilled here.

Okay, I would describe pre-conditions.
> 
> > +        // FIXME: switch to read_once() when it's available.
> > +        let addr = unsafe { core::ptr::read_volatile(cmd_data) };
> 
> So drivers have to write "unsafe" directly? It isn´t forbidden, but
> we should try our best to avoid it.

I don't know it's the best way to use &[u8] `cmd_data` in driver. The driver should
cast the `cmd_data` to user structure i32 in this time. is there any safe way
to provide safe interface for user driver?

> 
> > +
> > +        match cmd {
> > +            RUST_MISC_DEV_URING_CMD_SET_VALUE => {
> > +                me.set_value(UserSlice::new(addr, 8).reader())?;
> > +            }
> > +            RUST_MISC_DEV_URING_CMD_GET_VALUE => {
> > +                me.get_value(UserSlice::new(addr, 8).writer())?;
> > +            }
> > +            _ => {
> > +                dev_err!(me.dev, "-> uring_cmd not recognised: {}\n", cmd);
> > +                return Err(ENOTTY);
> > +            }
> > +        }
> > +        Ok(0)
> > +    }
> > }
> > 
> 
> Who calls this function?

This function would be called in io_uring subsystem. In detail, there is caller
io_uring_cmd() in io_uring/uring_cmd.c. When io_uring subsystem noticed that
submission queue entry which has uring cmd op pushed to submission queue, it
would be submitted and actually calls this function.

> 
> > #[pinned_drop]
> > -- 
> > 2.43.0
> > 
> > 
> 
> - Daniel
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait
  2025-08-01 14:04   ` Daniel Almeida
@ 2025-08-07  7:46     ` Sidong Yang
  0 siblings, 0 replies; 41+ messages in thread
From: Sidong Yang @ 2025-08-07  7:46 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Caleb Sander Mateos, Benno Lossin, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Fri, Aug 01, 2025 at 11:04:36AM -0300, Daniel Almeida wrote:
> Hi Sidong,
> 
> > On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> > 
> > This patch adds uring_cmd() function for MiscDevice trait and its
> > callback implementation. It uses IoUringCmd that io_uring_cmd rust
> > abstraction.
> 
> I can´t parse this.

Okay, I'll fix this.

> 
> > 
> > Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> > ---
> > rust/kernel/miscdevice.rs | 41 +++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 41 insertions(+)
> > 
> > diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
> > index 288f40e79906..54be866ea7ff 100644
> > --- a/rust/kernel/miscdevice.rs
> > +++ b/rust/kernel/miscdevice.rs
> > @@ -14,6 +14,7 @@
> >     error::{to_result, Error, Result, VTABLE_DEFAULT_ERROR},
> >     ffi::{c_int, c_long, c_uint, c_ulong},
> >     fs::File,
> > +    io_uring::IoUringCmd,
> >     mm::virt::VmaNew,
> >     prelude::*,
> >     seq_file::SeqFile,
> > @@ -175,6 +176,19 @@ fn show_fdinfo(
> >     ) {
> >         build_error!(VTABLE_DEFAULT_ERROR)
> >     }
> > +
> > +    /// Handler for uring_cmd.
> > +    ///
> > +    /// This function is invoked when userspace process submits the uring_cmd op
> > +    /// on io_uring submission queue. The `io_uring_cmd` would be used for get
> > +    /// arguments cmd_op, sqe, cmd_data.
> 
> Please improve this. I don´t think that anyone reading this can really get
> a good grasp on what this function does.
> 
> What does `issue_flags` do?
> 

Agreed, Let me revise this comments to make them easier to understand.

issue_flags includes flags options for io_uring. it's defined as `io_uring_cmd_flags`
in "include/linux/io_uring_types.h".

> > +    fn uring_cmd(
> > +        _device: <Self::Ptr as ForeignOwnable>::Borrowed<'_>,
> > +        _io_uring_cmd: Pin<&mut IoUringCmd>,
> > +        _issue_flags: u32,
> > +    ) -> Result<i32> {
> > +        build_error!(VTABLE_DEFAULT_ERROR)
> > +    }
> > }
> > 
> > /// A vtable for the file operations of a Rust miscdevice.
> > @@ -332,6 +346,28 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
> >         T::show_fdinfo(device, m, file);
> >     }
> > 
> > +    /// # Safety
> > +    ///
> > +    /// `ioucmd` is not null and points to a valid `bindings::io_uring_cmd`.
> 
> Please rewrite this as "the caller must ensure that  `ioucmd` points to a
> valid `bindings::io_uring_cmd`" or some variation thereof.

Okay, Thanks.
> 
> > +    unsafe extern "C" fn uring_cmd(
> > +        ioucmd: *mut bindings::io_uring_cmd,
> > +        issue_flags: ffi::c_uint,
> > +    ) -> ffi::c_int {
> > +        // SAFETY: The file is valid for the duration of this call.
> > +        let ioucmd = unsafe { IoUringCmd::from_raw(ioucmd) };
> 
> What file?
> 
> Also, this is what you wrote for IoUringCmd::from_raw:

Sorry, it's typo. It should be rewritted.

> 
> +
> + /// Constructs a new `IoUringCmd` from a raw `io_uring_cmd`
> + ///
> + /// # Safety
> + ///
> + /// The caller must guarantee that:
> + /// - The pointer `ptr` is not null and points to a valid `bindings::io_uring_cmd`.
> + /// - The memory pointed to by `ptr` remains valid for the duration of the returned reference's lifetime `'a`.
> + /// - The memory will not be moved or freed while the returned `Pin<&mut IoUringCmd>` is alive.
> + #[inline]
> + pub unsafe fn from_raw<'a>(ptr: *mut bindings::io_uring_cmd) -> Pin<&'a mut IoUringCmd> {
> 
> Here, you have to mention how the safety requirements above are fulfilled in this call site.

Okay, Actually, I'm little confused because it seems that the unsafe code deleted in email.
Anyway I would mention it in next.

> 
> > +        let file = ioucmd.file();
> > +
> > +        // SAFETY: The file is valid for the duration of this call.
> 
> Same here.

Thanks.
> 
> > +        let private = unsafe { (*file.as_ptr()).private_data }.cast();
> 
> Perhaps this can be hidden away in an accessor?

It seems that there is no accessor for private_data in File. 

> 
> > +        // SAFETY: uring_cmd calls can borrow the private data of the file.
> > +        let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
> 
> This is ForeignOwnable::borrow():
> 
>     /// Borrows a foreign-owned object immutably.
>     ///
>     /// This method provides a way to access a foreign-owned value from Rust immutably. It provides
>     /// you with exactly the same abilities as an `&Self` when the value is Rust-owned.
>     ///
>     /// # Safety
>     ///
>     /// The provided pointer must have been returned by a previous call to [`into_foreign`], and if
>     /// the pointer is ever passed to [`from_foreign`], then that call must happen after the end of
>     /// the lifetime `'a`.
>     ///
>     /// [`into_foreign`]: Self::into_foreign
>     /// [`from_foreign`]: Self::from_foreign
>     unsafe fn borrow<'a>(ptr: *mut Self::PointedTo) -> Self::Borrowed<'a>;
> 
> You must say how the safety requirements above are fulfilled in this call site
> as well. In particular, are you sure that this is true? i.e.:
> 
> > The provided pointer must have been returned by a previous call to
> > [`into_foreign`],

Okay, I would mention that the this call fulfilled the requirements.
> 
> 
> > +
> > +        match T::uring_cmd(device, ioucmd, issue_flags) {
> > +            Ok(ret) => ret as ffi::c_int,
> > +            Err(err) => err.to_errno() as ffi::c_int,
> 
> c_int is in the prelude. Also, please have a look at error::from_result().

Thanks.


Thank you for detailed Review.
Sidong

> 
> > +        }
> > +    }
> > +
> >     const VTABLE: bindings::file_operations = bindings::file_operations {
> >         open: Some(Self::open),
> >         release: Some(Self::release),
> > @@ -354,6 +390,11 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
> >         } else {
> >             None
> >         },
> > +        uring_cmd: if T::HAS_URING_CMD {
> > +            Some(Self::uring_cmd)
> > +        } else {
> > +            None
> > +        },
> >         // SAFETY: All zeros is a valid value for `bindings::file_operations`.
> >         ..unsafe { MaybeUninit::zeroed().assume_init() }
> >     };
> > -- 
> > 2.43.0
> > 
> > 
> 
> - Daniel
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-06 13:38         ` Benno Lossin
@ 2025-08-08  6:56           ` Sidong Yang
  2025-08-08  8:49             ` Benno Lossin
  2025-08-08 13:55             ` Caleb Sander Mateos
  0 siblings, 2 replies; 41+ messages in thread
From: Sidong Yang @ 2025-08-08  6:56 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Daniel Almeida, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Wed, Aug 06, 2025 at 03:38:24PM +0200, Benno Lossin wrote:
> On Wed Aug 6, 2025 at 2:38 PM CEST, Daniel Almeida wrote:
> > Hi Benno,
> >
> >> On 2 Aug 2025, at 07:52, Benno Lossin <lossin@kernel.org> wrote:
> >> 
> >> On Fri Aug 1, 2025 at 3:48 PM CEST, Daniel Almeida wrote:
> >>>> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> >>>> +    #[inline]
> >>>> +    pub fn pdu(&mut self) -> &mut MaybeUninit<[u8; 32]> {
> >>> 
> >>> Why MaybeUninit? Also, this is a question for others, but I don´t think
> >>> that `u8`s can ever be uninitialized as all byte values are valid for `u8`.
> >> 
> >> `u8` can be uninitialized. Uninitialized doesn't just mean "can take any
> >> bit pattern", but also "is known to the compiler as being
> >> uninitialized". The docs of `MaybeUninit` explain it like this:
> >> 
> >>    Moreover, uninitialized memory is special in that it does not have a
> >>    fixed value ("fixed" meaning "it won´t change without being written
> >>    to"). Reading the same uninitialized byte multiple times can give
> >>    different results.
> >> 
> >> But the return type probably should be `&mut [MaybeUninit<u8>; 32]`
> >> instead.
> >
> >
> > Right, but I guess the question then is why would we ever need to use
> > MaybeUninit here anyways.
> >
> > It's a reference to a C array. Just treat that as initialized.
> 
> AFAIK C uninitialized memory also is considered uninitialized in Rust.
> So if this array is not properly initialized on the C side, this would
> be the correct type. If it is initialized, then just use `&mut [u8; 32]`.

pdu field is memory chunk for driver can use it freely. The driver usually
saves a private data and read or modify it on the other context. using
just `&mut [u8;32]` would be simple and easy to use.

> 
> ---
> Cheers,
> Benno

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-08  6:56           ` Sidong Yang
@ 2025-08-08  8:49             ` Benno Lossin
  2025-08-08  9:43               ` Sidong Yang
  2025-08-08 13:55             ` Caleb Sander Mateos
  1 sibling, 1 reply; 41+ messages in thread
From: Benno Lossin @ 2025-08-08  8:49 UTC (permalink / raw)
  To: Sidong Yang
  Cc: Daniel Almeida, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Fri Aug 8, 2025 at 8:56 AM CEST, Sidong Yang wrote:
> On Wed, Aug 06, 2025 at 03:38:24PM +0200, Benno Lossin wrote:
>> On Wed Aug 6, 2025 at 2:38 PM CEST, Daniel Almeida wrote:
>> > Hi Benno,
>> >
>> >> On 2 Aug 2025, at 07:52, Benno Lossin <lossin@kernel.org> wrote:
>> >> 
>> >> On Fri Aug 1, 2025 at 3:48 PM CEST, Daniel Almeida wrote:
>> >>>> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
>> >>>> +    #[inline]
>> >>>> +    pub fn pdu(&mut self) -> &mut MaybeUninit<[u8; 32]> {
>> >>> 
>> >>> Why MaybeUninit? Also, this is a question for others, but I don´t think
>> >>> that `u8`s can ever be uninitialized as all byte values are valid for `u8`.
>> >> 
>> >> `u8` can be uninitialized. Uninitialized doesn't just mean "can take any
>> >> bit pattern", but also "is known to the compiler as being
>> >> uninitialized". The docs of `MaybeUninit` explain it like this:
>> >> 
>> >>    Moreover, uninitialized memory is special in that it does not have a
>> >>    fixed value ("fixed" meaning "it won´t change without being written
>> >>    to"). Reading the same uninitialized byte multiple times can give
>> >>    different results.
>> >> 
>> >> But the return type probably should be `&mut [MaybeUninit<u8>; 32]`
>> >> instead.
>> >
>> >
>> > Right, but I guess the question then is why would we ever need to use
>> > MaybeUninit here anyways.
>> >
>> > It's a reference to a C array. Just treat that as initialized.
>> 
>> AFAIK C uninitialized memory also is considered uninitialized in Rust.
>> So if this array is not properly initialized on the C side, this would
>> be the correct type. If it is initialized, then just use `&mut [u8; 32]`.
>
> pdu field is memory chunk for driver can use it freely. The driver usually
> saves a private data and read or modify it on the other context. using
> just `&mut [u8;32]` would be simple and easy to use.

Private data is usually handled using `ForeignOwnable` in Rust. What
kind of data would be stored there? If it's a pointer, then `&mut [u8;
32]` would not be the correct choice.

---
Cheers,
Benno

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-08  8:49             ` Benno Lossin
@ 2025-08-08  9:43               ` Sidong Yang
  2025-08-09 10:18                 ` Benno Lossin
  0 siblings, 1 reply; 41+ messages in thread
From: Sidong Yang @ 2025-08-08  9:43 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Daniel Almeida, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Fri, Aug 08, 2025 at 10:49:14AM +0200, Benno Lossin wrote:
> On Fri Aug 8, 2025 at 8:56 AM CEST, Sidong Yang wrote:
> > On Wed, Aug 06, 2025 at 03:38:24PM +0200, Benno Lossin wrote:
> >> On Wed Aug 6, 2025 at 2:38 PM CEST, Daniel Almeida wrote:
> >> > Hi Benno,
> >> >
> >> >> On 2 Aug 2025, at 07:52, Benno Lossin <lossin@kernel.org> wrote:
> >> >> 
> >> >> On Fri Aug 1, 2025 at 3:48 PM CEST, Daniel Almeida wrote:
> >> >>>> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> >> >>>> +    #[inline]
> >> >>>> +    pub fn pdu(&mut self) -> &mut MaybeUninit<[u8; 32]> {
> >> >>> 
> >> >>> Why MaybeUninit? Also, this is a question for others, but I don´t think
> >> >>> that `u8`s can ever be uninitialized as all byte values are valid for `u8`.
> >> >> 
> >> >> `u8` can be uninitialized. Uninitialized doesn't just mean "can take any
> >> >> bit pattern", but also "is known to the compiler as being
> >> >> uninitialized". The docs of `MaybeUninit` explain it like this:
> >> >> 
> >> >>    Moreover, uninitialized memory is special in that it does not have a
> >> >>    fixed value ("fixed" meaning "it won´t change without being written
> >> >>    to"). Reading the same uninitialized byte multiple times can give
> >> >>    different results.
> >> >> 
> >> >> But the return type probably should be `&mut [MaybeUninit<u8>; 32]`
> >> >> instead.
> >> >
> >> >
> >> > Right, but I guess the question then is why would we ever need to use
> >> > MaybeUninit here anyways.
> >> >
> >> > It's a reference to a C array. Just treat that as initialized.
> >> 
> >> AFAIK C uninitialized memory also is considered uninitialized in Rust.
> >> So if this array is not properly initialized on the C side, this would
> >> be the correct type. If it is initialized, then just use `&mut [u8; 32]`.
> >
> > pdu field is memory chunk for driver can use it freely. The driver usually
> > saves a private data and read or modify it on the other context. using
> > just `&mut [u8;32]` would be simple and easy to use.
> 
> Private data is usually handled using `ForeignOwnable` in Rust. What
> kind of data would be stored there? If it's a pointer, then `&mut [u8;
> 32]` would not be the correct choice.

Most driver uses `io_uring_cmd_to_pdu` macro that casts address of pdu to
private data type. It seems that all driver use this macro has it's own
struct type. How about make 2 function for pdu? like store_pdu(), borrow_pdu().

> 
> ---
> Cheers,
> Benno

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-08  6:56           ` Sidong Yang
  2025-08-08  8:49             ` Benno Lossin
@ 2025-08-08 13:55             ` Caleb Sander Mateos
  2025-08-09 12:53               ` Sidong Yang
  1 sibling, 1 reply; 41+ messages in thread
From: Caleb Sander Mateos @ 2025-08-08 13:55 UTC (permalink / raw)
  To: Sidong Yang
  Cc: Benno Lossin, Daniel Almeida, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Fri, Aug 8, 2025 at 2:56 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
>
> On Wed, Aug 06, 2025 at 03:38:24PM +0200, Benno Lossin wrote:
> > On Wed Aug 6, 2025 at 2:38 PM CEST, Daniel Almeida wrote:
> > > Hi Benno,
> > >
> > >> On 2 Aug 2025, at 07:52, Benno Lossin <lossin@kernel.org> wrote:
> > >>
> > >> On Fri Aug 1, 2025 at 3:48 PM CEST, Daniel Almeida wrote:
> > >>>> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> > >>>> +    #[inline]
> > >>>> +    pub fn pdu(&mut self) -> &mut MaybeUninit<[u8; 32]> {
> > >>>
> > >>> Why MaybeUninit? Also, this is a question for others, but I don´t think
> > >>> that `u8`s can ever be uninitialized as all byte values are valid for `u8`.
> > >>
> > >> `u8` can be uninitialized. Uninitialized doesn't just mean "can take any
> > >> bit pattern", but also "is known to the compiler as being
> > >> uninitialized". The docs of `MaybeUninit` explain it like this:
> > >>
> > >>    Moreover, uninitialized memory is special in that it does not have a
> > >>    fixed value ("fixed" meaning "it won´t change without being written
> > >>    to"). Reading the same uninitialized byte multiple times can give
> > >>    different results.
> > >>
> > >> But the return type probably should be `&mut [MaybeUninit<u8>; 32]`
> > >> instead.
> > >
> > >
> > > Right, but I guess the question then is why would we ever need to use
> > > MaybeUninit here anyways.
> > >
> > > It's a reference to a C array. Just treat that as initialized.
> >
> > AFAIK C uninitialized memory also is considered uninitialized in Rust.
> > So if this array is not properly initialized on the C side, this would
> > be the correct type. If it is initialized, then just use `&mut [u8; 32]`.
>
> pdu field is memory chunk for driver can use it freely. The driver usually
> saves a private data and read or modify it on the other context. using
> just `&mut [u8;32]` would be simple and easy to use.

MaybeUninit is correct. The io_uring/uring_cmd layer doesn't
initialize the pdu field. struct io_uring_cmd is overlaid with struct
io_kiocb's cmd field. struct io_kiocb's are allocated using
kmem_cache_alloc(_bulk)() in __io_alloc_req_refill(). io_preinit_req()
is called to initialize each struct io_kiocb but doesn't initialize
the cmd field. As Sidong said, it's uninitialized memory for the
->uring_cmd() implementation to use however it wants for the duration
of the command.

Best,
Caleb

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-08  9:43               ` Sidong Yang
@ 2025-08-09 10:18                 ` Benno Lossin
  2025-08-09 12:51                   ` Sidong Yang
  0 siblings, 1 reply; 41+ messages in thread
From: Benno Lossin @ 2025-08-09 10:18 UTC (permalink / raw)
  To: Sidong Yang
  Cc: Daniel Almeida, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Fri Aug 8, 2025 at 11:43 AM CEST, Sidong Yang wrote:
> On Fri, Aug 08, 2025 at 10:49:14AM +0200, Benno Lossin wrote:
>> On Fri Aug 8, 2025 at 8:56 AM CEST, Sidong Yang wrote:
>> > On Wed, Aug 06, 2025 at 03:38:24PM +0200, Benno Lossin wrote:
>> >> On Wed Aug 6, 2025 at 2:38 PM CEST, Daniel Almeida wrote:
>> >> > Hi Benno,
>> >> >
>> >> >> On 2 Aug 2025, at 07:52, Benno Lossin <lossin@kernel.org> wrote:
>> >> >> 
>> >> >> On Fri Aug 1, 2025 at 3:48 PM CEST, Daniel Almeida wrote:
>> >> >>>> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
>> >> >>>> +    #[inline]
>> >> >>>> +    pub fn pdu(&mut self) -> &mut MaybeUninit<[u8; 32]> {
>> >> >>> 
>> >> >>> Why MaybeUninit? Also, this is a question for others, but I don´t think
>> >> >>> that `u8`s can ever be uninitialized as all byte values are valid for `u8`.
>> >> >> 
>> >> >> `u8` can be uninitialized. Uninitialized doesn't just mean "can take any
>> >> >> bit pattern", but also "is known to the compiler as being
>> >> >> uninitialized". The docs of `MaybeUninit` explain it like this:
>> >> >> 
>> >> >>    Moreover, uninitialized memory is special in that it does not have a
>> >> >>    fixed value ("fixed" meaning "it won´t change without being written
>> >> >>    to"). Reading the same uninitialized byte multiple times can give
>> >> >>    different results.
>> >> >> 
>> >> >> But the return type probably should be `&mut [MaybeUninit<u8>; 32]`
>> >> >> instead.
>> >> >
>> >> >
>> >> > Right, but I guess the question then is why would we ever need to use
>> >> > MaybeUninit here anyways.
>> >> >
>> >> > It's a reference to a C array. Just treat that as initialized.
>> >> 
>> >> AFAIK C uninitialized memory also is considered uninitialized in Rust.
>> >> So if this array is not properly initialized on the C side, this would
>> >> be the correct type. If it is initialized, then just use `&mut [u8; 32]`.
>> >
>> > pdu field is memory chunk for driver can use it freely. The driver usually
>> > saves a private data and read or modify it on the other context. using
>> > just `&mut [u8;32]` would be simple and easy to use.
>> 
>> Private data is usually handled using `ForeignOwnable` in Rust. What
>> kind of data would be stored there? If it's a pointer, then `&mut [u8;
>> 32]` would not be the correct choice.
>
> Most driver uses `io_uring_cmd_to_pdu` macro that casts address of pdu to
> private data type. It seems that all driver use this macro has it's own
> struct type. How about make 2 function for pdu? like store_pdu(), borrow_pdu().

We'd need to ensure that `borrow_pdu` can only be called if `store_pdu`
has been called before. Is there any way we can just ensure that pdu is
always initialized? Like a callback that's called once, before the value
is used at all?

---
Cheers,
Benno

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-09 10:18                 ` Benno Lossin
@ 2025-08-09 12:51                   ` Sidong Yang
  2025-08-09 20:22                     ` Benno Lossin
  0 siblings, 1 reply; 41+ messages in thread
From: Sidong Yang @ 2025-08-09 12:51 UTC (permalink / raw)
  To: Benno Lossin, Caleb Sander Mateos
  Cc: Daniel Almeida, Miguel Ojeda, Arnd Bergmann, Jens Axboe,
	Greg Kroah-Hartman, rust-for-linux, linux-kernel, io-uring

On Sat, Aug 09, 2025 at 12:18:49PM +0200, Benno Lossin wrote:
> On Fri Aug 8, 2025 at 11:43 AM CEST, Sidong Yang wrote:
> > On Fri, Aug 08, 2025 at 10:49:14AM +0200, Benno Lossin wrote:
> >> On Fri Aug 8, 2025 at 8:56 AM CEST, Sidong Yang wrote:
> >> > On Wed, Aug 06, 2025 at 03:38:24PM +0200, Benno Lossin wrote:
> >> >> On Wed Aug 6, 2025 at 2:38 PM CEST, Daniel Almeida wrote:
> >> >> > Hi Benno,
> >> >> >
> >> >> >> On 2 Aug 2025, at 07:52, Benno Lossin <lossin@kernel.org> wrote:
> >> >> >> 
> >> >> >> On Fri Aug 1, 2025 at 3:48 PM CEST, Daniel Almeida wrote:
> >> >> >>>> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> >> >> >>>> +    #[inline]
> >> >> >>>> +    pub fn pdu(&mut self) -> &mut MaybeUninit<[u8; 32]> {
> >> >> >>> 
> >> >> >>> Why MaybeUninit? Also, this is a question for others, but I don´t think
> >> >> >>> that `u8`s can ever be uninitialized as all byte values are valid for `u8`.
> >> >> >> 
> >> >> >> `u8` can be uninitialized. Uninitialized doesn't just mean "can take any
> >> >> >> bit pattern", but also "is known to the compiler as being
> >> >> >> uninitialized". The docs of `MaybeUninit` explain it like this:
> >> >> >> 
> >> >> >>    Moreover, uninitialized memory is special in that it does not have a
> >> >> >>    fixed value ("fixed" meaning "it won´t change without being written
> >> >> >>    to"). Reading the same uninitialized byte multiple times can give
> >> >> >>    different results.
> >> >> >> 
> >> >> >> But the return type probably should be `&mut [MaybeUninit<u8>; 32]`
> >> >> >> instead.
> >> >> >
> >> >> >
> >> >> > Right, but I guess the question then is why would we ever need to use
> >> >> > MaybeUninit here anyways.
> >> >> >
> >> >> > It's a reference to a C array. Just treat that as initialized.
> >> >> 
> >> >> AFAIK C uninitialized memory also is considered uninitialized in Rust.
> >> >> So if this array is not properly initialized on the C side, this would
> >> >> be the correct type. If it is initialized, then just use `&mut [u8; 32]`.
> >> >
> >> > pdu field is memory chunk for driver can use it freely. The driver usually
> >> > saves a private data and read or modify it on the other context. using
> >> > just `&mut [u8;32]` would be simple and easy to use.
> >> 
> >> Private data is usually handled using `ForeignOwnable` in Rust. What
> >> kind of data would be stored there? If it's a pointer, then `&mut [u8;
> >> 32]` would not be the correct choice.
> >
> > Most driver uses `io_uring_cmd_to_pdu` macro that casts address of pdu to
> > private data type. It seems that all driver use this macro has it's own
> > struct type. How about make 2 function for pdu? like store_pdu(), borrow_pdu().
> 
> We'd need to ensure that `borrow_pdu` can only be called if `store_pdu`
> has been called before. Is there any way we can just ensure that pdu is
> always initialized? Like a callback that's called once, before the value
> is used at all?

I've thought about this. As Celab said, returning `&mut MaybeUninit<[u8;32]> is
simple and best. Only driver knows it's initialized. There is no way to
check whether it's initialized with reading the pdu. The best way is to return
`&mut MaybeUninit<[u8;32]>` and driver initializes it in first time. After 
init, driver knows it's guranteed that it's initialized so it could call 
`assume_init_mut()`. And casting to other struct is another problem. The driver
is responsible for determining how to interpret the PDU, whether by using it
directly as a byte array or by performing an unsafe cast to another struct.

Thanks,
Sidong


> 
> ---
> Cheers,
> Benno

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-08 13:55             ` Caleb Sander Mateos
@ 2025-08-09 12:53               ` Sidong Yang
  0 siblings, 0 replies; 41+ messages in thread
From: Sidong Yang @ 2025-08-09 12:53 UTC (permalink / raw)
  To: Caleb Sander Mateos
  Cc: Benno Lossin, Daniel Almeida, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Fri, Aug 08, 2025 at 09:55:22AM -0400, Caleb Sander Mateos wrote:
> On Fri, Aug 8, 2025 at 2:56 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
> >
> > On Wed, Aug 06, 2025 at 03:38:24PM +0200, Benno Lossin wrote:
> > > On Wed Aug 6, 2025 at 2:38 PM CEST, Daniel Almeida wrote:
> > > > Hi Benno,
> > > >
> > > >> On 2 Aug 2025, at 07:52, Benno Lossin <lossin@kernel.org> wrote:
> > > >>
> > > >> On Fri Aug 1, 2025 at 3:48 PM CEST, Daniel Almeida wrote:
> > > >>>> On 27 Jul 2025, at 12:03, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> > > >>>> +    #[inline]
> > > >>>> +    pub fn pdu(&mut self) -> &mut MaybeUninit<[u8; 32]> {
> > > >>>
> > > >>> Why MaybeUninit? Also, this is a question for others, but I don´t think
> > > >>> that `u8`s can ever be uninitialized as all byte values are valid for `u8`.
> > > >>
> > > >> `u8` can be uninitialized. Uninitialized doesn't just mean "can take any
> > > >> bit pattern", but also "is known to the compiler as being
> > > >> uninitialized". The docs of `MaybeUninit` explain it like this:
> > > >>
> > > >>    Moreover, uninitialized memory is special in that it does not have a
> > > >>    fixed value ("fixed" meaning "it won´t change without being written
> > > >>    to"). Reading the same uninitialized byte multiple times can give
> > > >>    different results.
> > > >>
> > > >> But the return type probably should be `&mut [MaybeUninit<u8>; 32]`
> > > >> instead.
> > > >
> > > >
> > > > Right, but I guess the question then is why would we ever need to use
> > > > MaybeUninit here anyways.
> > > >
> > > > It's a reference to a C array. Just treat that as initialized.
> > >
> > > AFAIK C uninitialized memory also is considered uninitialized in Rust.
> > > So if this array is not properly initialized on the C side, this would
> > > be the correct type. If it is initialized, then just use `&mut [u8; 32]`.
> >
> > pdu field is memory chunk for driver can use it freely. The driver usually
> > saves a private data and read or modify it on the other context. using
> > just `&mut [u8;32]` would be simple and easy to use.
> 
> MaybeUninit is correct. The io_uring/uring_cmd layer doesn't
> initialize the pdu field. struct io_uring_cmd is overlaid with struct
> io_kiocb's cmd field. struct io_kiocb's are allocated using
> kmem_cache_alloc(_bulk)() in __io_alloc_req_refill(). io_preinit_req()
> is called to initialize each struct io_kiocb but doesn't initialize
> the cmd field. As Sidong said, it's uninitialized memory for the
> ->uring_cmd() implementation to use however it wants for the duration
> of the command.

Agreed. Thanks.

Thanks,
Sidong
> 
> Best,
> Caleb

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-09 12:51                   ` Sidong Yang
@ 2025-08-09 20:22                     ` Benno Lossin
  2025-08-10 13:50                       ` Sidong Yang
  0 siblings, 1 reply; 41+ messages in thread
From: Benno Lossin @ 2025-08-09 20:22 UTC (permalink / raw)
  To: Sidong Yang, Caleb Sander Mateos
  Cc: Daniel Almeida, Miguel Ojeda, Arnd Bergmann, Jens Axboe,
	Greg Kroah-Hartman, rust-for-linux, linux-kernel, io-uring

On Sat Aug 9, 2025 at 2:51 PM CEST, Sidong Yang wrote:
> On Sat, Aug 09, 2025 at 12:18:49PM +0200, Benno Lossin wrote:
>> We'd need to ensure that `borrow_pdu` can only be called if `store_pdu`
>> has been called before. Is there any way we can just ensure that pdu is
>> always initialized? Like a callback that's called once, before the value
>> is used at all?
>
> I've thought about this. As Celab said, returning `&mut MaybeUninit<[u8;32]> is
> simple and best. Only driver knows it's initialized. There is no way to
> check whether it's initialized with reading the pdu. The best way is to return
> `&mut MaybeUninit<[u8;32]>` and driver initializes it in first time. After 
> init, driver knows it's guranteed that it's initialized so it could call 
> `assume_init_mut()`. And casting to other struct is another problem. The driver
> is responsible for determining how to interpret the PDU, whether by using it
> directly as a byte array or by performing an unsafe cast to another struct.

But then drivers will have to use `unsafe` & possibly cast the slice to
a struct? I think that's bad design since we try to avoid unsafe code in
drivers as much as possible. Couldn't we try to ensure from the
abstraction side that any time you create such an object, the driver
needs to provide the pdu data? Or we could make it implement `Default`
and then set it to that before handing it to the driver.

---
Cheers,
Benno

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-09 20:22                     ` Benno Lossin
@ 2025-08-10 13:50                       ` Sidong Yang
  2025-08-10 14:27                         ` Daniel Almeida
  0 siblings, 1 reply; 41+ messages in thread
From: Sidong Yang @ 2025-08-10 13:50 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Caleb Sander Mateos, Daniel Almeida, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Sat, Aug 09, 2025 at 10:22:06PM +0200, Benno Lossin wrote:
> On Sat Aug 9, 2025 at 2:51 PM CEST, Sidong Yang wrote:
> > On Sat, Aug 09, 2025 at 12:18:49PM +0200, Benno Lossin wrote:
> >> We'd need to ensure that `borrow_pdu` can only be called if `store_pdu`
> >> has been called before. Is there any way we can just ensure that pdu is
> >> always initialized? Like a callback that's called once, before the value
> >> is used at all?
> >
> > I've thought about this. As Celab said, returning `&mut MaybeUninit<[u8;32]> is
> > simple and best. Only driver knows it's initialized. There is no way to
> > check whether it's initialized with reading the pdu. The best way is to return
> > `&mut MaybeUninit<[u8;32]>` and driver initializes it in first time. After 
> > init, driver knows it's guranteed that it's initialized so it could call 
> > `assume_init_mut()`. And casting to other struct is another problem. The driver
> > is responsible for determining how to interpret the PDU, whether by using it
> > directly as a byte array or by performing an unsafe cast to another struct.
> 
> But then drivers will have to use `unsafe` & possibly cast the slice to
> a struct? I think that's bad design since we try to avoid unsafe code in
> drivers as much as possible. Couldn't we try to ensure from the
> abstraction side that any time you create such an object, the driver
> needs to provide the pdu data? Or we could make it implement `Default`
> and then set it to that before handing it to the driver.

pdu data is [u8; 32] memory space that driver can borrow. this has two kind of
issues. The one is that the array is not initialized and another one is it's
array type that driver should cast it to private data structure unsafely.
The first one could be resolved with returning `&mut MaybeUninit<>`. And the
second one, casting issue, is remaining. 

It seems that we need new unsafe trait like below:

/// Pdu should be... repr C or transparent, sizeof <= 20
unsafe trait Pdu: Sized {}

/// Returning to casted Pdu type T
pub fn pdu<T: Pdu>(&mut self) -> &mut MaybeUninit<T>

I think it is like bytemuck::Pod trait. Pod meaning plain old data.

Thanks,
Sidong


> 
> ---
> Cheers,
> Benno

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-10 13:50                       ` Sidong Yang
@ 2025-08-10 14:27                         ` Daniel Almeida
  2025-08-10 14:46                           ` Sidong Yang
  0 siblings, 1 reply; 41+ messages in thread
From: Daniel Almeida @ 2025-08-10 14:27 UTC (permalink / raw)
  To: Sidong Yang
  Cc: Benno Lossin, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring



> On 10 Aug 2025, at 10:50, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> 
> On Sat, Aug 09, 2025 at 10:22:06PM +0200, Benno Lossin wrote:
>> On Sat Aug 9, 2025 at 2:51 PM CEST, Sidong Yang wrote:
>>> On Sat, Aug 09, 2025 at 12:18:49PM +0200, Benno Lossin wrote:
>>>> We'd need to ensure that `borrow_pdu` can only be called if `store_pdu`
>>>> has been called before. Is there any way we can just ensure that pdu is
>>>> always initialized? Like a callback that's called once, before the value
>>>> is used at all?
>>> 
>>> I've thought about this. As Celab said, returning `&mut MaybeUninit<[u8;32]> is
>>> simple and best. Only driver knows it's initialized. There is no way to
>>> check whether it's initialized with reading the pdu. The best way is to return
>>> `&mut MaybeUninit<[u8;32]>` and driver initializes it in first time. After 
>>> init, driver knows it's guranteed that it's initialized so it could call 
>>> `assume_init_mut()`. And casting to other struct is another problem. The driver
>>> is responsible for determining how to interpret the PDU, whether by using it
>>> directly as a byte array or by performing an unsafe cast to another struct.
>> 
>> But then drivers will have to use `unsafe` & possibly cast the slice to
>> a struct? I think that's bad design since we try to avoid unsafe code in
>> drivers as much as possible. Couldn't we try to ensure from the
>> abstraction side that any time you create such an object, the driver
>> needs to provide the pdu data? Or we could make it implement `Default`
>> and then set it to that before handing it to the driver.
> 
> pdu data is [u8; 32] memory space that driver can borrow. this has two kind of
> issues. The one is that the array is not initialized and another one is it's
> array type that driver should cast it to private data structure unsafely.
> The first one could be resolved with returning `&mut MaybeUninit<>`. And the
> second one, casting issue, is remaining. 
> 
> It seems that we need new unsafe trait like below:
> 
> /// Pdu should be... repr C or transparent, sizeof <= 20
> unsafe trait Pdu: Sized {}
> 
> /// Returning to casted Pdu type T
> pub fn pdu<T: Pdu>(&mut self) -> &mut MaybeUninit<T>

Wait, you receive an uninitialized array, and you’re supposed to cast it to
T, is that correct? Because that does not fit the signature above.

> 
> I think it is like bytemuck::Pod trait. Pod meaning plain old data.
> 
> Thanks,
> Sidong
> 
> 
>> 
>> ---
>> Cheers,
>> Benno


I'm not really sure how this solves the transmute/cast problem. Is the trait
you're referring to supposed to have any member functions? Or is it just a
marker trait?

I wonder if we can fit the existing "kernel::FromBytes" for this problem.

— Daniel


^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-10 14:27                         ` Daniel Almeida
@ 2025-08-10 14:46                           ` Sidong Yang
  2025-08-10 20:06                             ` Benno Lossin
  0 siblings, 1 reply; 41+ messages in thread
From: Sidong Yang @ 2025-08-10 14:46 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Benno Lossin, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Sun, Aug 10, 2025 at 11:27:12AM -0300, Daniel Almeida wrote:
> 
> 
> > On 10 Aug 2025, at 10:50, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> > 
> > On Sat, Aug 09, 2025 at 10:22:06PM +0200, Benno Lossin wrote:
> >> On Sat Aug 9, 2025 at 2:51 PM CEST, Sidong Yang wrote:
> >>> On Sat, Aug 09, 2025 at 12:18:49PM +0200, Benno Lossin wrote:
> >>>> We'd need to ensure that `borrow_pdu` can only be called if `store_pdu`
> >>>> has been called before. Is there any way we can just ensure that pdu is
> >>>> always initialized? Like a callback that's called once, before the value
> >>>> is used at all?
> >>> 
> >>> I've thought about this. As Celab said, returning `&mut MaybeUninit<[u8;32]> is
> >>> simple and best. Only driver knows it's initialized. There is no way to
> >>> check whether it's initialized with reading the pdu. The best way is to return
> >>> `&mut MaybeUninit<[u8;32]>` and driver initializes it in first time. After 
> >>> init, driver knows it's guranteed that it's initialized so it could call 
> >>> `assume_init_mut()`. And casting to other struct is another problem. The driver
> >>> is responsible for determining how to interpret the PDU, whether by using it
> >>> directly as a byte array or by performing an unsafe cast to another struct.
> >> 
> >> But then drivers will have to use `unsafe` & possibly cast the slice to
> >> a struct? I think that's bad design since we try to avoid unsafe code in
> >> drivers as much as possible. Couldn't we try to ensure from the
> >> abstraction side that any time you create such an object, the driver
> >> needs to provide the pdu data? Or we could make it implement `Default`
> >> and then set it to that before handing it to the driver.
> > 
> > pdu data is [u8; 32] memory space that driver can borrow. this has two kind of
> > issues. The one is that the array is not initialized and another one is it's
> > array type that driver should cast it to private data structure unsafely.
> > The first one could be resolved with returning `&mut MaybeUninit<>`. And the
> > second one, casting issue, is remaining. 
> > 
> > It seems that we need new unsafe trait like below:
> > 
> > /// Pdu should be... repr C or transparent, sizeof <= 20
> > unsafe trait Pdu: Sized {}
> > 
> > /// Returning to casted Pdu type T
> > pub fn pdu<T: Pdu>(&mut self) -> &mut MaybeUninit<T>
> 
> Wait, you receive an uninitialized array, and you´re supposed to cast it to
> T, is that correct? Because that does not fit the signature above.

Sorry if my intent wasn´t clear. More example below:

// in rust/kernel/io_uring.rs
unsafe trait Pdu: Sized {}
pub fn pdu<T: Pdu>(&mut self) -> &mut MaybeUninit<T> {
    let inner = unsafe { &mut *self.inner.get() };
    let ptr = &raw mut inner.pdu as *mut MaybeUninit<T>; // the cast here
    unsafe { &mut *ptr }
}

// in driver code
#[repr(C)] struct MyPdu { value: u64 }
unsafe impl Pdu for MyPdu {}

// initialize
ioucmd.pdu().write(MyPdu { value: 1 });

// read or modify
let mypdu = unsafe { ioucmd.pdu().assume_init_mut() };

Thanks,
Sidong
> 
> > 
> > I think it is like bytemuck::Pod trait. Pod meaning plain old data.
> > 
> > Thanks,
> > Sidong
> > 
> > 
> >> 
> >> ---
> >> Cheers,
> >> Benno
> 
> 
> I'm not really sure how this solves the transmute/cast problem. Is the trait
> you're referring to supposed to have any member functions? Or is it just a
> marker trait?
> 
> I wonder if we can fit the existing "kernel::FromBytes" for this problem.
> 
> - Daniel
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-10 14:46                           ` Sidong Yang
@ 2025-08-10 20:06                             ` Benno Lossin
  2025-08-11 12:34                               ` Sidong Yang
  0 siblings, 1 reply; 41+ messages in thread
From: Benno Lossin @ 2025-08-10 20:06 UTC (permalink / raw)
  To: Sidong Yang, Daniel Almeida
  Cc: Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann, Jens Axboe,
	Greg Kroah-Hartman, rust-for-linux, linux-kernel, io-uring

On Sun Aug 10, 2025 at 4:46 PM CEST, Sidong Yang wrote:
> On Sun, Aug 10, 2025 at 11:27:12AM -0300, Daniel Almeida wrote:
>> > On 10 Aug 2025, at 10:50, Sidong Yang <sidong.yang@furiosa.ai> wrote:
>> > 
>> > On Sat, Aug 09, 2025 at 10:22:06PM +0200, Benno Lossin wrote:
>> >> On Sat Aug 9, 2025 at 2:51 PM CEST, Sidong Yang wrote:
>> >>> On Sat, Aug 09, 2025 at 12:18:49PM +0200, Benno Lossin wrote:
>> >>>> We'd need to ensure that `borrow_pdu` can only be called if `store_pdu`
>> >>>> has been called before. Is there any way we can just ensure that pdu is
>> >>>> always initialized? Like a callback that's called once, before the value
>> >>>> is used at all?
>> >>> 
>> >>> I've thought about this. As Celab said, returning `&mut MaybeUninit<[u8;32]> is
>> >>> simple and best. Only driver knows it's initialized. There is no way to
>> >>> check whether it's initialized with reading the pdu. The best way is to return
>> >>> `&mut MaybeUninit<[u8;32]>` and driver initializes it in first time. After 
>> >>> init, driver knows it's guranteed that it's initialized so it could call 
>> >>> `assume_init_mut()`. And casting to other struct is another problem. The driver
>> >>> is responsible for determining how to interpret the PDU, whether by using it
>> >>> directly as a byte array or by performing an unsafe cast to another struct.
>> >> 
>> >> But then drivers will have to use `unsafe` & possibly cast the slice to
>> >> a struct? I think that's bad design since we try to avoid unsafe code in
>> >> drivers as much as possible. Couldn't we try to ensure from the
>> >> abstraction side that any time you create such an object, the driver
>> >> needs to provide the pdu data? Or we could make it implement `Default`
>> >> and then set it to that before handing it to the driver.
>> > 
>> > pdu data is [u8; 32] memory space that driver can borrow. this has two kind of
>> > issues. The one is that the array is not initialized and another one is it's
>> > array type that driver should cast it to private data structure unsafely.
>> > The first one could be resolved with returning `&mut MaybeUninit<>`. And the
>> > second one, casting issue, is remaining. 
>> > 
>> > It seems that we need new unsafe trait like below:
>> > 
>> > /// Pdu should be... repr C or transparent, sizeof <= 20
>> > unsafe trait Pdu: Sized {}
>> > 
>> > /// Returning to casted Pdu type T
>> > pub fn pdu<T: Pdu>(&mut self) -> &mut MaybeUninit<T>
>> 
>> Wait, you receive an uninitialized array, and you´re supposed to cast it to
>> T, is that correct? Because that does not fit the signature above.
>
> Sorry if my intent wasn´t clear. More example below:
>
> // in rust/kernel/io_uring.rs
> unsafe trait Pdu: Sized {}
> pub fn pdu<T: Pdu>(&mut self) -> &mut MaybeUninit<T> {
>     let inner = unsafe { &mut *self.inner.get() };
>     let ptr = &raw mut inner.pdu as *mut MaybeUninit<T>; // the cast here
>     unsafe { &mut *ptr }
> }
>
> // in driver code
> #[repr(C)] struct MyPdu { value: u64 }
> unsafe impl Pdu for MyPdu {}
>
> // initialize
> ioucmd.pdu().write(MyPdu { value: 1 });
>
> // read or modify
> let mypdu = unsafe { ioucmd.pdu().assume_init_mut() };

This is the kind of code I'd like to avoid, since it plans to use
`unsafe` in driver code (the `unsafe impl` above is also a problem, but
we can solve that with a derive macro).

Where are the entrypoints for `IoUringCmd` for driver code? I imagine
that there is some kind of a driver callback (like `probe`, `open` etc)
that contains an `Pin<&mut IoUringCmd>` as an argument, right? When is
it created, can we control that & just write some default value to the
pdu field?

---
Cheers,
Benno

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-10 20:06                             ` Benno Lossin
@ 2025-08-11 12:34                               ` Sidong Yang
  2025-08-11 12:44                                 ` Daniel Almeida
  0 siblings, 1 reply; 41+ messages in thread
From: Sidong Yang @ 2025-08-11 12:34 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Daniel Almeida, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Sun, Aug 10, 2025 at 10:06:21PM +0200, Benno Lossin wrote:
> On Sun Aug 10, 2025 at 4:46 PM CEST, Sidong Yang wrote:
> > On Sun, Aug 10, 2025 at 11:27:12AM -0300, Daniel Almeida wrote:
> >> > On 10 Aug 2025, at 10:50, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> >> > 
> >> > On Sat, Aug 09, 2025 at 10:22:06PM +0200, Benno Lossin wrote:
> >> >> On Sat Aug 9, 2025 at 2:51 PM CEST, Sidong Yang wrote:
> >> >>> On Sat, Aug 09, 2025 at 12:18:49PM +0200, Benno Lossin wrote:
> >> >>>> We'd need to ensure that `borrow_pdu` can only be called if `store_pdu`
> >> >>>> has been called before. Is there any way we can just ensure that pdu is
> >> >>>> always initialized? Like a callback that's called once, before the value
> >> >>>> is used at all?
> >> >>> 
> >> >>> I've thought about this. As Celab said, returning `&mut MaybeUninit<[u8;32]> is
> >> >>> simple and best. Only driver knows it's initialized. There is no way to
> >> >>> check whether it's initialized with reading the pdu. The best way is to return
> >> >>> `&mut MaybeUninit<[u8;32]>` and driver initializes it in first time. After 
> >> >>> init, driver knows it's guranteed that it's initialized so it could call 
> >> >>> `assume_init_mut()`. And casting to other struct is another problem. The driver
> >> >>> is responsible for determining how to interpret the PDU, whether by using it
> >> >>> directly as a byte array or by performing an unsafe cast to another struct.
> >> >> 
> >> >> But then drivers will have to use `unsafe` & possibly cast the slice to
> >> >> a struct? I think that's bad design since we try to avoid unsafe code in
> >> >> drivers as much as possible. Couldn't we try to ensure from the
> >> >> abstraction side that any time you create such an object, the driver
> >> >> needs to provide the pdu data? Or we could make it implement `Default`
> >> >> and then set it to that before handing it to the driver.
> >> > 
> >> > pdu data is [u8; 32] memory space that driver can borrow. this has two kind of
> >> > issues. The one is that the array is not initialized and another one is it's
> >> > array type that driver should cast it to private data structure unsafely.
> >> > The first one could be resolved with returning `&mut MaybeUninit<>`. And the
> >> > second one, casting issue, is remaining. 
> >> > 
> >> > It seems that we need new unsafe trait like below:
> >> > 
> >> > /// Pdu should be... repr C or transparent, sizeof <= 20
> >> > unsafe trait Pdu: Sized {}
> >> > 
> >> > /// Returning to casted Pdu type T
> >> > pub fn pdu<T: Pdu>(&mut self) -> &mut MaybeUninit<T>
> >> 
> >> Wait, you receive an uninitialized array, and you´re supposed to cast it to
> >> T, is that correct? Because that does not fit the signature above.
> >
> > Sorry if my intent wasn´t clear. More example below:
> >
> > // in rust/kernel/io_uring.rs
> > unsafe trait Pdu: Sized {}
> > pub fn pdu<T: Pdu>(&mut self) -> &mut MaybeUninit<T> {
> >     let inner = unsafe { &mut *self.inner.get() };
> >     let ptr = &raw mut inner.pdu as *mut MaybeUninit<T>; // the cast here
> >     unsafe { &mut *ptr }
> > }
> >
> > // in driver code
> > #[repr(C)] struct MyPdu { value: u64 }
> > unsafe impl Pdu for MyPdu {}
> >
> > // initialize
> > ioucmd.pdu().write(MyPdu { value: 1 });
> >
> > // read or modify
> > let mypdu = unsafe { ioucmd.pdu().assume_init_mut() };
> 
> This is the kind of code I'd like to avoid, since it plans to use
> `unsafe` in driver code (the `unsafe impl` above is also a problem, but
> we can solve that with a derive macro).
> 
> Where are the entrypoints for `IoUringCmd` for driver code? I imagine
> that there is some kind of a driver callback (like `probe`, `open` etc)
> that contains an `Pin<&mut IoUringCmd>` as an argument, right? When is
> it created, can we control that & just write some default value to the
> pdu field?

There is `uring_cmd` callback in `file_operation` at c side. `Pin<&mut IoUringCmd>`
would be create in the callback function. But the callback function could be
called repeatedly with same `io_uring_cmd` instance as far as I know.

But in c side, there is initialization step `io_uring_cmd_prep()`.
How about fill zero pdu in `io_uring_cmd_prep()`? And we could assign a byte
as flag in pdu for checking initialized also we should provide 31 bytes except
a byte for the flag.

Thanks,
Sidong
> 
> ---
> Cheers,
> Benno

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-11 12:34                               ` Sidong Yang
@ 2025-08-11 12:44                                 ` Daniel Almeida
  2025-08-11 14:50                                   ` Sidong Yang
  0 siblings, 1 reply; 41+ messages in thread
From: Daniel Almeida @ 2025-08-11 12:44 UTC (permalink / raw)
  To: Sidong Yang
  Cc: Benno Lossin, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring


> 
> There is `uring_cmd` callback in `file_operation` at c side. `Pin<&mut IoUringCmd>`
> would be create in the callback function. But the callback function could be
> called repeatedly with same `io_uring_cmd` instance as far as I know.
> 
> But in c side, there is initialization step `io_uring_cmd_prep()`.
> How about fill zero pdu in `io_uring_cmd_prep()`? And we could assign a byte
> as flag in pdu for checking initialized also we should provide 31 bytes except
> a byte for the flag.
> 

That was a follow-up question of mine. Can’t we enforce zero-initialization
in C to get rid of this MaybeUninit? Uninitialized data is just bad in general.

Hopefully this can be done as you've described above, but I don't want to over
extend my opinion on something I know nothing about.

— Daniel

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-11 12:44                                 ` Daniel Almeida
@ 2025-08-11 14:50                                   ` Sidong Yang
  2025-08-12  8:34                                     ` Benno Lossin
  0 siblings, 1 reply; 41+ messages in thread
From: Sidong Yang @ 2025-08-11 14:50 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Benno Lossin, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Mon, Aug 11, 2025 at 09:44:22AM -0300, Daniel Almeida wrote:
> 
> > 
> > There is `uring_cmd` callback in `file_operation` at c side. `Pin<&mut IoUringCmd>`
> > would be create in the callback function. But the callback function could be
> > called repeatedly with same `io_uring_cmd` instance as far as I know.
> > 
> > But in c side, there is initialization step `io_uring_cmd_prep()`.
> > How about fill zero pdu in `io_uring_cmd_prep()`? And we could assign a byte
> > as flag in pdu for checking initialized also we should provide 31 bytes except
> > a byte for the flag.
> > 
> 
> That was a follow-up question of mine. Can´t we enforce zero-initialization
> in C to get rid of this MaybeUninit? Uninitialized data is just bad in general.
> 
> Hopefully this can be done as you've described above, but I don't want to over
> extend my opinion on something I know nothing about.

I need to add a commit that initialize pdu in prep step in next version. 
I'd like to get a comment from io_uring maintainer Jens. Thanks.

If we could initialize (filling zero) in prep step, How about casting issue?
Driver still needs to cast array to its private struct in unsafe?

Thanks,
Sidong

> 
> - Daniel

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-11 14:50                                   ` Sidong Yang
@ 2025-08-12  8:34                                     ` Benno Lossin
  2025-08-12 12:19                                       ` Sidong Yang
  2025-08-12 14:38                                       ` Daniel Almeida
  0 siblings, 2 replies; 41+ messages in thread
From: Benno Lossin @ 2025-08-12  8:34 UTC (permalink / raw)
  To: Sidong Yang, Daniel Almeida
  Cc: Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann, Jens Axboe,
	Greg Kroah-Hartman, rust-for-linux, linux-kernel, io-uring

On Mon Aug 11, 2025 at 4:50 PM CEST, Sidong Yang wrote:
> On Mon, Aug 11, 2025 at 09:44:22AM -0300, Daniel Almeida wrote:
>> > There is `uring_cmd` callback in `file_operation` at c side. `Pin<&mut IoUringCmd>`
>> > would be create in the callback function. But the callback function could be
>> > called repeatedly with same `io_uring_cmd` instance as far as I know.
>> > 
>> > But in c side, there is initialization step `io_uring_cmd_prep()`.
>> > How about fill zero pdu in `io_uring_cmd_prep()`? And we could assign a byte
>> > as flag in pdu for checking initialized also we should provide 31 bytes except
>> > a byte for the flag.
>> > 
>> 
>> That was a follow-up question of mine. Can´t we enforce zero-initialization
>> in C to get rid of this MaybeUninit? Uninitialized data is just bad in general.
>> 
>> Hopefully this can be done as you've described above, but I don't want to over
>> extend my opinion on something I know nothing about.
>
> I need to add a commit that initialize pdu in prep step in next version. 
> I'd like to get a comment from io_uring maintainer Jens. Thanks.
>
> If we could initialize (filling zero) in prep step, How about casting issue?
> Driver still needs to cast array to its private struct in unsafe?

We still would have the casting issue.

Can't we do the following:

* Add a new associated type to `MiscDevice` called `IoUringPdu` that
  has to implement `Default` and have a size of at most 32 bytes.
* make `IoUringCmd` generic
* make `MiscDevice::uring_cmd` take `Pin<&mut IoUringCmd<Self::IoUringPdu>>`
* initialize the private data to be `IoUringPdu::default()` when we
  create the `IoUringCmd` object.
* provide a `fn pdu(&mut self) -> &mut Pdu` on `IoUringPdu<Pdu>`.

Any thoughts? If we don't want to add a new associated type to
`MiscDevice` (because not everyone has to declare the `IoUringCmd`
data), I have a small trait dance that we can do to avoid that:

    pub trait IoUringMiscDevice: MiscDevice {
        type IoUringPdu: Default; // missing the 32 byte constraint
    }

and then in MiscDevice we still add this function:

        fn uring_cmd(
            _device: <Self::Ptr as ForeignOwnable>::Borrowed<'_>,
            _io_uring_cmd: Pin<&mut IoUringCmd<Self::IoUringPdu>>,
            _issue_flags: u32,
        ) -> Result<i32>
        where
            Self: IoUringMiscDevice,
        {
            build_error!(VTABLE_DEFAULT_ERROR)
        }

It can only be called when the user also implements `IoUringMiscDevice`.

---
Cheers,
Benno

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-12  8:34                                     ` Benno Lossin
@ 2025-08-12 12:19                                       ` Sidong Yang
  2025-08-12 12:43                                         ` Daniel Almeida
  2025-08-12 14:38                                       ` Daniel Almeida
  1 sibling, 1 reply; 41+ messages in thread
From: Sidong Yang @ 2025-08-12 12:19 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Daniel Almeida, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Tue, Aug 12, 2025 at 10:34:56AM +0200, Benno Lossin wrote:
> On Mon Aug 11, 2025 at 4:50 PM CEST, Sidong Yang wrote:
> > On Mon, Aug 11, 2025 at 09:44:22AM -0300, Daniel Almeida wrote:
> >> > There is `uring_cmd` callback in `file_operation` at c side. `Pin<&mut IoUringCmd>`
> >> > would be create in the callback function. But the callback function could be
> >> > called repeatedly with same `io_uring_cmd` instance as far as I know.
> >> > 
> >> > But in c side, there is initialization step `io_uring_cmd_prep()`.
> >> > How about fill zero pdu in `io_uring_cmd_prep()`? And we could assign a byte
> >> > as flag in pdu for checking initialized also we should provide 31 bytes except
> >> > a byte for the flag.
> >> > 
> >> 
> >> That was a follow-up question of mine. Can´t we enforce zero-initialization
> >> in C to get rid of this MaybeUninit? Uninitialized data is just bad in general.
> >> 
> >> Hopefully this can be done as you've described above, but I don't want to over
> >> extend my opinion on something I know nothing about.
> >
> > I need to add a commit that initialize pdu in prep step in next version. 
> > I'd like to get a comment from io_uring maintainer Jens. Thanks.
> >
> > If we could initialize (filling zero) in prep step, How about casting issue?
> > Driver still needs to cast array to its private struct in unsafe?
> 
> We still would have the casting issue.
> 
> Can't we do the following:
> 
> * Add a new associated type to `MiscDevice` called `IoUringPdu` that
>   has to implement `Default` and have a size of at most 32 bytes.
> * make `IoUringCmd` generic
> * make `MiscDevice::uring_cmd` take `Pin<&mut IoUringCmd<Self::IoUringPdu>>`
> * initialize the private data to be `IoUringPdu::default()` when we
>   create the `IoUringCmd` object.

`uring_cmd` could be called multiple times. So we can't initialize
in that time. I don't understand that how can we cast [u8; 32] to
`IoUringPdu` safely. It seems that casting can't help to use unsafe.
I think best way is that just return zerod `&mut [u8; 32]` and
each driver implements safe serde logic for its private data. 

> * provide a `fn pdu(&mut self) -> &mut Pdu` on `IoUringPdu<Pdu>`.
> 
> Any thoughts? If we don't want to add a new associated type to
> `MiscDevice` (because not everyone has to declare the `IoUringCmd`
> data), I have a small trait dance that we can do to avoid that:
> 
>     pub trait IoUringMiscDevice: MiscDevice {
>         type IoUringPdu: Default; // missing the 32 byte constraint
>     }
> 
> and then in MiscDevice we still add this function:
> 
>         fn uring_cmd(
>             _device: <Self::Ptr as ForeignOwnable>::Borrowed<'_>,
>             _io_uring_cmd: Pin<&mut IoUringCmd<Self::IoUringPdu>>,
>             _issue_flags: u32,
>         ) -> Result<i32>
>         where
>             Self: IoUringMiscDevice,
>         {
>             build_error!(VTABLE_DEFAULT_ERROR)
>         }
> 
> It can only be called when the user also implements `IoUringMiscDevice`.
> 
> ---
> Cheers,
> Benno

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-12 12:19                                       ` Sidong Yang
@ 2025-08-12 12:43                                         ` Daniel Almeida
  2025-08-12 13:56                                           ` Sidong Yang
  0 siblings, 1 reply; 41+ messages in thread
From: Daniel Almeida @ 2025-08-12 12:43 UTC (permalink / raw)
  To: Sidong Yang
  Cc: Benno Lossin, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring



> On 12 Aug 2025, at 09:19, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> 
> On Tue, Aug 12, 2025 at 10:34:56AM +0200, Benno Lossin wrote:
>> On Mon Aug 11, 2025 at 4:50 PM CEST, Sidong Yang wrote:
>>> On Mon, Aug 11, 2025 at 09:44:22AM -0300, Daniel Almeida wrote:
>>>>> There is `uring_cmd` callback in `file_operation` at c side. `Pin<&mut IoUringCmd>`
>>>>> would be create in the callback function. But the callback function could be
>>>>> called repeatedly with same `io_uring_cmd` instance as far as I know.
>>>>> 
>>>>> But in c side, there is initialization step `io_uring_cmd_prep()`.
>>>>> How about fill zero pdu in `io_uring_cmd_prep()`? And we could assign a byte
>>>>> as flag in pdu for checking initialized also we should provide 31 bytes except
>>>>> a byte for the flag.
>>>>> 
>>>> 
>>>> That was a follow-up question of mine. Can´t we enforce zero-initialization
>>>> in C to get rid of this MaybeUninit? Uninitialized data is just bad in general.
>>>> 
>>>> Hopefully this can be done as you've described above, but I don't want to over
>>>> extend my opinion on something I know nothing about.
>>> 
>>> I need to add a commit that initialize pdu in prep step in next version. 
>>> I'd like to get a comment from io_uring maintainer Jens. Thanks.
>>> 
>>> If we could initialize (filling zero) in prep step, How about casting issue?
>>> Driver still needs to cast array to its private struct in unsafe?
>> 
>> We still would have the casting issue.
>> 
>> Can't we do the following:
>> 
>> * Add a new associated type to `MiscDevice` called `IoUringPdu` that
>>  has to implement `Default` and have a size of at most 32 bytes.
>> * make `IoUringCmd` generic
>> * make `MiscDevice::uring_cmd` take `Pin<&mut IoUringCmd<Self::IoUringPdu>>`
>> * initialize the private data to be `IoUringPdu::default()` when we
>>  create the `IoUringCmd` object.
> 
> `uring_cmd` could be called multiple times. So we can't initialize
> in that time. I don't understand that how can we cast [u8; 32] to
> `IoUringPdu` safely. It seems that casting can't help to use unsafe.
> I think best way is that just return zerod `&mut [u8; 32]` and
> each driver implements safe serde logic for its private data. 
> 

Again, can’t we use FromBytes for this?



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-12 12:43                                         ` Daniel Almeida
@ 2025-08-12 13:56                                           ` Sidong Yang
  2025-08-12 13:59                                             ` Daniel Almeida
  0 siblings, 1 reply; 41+ messages in thread
From: Sidong Yang @ 2025-08-12 13:56 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Benno Lossin, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Tue, Aug 12, 2025 at 09:43:56AM -0300, Daniel Almeida wrote:
> 
> 
> > On 12 Aug 2025, at 09:19, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> > 
> > On Tue, Aug 12, 2025 at 10:34:56AM +0200, Benno Lossin wrote:
> >> On Mon Aug 11, 2025 at 4:50 PM CEST, Sidong Yang wrote:
> >>> On Mon, Aug 11, 2025 at 09:44:22AM -0300, Daniel Almeida wrote:
> >>>>> There is `uring_cmd` callback in `file_operation` at c side. `Pin<&mut IoUringCmd>`
> >>>>> would be create in the callback function. But the callback function could be
> >>>>> called repeatedly with same `io_uring_cmd` instance as far as I know.
> >>>>> 
> >>>>> But in c side, there is initialization step `io_uring_cmd_prep()`.
> >>>>> How about fill zero pdu in `io_uring_cmd_prep()`? And we could assign a byte
> >>>>> as flag in pdu for checking initialized also we should provide 31 bytes except
> >>>>> a byte for the flag.
> >>>>> 
> >>>> 
> >>>> That was a follow-up question of mine. Can´t we enforce zero-initialization
> >>>> in C to get rid of this MaybeUninit? Uninitialized data is just bad in general.
> >>>> 
> >>>> Hopefully this can be done as you've described above, but I don't want to over
> >>>> extend my opinion on something I know nothing about.
> >>> 
> >>> I need to add a commit that initialize pdu in prep step in next version. 
> >>> I'd like to get a comment from io_uring maintainer Jens. Thanks.
> >>> 
> >>> If we could initialize (filling zero) in prep step, How about casting issue?
> >>> Driver still needs to cast array to its private struct in unsafe?
> >> 
> >> We still would have the casting issue.
> >> 
> >> Can't we do the following:
> >> 
> >> * Add a new associated type to `MiscDevice` called `IoUringPdu` that
> >>  has to implement `Default` and have a size of at most 32 bytes.
> >> * make `IoUringCmd` generic
> >> * make `MiscDevice::uring_cmd` take `Pin<&mut IoUringCmd<Self::IoUringPdu>>`
> >> * initialize the private data to be `IoUringPdu::default()` when we
> >>  create the `IoUringCmd` object.
> > 
> > `uring_cmd` could be called multiple times. So we can't initialize
> > in that time. I don't understand that how can we cast [u8; 32] to
> > `IoUringPdu` safely. It seems that casting can't help to use unsafe.
> > I think best way is that just return zerod `&mut [u8; 32]` and
> > each driver implements safe serde logic for its private data. 
> > 
> 
> Again, can´t we use FromBytes for this?

Agreed, we need FromBytes for read_pdu and AsBytes for write_pdu. I'll reference
dma code for next version.

Thanks,
Sidong
> 
> 

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-12 13:56                                           ` Sidong Yang
@ 2025-08-12 13:59                                             ` Daniel Almeida
  0 siblings, 0 replies; 41+ messages in thread
From: Daniel Almeida @ 2025-08-12 13:59 UTC (permalink / raw)
  To: Sidong Yang
  Cc: Benno Lossin, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring



> On 12 Aug 2025, at 10:56, Sidong Yang <sidong.yang@furiosa.ai> wrote:
> 
> On Tue, Aug 12, 2025 at 09:43:56AM -0300, Daniel Almeida wrote:
>> 
>> 
>>> On 12 Aug 2025, at 09:19, Sidong Yang <sidong.yang@furiosa.ai> wrote:
>>> 
>>> On Tue, Aug 12, 2025 at 10:34:56AM +0200, Benno Lossin wrote:
>>>> On Mon Aug 11, 2025 at 4:50 PM CEST, Sidong Yang wrote:
>>>>> On Mon, Aug 11, 2025 at 09:44:22AM -0300, Daniel Almeida wrote:
>>>>>>> There is `uring_cmd` callback in `file_operation` at c side. `Pin<&mut IoUringCmd>`
>>>>>>> would be create in the callback function. But the callback function could be
>>>>>>> called repeatedly with same `io_uring_cmd` instance as far as I know.
>>>>>>> 
>>>>>>> But in c side, there is initialization step `io_uring_cmd_prep()`.
>>>>>>> How about fill zero pdu in `io_uring_cmd_prep()`? And we could assign a byte
>>>>>>> as flag in pdu for checking initialized also we should provide 31 bytes except
>>>>>>> a byte for the flag.
>>>>>>> 
>>>>>> 
>>>>>> That was a follow-up question of mine. Can´t we enforce zero-initialization
>>>>>> in C to get rid of this MaybeUninit? Uninitialized data is just bad in general.
>>>>>> 
>>>>>> Hopefully this can be done as you've described above, but I don't want to over
>>>>>> extend my opinion on something I know nothing about.
>>>>> 
>>>>> I need to add a commit that initialize pdu in prep step in next version. 
>>>>> I'd like to get a comment from io_uring maintainer Jens. Thanks.
>>>>> 
>>>>> If we could initialize (filling zero) in prep step, How about casting issue?
>>>>> Driver still needs to cast array to its private struct in unsafe?
>>>> 
>>>> We still would have the casting issue.
>>>> 
>>>> Can't we do the following:
>>>> 
>>>> * Add a new associated type to `MiscDevice` called `IoUringPdu` that
>>>> has to implement `Default` and have a size of at most 32 bytes.
>>>> * make `IoUringCmd` generic
>>>> * make `MiscDevice::uring_cmd` take `Pin<&mut IoUringCmd<Self::IoUringPdu>>`
>>>> * initialize the private data to be `IoUringPdu::default()` when we
>>>> create the `IoUringCmd` object.
>>> 
>>> `uring_cmd` could be called multiple times. So we can't initialize
>>> in that time. I don't understand that how can we cast [u8; 32] to
>>> `IoUringPdu` safely. It seems that casting can't help to use unsafe.
>>> I think best way is that just return zerod `&mut [u8; 32]` and

Also, I agree about zeroing out the array, let’s try to not have this
MaybeUninit thing here if possible.

>>> each driver implements safe serde logic for its private data. 
>>> 
>> 
>> Again, can´t we use FromBytes for this?
> 
> Agreed, we need FromBytes for read_pdu and AsBytes for write_pdu. I'll reference
> dma code for next version.
> 
> Thanks,
> Sidong
>> 
>> 



^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-12  8:34                                     ` Benno Lossin
  2025-08-12 12:19                                       ` Sidong Yang
@ 2025-08-12 14:38                                       ` Daniel Almeida
  2025-08-13  0:54                                         ` Sidong Yang
  1 sibling, 1 reply; 41+ messages in thread
From: Daniel Almeida @ 2025-08-12 14:38 UTC (permalink / raw)
  To: Benno Lossin
  Cc: Sidong Yang, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring



> On 12 Aug 2025, at 05:34, Benno Lossin <lossin@kernel.org> wrote:
> 
> On Mon Aug 11, 2025 at 4:50 PM CEST, Sidong Yang wrote:
>> On Mon, Aug 11, 2025 at 09:44:22AM -0300, Daniel Almeida wrote:
>>>> There is `uring_cmd` callback in `file_operation` at c side. `Pin<&mut IoUringCmd>`
>>>> would be create in the callback function. But the callback function could be
>>>> called repeatedly with same `io_uring_cmd` instance as far as I know.
>>>> 
>>>> But in c side, there is initialization step `io_uring_cmd_prep()`.
>>>> How about fill zero pdu in `io_uring_cmd_prep()`? And we could assign a byte
>>>> as flag in pdu for checking initialized also we should provide 31 bytes except
>>>> a byte for the flag.
>>>> 
>>> 
>>> That was a follow-up question of mine. Can´t we enforce zero-initialization
>>> in C to get rid of this MaybeUninit? Uninitialized data is just bad in general.
>>> 
>>> Hopefully this can be done as you've described above, but I don't want to over
>>> extend my opinion on something I know nothing about.
>> 
>> I need to add a commit that initialize pdu in prep step in next version. 
>> I'd like to get a comment from io_uring maintainer Jens. Thanks.
>> 
>> If we could initialize (filling zero) in prep step, How about casting issue?
>> Driver still needs to cast array to its private struct in unsafe?
> 
> We still would have the casting issue.
> 
> Can't we do the following:
> 
> * Add a new associated type to `MiscDevice` called `IoUringPdu` that
>  has to implement `Default` and have a size of at most 32 bytes.
> * make `IoUringCmd` generic
> * make `MiscDevice::uring_cmd` take `Pin<&mut IoUringCmd<Self::IoUringPdu>>`
> * initialize the private data to be `IoUringPdu::default()` when we
>  create the `IoUringCmd` object.
> * provide a `fn pdu(&mut self) -> &mut Pdu` on `IoUringPdu<Pdu>`.
> 
> Any thoughts? If we don't want to add a new associated type to
> `MiscDevice` (because not everyone has to declare the `IoUringCmd`
> data), I have a small trait dance that we can do to avoid that:


Benno,

IIUC, and note that I'm not proficient with io_uring in general:

I think we have to accept that we will need to parse types from and to byte
arrays, and that is inherently unsafe. It is no different from what is going on
in UserSliceReader/UserSliceWriter, and IMHO, we should copy that in as much as
it makes sense.

I think that the only difference is that all uAPI types de-facto satisfy all
the requirements for FromBytes/AsBytes, as we've discussed previously, whereas
here, drivers have to prove that their types can implement the trait.


By the way, Sidong, is this byte array shared with userspace? i.e.: is there
any copy_to/from_user() taking place here?

-- Daniel

^ permalink raw reply	[flat|nested] 41+ messages in thread

* Re: [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
  2025-08-12 14:38                                       ` Daniel Almeida
@ 2025-08-13  0:54                                         ` Sidong Yang
  0 siblings, 0 replies; 41+ messages in thread
From: Sidong Yang @ 2025-08-13  0:54 UTC (permalink / raw)
  To: Daniel Almeida
  Cc: Benno Lossin, Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann,
	Jens Axboe, Greg Kroah-Hartman, rust-for-linux, linux-kernel,
	io-uring

On Tue, Aug 12, 2025 at 11:38:51AM -0300, Daniel Almeida wrote:
> 
> 
> > On 12 Aug 2025, at 05:34, Benno Lossin <lossin@kernel.org> wrote:
> > 
> > On Mon Aug 11, 2025 at 4:50 PM CEST, Sidong Yang wrote:
> >> On Mon, Aug 11, 2025 at 09:44:22AM -0300, Daniel Almeida wrote:
> >>>> There is `uring_cmd` callback in `file_operation` at c side. `Pin<&mut IoUringCmd>`
> >>>> would be create in the callback function. But the callback function could be
> >>>> called repeatedly with same `io_uring_cmd` instance as far as I know.
> >>>> 
> >>>> But in c side, there is initialization step `io_uring_cmd_prep()`.
> >>>> How about fill zero pdu in `io_uring_cmd_prep()`? And we could assign a byte
> >>>> as flag in pdu for checking initialized also we should provide 31 bytes except
> >>>> a byte for the flag.
> >>>> 
> >>> 
> >>> That was a follow-up question of mine. Can´t we enforce zero-initialization
> >>> in C to get rid of this MaybeUninit? Uninitialized data is just bad in general.
> >>> 
> >>> Hopefully this can be done as you've described above, but I don't want to over
> >>> extend my opinion on something I know nothing about.
> >> 
> >> I need to add a commit that initialize pdu in prep step in next version. 
> >> I'd like to get a comment from io_uring maintainer Jens. Thanks.
> >> 
> >> If we could initialize (filling zero) in prep step, How about casting issue?
> >> Driver still needs to cast array to its private struct in unsafe?
> > 
> > We still would have the casting issue.
> > 
> > Can't we do the following:
> > 
> > * Add a new associated type to `MiscDevice` called `IoUringPdu` that
> >  has to implement `Default` and have a size of at most 32 bytes.
> > * make `IoUringCmd` generic
> > * make `MiscDevice::uring_cmd` take `Pin<&mut IoUringCmd<Self::IoUringPdu>>`
> > * initialize the private data to be `IoUringPdu::default()` when we
> >  create the `IoUringCmd` object.
> > * provide a `fn pdu(&mut self) -> &mut Pdu` on `IoUringPdu<Pdu>`.
> > 
> > Any thoughts? If we don't want to add a new associated type to
> > `MiscDevice` (because not everyone has to declare the `IoUringCmd`
> > data), I have a small trait dance that we can do to avoid that:
> 
> 
> Benno,
> 
> IIUC, and note that I'm not proficient with io_uring in general:
> 
> I think we have to accept that we will need to parse types from and to byte
> arrays, and that is inherently unsafe. It is no different from what is going on
> in UserSliceReader/UserSliceWriter, and IMHO, we should copy that in as much as
> it makes sense.
> 
> I think that the only difference is that all uAPI types de-facto satisfy all
> the requirements for FromBytes/AsBytes, as we've discussed previously, whereas
> here, drivers have to prove that their types can implement the trait.
> 
> 
> By the way, Sidong, is this byte array shared with userspace? i.e.: is there
> any copy_to/from_user() taking place here?

No. pdu array allocated from kernel. I'll use `core::ptr::copy_nonoverlapping`.

Thanks,
Sidong
> 
> -- Daniel

^ permalink raw reply	[flat|nested] 41+ messages in thread

end of thread, other threads:[~2025-08-13  0:54 UTC | newest]

Thread overview: 41+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-27 15:03 [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
2025-07-27 15:03 ` [RFC PATCH v2 1/4] rust: bindings: add io_uring headers in bindings_helper.h Sidong Yang
2025-07-27 15:03 ` [RFC PATCH v2 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd Sidong Yang
2025-08-01 13:48   ` Daniel Almeida
2025-08-02 10:52     ` Benno Lossin
2025-08-06 12:38       ` Daniel Almeida
2025-08-06 13:38         ` Benno Lossin
2025-08-08  6:56           ` Sidong Yang
2025-08-08  8:49             ` Benno Lossin
2025-08-08  9:43               ` Sidong Yang
2025-08-09 10:18                 ` Benno Lossin
2025-08-09 12:51                   ` Sidong Yang
2025-08-09 20:22                     ` Benno Lossin
2025-08-10 13:50                       ` Sidong Yang
2025-08-10 14:27                         ` Daniel Almeida
2025-08-10 14:46                           ` Sidong Yang
2025-08-10 20:06                             ` Benno Lossin
2025-08-11 12:34                               ` Sidong Yang
2025-08-11 12:44                                 ` Daniel Almeida
2025-08-11 14:50                                   ` Sidong Yang
2025-08-12  8:34                                     ` Benno Lossin
2025-08-12 12:19                                       ` Sidong Yang
2025-08-12 12:43                                         ` Daniel Almeida
2025-08-12 13:56                                           ` Sidong Yang
2025-08-12 13:59                                             ` Daniel Almeida
2025-08-12 14:38                                       ` Daniel Almeida
2025-08-13  0:54                                         ` Sidong Yang
2025-08-08 13:55             ` Caleb Sander Mateos
2025-08-09 12:53               ` Sidong Yang
2025-08-05  3:39     ` Sidong Yang
2025-08-05 13:02       ` Daniel Almeida
2025-08-06  9:11         ` Sidong Yang
2025-07-27 15:03 ` [RFC PATCH v2 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait Sidong Yang
2025-08-01 14:04   ` Daniel Almeida
2025-08-07  7:46     ` Sidong Yang
2025-07-27 15:03 ` [RFC PATCH v2 4/4] samples: rust: rust_misc_device: add uring_cmd example Sidong Yang
2025-08-01 14:11   ` Daniel Almeida
2025-08-07  6:30     ` Sidong Yang
2025-07-27 17:17 ` [RFC PATCH v2 0/4] rust: miscdevice: abstraction for uring-cmd Daniel Almeida
2025-08-01 14:13 ` Daniel Almeida
2025-08-07  6:17   ` Sidong Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox