[PATCH v5 4/4] samples: rust: Add `uring_cmd` example to `rust_misc_device`
From: Sidong Yang
Date: Wed Apr 15 2026 - 05:12:05 EST
Extend the rust_misc_device sample to demonstrate uring_cmd handling.
The example completes asynchronously using a workqueue combined with
complete_in_task(), showing the full async completion flow:
IoUringCmd -> queue() -> workqueue -> complete_in_task() ->
task_work -> done().
Signed-off-by: Sidong Yang <sidong.yang@xxxxxxxxxx>
---
samples/rust/rust_misc_device.rs | 62 +++++++++++++++++++++++++++++++-
1 file changed, 61 insertions(+), 1 deletion(-)
diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs
index 87a1fe63533a..4059348a56ad 100644
--- a/samples/rust/rust_misc_device.rs
+++ b/samples/rust/rust_misc_device.rs
@@ -98,13 +98,15 @@
use kernel::{
device::Device,
fs::{File, Kiocb},
+ io_uring::{self, IoUringCmd, IoUringTaskWork, QueuedIoUringCmd, UringCmdAction},
ioctl::{_IO, _IOC_SIZE, _IOR, _IOW},
iov::{IovIterDest, IovIterSource},
miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration},
new_mutex,
prelude::*,
- sync::{aref::ARef, Mutex},
+ sync::{Arc, aref::ARef, Mutex},
uaccess::{UserSlice, UserSliceReader, UserSliceWriter},
+ workqueue::{impl_has_work, new_work, HasWork},
};
const RUST_MISC_DEV_HELLO: u32 = _IO('|' as u32, 0x80);
@@ -151,6 +153,51 @@ struct RustMiscDevice {
dev: ARef<Device>,
}
+#[pin_data]
+struct IoUringCmdWork {
+ #[pin]
+ ioucmd: Mutex<Option<QueuedIoUringCmd>>,
+ #[pin]
+ work: kernel::workqueue::Work<IoUringCmdWork>,
+}
+
+impl_has_work! {
+ impl HasWork<Self> for IoUringCmdWork { self.work }
+}
+
+/// Task-work completion handler for the sample device.
+struct RustMiscDeviceCompletion;
+
+impl IoUringTaskWork for RustMiscDeviceCompletion {
+ fn task_work(cmd: QueuedIoUringCmd) {
+ cmd.done(Ok(0), 0, io_uring::TASK_WORK_ISSUE_FLAGS);
+ }
+}
+
+impl kernel::workqueue::WorkItem for IoUringCmdWork {
+ type Pointer = Arc<IoUringCmdWork>;
+
+ fn run(work: Arc<IoUringCmdWork>) {
+ pr_info!("IoUringCmdWork::run()");
+
+ if let Some(ioucmd) = work.ioucmd.lock().take() {
+ ioucmd.complete_in_task::<RustMiscDeviceCompletion>();
+ }
+ }
+}
+
+impl IoUringCmdWork {
+ fn new(ioucmd: QueuedIoUringCmd) -> Result<Arc<Self>> {
+ Arc::pin_init(
+ pin_init!(Self {
+ ioucmd <- new_mutex!(Some(ioucmd)),
+ work <- new_work!("IoUringCmdWork::work"),
+ }),
+ GFP_KERNEL,
+ )
+ }
+}
+
#[vtable]
impl MiscDevice for RustMiscDevice {
type Ptr = Pin<KBox<Self>>;
@@ -220,6 +267,19 @@ fn ioctl(me: Pin<&RustMiscDevice>, _file: &File, cmd: u32, arg: usize) -> Result
Ok(0)
}
+
+ fn uring_cmd(
+ me: Pin<&RustMiscDevice>,
+ ioucmd: IoUringCmd,
+ _issue_flags: u32,
+ ) -> Result<UringCmdAction> {
+ dev_info!(me.dev, "UringCmd Rust Misc Device Sample\n");
+
+ let (action, queued_ioucmd) = ioucmd.queue();
+ let work = IoUringCmdWork::new(queued_ioucmd)?;
+ let _ = kernel::workqueue::system().enqueue(work);
+ Ok(action)
+ }
}
#[pinned_drop]
--
2.43.0