From: Lee Jones <lee@kernel.org>
To: lee@kernel.org
Cc: linux-kernel@vger.kernel.org, ojeda@kernel.org,
alex.gaynor@gmail.com, boqun.feng@gmail.com, gary@garyguo.net,
bjorn3_gh@protonmail.com, benno.lossin@proton.me,
a.hindborg@kernel.org, aliceryhl@google.com, tmgross@umich.edu,
rust-for-linux@vger.kernel.org, gregkh@linuxfoundation.org
Subject: [PATCH 2/2] sample: rust_misc_device: Demonstrate additional get/set value functionality
Date: Wed, 4 Dec 2024 17:46:25 +0000 [thread overview]
Message-ID: <20241204174627.1151288-2-lee@kernel.org> (raw)
In-Reply-To: <20241204174627.1151288-1-lee@kernel.org>
Expand the complexity of the sample driver by providing the ability to
get and set an integer. The value is protected by a mutex.
Here is a simple userspace program that fully exercises the sample
driver's capabilities.
int main() {
int value, new_value;
int fd, ret;
// Open the device file
printf("Opening /dev/rust-misc-device for reading and writing\n");
fd = open("/dev/rust-misc-device", O_RDWR);
if (fd < 0) {
perror("open");
return errno;
}
// Make call into driver to say "hello"
printf("Calling Hello\n");
ret = ioctl(fd, RUST_MISC_DEV_HELLO, NULL);
if (ret < 0) {
perror("ioctl: Failed to call into Hello");
close(fd);
return errno;
}
// Get initial value
printf("Fetching initial value\n");
ret = ioctl(fd, RUST_MISC_DEV_GET_VALUE, &value);
if (ret < 0) {
perror("ioctl: Failed to fetch the initial value");
close(fd);
return errno;
}
value++;
// Set value to something different
printf("Submitting new value (%d)\n", value);
ret = ioctl(fd, RUST_MISC_DEV_SET_VALUE, &value);
if (ret < 0) {
perror("ioctl: Failed to submit new value");
close(fd);
return errno;
}
// Ensure new value was applied
printf("Fetching new value\n");
ret = ioctl(fd, RUST_MISC_DEV_GET_VALUE, &new_value);
if (ret < 0) {
perror("ioctl: Failed to fetch the new value");
close(fd);
return errno;
}
if (value != new_value) {
printf("Failed: Committed and retrieved values are different (%d - %d)\n", value, new_value);
close(fd);
return -1;
}
// Call the unsuccessful ioctl
printf("Attempting to call in to an non-existent IOCTL\n");
ret = ioctl(fd, RUST_MISC_DEV_FAIL, NULL);
if (ret < 0) {
perror("ioctl: Succeeded to fail - this was expected");
} else {
printf("ioctl: Failed to fail\n");
close(fd);
return -1;
}
// Close the device file
printf("Closing /dev/rust-misc-device\n");
close(fd);
printf("Success\n");
return 0;
}
Signed-off-by: Lee Jones <lee@kernel.org>
---
samples/rust/rust_misc_device.rs | 82 ++++++++++++++++++++++++--------
1 file changed, 62 insertions(+), 20 deletions(-)
diff --git a/samples/rust/rust_misc_device.rs b/samples/rust/rust_misc_device.rs
index 5f1b69569ef7..9c041497d881 100644
--- a/samples/rust/rust_misc_device.rs
+++ b/samples/rust/rust_misc_device.rs
@@ -2,13 +2,20 @@
//! Rust misc device sample.
+use core::pin::Pin;
+
use kernel::{
c_str,
- ioctl::_IO,
+ ioctl::{_IO, _IOC_SIZE, _IOR, _IOW},
miscdevice::{MiscDevice, MiscDeviceOptions, MiscDeviceRegistration},
+ new_mutex,
prelude::*,
+ sync::Mutex,
+ uaccess::{UserSlice, UserSliceReader, UserSliceWriter},
};
+const RUST_MISC_DEV_GET_VALUE: u32 = _IOR::<i32>('R' as u32, 7);
+const RUST_MISC_DEV_SET_VALUE: u32 = _IOW::<i32>('R' as u32, 8);
const RUST_MISC_DEV_HELLO: u32 = _IO('R' as u32, 9);
module! {
@@ -40,45 +47,80 @@ fn init(_module: &'static ThisModule) -> Result<Self> {
}
}
-struct RustMiscDevice;
+struct Inner {
+ value: i32,
+}
-impl RustMiscDevice {
- fn new() -> Self {
- Self
- }
+#[pin_data(PinnedDrop)]
+struct RustMiscDevice {
+ #[pin]
+ inner: Mutex<Inner>,
}
#[vtable]
impl MiscDevice for RustMiscDevice {
- type Ptr = KBox<Self>;
+ type Ptr = Pin<KBox<Self>>;
- fn open() -> Result<KBox<Self>> {
+ fn open() -> Result<Pin<KBox<Self>>> {
pr_info!("Opening Rust Misc Device Sample\n");
- Ok(KBox::new(RustMiscDevice::new(), GFP_KERNEL)?)
+ KBox::try_pin_init(
+ try_pin_init! {
+ RustMiscDevice { inner <- new_mutex!( Inner{ value: 0_i32 } )}
+ },
+ GFP_KERNEL,
+ )
}
- fn ioctl(
- _device: <Self::Ptr as kernel::types::ForeignOwnable>::Borrowed<'_>,
- cmd: u32,
- _arg: usize,
- ) -> Result<isize> {
+ fn ioctl(device: Pin<&RustMiscDevice>, cmd: u32, arg: usize) -> Result<isize> {
pr_info!("IOCTLing Rust Misc Device Sample\n");
- match cmd {
- RUST_MISC_DEV_HELLO => pr_info!("Hello from the Rust Misc Device\n"),
+ let size = _IOC_SIZE(cmd);
+
+ let _ = match cmd {
+ RUST_MISC_DEV_GET_VALUE => device.get_value(UserSlice::new(arg, size).writer())?,
+ RUST_MISC_DEV_SET_VALUE => device.set_value(UserSlice::new(arg, size).reader())?,
+ RUST_MISC_DEV_HELLO => device.hello()?,
_ => {
- pr_err!("IOCTL not recognised: {}\n", cmd);
+ pr_err!("-> IOCTL not recognised: {}\n", cmd);
return Err(EINVAL);
}
- }
+ };
Ok(0)
}
}
-impl Drop for RustMiscDevice {
- fn drop(&mut self) {
+#[pinned_drop]
+impl PinnedDrop for RustMiscDevice {
+ fn drop(self: Pin<&mut Self>) {
pr_info!("Exiting the Rust Misc Device Sample\n");
}
}
+
+impl RustMiscDevice {
+ fn set_value(&self, mut reader: UserSliceReader) -> Result<isize> {
+ let new_value = reader.read::<i32>()?;
+ let mut guard = self.inner.lock();
+
+ pr_info!("-> Copying data from userspace (value: {})\n", new_value);
+
+ guard.value = new_value;
+ Ok(0)
+ }
+
+ fn get_value(&self, mut writer: UserSliceWriter) -> Result<isize> {
+ let guard = self.inner.lock();
+
+ pr_info!("-> Copying data to userspace (value: {})\n", &guard.value);
+
+ writer.write::<i32>(&guard.value)?;
+ Ok(0)
+ }
+
+ fn hello(&self) -> Result<isize> {
+ pr_info!("-> Hello from the Rust Misc Device\n");
+
+ Ok(0)
+ }
+}
--
2.47.0.338.g60cca15819-goog
next prev parent reply other threads:[~2024-12-04 17:46 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-04 17:46 [PATCH 1/2] samples: rust: Provide example using the new Rust MiscDevice abstraction Lee Jones
2024-12-04 17:46 ` Lee Jones [this message]
2024-12-04 18:25 ` [PATCH 2/2] sample: rust_misc_device: Demonstrate additional get/set value functionality Greg KH
2024-12-05 8:38 ` Lee Jones
2024-12-05 9:01 ` Greg KH
2024-12-05 9:27 ` Lee Jones
2024-12-05 9:47 ` Greg KH
2024-12-09 21:34 ` Miguel Ojeda
2024-12-04 18:20 ` [PATCH 1/2] samples: rust: Provide example using the new Rust MiscDevice abstraction Greg KH
2024-12-05 8:41 ` Lee Jones
2024-12-05 9:03 ` Greg KH
2024-12-05 9:17 ` Lee Jones
2024-12-05 9:26 ` Greg KH
2024-12-05 9:21 ` Benoît du Garreau
2024-12-05 9:46 ` Lee Jones
2024-12-05 10:03 ` Lee Jones
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20241204174627.1151288-2-lee@kernel.org \
--to=lee@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.