From e5b0d7da941a7dc1ced09d57b967fdc124f510f8 Mon Sep 17 00:00:00 2001 From: Lee Jones Date: Fri, 22 Aug 2025 08:42:36 +0000 Subject: [PATCH] samples: rust_misc_device: Expand the sample to support read()ing from userspace A userland application can now operate on the char device with read() in order to consume a locally held buffer. Memory for the buffer is to be provisioned and the buffer populated in its subsequently provided write() counterpart. Signed-off-by: Lee Jones Reviewed-by: Andreas Hindborg Co-developed-by: Alice Ryhl Signed-off-by: Alice Ryhl Signed-off-by: Greg Kroah-Hartman Link: https://lore.kernel.org/r/20250822-iov-iter-v5-5-6ce4819c2977@google.com --- samples/rust/rust_misc_device.rs | 36 ++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs index e7ab77448f75..9e4005e33796 100644 --- a/samples/rust/rust_misc_device.rs +++ b/samples/rust/rust_misc_device.rs @@ -100,8 +100,9 @@ use core::pin::Pin; use kernel::{ c_str, device::Device, - fs::File, + fs::{File, Kiocb}, ioctl::{_IO, _IOC_SIZE, _IOR, _IOW}, + iov::{IovIterDest, IovIterSource}, miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration}, new_mutex, prelude::*, @@ -144,6 +145,7 @@ impl kernel::InPlaceModule for RustMiscDeviceModule { struct Inner { value: i32, + buffer: KVVec, } #[pin_data(PinnedDrop)] @@ -165,7 +167,10 @@ impl MiscDevice for RustMiscDevice { KBox::try_pin_init( try_pin_init! { RustMiscDevice { - inner <- new_mutex!( Inner{ value: 0_i32 } ), + inner <- new_mutex!(Inner { + value: 0_i32, + buffer: KVVec::new(), + }), dev: dev, } }, @@ -173,6 +178,33 @@ impl MiscDevice for RustMiscDevice { ) } + fn read_iter(mut kiocb: Kiocb<'_, Self::Ptr>, iov: &mut IovIterDest<'_>) -> Result { + let me = kiocb.file(); + dev_info!(me.dev, "Reading from Rust Misc Device Sample\n"); + + let inner = me.inner.lock(); + // Read the buffer contents, taking the file position into account. + let read = iov.simple_read_from_buffer(kiocb.ki_pos_mut(), &inner.buffer)?; + + Ok(read) + } + + fn write_iter(mut kiocb: Kiocb<'_, Self::Ptr>, iov: &mut IovIterSource<'_>) -> Result { + let me = kiocb.file(); + dev_info!(me.dev, "Writing to Rust Misc Device Sample\n"); + + let mut inner = me.inner.lock(); + + // Replace buffer contents. + inner.buffer.clear(); + let len = iov.copy_from_iter_vec(&mut inner.buffer, GFP_KERNEL)?; + + // Set position to zero so that future `read` calls will see the new contents. + *kiocb.ki_pos_mut() = 0; + + Ok(len) + } + fn ioctl(me: Pin<&RustMiscDevice>, _file: &File, cmd: u32, arg: usize) -> Result { dev_info!(me.dev, "IOCTLing Rust Misc Device Sample\n"); -- 2.47.3