diff options
Diffstat (limited to 'rust/kernel/miscdevice.rs')
| -rw-r--r-- | rust/kernel/miscdevice.rs | 65 | 
1 files changed, 63 insertions, 2 deletions
| diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs index 6373fe183b27..d698cddcb4a5 100644 --- a/rust/kernel/miscdevice.rs +++ b/rust/kernel/miscdevice.rs @@ -13,7 +13,8 @@ use crate::{      device::Device,      error::{to_result, Error, Result, VTABLE_DEFAULT_ERROR},      ffi::{c_int, c_long, c_uint, c_ulong}, -    fs::File, +    fs::{File, Kiocb}, +    iov::{IovIterDest, IovIterSource},      mm::virt::VmaNew,      prelude::*,      seq_file::SeqFile, @@ -34,7 +35,7 @@ impl MiscDeviceOptions {          // SAFETY: All zeros is valid for this C type.          let mut result: bindings::miscdevice = unsafe { MaybeUninit::zeroed().assume_init() };          result.minor = bindings::MISC_DYNAMIC_MINOR as ffi::c_int; -        result.name = self.name.as_char_ptr(); +        result.name = crate::str::as_char_ptr_in_const_context(self.name);          result.fops = MiscdeviceVTable::<T>::build();          result      } @@ -141,6 +142,16 @@ pub trait MiscDevice: Sized {          build_error!(VTABLE_DEFAULT_ERROR)      } +    /// Read from this miscdevice. +    fn read_iter(_kiocb: Kiocb<'_, Self::Ptr>, _iov: &mut IovIterDest<'_>) -> Result<usize> { +        build_error!(VTABLE_DEFAULT_ERROR) +    } + +    /// Write to this miscdevice. +    fn write_iter(_kiocb: Kiocb<'_, Self::Ptr>, _iov: &mut IovIterSource<'_>) -> Result<usize> { +        build_error!(VTABLE_DEFAULT_ERROR) +    } +      /// Handler for ioctls.      ///      /// The `cmd` argument is usually manipulated using the utilities in [`kernel::ioctl`]. @@ -247,6 +258,46 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {      /// # Safety      /// +    /// `kiocb` must be correspond to a valid file that is associated with a +    /// `MiscDeviceRegistration<T>`. `iter` must be a valid `struct iov_iter` for writing. +    unsafe extern "C" fn read_iter( +        kiocb: *mut bindings::kiocb, +        iter: *mut bindings::iov_iter, +    ) -> isize { +        // SAFETY: The caller provides a valid `struct kiocb` associated with a +        // `MiscDeviceRegistration<T>` file. +        let kiocb = unsafe { Kiocb::from_raw(kiocb) }; +        // SAFETY: This is a valid `struct iov_iter` for writing. +        let iov = unsafe { IovIterDest::from_raw(iter) }; + +        match T::read_iter(kiocb, iov) { +            Ok(res) => res as isize, +            Err(err) => err.to_errno() as isize, +        } +    } + +    /// # Safety +    /// +    /// `kiocb` must be correspond to a valid file that is associated with a +    /// `MiscDeviceRegistration<T>`. `iter` must be a valid `struct iov_iter` for writing. +    unsafe extern "C" fn write_iter( +        kiocb: *mut bindings::kiocb, +        iter: *mut bindings::iov_iter, +    ) -> isize { +        // SAFETY: The caller provides a valid `struct kiocb` associated with a +        // `MiscDeviceRegistration<T>` file. +        let kiocb = unsafe { Kiocb::from_raw(kiocb) }; +        // SAFETY: This is a valid `struct iov_iter` for reading. +        let iov = unsafe { IovIterSource::from_raw(iter) }; + +        match T::write_iter(kiocb, iov) { +            Ok(res) => res as isize, +            Err(err) => err.to_errno() as isize, +        } +    } + +    /// # Safety +    ///      /// `file` must be a valid file that is associated with a `MiscDeviceRegistration<T>`.      /// `vma` must be a vma that is currently being mmap'ed with this file.      unsafe extern "C" fn mmap( @@ -341,6 +392,16 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {          open: Some(Self::open),          release: Some(Self::release),          mmap: if T::HAS_MMAP { Some(Self::mmap) } else { None }, +        read_iter: if T::HAS_READ_ITER { +            Some(Self::read_iter) +        } else { +            None +        }, +        write_iter: if T::HAS_WRITE_ITER { +            Some(Self::write_iter) +        } else { +            None +        },          unlocked_ioctl: if T::HAS_IOCTL {              Some(Self::ioctl)          } else { | 
