* [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd
@ 2025-07-19 14:33 Sidong Yang
2025-07-19 14:33 ` [PATCH 1/4] rust: bindings: add io_uring headers in bindings_helper.h Sidong Yang
` (6 more replies)
0 siblings, 7 replies; 30+ messages in thread
From: Sidong Yang @ 2025-07-19 14:33 UTC (permalink / raw)
To: Miguel Ojeda, Arnd Bergmann, Jens Axboe
Cc: 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.
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 | 114 +++++++++++++++++++++++++++++++
rust/kernel/lib.rs | 1 +
rust/kernel/miscdevice.rs | 34 +++++++++
samples/rust/rust_misc_device.rs | 30 ++++++++
5 files changed, 181 insertions(+)
create mode 100644 rust/kernel/io_uring.rs
--
2.43.0
^ permalink raw reply [flat|nested] 30+ messages in thread
* [PATCH 1/4] rust: bindings: add io_uring headers in bindings_helper.h
2025-07-19 14:33 [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
@ 2025-07-19 14:33 ` Sidong Yang
2025-07-20 12:29 ` kernel test robot
2025-07-19 14:33 ` [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd Sidong Yang
` (5 subsequent siblings)
6 siblings, 1 reply; 30+ messages in thread
From: Sidong Yang @ 2025-07-19 14:33 UTC (permalink / raw)
To: Miguel Ojeda, Arnd Bergmann, Jens Axboe
Cc: 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] 30+ messages in thread
* [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
2025-07-19 14:33 [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
2025-07-19 14:33 ` [PATCH 1/4] rust: bindings: add io_uring headers in bindings_helper.h Sidong Yang
@ 2025-07-19 14:33 ` Sidong Yang
2025-07-20 19:10 ` Caleb Sander Mateos
2025-07-19 14:33 ` [PATCH 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait Sidong Yang
` (4 subsequent siblings)
6 siblings, 1 reply; 30+ messages in thread
From: Sidong Yang @ 2025-07-19 14:33 UTC (permalink / raw)
To: Miguel Ojeda, Arnd Bergmann, Jens Axboe
Cc: 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 | 114 ++++++++++++++++++++++++++++++++++++++++
rust/kernel/lib.rs | 1 +
2 files changed, 115 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..7843effbedb4
--- /dev/null
+++ b/rust/kernel/io_uring.rs
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2025 Furiosa AI.
+
+//! Files and file descriptors.
+//!
+//! C headers: [`include/linux/io_uring/cmd.h`](srctree/include/linux/io_uring/cmd.h) and
+//! [`include/linux/file.h`](srctree/include/linux/file.h)
+
+use core::mem::MaybeUninit;
+
+use crate::{fs::File, types::Opaque};
+
+pub mod flags {
+ pub const COMPLETE_DEFER: i32 = bindings::io_uring_cmd_flags_IO_URING_F_COMPLETE_DEFER;
+ pub const UNLOCKED: i32 = bindings::io_uring_cmd_flags_IO_URING_F_UNLOCKED;
+
+ pub const MULTISHOT: i32 = bindings::io_uring_cmd_flags_IO_URING_F_MULTISHOT;
+ pub const IOWQ: i32 = bindings::io_uring_cmd_flags_IO_URING_F_IOWQ;
+ pub const NONBLOCK: i32 = bindings::io_uring_cmd_flags_IO_URING_F_NONBLOCK;
+
+ pub const SQE128: i32 = bindings::io_uring_cmd_flags_IO_URING_F_SQE128;
+ pub const CQE32: i32 = bindings::io_uring_cmd_flags_IO_URING_F_CQE32;
+ pub const IOPOLL: i32 = bindings::io_uring_cmd_flags_IO_URING_F_IOPOLL;
+
+ pub const CANCEL: i32 = bindings::io_uring_cmd_flags_IO_URING_F_CANCEL;
+ pub const COMPAT: i32 = bindings::io_uring_cmd_flags_IO_URING_F_COMPAT;
+ pub const TASK_DEAD: i32 = bindings::io_uring_cmd_flags_IO_URING_F_TASK_DEAD;
+}
+
+#[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 the pointer 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 the pointer is not dangling and stays valid
+ unsafe { (*self.inner.get()).flags }
+ }
+
+ /// Returns the ref pdu for free use.
+ #[inline]
+ pub fn pdu(&mut self) -> MaybeUninit<&mut [u8; 32]> {
+ // SAFETY: The call guarantees that the pointer is not dangling and stays valid
+ unsafe { MaybeUninit::new(&mut (*self.inner.get()).pdu) }
+ }
+
+ /// Constructs a new `struct io_uring_cmd` wrapper from a file descriptor.
+ #[inline]
+ pub unsafe fn from_raw<'a>(ptr: *const bindings::io_uring_cmd) -> &'a IoUringCmd {
+ // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
+ // duration of 'a. The cast is okay because `File` is `repr(transparent)`.
+ unsafe { &*ptr.cast() }
+ }
+
+ // Returns the file that referenced by uring cmd self.
+ #[inline]
+ pub fn file<'a>(&'a self) -> &'a File {
+ // SAFETY: The call guarantees that the pointer is not dangling and stays valid
+ let file = unsafe { (*self.inner.get()).file };
+ unsafe { File::from_raw_file(file) }
+ }
+
+ // Returns the sqe that referenced by uring cmd self.
+ #[inline]
+ pub fn sqe(&self) -> &IoUringSqe {
+ // SAFETY: The call guarantees that the pointer is not dangling and stays valid
+ let ptr = unsafe { (*self.inner.get()).sqe };
+ unsafe { IoUringSqe::from_raw(ptr) }
+ }
+
+ // Called by consumers of io_uring_cmd, if they originally returned -EIOCBQUEUED upon receiving the command
+ #[inline]
+ pub fn done(self, ret: isize, res2: u64, issue_flags: u32) {
+ // SAFETY: The call guarantees that the pointer is not dangling and stays valid
+ unsafe {
+ bindings::io_uring_cmd_done(self.inner.get(), ret, res2, issue_flags);
+ }
+ }
+}
+
+#[repr(transparent)]
+pub struct IoUringSqe {
+ inner: Opaque<bindings::io_uring_sqe>,
+}
+
+impl<'a> IoUringSqe {
+ pub fn cmd_data(&'a self) -> &'a [Opaque<u8>] {
+ // SAFETY: The call guarantees that the pointer is not dangling and stays valid
+ unsafe {
+ let cmd = (*self.inner.get()).__bindgen_anon_6.cmd.as_ref();
+ core::slice::from_raw_parts(cmd.as_ptr() as *const Opaque<u8>, 8)
+ }
+ }
+
+ #[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 `File` is `repr(transparent)`.
+ //
+ // INVARIANT: The caller guarantees that there are no problematic `fdget_pos` calls.
+ 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] 30+ messages in thread
* [PATCH 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait
2025-07-19 14:33 [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
2025-07-19 14:33 ` [PATCH 1/4] rust: bindings: add io_uring headers in bindings_helper.h Sidong Yang
2025-07-19 14:33 ` [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd Sidong Yang
@ 2025-07-19 14:33 ` Sidong Yang
2025-07-20 19:38 ` kernel test robot
2025-07-20 20:08 ` Caleb Sander Mateos
2025-07-19 14:33 ` [PATCH 4/4] samples: rust: rust_misc_device: add uring_cmd example Sidong Yang
` (3 subsequent siblings)
6 siblings, 2 replies; 30+ messages in thread
From: Sidong Yang @ 2025-07-19 14:33 UTC (permalink / raw)
To: Miguel Ojeda, Arnd Bergmann, Jens Axboe
Cc: 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 | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
index 288f40e79906..5255faf27934 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,15 @@ fn show_fdinfo(
) {
build_error!(VTABLE_DEFAULT_ERROR)
}
+
+ fn uring_cmd(
+ _device: <Self::Ptr as ForeignOwnable>::Borrowed<'_>,
+ _file: &File,
+ _io_uring_cmd: &IoUringCmd,
+ issue_flags: u32,
+ ) -> Result<isize> {
+ build_error!(VTABLE_DEFAULT_ERROR)
+ }
}
/// A vtable for the file operations of a Rust miscdevice.
@@ -332,6 +342,25 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
T::show_fdinfo(device, m, file);
}
+ 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: Ioctl calls can borrow the private data of the file.
+ let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
+
+ match T::uring_cmd(device, file, 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 +383,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] 30+ messages in thread
* [PATCH 4/4] samples: rust: rust_misc_device: add uring_cmd example
2025-07-19 14:33 [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
` (2 preceding siblings ...)
2025-07-19 14:33 ` [PATCH 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait Sidong Yang
@ 2025-07-19 14:33 ` Sidong Yang
2025-07-20 20:21 ` Caleb Sander Mateos
2025-07-19 15:00 ` [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd Nikita Krasnov
` (2 subsequent siblings)
6 siblings, 1 reply; 30+ messages in thread
From: Sidong Yang @ 2025-07-19 14:33 UTC (permalink / raw)
To: Miguel Ojeda, Arnd Bergmann, Jens Axboe
Cc: 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 | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs
index c881fd6dbd08..cd0e578231d2 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 = 0x83;
+const RUST_MISC_DEV_URING_CMD_GET_VALUE: u32 = 0x84;
+
module! {
type: RustMiscDeviceModule,
name: "rust_misc_device",
@@ -190,6 +194,32 @@ fn ioctl(me: Pin<&RustMiscDevice>, _file: &File, cmd: u32, arg: usize) -> Result
Ok(0)
}
+
+ fn uring_cmd(
+ me: Pin<&RustMiscDevice>,
+ _file: &File,
+ io_uring_cmd: &IoUringCmd,
+ _issue_flags: u32,
+ ) -> Result<isize> {
+ 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;
+ let addr = unsafe { *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] 30+ messages in thread
* Re: [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd
2025-07-19 14:33 [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
` (3 preceding siblings ...)
2025-07-19 14:33 ` [PATCH 4/4] samples: rust: rust_misc_device: add uring_cmd example Sidong Yang
@ 2025-07-19 15:00 ` Nikita Krasnov
2025-07-19 16:33 ` Nikita Krasnov
2025-07-19 16:34 ` Miguel Ojeda
2025-07-19 17:03 ` Danilo Krummrich
6 siblings, 1 reply; 30+ messages in thread
From: Nikita Krasnov @ 2025-07-19 15:00 UTC (permalink / raw)
To: Sidong Yang, Miguel Ojeda, Arnd Bergmann, Jens Axboe
Cc: rust-for-linux, linux-kernel, io-uring
[-- Attachment #1.1: Type: text/plain, Size: 1034 bytes --]
On Sat, Jul 19, 2025 at 05:33:54PM +0300 Sidong Yang 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.
>
> 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 | 114 +++++++++++++++++++++++++++++++
> rust/kernel/lib.rs | 1 +
> rust/kernel/miscdevice.rs | 34 +++++++++
> samples/rust/rust_misc_device.rs | 30 ++++++++
> 5 files changed, 181 insertions(+)
> create mode 100644 rust/kernel/io_uring.rs
>
Is it just me or did the [PATCH 2/4] get lost? I only see
[RFC PATCH 0/4], [PATCH 1/4], [PATCH 3/4] and [PATCH 4/4].
--
Nikita Krasnov
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd
2025-07-19 15:00 ` [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd Nikita Krasnov
@ 2025-07-19 16:33 ` Nikita Krasnov
0 siblings, 0 replies; 30+ messages in thread
From: Nikita Krasnov @ 2025-07-19 16:33 UTC (permalink / raw)
To: Sidong Yang, Miguel Ojeda, Arnd Bergmann, Jens Axboe
Cc: rust-for-linux, linux-kernel, io-uring
[-- Attachment #1.1: Type: text/plain, Size: 1169 bytes --]
On Sat, Jul 19, 2025 at 06:00:18PM +0300 Nikita Krasnov wrote:
> On Sat, Jul 19, 2025 at 05:33:54PM +0300 Sidong Yang 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.
>>
>> 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 | 114 +++++++++++++++++++++++++++++++
>> rust/kernel/lib.rs | 1 +
>> rust/kernel/miscdevice.rs | 34 +++++++++
>> samples/rust/rust_misc_device.rs | 30 ++++++++
>> 5 files changed, 181 insertions(+)
>> create mode 100644 rust/kernel/io_uring.rs
>>
>
> Is it just me or did the [PATCH 2/4] get lost? I only see
> [RFC PATCH 0/4], [PATCH 1/4], [PATCH 3/4] and [PATCH 4/4].
Never mind, there it is. Sorry for noise.
--
Nikita Krasnov
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 840 bytes --]
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd
2025-07-19 14:33 [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
` (4 preceding siblings ...)
2025-07-19 15:00 ` [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd Nikita Krasnov
@ 2025-07-19 16:34 ` Miguel Ojeda
2025-07-20 16:07 ` Sidong Yang
2025-07-19 17:03 ` Danilo Krummrich
6 siblings, 1 reply; 30+ messages in thread
From: Miguel Ojeda @ 2025-07-19 16:34 UTC (permalink / raw)
To: Sidong Yang
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring
On Sat, Jul 19, 2025 at 4:34 PM 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.
Who will be using these?
Thanks!
Cheers,
Miguel
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd
2025-07-19 14:33 [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
` (5 preceding siblings ...)
2025-07-19 16:34 ` Miguel Ojeda
@ 2025-07-19 17:03 ` Danilo Krummrich
2025-07-20 16:11 ` Sidong Yang
6 siblings, 1 reply; 30+ messages in thread
From: Danilo Krummrich @ 2025-07-19 17:03 UTC (permalink / raw)
To: Sidong Yang
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring, Greg Kroah-Hartman
Hi Sidong,
On 7/19/25 4:33 PM, Sidong Yang 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.
Please also add Greg, maybe get_maintainer.pl does not list him, since the
entries for miscdevice were missing for a while I think.
For new abstractions I also recommend to Cc the RUST reviewers.
Thanks,
Danilo
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 1/4] rust: bindings: add io_uring headers in bindings_helper.h
2025-07-19 14:33 ` [PATCH 1/4] rust: bindings: add io_uring headers in bindings_helper.h Sidong Yang
@ 2025-07-20 12:29 ` kernel test robot
0 siblings, 0 replies; 30+ messages in thread
From: kernel test robot @ 2025-07-20 12:29 UTC (permalink / raw)
To: Sidong Yang, Miguel Ojeda, Arnd Bergmann, Jens Axboe
Cc: llvm, oe-kbuild-all, rust-for-linux, linux-kernel, io-uring,
Sidong Yang
Hi Sidong,
kernel test robot noticed the following build warnings:
[auto build test WARNING on rust/rust-next]
[also build test WARNING on char-misc/char-misc-testing char-misc/char-misc-next char-misc/char-misc-linus soc/for-next linus/master v6.16-rc6 next-20250718]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Sidong-Yang/rust-bindings-add-io_uring-headers-in-bindings_helper-h/20250719-223630
base: https://github.com/Rust-for-Linux/linux rust-next
patch link: https://lore.kernel.org/r/20250719143358.22363-2-sidong.yang%40furiosa.ai
patch subject: [PATCH 1/4] rust: bindings: add io_uring headers in bindings_helper.h
config: x86_64-rhel-9.4-rust (https://download.01.org/0day-ci/archive/20250720/202507202006.8ZnBwBsW-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
rustc: rustc 1.88.0 (6b00bc388 2025-06-23)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250720/202507202006.8ZnBwBsW-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507202006.8ZnBwBsW-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> warning: `extern` fn uses type `io_tw_state`, which is not FFI-safe
--> rust/bindings/bindings_generated.rs:109725:28
|
109725 | ::core::option::Option<unsafe extern "C" fn(req: *mut io_kiocb, tw: io_tw_token_t)>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
|
= help: consider adding a member to this struct
= note: this struct has no fields
note: the type is defined here
--> rust/bindings/bindings_generated.rs:109642:1
|
109642 | pub struct io_tw_state {}
| ^^^^^^^^^^^^^^^^^^^^^^
= note: `#[warn(improper_ctypes_definitions)]` on by default
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd
2025-07-19 16:34 ` Miguel Ojeda
@ 2025-07-20 16:07 ` Sidong Yang
2025-07-20 16:41 ` Miguel Ojeda
0 siblings, 1 reply; 30+ messages in thread
From: Sidong Yang @ 2025-07-20 16:07 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Greg Kroah-Hartman
On Sat, Jul 19, 2025 at 06:34:49PM +0200, Miguel Ojeda wrote:
> On Sat, Jul 19, 2025 at 4:34 PM 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.
>
> Who will be using these?
Hi, Miguel
Although some existing kernel modules already use uring_cmd, they aren’t
implemented in Rust. Currently, no Rust code leverages this abstraction,
but it will enable anyone who wants to write kernel drivers in Rust using
uring_cmd.
Thanks,
Sidong
>
> Thanks!
>
> Cheers,
> Miguel
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd
2025-07-19 17:03 ` Danilo Krummrich
@ 2025-07-20 16:11 ` Sidong Yang
0 siblings, 0 replies; 30+ messages in thread
From: Sidong Yang @ 2025-07-20 16:11 UTC (permalink / raw)
To: Danilo Krummrich
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring, Greg Kroah-Hartman, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross
On Sat, Jul 19, 2025 at 07:03:24PM +0200, Danilo Krummrich wrote:
> Hi Sidong,
>
> On 7/19/25 4:33 PM, Sidong Yang 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.
>
> Please also add Greg, maybe get_maintainer.pl does not list him, since the
> entries for miscdevice were missing for a while I think.
>
> For new abstractions I also recommend to Cc the RUST reviewers.
Thanks for a advice. I've added Greg, and other RUST reviewers to Cc.
Thanks,
Sidong
>
> Thanks,
> Danilo
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd
2025-07-20 16:07 ` Sidong Yang
@ 2025-07-20 16:41 ` Miguel Ojeda
2025-07-20 16:52 ` Sidong Yang
0 siblings, 1 reply; 30+ messages in thread
From: Miguel Ojeda @ 2025-07-20 16:41 UTC (permalink / raw)
To: Sidong Yang
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Greg Kroah-Hartman
On Sun, Jul 20, 2025 at 6:07 PM Sidong Yang <sidong.yang@furiosa.ai> wrote:
>
> Although some existing kernel modules already use uring_cmd, they aren’t
> implemented in Rust. Currently, no Rust code leverages this abstraction,
> but it will enable anyone who wants to write kernel drivers in Rust using
> uring_cmd.
Do you have a concrete user in mind?
i.e. I am asking because the kernel, in general, requires a user (in
mainline) for code to be merged. So maintainers normally don't merge
code unless it is clear who will use a feature upstream -- please see
the last bullet of:
https://rust-for-linux.com/contributing#submitting-new-abstractions-and-modules
Thanks!
Cheers,
Miguel
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd
2025-07-20 16:41 ` Miguel Ojeda
@ 2025-07-20 16:52 ` Sidong Yang
2025-07-20 17:00 ` Miguel Ojeda
0 siblings, 1 reply; 30+ messages in thread
From: Sidong Yang @ 2025-07-20 16:52 UTC (permalink / raw)
To: Miguel Ojeda
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Greg Kroah-Hartman
On Sun, Jul 20, 2025 at 06:41:06PM +0200, Miguel Ojeda wrote:
> On Sun, Jul 20, 2025 at 6:07 PM Sidong Yang <sidong.yang@furiosa.ai> wrote:
> >
> > Although some existing kernel modules already use uring_cmd, they aren’t
> > implemented in Rust. Currently, no Rust code leverages this abstraction,
> > but it will enable anyone who wants to write kernel drivers in Rust using
> > uring_cmd.
>
> Do you have a concrete user in mind?
Sadly, there isn’t a concrete user yet. I understand that an abstraction by itself
won’t be merged without a real in-tree user.
I’ll identify a suitable kernel module to port to Rust and follow up once I have one.
Thanks,
Sidong
>
> i.e. I am asking because the kernel, in general, requires a user (in
> mainline) for code to be merged. So maintainers normally don't merge
> code unless it is clear who will use a feature upstream -- please see
> the last bullet of:
>
> https://rust-for-linux.com/contributing#submitting-new-abstractions-and-modules
>
> Thanks!
>
> Cheers,
> Miguel
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd
2025-07-20 16:52 ` Sidong Yang
@ 2025-07-20 17:00 ` Miguel Ojeda
0 siblings, 0 replies; 30+ messages in thread
From: Miguel Ojeda @ 2025-07-20 17:00 UTC (permalink / raw)
To: Sidong Yang
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring, Boqun Feng, Gary Guo,
Björn Roy Baron, Benno Lossin, Andreas Hindborg, Alice Ryhl,
Trevor Gross, Danilo Krummrich, Greg Kroah-Hartman
On Sun, Jul 20, 2025 at 6:52 PM Sidong Yang <sidong.yang@furiosa.ai> wrote:
>
> Sadly, there isn’t a concrete user yet. I understand that an abstraction by itself
> won’t be merged without a real in-tree user.
> I’ll identify a suitable kernel module to port to Rust and follow up once I have one.
Sounds good, thanks!
(Just in case: maintainers may or may not want to have an equivalent
Rust module for a C one, it is up to them. In that case,
https://rust-for-linux.com/rust-reference-drivers may help.).
Cheers,
Miguel
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
2025-07-19 14:33 ` [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd Sidong Yang
@ 2025-07-20 19:10 ` Caleb Sander Mateos
2025-07-21 5:22 ` Sidong Yang
0 siblings, 1 reply; 30+ messages in thread
From: Caleb Sander Mateos @ 2025-07-20 19:10 UTC (permalink / raw)
To: Sidong Yang
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring
On Sat, Jul 19, 2025 at 10:34 AM 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.
>
> Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> ---
> rust/kernel/io_uring.rs | 114 ++++++++++++++++++++++++++++++++++++++++
> rust/kernel/lib.rs | 1 +
> 2 files changed, 115 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..7843effbedb4
> --- /dev/null
> +++ b/rust/kernel/io_uring.rs
> @@ -0,0 +1,114 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +// Copyright (C) 2025 Furiosa AI.
> +
> +//! Files and file descriptors.
> +//!
> +//! C headers: [`include/linux/io_uring/cmd.h`](srctree/include/linux/io_uring/cmd.h) and
> +//! [`include/linux/file.h`](srctree/include/linux/file.h)
> +
> +use core::mem::MaybeUninit;
> +
> +use crate::{fs::File, types::Opaque};
> +
> +pub mod flags {
> + pub const COMPLETE_DEFER: i32 = bindings::io_uring_cmd_flags_IO_URING_F_COMPLETE_DEFER;
> + pub const UNLOCKED: i32 = bindings::io_uring_cmd_flags_IO_URING_F_UNLOCKED;
> +
> + pub const MULTISHOT: i32 = bindings::io_uring_cmd_flags_IO_URING_F_MULTISHOT;
> + pub const IOWQ: i32 = bindings::io_uring_cmd_flags_IO_URING_F_IOWQ;
> + pub const NONBLOCK: i32 = bindings::io_uring_cmd_flags_IO_URING_F_NONBLOCK;
> +
> + pub const SQE128: i32 = bindings::io_uring_cmd_flags_IO_URING_F_SQE128;
> + pub const CQE32: i32 = bindings::io_uring_cmd_flags_IO_URING_F_CQE32;
> + pub const IOPOLL: i32 = bindings::io_uring_cmd_flags_IO_URING_F_IOPOLL;
> +
> + pub const CANCEL: i32 = bindings::io_uring_cmd_flags_IO_URING_F_CANCEL;
> + pub const COMPAT: i32 = bindings::io_uring_cmd_flags_IO_URING_F_COMPAT;
> + pub const TASK_DEAD: i32 = bindings::io_uring_cmd_flags_IO_URING_F_TASK_DEAD;
> +}
> +
> +#[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 the pointer 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 the pointer is not dangling and stays valid
> + unsafe { (*self.inner.get()).flags }
> + }
> +
> + /// Returns the ref pdu for free use.
> + #[inline]
> + pub fn pdu(&mut self) -> MaybeUninit<&mut [u8; 32]> {
Should be &mut MaybeUninit, right? It's the bytes that may be
uninitialized, not the reference.
> + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> + unsafe { MaybeUninit::new(&mut (*self.inner.get()).pdu) }
> + }
> +
> + /// Constructs a new `struct io_uring_cmd` wrapper from a file descriptor.
Why "from a file descriptor"?
Also, missing a comment documenting the safety preconditions?
> + #[inline]
> + pub unsafe fn from_raw<'a>(ptr: *const bindings::io_uring_cmd) -> &'a IoUringCmd {
Could take NonNull instead of a raw pointer.
> + // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
> + // duration of 'a. The cast is okay because `File` is `repr(transparent)`.
"File" -> "IoUringCmd"?
> + unsafe { &*ptr.cast() }
> + }
> +
> + // Returns the file that referenced by uring cmd self.
I had a hard time parsing this comment. How about "Returns a reference
to the uring cmd's file object"?
> + #[inline]
> + pub fn file<'a>(&'a self) -> &'a File {
Could elide the lifetime.
> + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> + let file = unsafe { (*self.inner.get()).file };
> + unsafe { File::from_raw_file(file) }
Missing a SAFETY comment for File::from_raw_file()? I would expect
something about io_uring_cmd's file field storing a non-null pointer
to a struct file on which a reference is held for the duration of the
uring cmd.
> + }
> +
> + // Returns the sqe that referenced by uring cmd self.
"Returns a reference to the uring cmd's SQE"?
> + #[inline]
> + pub fn sqe(&self) -> &IoUringSqe {
> + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> + let ptr = unsafe { (*self.inner.get()).sqe };
"ptr" isn't very descriptive. How about "sqe"?
> + unsafe { IoUringSqe::from_raw(ptr) }
Similar, missing SAFETY comment for IoUringSqe::from_raw()?
> + }
> +
> + // Called by consumers of io_uring_cmd, if they originally returned -EIOCBQUEUED upon receiving the command
> + #[inline]
> + pub fn done(self, ret: isize, res2: u64, issue_flags: u32) {
I don't think it's safe to move io_uring_cmd. io_uring_cmd_done(), for
example, calls cmd_to_io_kiocb() to turn struct io_uring_cmd *ioucmd
into struct io_kiocb *req via a pointer cast. And struct io_kiocb's
definitely need to be pinned in memory. For example,
io_req_normal_work_add() inserts the struct io_kiocb into a linked
list. Probably some sort of pinning is necessary for IoUringCmd.
> + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> + unsafe {
> + bindings::io_uring_cmd_done(self.inner.get(), ret, res2, issue_flags);
> + }
> + }
> +}
> +
> +#[repr(transparent)]
> +pub struct IoUringSqe {
> + inner: Opaque<bindings::io_uring_sqe>,
> +}
> +
> +impl<'a> IoUringSqe {
> + pub fn cmd_data(&'a self) -> &'a [Opaque<u8>] {
> + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> + unsafe {
> + let cmd = (*self.inner.get()).__bindgen_anon_6.cmd.as_ref();
> + core::slice::from_raw_parts(cmd.as_ptr() as *const Opaque<u8>, 8)
Why 8? Should be 16 bytes for a 64-byte SQE and 80 bytes for a
128-byte SQE, right?
> + }
> + }
> +
> + #[inline]
> + pub unsafe fn from_raw(ptr: *const bindings::io_uring_sqe) -> &'a IoUringSqe {
Take NonNull here too?
> + // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
> + // duration of 'a. The cast is okay because `File` is `repr(transparent)`.
> + //
> + // INVARIANT: The caller guarantees that there are no problematic `fdget_pos` calls.
Why "File" and "fdget_pos"?
Best,
Caleb
> + 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 [flat|nested] 30+ messages in thread
* Re: [PATCH 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait
2025-07-19 14:33 ` [PATCH 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait Sidong Yang
@ 2025-07-20 19:38 ` kernel test robot
2025-07-20 20:08 ` Caleb Sander Mateos
1 sibling, 0 replies; 30+ messages in thread
From: kernel test robot @ 2025-07-20 19:38 UTC (permalink / raw)
To: Sidong Yang, Miguel Ojeda, Arnd Bergmann, Jens Axboe
Cc: llvm, oe-kbuild-all, rust-for-linux, linux-kernel, io-uring,
Sidong Yang
Hi Sidong,
kernel test robot noticed the following build warnings:
[auto build test WARNING on rust/rust-next]
[also build test WARNING on char-misc/char-misc-testing char-misc/char-misc-next char-misc/char-misc-linus soc/for-next linus/master v6.16-rc6 next-20250718]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Sidong-Yang/rust-bindings-add-io_uring-headers-in-bindings_helper-h/20250719-223630
base: https://github.com/Rust-for-Linux/linux rust-next
patch link: https://lore.kernel.org/r/20250719143358.22363-4-sidong.yang%40furiosa.ai
patch subject: [PATCH 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait
config: x86_64-rhel-9.4-rust (https://download.01.org/0day-ci/archive/20250721/202507210306.zCOB3QtO-lkp@intel.com/config)
compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261)
rustc: rustc 1.88.0 (6b00bc388 2025-06-23)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250721/202507210306.zCOB3QtO-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202507210306.zCOB3QtO-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> warning: unused variable: `issue_flags`
--> rust/kernel/miscdevice.rs:184:9
|
184 | issue_flags: u32,
| ^^^^^^^^^^^ help: if this is intentional, prefix it with an underscore: `_issue_flags`
|
= note: `#[warn(unused_variables)]` on by default
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait
2025-07-19 14:33 ` [PATCH 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait Sidong Yang
2025-07-20 19:38 ` kernel test robot
@ 2025-07-20 20:08 ` Caleb Sander Mateos
2025-07-21 5:42 ` Sidong Yang
1 sibling, 1 reply; 30+ messages in thread
From: Caleb Sander Mateos @ 2025-07-20 20:08 UTC (permalink / raw)
To: Sidong Yang
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring
On Sat, Jul 19, 2025 at 10:35 AM 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.
>
> Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> ---
> rust/kernel/miscdevice.rs | 34 ++++++++++++++++++++++++++++++++++
> 1 file changed, 34 insertions(+)
>
> diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
> index 288f40e79906..5255faf27934 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,15 @@ fn show_fdinfo(
> ) {
> build_error!(VTABLE_DEFAULT_ERROR)
> }
> +
> + fn uring_cmd(
> + _device: <Self::Ptr as ForeignOwnable>::Borrowed<'_>,
> + _file: &File,
> + _io_uring_cmd: &IoUringCmd,
> + issue_flags: u32,
> + ) -> Result<isize> {
Would i32 make more sense as the return value, since that's what
io_uring_cqe actually stores?
> + build_error!(VTABLE_DEFAULT_ERROR)
> + }
> }
>
> /// A vtable for the file operations of a Rust miscdevice.
> @@ -332,6 +342,25 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
> T::show_fdinfo(device, m, file);
> }
>
> + 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: Ioctl calls can borrow the private data of the file.
"Ioctl" -> "uring cmd"?
Best,
Caleb
> + let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
> +
> + match T::uring_cmd(device, file, 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 +383,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 [flat|nested] 30+ messages in thread
* Re: [PATCH 4/4] samples: rust: rust_misc_device: add uring_cmd example
2025-07-19 14:33 ` [PATCH 4/4] samples: rust: rust_misc_device: add uring_cmd example Sidong Yang
@ 2025-07-20 20:21 ` Caleb Sander Mateos
2025-07-21 5:45 ` Sidong Yang
0 siblings, 1 reply; 30+ messages in thread
From: Caleb Sander Mateos @ 2025-07-20 20:21 UTC (permalink / raw)
To: Sidong Yang
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring
On Sat, Jul 19, 2025 at 10:35 AM 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 | 30 ++++++++++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs
> index c881fd6dbd08..cd0e578231d2 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 = 0x83;
> +const RUST_MISC_DEV_URING_CMD_GET_VALUE: u32 = 0x84;
In real uring_cmd() implementations, the cmd_op values are assigned
using the _IO* macros, same as for ioctls. But I suppose that's not
strictly required for the sample driver.
> +
> module! {
> type: RustMiscDeviceModule,
> name: "rust_misc_device",
> @@ -190,6 +194,32 @@ fn ioctl(me: Pin<&RustMiscDevice>, _file: &File, cmd: u32, arg: usize) -> Result
>
> Ok(0)
> }
> +
> + fn uring_cmd(
> + me: Pin<&RustMiscDevice>,
> + _file: &File,
> + io_uring_cmd: &IoUringCmd,
> + _issue_flags: u32,
> + ) -> Result<isize> {
> + 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;
> + let addr = unsafe { *cmd_data };
The io_uring_sqe is user-mapped memory, so this load needs to be
atomic. In C, the uring_cmd() implementation would use READ_ONCE().
Sounds like Rust code is currently using read_volatile() (with a FIXME
comment to switch to read_once() once that's available).
Best,
Caleb
> +
> + 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 [flat|nested] 30+ messages in thread
* Re: [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
2025-07-20 19:10 ` Caleb Sander Mateos
@ 2025-07-21 5:22 ` Sidong Yang
2025-07-21 15:04 ` Caleb Sander Mateos
0 siblings, 1 reply; 30+ messages in thread
From: Sidong Yang @ 2025-07-21 5:22 UTC (permalink / raw)
To: Caleb Sander Mateos
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring
On Sun, Jul 20, 2025 at 03:10:28PM -0400, Caleb Sander Mateos wrote:
> On Sat, Jul 19, 2025 at 10:34 AM 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.
> >
> > Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> > ---
> > rust/kernel/io_uring.rs | 114 ++++++++++++++++++++++++++++++++++++++++
> > rust/kernel/lib.rs | 1 +
> > 2 files changed, 115 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..7843effbedb4
> > --- /dev/null
> > +++ b/rust/kernel/io_uring.rs
> > @@ -0,0 +1,114 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +// Copyright (C) 2025 Furiosa AI.
> > +
> > +//! Files and file descriptors.
> > +//!
> > +//! C headers: [`include/linux/io_uring/cmd.h`](srctree/include/linux/io_uring/cmd.h) and
> > +//! [`include/linux/file.h`](srctree/include/linux/file.h)
> > +
> > +use core::mem::MaybeUninit;
> > +
> > +use crate::{fs::File, types::Opaque};
> > +
> > +pub mod flags {
> > + pub const COMPLETE_DEFER: i32 = bindings::io_uring_cmd_flags_IO_URING_F_COMPLETE_DEFER;
> > + pub const UNLOCKED: i32 = bindings::io_uring_cmd_flags_IO_URING_F_UNLOCKED;
> > +
> > + pub const MULTISHOT: i32 = bindings::io_uring_cmd_flags_IO_URING_F_MULTISHOT;
> > + pub const IOWQ: i32 = bindings::io_uring_cmd_flags_IO_URING_F_IOWQ;
> > + pub const NONBLOCK: i32 = bindings::io_uring_cmd_flags_IO_URING_F_NONBLOCK;
> > +
> > + pub const SQE128: i32 = bindings::io_uring_cmd_flags_IO_URING_F_SQE128;
> > + pub const CQE32: i32 = bindings::io_uring_cmd_flags_IO_URING_F_CQE32;
> > + pub const IOPOLL: i32 = bindings::io_uring_cmd_flags_IO_URING_F_IOPOLL;
> > +
> > + pub const CANCEL: i32 = bindings::io_uring_cmd_flags_IO_URING_F_CANCEL;
> > + pub const COMPAT: i32 = bindings::io_uring_cmd_flags_IO_URING_F_COMPAT;
> > + pub const TASK_DEAD: i32 = bindings::io_uring_cmd_flags_IO_URING_F_TASK_DEAD;
> > +}
> > +
> > +#[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 the pointer 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 the pointer is not dangling and stays valid
> > + unsafe { (*self.inner.get()).flags }
> > + }
> > +
> > + /// Returns the ref pdu for free use.
> > + #[inline]
> > + pub fn pdu(&mut self) -> MaybeUninit<&mut [u8; 32]> {
>
> Should be &mut MaybeUninit, right? It's the bytes that may be
> uninitialized, not the reference.
Yes, it should be &mut MaybeUninit.
>
> > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > + unsafe { MaybeUninit::new(&mut (*self.inner.get()).pdu) }
> > + }
> > +
> > + /// Constructs a new `struct io_uring_cmd` wrapper from a file descriptor.
>
> Why "from a file descriptor"?
>
> Also, missing a comment documenting the safety preconditions?
Yes, it's a mistake in comment and also ptr should be NonNull.
>
> > + #[inline]
> > + pub unsafe fn from_raw<'a>(ptr: *const bindings::io_uring_cmd) -> &'a IoUringCmd {
>
> Could take NonNull instead of a raw pointer.
>
> > + // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
> > + // duration of 'a. The cast is okay because `File` is `repr(transparent)`.
>
> "File" -> "IoUringCmd"?
>
> > + unsafe { &*ptr.cast() }
> > + }
> > +
> > + // Returns the file that referenced by uring cmd self.
>
> I had a hard time parsing this comment. How about "Returns a reference
> to the uring cmd's file object"?
Agreed. thanks.
>
> > + #[inline]
> > + pub fn file<'a>(&'a self) -> &'a File {
>
> Could elide the lifetime.
Thanks, I didn't know about this.
>
> > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > + let file = unsafe { (*self.inner.get()).file };
> > + unsafe { File::from_raw_file(file) }
>
> Missing a SAFETY comment for File::from_raw_file()? I would expect
> something about io_uring_cmd's file field storing a non-null pointer
> to a struct file on which a reference is held for the duration of the
> uring cmd.
Yes, I missed. thanks.
>
> > + }
> > +
> > + // Returns the sqe that referenced by uring cmd self.
>
> "Returns a reference to the uring cmd's SQE"?
Agreed, thanks.
>
> > + #[inline]
> > + pub fn sqe(&self) -> &IoUringSqe {
> > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > + let ptr = unsafe { (*self.inner.get()).sqe };
>
> "ptr" isn't very descriptive. How about "sqe"?
Sounds good.
>
> > + unsafe { IoUringSqe::from_raw(ptr) }
>
> Similar, missing SAFETY comment for IoUringSqe::from_raw()?
Thanks. I missed.
>
> > + }
> > +
> > + // Called by consumers of io_uring_cmd, if they originally returned -EIOCBQUEUED upon receiving the command
> > + #[inline]
> > + pub fn done(self, ret: isize, res2: u64, issue_flags: u32) {
>
> I don't think it's safe to move io_uring_cmd. io_uring_cmd_done(), for
> example, calls cmd_to_io_kiocb() to turn struct io_uring_cmd *ioucmd
> into struct io_kiocb *req via a pointer cast. And struct io_kiocb's
> definitely need to be pinned in memory. For example,
> io_req_normal_work_add() inserts the struct io_kiocb into a linked
> list. Probably some sort of pinning is necessary for IoUringCmd.
Understood, Normally the users wouldn't create IoUringCmd than use borrowed cmd
in uring_cmd() callback. How about change to &mut self and also uring_cmd provides
&mut IoUringCmd for arg.
>
> > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > + unsafe {
> > + bindings::io_uring_cmd_done(self.inner.get(), ret, res2, issue_flags);
> > + }
> > + }
> > +}
> > +
> > +#[repr(transparent)]
> > +pub struct IoUringSqe {
> > + inner: Opaque<bindings::io_uring_sqe>,
> > +}
> > +
> > +impl<'a> IoUringSqe {
> > + pub fn cmd_data(&'a self) -> &'a [Opaque<u8>] {
> > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > + unsafe {
> > + let cmd = (*self.inner.get()).__bindgen_anon_6.cmd.as_ref();
> > + core::slice::from_raw_parts(cmd.as_ptr() as *const Opaque<u8>, 8)
>
> Why 8? Should be 16 bytes for a 64-byte SQE and 80 bytes for a
> 128-byte SQE, right?
Yes, it should be 16 bytes or 80 bytes. I'll fix this.
>
> > + }
> > + }
> > +
> > + #[inline]
> > + pub unsafe fn from_raw(ptr: *const bindings::io_uring_sqe) -> &'a IoUringSqe {
>
> Take NonNull here too?
Yes, Thanks.
>
> > + // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
> > + // duration of 'a. The cast is okay because `File` is `repr(transparent)`.
> > + //
> > + // INVARIANT: The caller guarantees that there are no problematic `fdget_pos` calls.
>
> Why "File" and "fdget_pos"?
It's a bad mistake. thanks!
Thank you so much for deatiled review!
Thanks,
Sidong
>
> Best,
> Caleb
>
> > + 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 [flat|nested] 30+ messages in thread
* Re: [PATCH 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait
2025-07-20 20:08 ` Caleb Sander Mateos
@ 2025-07-21 5:42 ` Sidong Yang
0 siblings, 0 replies; 30+ messages in thread
From: Sidong Yang @ 2025-07-21 5:42 UTC (permalink / raw)
To: Caleb Sander Mateos
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring
On Sun, Jul 20, 2025 at 04:08:19PM -0400, Caleb Sander Mateos wrote:
> On Sat, Jul 19, 2025 at 10:35 AM 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.
> >
> > Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> > ---
> > rust/kernel/miscdevice.rs | 34 ++++++++++++++++++++++++++++++++++
> > 1 file changed, 34 insertions(+)
> >
> > diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
> > index 288f40e79906..5255faf27934 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,15 @@ fn show_fdinfo(
> > ) {
> > build_error!(VTABLE_DEFAULT_ERROR)
> > }
> > +
> > + fn uring_cmd(
> > + _device: <Self::Ptr as ForeignOwnable>::Borrowed<'_>,
> > + _file: &File,
> > + _io_uring_cmd: &IoUringCmd,
> > + issue_flags: u32,
> > + ) -> Result<isize> {
>
> Would i32 make more sense as the return value, since that's what
> io_uring_cqe actually stores?
Agreed. thanks.
>
> > + build_error!(VTABLE_DEFAULT_ERROR)
> > + }
> > }
> >
> > /// A vtable for the file operations of a Rust miscdevice.
> > @@ -332,6 +342,25 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
> > T::show_fdinfo(device, m, file);
> > }
> >
> > + 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: Ioctl calls can borrow the private data of the file.
>
> "Ioctl" -> "uring cmd"?
Thanks it's a bad mistake.
Thanks,
Sidong
>
> Best,
> Caleb
>
> > + let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
> > +
> > + match T::uring_cmd(device, file, 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 +383,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 [flat|nested] 30+ messages in thread
* Re: [PATCH 4/4] samples: rust: rust_misc_device: add uring_cmd example
2025-07-20 20:21 ` Caleb Sander Mateos
@ 2025-07-21 5:45 ` Sidong Yang
0 siblings, 0 replies; 30+ messages in thread
From: Sidong Yang @ 2025-07-21 5:45 UTC (permalink / raw)
To: Caleb Sander Mateos
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring
On Sun, Jul 20, 2025 at 04:21:00PM -0400, Caleb Sander Mateos wrote:
> On Sat, Jul 19, 2025 at 10:35 AM 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 | 30 ++++++++++++++++++++++++++++++
> > 1 file changed, 30 insertions(+)
> >
> > diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs
> > index c881fd6dbd08..cd0e578231d2 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 = 0x83;
> > +const RUST_MISC_DEV_URING_CMD_GET_VALUE: u32 = 0x84;
>
> In real uring_cmd() implementations, the cmd_op values are assigned
> using the _IO* macros, same as for ioctls. But I suppose that's not
> strictly required for the sample driver.
Okay, I'll use same _IO* pattern with ioctl.
>
> > +
> > module! {
> > type: RustMiscDeviceModule,
> > name: "rust_misc_device",
> > @@ -190,6 +194,32 @@ fn ioctl(me: Pin<&RustMiscDevice>, _file: &File, cmd: u32, arg: usize) -> Result
> >
> > Ok(0)
> > }
> > +
> > + fn uring_cmd(
> > + me: Pin<&RustMiscDevice>,
> > + _file: &File,
> > + io_uring_cmd: &IoUringCmd,
> > + _issue_flags: u32,
> > + ) -> Result<isize> {
> > + 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;
> > + let addr = unsafe { *cmd_data };
>
> The io_uring_sqe is user-mapped memory, so this load needs to be
> atomic. In C, the uring_cmd() implementation would use READ_ONCE().
> Sounds like Rust code is currently using read_volatile() (with a FIXME
> comment to switch to read_once() once that's available).
Yes, I've missed this. read_volatile with comment would be good.
Thanks,
Sidong
>
> Best,
> Caleb
>
> > +
> > + 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 [flat|nested] 30+ messages in thread
* Re: [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
2025-07-21 5:22 ` Sidong Yang
@ 2025-07-21 15:04 ` Caleb Sander Mateos
2025-07-21 15:47 ` Sidong Yang
2025-07-21 15:52 ` Benno Lossin
0 siblings, 2 replies; 30+ messages in thread
From: Caleb Sander Mateos @ 2025-07-21 15:04 UTC (permalink / raw)
To: Sidong Yang
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring
On Mon, Jul 21, 2025 at 1:23 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
>
> On Sun, Jul 20, 2025 at 03:10:28PM -0400, Caleb Sander Mateos wrote:
> > On Sat, Jul 19, 2025 at 10:34 AM 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.
> > >
> > > Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> > > ---
> > > rust/kernel/io_uring.rs | 114 ++++++++++++++++++++++++++++++++++++++++
> > > rust/kernel/lib.rs | 1 +
> > > 2 files changed, 115 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..7843effbedb4
> > > --- /dev/null
> > > +++ b/rust/kernel/io_uring.rs
> > > @@ -0,0 +1,114 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +
> > > +// Copyright (C) 2025 Furiosa AI.
> > > +
> > > +//! Files and file descriptors.
> > > +//!
> > > +//! C headers: [`include/linux/io_uring/cmd.h`](srctree/include/linux/io_uring/cmd.h) and
> > > +//! [`include/linux/file.h`](srctree/include/linux/file.h)
> > > +
> > > +use core::mem::MaybeUninit;
> > > +
> > > +use crate::{fs::File, types::Opaque};
> > > +
> > > +pub mod flags {
> > > + pub const COMPLETE_DEFER: i32 = bindings::io_uring_cmd_flags_IO_URING_F_COMPLETE_DEFER;
> > > + pub const UNLOCKED: i32 = bindings::io_uring_cmd_flags_IO_URING_F_UNLOCKED;
> > > +
> > > + pub const MULTISHOT: i32 = bindings::io_uring_cmd_flags_IO_URING_F_MULTISHOT;
> > > + pub const IOWQ: i32 = bindings::io_uring_cmd_flags_IO_URING_F_IOWQ;
> > > + pub const NONBLOCK: i32 = bindings::io_uring_cmd_flags_IO_URING_F_NONBLOCK;
> > > +
> > > + pub const SQE128: i32 = bindings::io_uring_cmd_flags_IO_URING_F_SQE128;
> > > + pub const CQE32: i32 = bindings::io_uring_cmd_flags_IO_URING_F_CQE32;
> > > + pub const IOPOLL: i32 = bindings::io_uring_cmd_flags_IO_URING_F_IOPOLL;
> > > +
> > > + pub const CANCEL: i32 = bindings::io_uring_cmd_flags_IO_URING_F_CANCEL;
> > > + pub const COMPAT: i32 = bindings::io_uring_cmd_flags_IO_URING_F_COMPAT;
> > > + pub const TASK_DEAD: i32 = bindings::io_uring_cmd_flags_IO_URING_F_TASK_DEAD;
> > > +}
> > > +
> > > +#[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 the pointer 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 the pointer is not dangling and stays valid
> > > + unsafe { (*self.inner.get()).flags }
> > > + }
> > > +
> > > + /// Returns the ref pdu for free use.
> > > + #[inline]
> > > + pub fn pdu(&mut self) -> MaybeUninit<&mut [u8; 32]> {
> >
> > Should be &mut MaybeUninit, right? It's the bytes that may be
> > uninitialized, not the reference.
>
> Yes, it should be &mut MaybeUninit.
> >
> > > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > > + unsafe { MaybeUninit::new(&mut (*self.inner.get()).pdu) }
> > > + }
> > > +
> > > + /// Constructs a new `struct io_uring_cmd` wrapper from a file descriptor.
> >
> > Why "from a file descriptor"?
> >
> > Also, missing a comment documenting the safety preconditions?
>
> Yes, it's a mistake in comment and also ptr should be NonNull.
> >
> > > + #[inline]
> > > + pub unsafe fn from_raw<'a>(ptr: *const bindings::io_uring_cmd) -> &'a IoUringCmd {
> >
> > Could take NonNull instead of a raw pointer.
> >
> > > + // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
> > > + // duration of 'a. The cast is okay because `File` is `repr(transparent)`.
> >
> > "File" -> "IoUringCmd"?
> >
> > > + unsafe { &*ptr.cast() }
> > > + }
> > > +
> > > + // Returns the file that referenced by uring cmd self.
> >
> > I had a hard time parsing this comment. How about "Returns a reference
> > to the uring cmd's file object"?
>
> Agreed. thanks.
> >
> > > + #[inline]
> > > + pub fn file<'a>(&'a self) -> &'a File {
> >
> > Could elide the lifetime.
>
> Thanks, I didn't know about this.
> >
> > > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > > + let file = unsafe { (*self.inner.get()).file };
> > > + unsafe { File::from_raw_file(file) }
> >
> > Missing a SAFETY comment for File::from_raw_file()? I would expect
> > something about io_uring_cmd's file field storing a non-null pointer
> > to a struct file on which a reference is held for the duration of the
> > uring cmd.
>
> Yes, I missed. thanks.
> >
> > > + }
> > > +
> > > + // Returns the sqe that referenced by uring cmd self.
> >
> > "Returns a reference to the uring cmd's SQE"?
>
> Agreed, thanks.
> >
> > > + #[inline]
> > > + pub fn sqe(&self) -> &IoUringSqe {
> > > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > > + let ptr = unsafe { (*self.inner.get()).sqe };
> >
> > "ptr" isn't very descriptive. How about "sqe"?
>
> Sounds good.
> >
> > > + unsafe { IoUringSqe::from_raw(ptr) }
> >
> > Similar, missing SAFETY comment for IoUringSqe::from_raw()?
>
> Thanks. I missed.
> >
> > > + }
> > > +
> > > + // Called by consumers of io_uring_cmd, if they originally returned -EIOCBQUEUED upon receiving the command
> > > + #[inline]
> > > + pub fn done(self, ret: isize, res2: u64, issue_flags: u32) {
> >
> > I don't think it's safe to move io_uring_cmd. io_uring_cmd_done(), for
> > example, calls cmd_to_io_kiocb() to turn struct io_uring_cmd *ioucmd
> > into struct io_kiocb *req via a pointer cast. And struct io_kiocb's
> > definitely need to be pinned in memory. For example,
> > io_req_normal_work_add() inserts the struct io_kiocb into a linked
> > list. Probably some sort of pinning is necessary for IoUringCmd.
>
> Understood, Normally the users wouldn't create IoUringCmd than use borrowed cmd
> in uring_cmd() callback. How about change to &mut self and also uring_cmd provides
> &mut IoUringCmd for arg.
I'm still a little worried about exposing &mut IoUringCmd without
pinning. It would allow swapping the fields of two IoUringCmd's (and
therefore struct io_uring_cmd's), for example. If a struct
io_uring_cmd belongs to a struct io_kiocb linked into task_list,
swapping it with another struct io_uring_cmd would result in
io_uring_cmd_work() being invoked on the wrong struct io_uring_cmd.
Maybe it would be okay if IoUringCmd had an invariant that the struct
io_uring_cmd is not on the task work list. But I would feel safer with
using Pin<&mut IoUringCmd>. I don't have much experience with Rust in
the kernel, though, so I would welcome other opinions.
Best,
Caleb
>
> >
> > > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > > + unsafe {
> > > + bindings::io_uring_cmd_done(self.inner.get(), ret, res2, issue_flags);
> > > + }
> > > + }
> > > +}
> > > +
> > > +#[repr(transparent)]
> > > +pub struct IoUringSqe {
> > > + inner: Opaque<bindings::io_uring_sqe>,
> > > +}
> > > +
> > > +impl<'a> IoUringSqe {
> > > + pub fn cmd_data(&'a self) -> &'a [Opaque<u8>] {
> > > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > > + unsafe {
> > > + let cmd = (*self.inner.get()).__bindgen_anon_6.cmd.as_ref();
> > > + core::slice::from_raw_parts(cmd.as_ptr() as *const Opaque<u8>, 8)
> >
> > Why 8? Should be 16 bytes for a 64-byte SQE and 80 bytes for a
> > 128-byte SQE, right?
>
> Yes, it should be 16 bytes or 80 bytes. I'll fix this.
>
> >
> > > + }
> > > + }
> > > +
> > > + #[inline]
> > > + pub unsafe fn from_raw(ptr: *const bindings::io_uring_sqe) -> &'a IoUringSqe {
> >
> > Take NonNull here too?
>
> Yes, Thanks.
> >
> > > + // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
> > > + // duration of 'a. The cast is okay because `File` is `repr(transparent)`.
> > > + //
> > > + // INVARIANT: The caller guarantees that there are no problematic `fdget_pos` calls.
> >
> > Why "File" and "fdget_pos"?
>
> It's a bad mistake. thanks!
>
> Thank you so much for deatiled review!
>
> Thanks,
> Sidong
> >
> > Best,
> > Caleb
> >
> > > + 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 [flat|nested] 30+ messages in thread
* Re: [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
2025-07-21 15:04 ` Caleb Sander Mateos
@ 2025-07-21 15:47 ` Sidong Yang
2025-07-21 16:28 ` Benno Lossin
2025-07-21 15:52 ` Benno Lossin
1 sibling, 1 reply; 30+ messages in thread
From: Sidong Yang @ 2025-07-21 15:47 UTC (permalink / raw)
To: Caleb Sander Mateos
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring
On Mon, Jul 21, 2025 at 11:04:31AM -0400, Caleb Sander Mateos wrote:
> On Mon, Jul 21, 2025 at 1:23 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
> >
> > On Sun, Jul 20, 2025 at 03:10:28PM -0400, Caleb Sander Mateos wrote:
> > > On Sat, Jul 19, 2025 at 10:34 AM 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.
> > > >
> > > > Signed-off-by: Sidong Yang <sidong.yang@furiosa.ai>
> > > > ---
> > > > rust/kernel/io_uring.rs | 114 ++++++++++++++++++++++++++++++++++++++++
> > > > rust/kernel/lib.rs | 1 +
> > > > 2 files changed, 115 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..7843effbedb4
> > > > --- /dev/null
> > > > +++ b/rust/kernel/io_uring.rs
> > > > @@ -0,0 +1,114 @@
> > > > +// SPDX-License-Identifier: GPL-2.0
> > > > +
> > > > +// Copyright (C) 2025 Furiosa AI.
> > > > +
> > > > +//! Files and file descriptors.
> > > > +//!
> > > > +//! C headers: [`include/linux/io_uring/cmd.h`](srctree/include/linux/io_uring/cmd.h) and
> > > > +//! [`include/linux/file.h`](srctree/include/linux/file.h)
> > > > +
> > > > +use core::mem::MaybeUninit;
> > > > +
> > > > +use crate::{fs::File, types::Opaque};
> > > > +
> > > > +pub mod flags {
> > > > + pub const COMPLETE_DEFER: i32 = bindings::io_uring_cmd_flags_IO_URING_F_COMPLETE_DEFER;
> > > > + pub const UNLOCKED: i32 = bindings::io_uring_cmd_flags_IO_URING_F_UNLOCKED;
> > > > +
> > > > + pub const MULTISHOT: i32 = bindings::io_uring_cmd_flags_IO_URING_F_MULTISHOT;
> > > > + pub const IOWQ: i32 = bindings::io_uring_cmd_flags_IO_URING_F_IOWQ;
> > > > + pub const NONBLOCK: i32 = bindings::io_uring_cmd_flags_IO_URING_F_NONBLOCK;
> > > > +
> > > > + pub const SQE128: i32 = bindings::io_uring_cmd_flags_IO_URING_F_SQE128;
> > > > + pub const CQE32: i32 = bindings::io_uring_cmd_flags_IO_URING_F_CQE32;
> > > > + pub const IOPOLL: i32 = bindings::io_uring_cmd_flags_IO_URING_F_IOPOLL;
> > > > +
> > > > + pub const CANCEL: i32 = bindings::io_uring_cmd_flags_IO_URING_F_CANCEL;
> > > > + pub const COMPAT: i32 = bindings::io_uring_cmd_flags_IO_URING_F_COMPAT;
> > > > + pub const TASK_DEAD: i32 = bindings::io_uring_cmd_flags_IO_URING_F_TASK_DEAD;
> > > > +}
> > > > +
> > > > +#[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 the pointer 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 the pointer is not dangling and stays valid
> > > > + unsafe { (*self.inner.get()).flags }
> > > > + }
> > > > +
> > > > + /// Returns the ref pdu for free use.
> > > > + #[inline]
> > > > + pub fn pdu(&mut self) -> MaybeUninit<&mut [u8; 32]> {
> > >
> > > Should be &mut MaybeUninit, right? It's the bytes that may be
> > > uninitialized, not the reference.
> >
> > Yes, it should be &mut MaybeUninit.
> > >
> > > > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > > > + unsafe { MaybeUninit::new(&mut (*self.inner.get()).pdu) }
> > > > + }
> > > > +
> > > > + /// Constructs a new `struct io_uring_cmd` wrapper from a file descriptor.
> > >
> > > Why "from a file descriptor"?
> > >
> > > Also, missing a comment documenting the safety preconditions?
> >
> > Yes, it's a mistake in comment and also ptr should be NonNull.
> > >
> > > > + #[inline]
> > > > + pub unsafe fn from_raw<'a>(ptr: *const bindings::io_uring_cmd) -> &'a IoUringCmd {
> > >
> > > Could take NonNull instead of a raw pointer.
> > >
> > > > + // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
> > > > + // duration of 'a. The cast is okay because `File` is `repr(transparent)`.
> > >
> > > "File" -> "IoUringCmd"?
> > >
> > > > + unsafe { &*ptr.cast() }
> > > > + }
> > > > +
> > > > + // Returns the file that referenced by uring cmd self.
> > >
> > > I had a hard time parsing this comment. How about "Returns a reference
> > > to the uring cmd's file object"?
> >
> > Agreed. thanks.
> > >
> > > > + #[inline]
> > > > + pub fn file<'a>(&'a self) -> &'a File {
> > >
> > > Could elide the lifetime.
> >
> > Thanks, I didn't know about this.
> > >
> > > > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > > > + let file = unsafe { (*self.inner.get()).file };
> > > > + unsafe { File::from_raw_file(file) }
> > >
> > > Missing a SAFETY comment for File::from_raw_file()? I would expect
> > > something about io_uring_cmd's file field storing a non-null pointer
> > > to a struct file on which a reference is held for the duration of the
> > > uring cmd.
> >
> > Yes, I missed. thanks.
> > >
> > > > + }
> > > > +
> > > > + // Returns the sqe that referenced by uring cmd self.
> > >
> > > "Returns a reference to the uring cmd's SQE"?
> >
> > Agreed, thanks.
> > >
> > > > + #[inline]
> > > > + pub fn sqe(&self) -> &IoUringSqe {
> > > > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > > > + let ptr = unsafe { (*self.inner.get()).sqe };
> > >
> > > "ptr" isn't very descriptive. How about "sqe"?
> >
> > Sounds good.
> > >
> > > > + unsafe { IoUringSqe::from_raw(ptr) }
> > >
> > > Similar, missing SAFETY comment for IoUringSqe::from_raw()?
> >
> > Thanks. I missed.
A> > >
> > > > + }
> > > > +
> > > > + // Called by consumers of io_uring_cmd, if they originally returned -EIOCBQUEUED upon receiving the command
> > > > + #[inline]
> > > > + pub fn done(self, ret: isize, res2: u64, issue_flags: u32) {
> > >
> > > I don't think it's safe to move io_uring_cmd. io_uring_cmd_done(), for
> > > example, calls cmd_to_io_kiocb() to turn struct io_uring_cmd *ioucmd
> > > into struct io_kiocb *req via a pointer cast. And struct io_kiocb's
> > > definitely need to be pinned in memory. For example,
> > > io_req_normal_work_add() inserts the struct io_kiocb into a linked
> > > list. Probably some sort of pinning is necessary for IoUringCmd.
> >
> > Understood, Normally the users wouldn't create IoUringCmd than use borrowed cmd
> > in uring_cmd() callback. How about change to &mut self and also uring_cmd provides
> > &mut IoUringCmd for arg.
>
> I'm still a little worried about exposing &mut IoUringCmd without
> pinning. It would allow swapping the fields of two IoUringCmd's (and
> therefore struct io_uring_cmd's), for example. If a struct
> io_uring_cmd belongs to a struct io_kiocb linked into task_list,
> swapping it with another struct io_uring_cmd would result in
> io_uring_cmd_work() being invoked on the wrong struct io_uring_cmd.
> Maybe it would be okay if IoUringCmd had an invariant that the struct
> io_uring_cmd is not on the task work list. But I would feel safer with
> using Pin<&mut IoUringCmd>. I don't have much experience with Rust in
> the kernel, though, so I would welcome other opinions.
I've thought about this deeply. You're right. exposing &mut without
pinning make it unsafe. User also can make *mut and memmove to anywhere
without unsafe block. It's safest to get NonNull from from_raw and it
returns Pin<&mut IoUringCmd>. from_raw() name is weird. it should be
from_nonnnull()? Also, done() would get Pin<&mut Self>.
Thanks,
Sidong
>
> Best,
> Caleb
>
> >
> > >
> > > > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > > > + unsafe {
> > > > + bindings::io_uring_cmd_done(self.inner.get(), ret, res2, issue_flags);
> > > > + }
> > > > + }
> > > > +}
> > > > +
> > > > +#[repr(transparent)]
> > > > +pub struct IoUringSqe {
> > > > + inner: Opaque<bindings::io_uring_sqe>,
> > > > +}
> > > > +
> > > > +impl<'a> IoUringSqe {
> > > > + pub fn cmd_data(&'a self) -> &'a [Opaque<u8>] {
> > > > + // SAFETY: The call guarantees that the pointer is not dangling and stays valid
> > > > + unsafe {
> > > > + let cmd = (*self.inner.get()).__bindgen_anon_6.cmd.as_ref();
> > > > + core::slice::from_raw_parts(cmd.as_ptr() as *const Opaque<u8>, 8)
> > >
> > > Why 8? Should be 16 bytes for a 64-byte SQE and 80 bytes for a
> > > 128-byte SQE, right?
> >
> > Yes, it should be 16 bytes or 80 bytes. I'll fix this.
> >
> > >
> > > > + }
> > > > + }
> > > > +
> > > > + #[inline]
> > > > + pub unsafe fn from_raw(ptr: *const bindings::io_uring_sqe) -> &'a IoUringSqe {
> > >
> > > Take NonNull here too?
> >
> > Yes, Thanks.
> > >
> > > > + // SAFETY: The caller guarantees that the pointer is not dangling and stays valid for the
> > > > + // duration of 'a. The cast is okay because `File` is `repr(transparent)`.
> > > > + //
> > > > + // INVARIANT: The caller guarantees that there are no problematic `fdget_pos` calls.
> > >
> > > Why "File" and "fdget_pos"?
> >
> > It's a bad mistake. thanks!
> >
> > Thank you so much for deatiled review!
> >
> > Thanks,
> > Sidong
> > >
> > > Best,
> > > Caleb
> > >
> > > > + 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 [flat|nested] 30+ messages in thread
* Re: [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
2025-07-21 15:04 ` Caleb Sander Mateos
2025-07-21 15:47 ` Sidong Yang
@ 2025-07-21 15:52 ` Benno Lossin
2025-07-22 14:33 ` Sidong Yang
1 sibling, 1 reply; 30+ messages in thread
From: Benno Lossin @ 2025-07-21 15:52 UTC (permalink / raw)
To: Caleb Sander Mateos, Sidong Yang
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring
On Mon Jul 21, 2025 at 5:04 PM CEST, Caleb Sander Mateos wrote:
> On Mon, Jul 21, 2025 at 1:23 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
>> On Sun, Jul 20, 2025 at 03:10:28PM -0400, Caleb Sander Mateos wrote:
>> > On Sat, Jul 19, 2025 at 10:34 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
>> > > + }
>> > > +
>> > > + // Called by consumers of io_uring_cmd, if they originally returned -EIOCBQUEUED upon receiving the command
>> > > + #[inline]
>> > > + pub fn done(self, ret: isize, res2: u64, issue_flags: u32) {
>> >
>> > I don't think it's safe to move io_uring_cmd. io_uring_cmd_done(), for
>> > example, calls cmd_to_io_kiocb() to turn struct io_uring_cmd *ioucmd
>> > into struct io_kiocb *req via a pointer cast. And struct io_kiocb's
>> > definitely need to be pinned in memory. For example,
>> > io_req_normal_work_add() inserts the struct io_kiocb into a linked
>> > list. Probably some sort of pinning is necessary for IoUringCmd.
>>
>> Understood, Normally the users wouldn't create IoUringCmd than use borrowed cmd
>> in uring_cmd() callback. How about change to &mut self and also uring_cmd provides
>> &mut IoUringCmd for arg.
>
> I'm still a little worried about exposing &mut IoUringCmd without
> pinning. It would allow swapping the fields of two IoUringCmd's (and
> therefore struct io_uring_cmd's), for example. If a struct
> io_uring_cmd belongs to a struct io_kiocb linked into task_list,
> swapping it with another struct io_uring_cmd would result in
> io_uring_cmd_work() being invoked on the wrong struct io_uring_cmd.
> Maybe it would be okay if IoUringCmd had an invariant that the struct
> io_uring_cmd is not on the task work list. But I would feel safer with
> using Pin<&mut IoUringCmd>. I don't have much experience with Rust in
> the kernel, though, so I would welcome other opinions.
Pinning in the kernel isn't much different from userspace. From your
description of what normally happens with `struct io_uring_cmd`, it
definitely must be pinned.
From a quick glance at the patch series, I don't see a way to create a
`IoUringCmd` by-value, which also means that the `done` function won't
be callable (also the `fn pdu(&mut self)` function won't be callable,
since you only ever create a `&IoUringCmd`). I'm not sure if I'm missing
something, do you plan on further patches in the future?
How (aside from `from_raw`) are `IoUringCmd` values going to be created
or exposed to the user?
---
Cheers,
Benno
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
2025-07-21 15:47 ` Sidong Yang
@ 2025-07-21 16:28 ` Benno Lossin
2025-07-22 14:30 ` Sidong Yang
0 siblings, 1 reply; 30+ messages in thread
From: Benno Lossin @ 2025-07-21 16:28 UTC (permalink / raw)
To: Sidong Yang, Caleb Sander Mateos
Cc: Miguel Ojeda, Arnd Bergmann, Jens Axboe, rust-for-linux,
linux-kernel, io-uring
On Mon Jul 21, 2025 at 5:47 PM CEST, Sidong Yang wrote:
> On Mon, Jul 21, 2025 at 11:04:31AM -0400, Caleb Sander Mateos wrote:
>> On Mon, Jul 21, 2025 at 1:23 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
>> > On Sun, Jul 20, 2025 at 03:10:28PM -0400, Caleb Sander Mateos wrote:
>> > > On Sat, Jul 19, 2025 at 10:34 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
>> > > > + }
>> > > > +
>> > > > + // Called by consumers of io_uring_cmd, if they originally returned -EIOCBQUEUED upon receiving the command
>> > > > + #[inline]
>> > > > + pub fn done(self, ret: isize, res2: u64, issue_flags: u32) {
>> > >
>> > > I don't think it's safe to move io_uring_cmd. io_uring_cmd_done(), for
>> > > example, calls cmd_to_io_kiocb() to turn struct io_uring_cmd *ioucmd
>> > > into struct io_kiocb *req via a pointer cast. And struct io_kiocb's
>> > > definitely need to be pinned in memory. For example,
>> > > io_req_normal_work_add() inserts the struct io_kiocb into a linked
>> > > list. Probably some sort of pinning is necessary for IoUringCmd.
>> >
>> > Understood, Normally the users wouldn't create IoUringCmd than use borrowed cmd
>> > in uring_cmd() callback. How about change to &mut self and also uring_cmd provides
>> > &mut IoUringCmd for arg.
>>
>> I'm still a little worried about exposing &mut IoUringCmd without
>> pinning. It would allow swapping the fields of two IoUringCmd's (and
>> therefore struct io_uring_cmd's), for example. If a struct
>> io_uring_cmd belongs to a struct io_kiocb linked into task_list,
>> swapping it with another struct io_uring_cmd would result in
>> io_uring_cmd_work() being invoked on the wrong struct io_uring_cmd.
>> Maybe it would be okay if IoUringCmd had an invariant that the struct
>> io_uring_cmd is not on the task work list. But I would feel safer with
>> using Pin<&mut IoUringCmd>. I don't have much experience with Rust in
>> the kernel, though, so I would welcome other opinions.
>
> I've thought about this deeply. You're right. exposing &mut without
> pinning make it unsafe.
> User also can make *mut and memmove to anywhere without unsafe block.
How so? Using `*mut T` always needs unsafe.
> It's safest to get NonNull from from_raw and it returns
> Pin<&mut IoUringCmd>.
I don't think you need `NonNull<T>`.
> from_raw() name is weird. it should be from_nonnnull()? Also, done()
> would get Pin<&mut Self>.
That sounds reasonable.
Are you certain that it's an exclusive reference?
---
Cheers,
Benno
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
2025-07-21 16:28 ` Benno Lossin
@ 2025-07-22 14:30 ` Sidong Yang
2025-07-22 18:52 ` Benno Lossin
0 siblings, 1 reply; 30+ messages in thread
From: Sidong Yang @ 2025-07-22 14:30 UTC (permalink / raw)
To: Benno Lossin
Cc: Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann, Jens Axboe,
rust-for-linux, linux-kernel, io-uring
On Mon, Jul 21, 2025 at 06:28:09PM +0200, Benno Lossin wrote:
> On Mon Jul 21, 2025 at 5:47 PM CEST, Sidong Yang wrote:
> > On Mon, Jul 21, 2025 at 11:04:31AM -0400, Caleb Sander Mateos wrote:
> >> On Mon, Jul 21, 2025 at 1:23 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
> >> > On Sun, Jul 20, 2025 at 03:10:28PM -0400, Caleb Sander Mateos wrote:
> >> > > On Sat, Jul 19, 2025 at 10:34 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
> >> > > > + }
> >> > > > +
> >> > > > + // Called by consumers of io_uring_cmd, if they originally returned -EIOCBQUEUED upon receiving the command
> >> > > > + #[inline]
> >> > > > + pub fn done(self, ret: isize, res2: u64, issue_flags: u32) {
> >> > >
> >> > > I don't think it's safe to move io_uring_cmd. io_uring_cmd_done(), for
> >> > > example, calls cmd_to_io_kiocb() to turn struct io_uring_cmd *ioucmd
> >> > > into struct io_kiocb *req via a pointer cast. And struct io_kiocb's
> >> > > definitely need to be pinned in memory. For example,
> >> > > io_req_normal_work_add() inserts the struct io_kiocb into a linked
> >> > > list. Probably some sort of pinning is necessary for IoUringCmd.
> >> >
> >> > Understood, Normally the users wouldn't create IoUringCmd than use borrowed cmd
> >> > in uring_cmd() callback. How about change to &mut self and also uring_cmd provides
> >> > &mut IoUringCmd for arg.
> >>
> >> I'm still a little worried about exposing &mut IoUringCmd without
> >> pinning. It would allow swapping the fields of two IoUringCmd's (and
> >> therefore struct io_uring_cmd's), for example. If a struct
> >> io_uring_cmd belongs to a struct io_kiocb linked into task_list,
> >> swapping it with another struct io_uring_cmd would result in
> >> io_uring_cmd_work() being invoked on the wrong struct io_uring_cmd.
> >> Maybe it would be okay if IoUringCmd had an invariant that the struct
> >> io_uring_cmd is not on the task work list. But I would feel safer with
> >> using Pin<&mut IoUringCmd>. I don't have much experience with Rust in
> >> the kernel, though, so I would welcome other opinions.
> >
> > I've thought about this deeply. You're right. exposing &mut without
> > pinning make it unsafe.
>
> > User also can make *mut and memmove to anywhere without unsafe block.
>
> How so? Using `*mut T` always needs unsafe.
You're right. Please forget about this.
>
> > It's safest to get NonNull from from_raw and it returns
> > Pin<&mut IoUringCmd>.
>
> I don't think you need `NonNull<T>`.
NonNull<T> gurantees that it's not null. It could be also dangling but it's
safer than *mut T. Could you tell me why I don't need it?
>
> > from_raw() name is weird. it should be from_nonnnull()? Also, done()
> > would get Pin<&mut Self>.
>
> That sounds reasonable.
>
> Are you certain that it's an exclusive reference?
As far as I know, yes.
Thanks,
Sidong
>
> ---
> Cheers,
> Benno
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
2025-07-21 15:52 ` Benno Lossin
@ 2025-07-22 14:33 ` Sidong Yang
0 siblings, 0 replies; 30+ messages in thread
From: Sidong Yang @ 2025-07-22 14:33 UTC (permalink / raw)
To: Benno Lossin
Cc: Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann, Jens Axboe,
rust-for-linux, linux-kernel, io-uring
On Mon, Jul 21, 2025 at 05:52:41PM +0200, Benno Lossin wrote:
> On Mon Jul 21, 2025 at 5:04 PM CEST, Caleb Sander Mateos wrote:
> > On Mon, Jul 21, 2025 at 1:23 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
> >> On Sun, Jul 20, 2025 at 03:10:28PM -0400, Caleb Sander Mateos wrote:
> >> > On Sat, Jul 19, 2025 at 10:34 AM Sidong Yang <sidong.yang@furiosa.ai> wrote:
> >> > > + }
> >> > > +
> >> > > + // Called by consumers of io_uring_cmd, if they originally returned -EIOCBQUEUED upon receiving the command
> >> > > + #[inline]
> >> > > + pub fn done(self, ret: isize, res2: u64, issue_flags: u32) {
> >> >
> >> > I don't think it's safe to move io_uring_cmd. io_uring_cmd_done(), for
> >> > example, calls cmd_to_io_kiocb() to turn struct io_uring_cmd *ioucmd
> >> > into struct io_kiocb *req via a pointer cast. And struct io_kiocb's
> >> > definitely need to be pinned in memory. For example,
> >> > io_req_normal_work_add() inserts the struct io_kiocb into a linked
> >> > list. Probably some sort of pinning is necessary for IoUringCmd.
> >>
> >> Understood, Normally the users wouldn't create IoUringCmd than use borrowed cmd
> >> in uring_cmd() callback. How about change to &mut self and also uring_cmd provides
> >> &mut IoUringCmd for arg.
> >
> > I'm still a little worried about exposing &mut IoUringCmd without
> > pinning. It would allow swapping the fields of two IoUringCmd's (and
> > therefore struct io_uring_cmd's), for example. If a struct
> > io_uring_cmd belongs to a struct io_kiocb linked into task_list,
> > swapping it with another struct io_uring_cmd would result in
> > io_uring_cmd_work() being invoked on the wrong struct io_uring_cmd.
> > Maybe it would be okay if IoUringCmd had an invariant that the struct
> > io_uring_cmd is not on the task work list. But I would feel safer with
> > using Pin<&mut IoUringCmd>. I don't have much experience with Rust in
> > the kernel, though, so I would welcome other opinions.
>
> Pinning in the kernel isn't much different from userspace. From your
> description of what normally happens with `struct io_uring_cmd`, it
> definitely must be pinned.
>
> From a quick glance at the patch series, I don't see a way to create a
> `IoUringCmd` by-value, which also means that the `done` function won't
> be callable (also the `fn pdu(&mut self)` function won't be callable,
> since you only ever create a `&IoUringCmd`). I'm not sure if I'm missing
> something, do you plan on further patches in the future?
Sure, this version is full of nonsence. v2 will be better than this.
>
> How (aside from `from_raw`) are `IoUringCmd` values going to be created
> or exposed to the user?
Nomrally user would gets Pin<&mut IoUringCmd> from MiscDevice::uring_cmd().
Thanks,
Sidong
>
> ---
> Cheers,
> Benno
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
2025-07-22 14:30 ` Sidong Yang
@ 2025-07-22 18:52 ` Benno Lossin
2025-07-24 16:05 ` Sidong Yang
0 siblings, 1 reply; 30+ messages in thread
From: Benno Lossin @ 2025-07-22 18:52 UTC (permalink / raw)
To: Sidong Yang
Cc: Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann, Jens Axboe,
rust-for-linux, linux-kernel, io-uring
On Tue Jul 22, 2025 at 4:30 PM CEST, Sidong Yang wrote:
> On Mon, Jul 21, 2025 at 06:28:09PM +0200, Benno Lossin wrote:
>> On Mon Jul 21, 2025 at 5:47 PM CEST, Sidong Yang wrote:
>> > It's safest to get NonNull from from_raw and it returns
>> > Pin<&mut IoUringCmd>.
>>
>> I don't think you need `NonNull<T>`.
>
> NonNull<T> gurantees that it's not null. It could be also dangling but it's
> safer than *mut T. Could you tell me why I don't need it?
Raw pointers have better ergonomics and if you're just passing it back
into ffi, I don't see the point of using `NonNull`...
>> > from_raw() name is weird. it should be from_nonnnull()? Also, done()
>> > would get Pin<&mut Self>.
>>
>> That sounds reasonable.
>>
>> Are you certain that it's an exclusive reference?
>
> As far as I know, yes.
So the `IoUringCmd` is not refcounted and it is also not owned by the
`done` callee?
---
Cheers,
Benno
^ permalink raw reply [flat|nested] 30+ messages in thread
* Re: [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd
2025-07-22 18:52 ` Benno Lossin
@ 2025-07-24 16:05 ` Sidong Yang
0 siblings, 0 replies; 30+ messages in thread
From: Sidong Yang @ 2025-07-24 16:05 UTC (permalink / raw)
To: Benno Lossin
Cc: Caleb Sander Mateos, Miguel Ojeda, Arnd Bergmann, Jens Axboe,
rust-for-linux, linux-kernel, io-uring
On Tue, Jul 22, 2025 at 08:52:05PM +0200, Benno Lossin wrote:
> On Tue Jul 22, 2025 at 4:30 PM CEST, Sidong Yang wrote:
> > On Mon, Jul 21, 2025 at 06:28:09PM +0200, Benno Lossin wrote:
> >> On Mon Jul 21, 2025 at 5:47 PM CEST, Sidong Yang wrote:
> >> > It's safest to get NonNull from from_raw and it returns
> >> > Pin<&mut IoUringCmd>.
> >>
> >> I don't think you need `NonNull<T>`.
> >
> > NonNull<T> gurantees that it's not null. It could be also dangling but it's
> > safer than *mut T. Could you tell me why I don't need it?
>
> Raw pointers have better ergonomics and if you're just passing it back
> into ffi, I don't see the point of using `NonNull`...
Agreed, from_raw() would be called in rust kernel unsafe condition not in safe
driver. Thinking it over, using a raw pointer would be convenient.
>
> >> > from_raw() name is weird. it should be from_nonnnull()? Also, done()
> >> > would get Pin<&mut Self>.
> >>
> >> That sounds reasonable.
> >>
> >> Are you certain that it's an exclusive reference?
> >
> > As far as I know, yes.
>
> So the `IoUringCmd` is not refcounted and it is also not owned by the
> `done` callee?
Yes, io_uring_cmd would be allocated in io_submit_sqes() and it's not accessed
concurrently. io_uring_cmd_done() sets its result to io_uring_cmd and prepare
some field to completion.
Thanks,
Sidong
>
> ---
> Cheers,
> Benno
^ permalink raw reply [flat|nested] 30+ messages in thread
end of thread, other threads:[~2025-07-24 16:05 UTC | newest]
Thread overview: 30+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-19 14:33 [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd Sidong Yang
2025-07-19 14:33 ` [PATCH 1/4] rust: bindings: add io_uring headers in bindings_helper.h Sidong Yang
2025-07-20 12:29 ` kernel test robot
2025-07-19 14:33 ` [PATCH 2/4] rust: io_uring: introduce rust abstraction for io-uring cmd Sidong Yang
2025-07-20 19:10 ` Caleb Sander Mateos
2025-07-21 5:22 ` Sidong Yang
2025-07-21 15:04 ` Caleb Sander Mateos
2025-07-21 15:47 ` Sidong Yang
2025-07-21 16:28 ` Benno Lossin
2025-07-22 14:30 ` Sidong Yang
2025-07-22 18:52 ` Benno Lossin
2025-07-24 16:05 ` Sidong Yang
2025-07-21 15:52 ` Benno Lossin
2025-07-22 14:33 ` Sidong Yang
2025-07-19 14:33 ` [PATCH 3/4] rust: miscdevice: add uring_cmd() for MiscDevice trait Sidong Yang
2025-07-20 19:38 ` kernel test robot
2025-07-20 20:08 ` Caleb Sander Mateos
2025-07-21 5:42 ` Sidong Yang
2025-07-19 14:33 ` [PATCH 4/4] samples: rust: rust_misc_device: add uring_cmd example Sidong Yang
2025-07-20 20:21 ` Caleb Sander Mateos
2025-07-21 5:45 ` Sidong Yang
2025-07-19 15:00 ` [RFC PATCH 0/4] rust: miscdevice: abstraction for uring-cmd Nikita Krasnov
2025-07-19 16:33 ` Nikita Krasnov
2025-07-19 16:34 ` Miguel Ojeda
2025-07-20 16:07 ` Sidong Yang
2025-07-20 16:41 ` Miguel Ojeda
2025-07-20 16:52 ` Sidong Yang
2025-07-20 17:00 ` Miguel Ojeda
2025-07-19 17:03 ` Danilo Krummrich
2025-07-20 16:11 ` Sidong Yang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).