rust: miscdevice: Provide additional abstractions for iov_iter and kiocb structures

These will be used for the read_iter() and write_iter() callbacks, which
are now the preferred back-ends for when a user operates on a char device
with read() and write() respectively.

Co-developed-by: Lee Jones <lee@kernel.org>
Signed-off-by: Lee Jones <lee@kernel.org>
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Link: https://lore.kernel.org/r/20250822-iov-iter-v5-4-6ce4819c2977@google.com
This commit is contained in:
Alice Ryhl 2025-08-22 08:42:35 +00:00 committed by Greg Kroah-Hartman
parent 5e15de179a
commit 39c2745b37

View File

@ -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,
@ -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`].
@ -245,6 +256,46 @@ impl<T: MiscDevice> MiscdeviceVTable<T> {
0
}
/// # 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>`.
@ -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 {