From: Lee Jones <lee@kernel.org>
To: Greg KH <gregkh@linuxfoundation.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
Subject: Re: [PATCH 2/2] sample: rust_misc_device: Demonstrate additional get/set value functionality
Date: Thu, 5 Dec 2024 08:38:48 +0000 [thread overview]
Message-ID: <20241205083848.GD7451@google.com> (raw)
In-Reply-To: <2024120453-unfunded-oversight-5161@gregkh>
On Wed, 04 Dec 2024, Greg KH wrote:
> On Wed, Dec 04, 2024 at 05:46:25PM +0000, Lee Jones wrote:
> > 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);
>
> Shouldn't this be 'W'?
No, I don't think so.
'W' doesn't mean 'write'. It's supposed to be a unique identifier:
'W' 00-1F linux/watchdog.h conflict!
'W' 00-1F linux/wanrouter.h conflict! (pre 3.9)
'W' 00-3F sound/asound.h conflict!
'W' 40-5F drivers/pci/switch/switchtec.c
'W' 60-61 linux/watch_queue.h
'R' isn't registered for this either:
'R' 00-1F linux/random.h conflict!
'R' 01 linux/rfkill.h conflict!
'R' 20-2F linux/trace_mmap.h
'R' C0-DF net/bluetooth/rfcomm.h
'R' E0 uapi/linux/fsl_mc.h
... but since this is just example code with no real purpose, I'm going
to hold short of registering a unique identifier for it.
> > 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);
>
> Nit, wrong return value for an invalid ioctl, I missed that in patch 1,
> sorry about that.
Good shout, thanks.
> > }
> > - }
> > + };
> >
> > 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)?;
>
> What happens if it fails, shouldn't your pr_info() happen after this?
If this fails, I need the line in the log to show where it failed.
It says "copying" as in "attempting to copy", rather than "copied".
--
Lee Jones [李琼斯]
next prev parent reply other threads:[~2024-12-05 8:38 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 ` [PATCH 2/2] sample: rust_misc_device: Demonstrate additional get/set value functionality Lee Jones
2024-12-04 18:25 ` Greg KH
2024-12-05 8:38 ` Lee Jones [this message]
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=20241205083848.GD7451@google.com \
--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.