Skip to content

Use generic associated types (GATs) to implement PointerWrapper. #556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 30 additions & 13 deletions drivers/android/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use kernel::{
pages::Pages,
prelude::*,
rbtree::RBTree,
sync::{GuardMut, Mutex, Ref, UniqueRef},
sync::{GuardMut, Mutex, Ref, RefBorrow, UniqueRef},
task::Task,
user_ptr::{UserSlicePtr, UserSlicePtrReader},
};
Expand Down Expand Up @@ -307,7 +307,7 @@ impl Process {
Either::Right(Registration::new(self, thread, &mut inner))
}

fn get_thread(self: &Ref<Self>, id: i32) -> Result<Ref<Thread>> {
fn get_thread(self: RefBorrow<'_, Self>, id: i32) -> Result<Ref<Thread>> {
// TODO: Consider using read/write locks here instead.
{
let inner = self.inner.lock();
Expand All @@ -317,7 +317,7 @@ impl Process {
}

// Allocate a new `Thread` without holding any locks.
let ta = Thread::new(id, self.clone())?;
let ta = Thread::new(id, self.into())?;
let node = RBTree::try_allocate_node(id, ta.clone())?;

let mut inner = self.inner.lock();
Expand All @@ -335,7 +335,11 @@ impl Process {
self.inner.lock().push_work(work)
}

fn set_as_manager(self: &Ref<Self>, info: Option<FlatBinderObject>, thread: &Thread) -> Result {
fn set_as_manager(
self: RefBorrow<'_, Self>,
info: Option<FlatBinderObject>,
thread: &Thread,
) -> Result {
let (ptr, cookie, flags) = if let Some(obj) = info {
(
// SAFETY: The object type for this ioctl is implicitly `BINDER_TYPE_BINDER`, so it
Expand All @@ -359,7 +363,7 @@ impl Process {
}

pub(crate) fn get_node(
self: &Ref<Self>,
self: RefBorrow<'_, Self>,
ptr: usize,
cookie: usize,
flags: u32,
Expand All @@ -375,7 +379,7 @@ impl Process {
}

// Allocate the node before reacquiring the lock.
let node = Ref::try_new(Node::new(ptr, cookie, flags, self.clone()))?;
let node = Ref::try_new(Node::new(ptr, cookie, flags, self.into()))?;
let rbnode = RBTree::try_allocate_node(ptr, node.clone())?;

let mut inner = self.inner.lock();
Expand Down Expand Up @@ -758,10 +762,10 @@ impl Process {
}

impl IoctlHandler for Process {
type Target = Ref<Process>;
type Target<'a> = RefBorrow<'a, Process>;

fn write(
this: &Ref<Process>,
this: RefBorrow<'_, Process>,
_file: &File,
cmd: u32,
reader: &mut UserSlicePtrReader,
Expand All @@ -779,7 +783,12 @@ impl IoctlHandler for Process {
Ok(0)
}

fn read_write(this: &Ref<Process>, file: &File, cmd: u32, data: UserSlicePtr) -> Result<i32> {
fn read_write(
this: RefBorrow<'_, Process>,
file: &File,
cmd: u32,
data: UserSlicePtr,
) -> Result<i32> {
let thread = this.get_thread(Task::current().pid())?;
match cmd {
bindings::BINDER_WRITE_READ => thread.write_read(data, file.is_blocking())?,
Expand Down Expand Up @@ -879,15 +888,23 @@ impl FileOperations for Process {
}
}

fn ioctl(this: &Ref<Process>, file: &File, cmd: &mut IoctlCommand) -> Result<i32> {
fn ioctl(this: RefBorrow<'_, Process>, file: &File, cmd: &mut IoctlCommand) -> Result<i32> {
cmd.dispatch::<Self>(this, file)
}

fn compat_ioctl(this: &Ref<Process>, file: &File, cmd: &mut IoctlCommand) -> Result<i32> {
fn compat_ioctl(
this: RefBorrow<'_, Process>,
file: &File,
cmd: &mut IoctlCommand,
) -> Result<i32> {
cmd.dispatch::<Self>(this, file)
}

fn mmap(this: &Ref<Process>, _file: &File, vma: &mut bindings::vm_area_struct) -> Result {
fn mmap(
this: RefBorrow<'_, Process>,
_file: &File,
vma: &mut bindings::vm_area_struct,
) -> Result {
// We don't allow mmap to be used in a different process.
if !Task::current().group_leader().eq(&this.task) {
return Err(Error::EINVAL);
Expand All @@ -908,7 +925,7 @@ impl FileOperations for Process {
this.create_mapping(vma)
}

fn poll(this: &Ref<Process>, file: &File, table: &PollTable) -> Result<u32> {
fn poll(this: RefBorrow<'_, Process>, file: &File, table: &PollTable) -> Result<u32> {
let thread = this.get_thread(Task::current().pid())?;
let (from_proc, mut mask) = thread.poll(file, table);
if mask == 0 && from_proc && !this.inner.lock().work.is_empty() {
Expand Down
8 changes: 7 additions & 1 deletion drivers/android/rust_binder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,13 @@
//! TODO: This module is a work in progress.

#![no_std]
#![feature(global_asm, try_reserve, allocator_api, concat_idents)]
#![feature(
global_asm,
try_reserve,
allocator_api,
concat_idents,
generic_associated_types
)]

use kernel::{
io_buffer::IoBufferWriter,
Expand Down
10 changes: 7 additions & 3 deletions drivers/android/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,9 +395,13 @@ impl Thread {
let ptr = unsafe { obj.__bindgen_anon_1.binder } as _;
let cookie = obj.cookie as _;
let flags = obj.flags as _;
let node = self
.process
.get_node(ptr, cookie, flags, strong, Some(self))?;
let node = self.process.as_ref_borrow().get_node(
ptr,
cookie,
flags,
strong,
Some(self),
)?;
security::binder_transfer_binder(&self.process.task, &view.alloc.process.task)?;
Ok(node)
})?;
Expand Down
56 changes: 30 additions & 26 deletions rust/kernel/file_operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! C header: [`include/linux/fs.h`](../../../../include/linux/fs.h)

use core::convert::{TryFrom, TryInto};
use core::{marker, mem, ops::Deref, ptr};
use core::{marker, mem, ptr};

use alloc::boxed::Box;

Expand Down Expand Up @@ -122,7 +122,7 @@ unsafe extern "C" fn read_callback<T: FileOperations>(
let f = unsafe { T::Wrapper::borrow((*file).private_data) };
// No `FMODE_UNSIGNED_OFFSET` support, so `offset` must be in [0, 2^63).
// See discussion in https://github.com/fishinabarrel/linux-kernel-module-rust/pull/113
let read = T::read(&f, unsafe { &FileRef::from_ptr(file) }, &mut data, unsafe { *offset }.try_into()?)?;
let read = T::read(f, unsafe { &FileRef::from_ptr(file) }, &mut data, unsafe { *offset }.try_into()?)?;
unsafe { (*offset) += bindings::loff_t::try_from(read).unwrap() };
Ok(read as _)
}
Expand All @@ -141,7 +141,7 @@ unsafe extern "C" fn read_iter_callback<T: FileOperations>(
// callback, which the C API guarantees that will be called only when all references to
// `file` have been released, so we know it can't be called while this function is running.
let f = unsafe { T::Wrapper::borrow((*file).private_data) };
let read = T::read(&f, unsafe { &FileRef::from_ptr(file) }, &mut iter, offset.try_into()?)?;
let read = T::read(f, unsafe { &FileRef::from_ptr(file) }, &mut iter, offset.try_into()?)?;
unsafe { (*iocb).ki_pos += bindings::loff_t::try_from(read).unwrap() };
Ok(read as _)
}
Expand All @@ -162,7 +162,7 @@ unsafe extern "C" fn write_callback<T: FileOperations>(
let f = unsafe { T::Wrapper::borrow((*file).private_data) };
// No `FMODE_UNSIGNED_OFFSET` support, so `offset` must be in [0, 2^63).
// See discussion in https://github.com/fishinabarrel/linux-kernel-module-rust/pull/113
let written = T::write(&f, unsafe { &FileRef::from_ptr(file) }, &mut data, unsafe { *offset }.try_into()?)?;
let written = T::write(f, unsafe { &FileRef::from_ptr(file) }, &mut data, unsafe { *offset }.try_into()?)?;
unsafe { (*offset) += bindings::loff_t::try_from(written).unwrap() };
Ok(written as _)
}
Expand All @@ -181,7 +181,7 @@ unsafe extern "C" fn write_iter_callback<T: FileOperations>(
// callback, which the C API guarantees that will be called only when all references to
// `file` have been released, so we know it can't be called while this function is running.
let f = unsafe { T::Wrapper::borrow((*file).private_data) };
let written = T::write(&f, unsafe { &FileRef::from_ptr(file) }, &mut iter, offset.try_into()?)?;
let written = T::write(f, unsafe { &FileRef::from_ptr(file) }, &mut iter, offset.try_into()?)?;
unsafe { (*iocb).ki_pos += bindings::loff_t::try_from(written).unwrap() };
Ok(written as _)
}
Expand Down Expand Up @@ -215,7 +215,7 @@ unsafe extern "C" fn llseek_callback<T: FileOperations>(
// callback, which the C API guarantees that will be called only when all references to
// `file` have been released, so we know it can't be called while this function is running.
let f = unsafe { T::Wrapper::borrow((*file).private_data) };
let off = T::seek(&f, unsafe { &FileRef::from_ptr(file) }, off)?;
let off = T::seek(f, unsafe { &FileRef::from_ptr(file) }, off)?;
Ok(off as bindings::loff_t)
}
}
Expand All @@ -232,7 +232,7 @@ unsafe extern "C" fn unlocked_ioctl_callback<T: FileOperations>(
// `file` have been released, so we know it can't be called while this function is running.
let f = unsafe { T::Wrapper::borrow((*file).private_data) };
let mut cmd = IoctlCommand::new(cmd as _, arg as _);
let ret = T::ioctl(&f, unsafe { &FileRef::from_ptr(file) }, &mut cmd)?;
let ret = T::ioctl(f, unsafe { &FileRef::from_ptr(file) }, &mut cmd)?;
Ok(ret as _)
}
}
Expand All @@ -249,7 +249,7 @@ unsafe extern "C" fn compat_ioctl_callback<T: FileOperations>(
// `file` have been released, so we know it can't be called while this function is running.
let f = unsafe { T::Wrapper::borrow((*file).private_data) };
let mut cmd = IoctlCommand::new(cmd as _, arg as _);
let ret = T::compat_ioctl(&f, unsafe { &FileRef::from_ptr(file) }, &mut cmd)?;
let ret = T::compat_ioctl(f, unsafe { &FileRef::from_ptr(file) }, &mut cmd)?;
Ok(ret as _)
}
}
Expand All @@ -264,7 +264,7 @@ unsafe extern "C" fn mmap_callback<T: FileOperations>(
// callback, which the C API guarantees that will be called only when all references to
// `file` have been released, so we know it can't be called while this function is running.
let f = unsafe { T::Wrapper::borrow((*file).private_data) };
T::mmap(&f, unsafe { &FileRef::from_ptr(file) }, unsafe { &mut *vma })?;
T::mmap(f, unsafe { &FileRef::from_ptr(file) }, unsafe { &mut *vma })?;
Ok(0)
}
}
Expand All @@ -284,7 +284,7 @@ unsafe extern "C" fn fsync_callback<T: FileOperations>(
// callback, which the C API guarantees that will be called only when all references to
// `file` have been released, so we know it can't be called while this function is running.
let f = unsafe { T::Wrapper::borrow((*file).private_data) };
let res = T::fsync(&f, unsafe { &FileRef::from_ptr(file) }, start, end, datasync)?;
let res = T::fsync(f, unsafe { &FileRef::from_ptr(file) }, start, end, datasync)?;
Ok(res.try_into().unwrap())
}
}
Expand All @@ -298,7 +298,7 @@ unsafe extern "C" fn poll_callback<T: FileOperations>(
// callback, which the C API guarantees that will be called only when all references to `file`
// have been released, so we know it can't be called while this function is running.
let f = unsafe { T::Wrapper::borrow((*file).private_data) };
match T::poll(&f, unsafe { &FileRef::from_ptr(file) }, unsafe {
match T::poll(f, unsafe { &FileRef::from_ptr(file) }, unsafe {
&PollTable::from_ptr(wait)
}) {
Ok(v) => v,
Expand Down Expand Up @@ -463,17 +463,17 @@ macro_rules! declare_file_operations {
/// For each macro, there is a handler function that takes the appropriate types as arguments.
pub trait IoctlHandler: Sync {
/// The type of the first argument to each associated function.
type Target;
type Target<'a>;

/// Handles ioctls defined with the `_IO` macro, that is, with no buffer as argument.
fn pure(_this: &Self::Target, _file: &File, _cmd: u32, _arg: usize) -> Result<i32> {
fn pure(_this: Self::Target<'_>, _file: &File, _cmd: u32, _arg: usize) -> Result<i32> {
Err(Error::EINVAL)
}

/// Handles ioctls defined with the `_IOR` macro, that is, with an output buffer provided as
/// argument.
fn read(
_this: &Self::Target,
_this: Self::Target<'_>,
_file: &File,
_cmd: u32,
_writer: &mut UserSlicePtrWriter,
Expand All @@ -484,7 +484,7 @@ pub trait IoctlHandler: Sync {
/// Handles ioctls defined with the `_IOW` macro, that is, with an input buffer provided as
/// argument.
fn write(
_this: &Self::Target,
_this: Self::Target<'_>,
_file: &File,
_cmd: u32,
_reader: &mut UserSlicePtrReader,
Expand All @@ -495,7 +495,7 @@ pub trait IoctlHandler: Sync {
/// Handles ioctls defined with the `_IOWR` macro, that is, with a buffer for both input and
/// output provided as argument.
fn read_write(
_this: &Self::Target,
_this: Self::Target<'_>,
_file: &File,
_cmd: u32,
_data: UserSlicePtr,
Expand Down Expand Up @@ -535,7 +535,11 @@ impl IoctlCommand {
///
/// It is meant to be used in implementations of [`FileOperations::ioctl`] and
/// [`FileOperations::compat_ioctl`].
pub fn dispatch<T: IoctlHandler>(&mut self, handler: &T::Target, file: &File) -> Result<i32> {
pub fn dispatch<T: IoctlHandler>(
&mut self,
handler: T::Target<'_>,
file: &File,
) -> Result<i32> {
let dir = (self.cmd >> bindings::_IOC_DIRSHIFT) & bindings::_IOC_DIRMASK;
if dir == bindings::_IOC_NONE {
return T::pure(handler, file, self.cmd, self.arg);
Expand Down Expand Up @@ -604,7 +608,7 @@ impl<T: FileOperations<Wrapper = Box<T>> + Default> FileOpener<()> for T {
/// File descriptors may be used from multiple threads/processes concurrently, so your type must be
/// [`Sync`]. It must also be [`Send`] because [`FileOperations::release`] will be called from the
/// thread that decrements that associated file's refcount to zero.
pub trait FileOperations: Send + Sync + Sized {
pub trait FileOperations: Send + Sync + Sized + 'static {
/// The methods to use to populate [`struct file_operations`].
const TO_USE: ToUse;

Expand All @@ -623,7 +627,7 @@ pub trait FileOperations: Send + Sync + Sized {
///
/// Corresponds to the `read` and `read_iter` function pointers in `struct file_operations`.
fn read(
_this: &<<Self::Wrapper as PointerWrapper>::Borrowed as Deref>::Target,
_this: <Self::Wrapper as PointerWrapper>::Borrowed<'_>,
_file: &File,
_data: &mut impl IoBufferWriter,
_offset: u64,
Expand All @@ -635,7 +639,7 @@ pub trait FileOperations: Send + Sync + Sized {
///
/// Corresponds to the `write` and `write_iter` function pointers in `struct file_operations`.
fn write(
_this: &<<Self::Wrapper as PointerWrapper>::Borrowed as Deref>::Target,
_this: <Self::Wrapper as PointerWrapper>::Borrowed<'_>,
_file: &File,
_data: &mut impl IoBufferReader,
_offset: u64,
Expand All @@ -647,7 +651,7 @@ pub trait FileOperations: Send + Sync + Sized {
///
/// Corresponds to the `llseek` function pointer in `struct file_operations`.
fn seek(
_this: &<<Self::Wrapper as PointerWrapper>::Borrowed as Deref>::Target,
_this: <Self::Wrapper as PointerWrapper>::Borrowed<'_>,
_file: &File,
_offset: SeekFrom,
) -> Result<u64> {
Expand All @@ -658,7 +662,7 @@ pub trait FileOperations: Send + Sync + Sized {
///
/// Corresponds to the `unlocked_ioctl` function pointer in `struct file_operations`.
fn ioctl(
_this: &<<Self::Wrapper as PointerWrapper>::Borrowed as Deref>::Target,
_this: <Self::Wrapper as PointerWrapper>::Borrowed<'_>,
_file: &File,
_cmd: &mut IoctlCommand,
) -> Result<i32> {
Expand All @@ -669,7 +673,7 @@ pub trait FileOperations: Send + Sync + Sized {
///
/// Corresponds to the `compat_ioctl` function pointer in `struct file_operations`.
fn compat_ioctl(
_this: &<<Self::Wrapper as PointerWrapper>::Borrowed as Deref>::Target,
_this: <Self::Wrapper as PointerWrapper>::Borrowed<'_>,
_file: &File,
_cmd: &mut IoctlCommand,
) -> Result<i32> {
Expand All @@ -680,7 +684,7 @@ pub trait FileOperations: Send + Sync + Sized {
///
/// Corresponds to the `fsync` function pointer in `struct file_operations`.
fn fsync(
_this: &<<Self::Wrapper as PointerWrapper>::Borrowed as Deref>::Target,
_this: <Self::Wrapper as PointerWrapper>::Borrowed<'_>,
_file: &File,
_start: u64,
_end: u64,
Expand All @@ -694,7 +698,7 @@ pub trait FileOperations: Send + Sync + Sized {
/// Corresponds to the `mmap` function pointer in `struct file_operations`.
/// TODO: wrap `vm_area_struct` so that we don't have to expose it.
fn mmap(
_this: &<<Self::Wrapper as PointerWrapper>::Borrowed as Deref>::Target,
_this: <Self::Wrapper as PointerWrapper>::Borrowed<'_>,
_file: &File,
_vma: &mut bindings::vm_area_struct,
) -> Result {
Expand All @@ -706,7 +710,7 @@ pub trait FileOperations: Send + Sync + Sized {
///
/// Corresponds to the `poll` function pointer in `struct file_operations`.
fn poll(
_this: &<<Self::Wrapper as PointerWrapper>::Borrowed as Deref>::Target,
_this: <Self::Wrapper as PointerWrapper>::Borrowed<'_>,
_file: &File,
_table: &PollTable,
) -> Result<u32> {
Expand Down
Loading