Skip to content

Commit

Permalink
Merge pull request torvalds#230 from wedsonaf/read-write
Browse files Browse the repository at this point in the history
Generalise `read` and `write`.
  • Loading branch information
alex authored Apr 28, 2021
2 parents d2a231a + 8aa5a4e commit 4e2d67e
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 21 deletions.
33 changes: 20 additions & 13 deletions rust/kernel/file_operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ use core::{marker, mem, ops::Deref, pin::Pin, ptr};
use alloc::boxed::Box;
use alloc::sync::Arc;

use crate::bindings;
use crate::c_types;
use crate::error::{Error, KernelResult};
use crate::sync::{CondVar, Ref, RefCounted};
use crate::user_ptr::{UserSlicePtr, UserSlicePtrReader, UserSlicePtrWriter};
use crate::{
bindings, c_types,
error::{Error, KernelResult},
io_buffer::{IoBufferReader, IoBufferWriter},
sync::{CondVar, Ref, RefCounted},
user_ptr::{UserSlicePtr, UserSlicePtrReader, UserSlicePtrWriter},
};

/// Wraps the kernel's `struct file`.
///
Expand Down Expand Up @@ -166,7 +168,7 @@ unsafe extern "C" fn write_callback<T: FileOperations>(
let f = &*((*file).private_data as *const T);
// 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 = f.write(&mut data, (*offset).try_into()?)?;
let written = f.write(&File::from_ptr(file), &mut data, (*offset).try_into()?)?;
(*offset) += bindings::loff_t::try_from(written).unwrap();
Ok(written as _)
}
Expand Down Expand Up @@ -548,22 +550,27 @@ pub trait FileOperations: Send + Sync + Sized {
/// Corresponds to the `release` function pointer in `struct file_operations`.
fn release(_obj: Self::Wrapper, _file: &File) {}

/// Reads data from this file to userspace.
/// Reads data from this file to the caller's buffer.
///
/// Corresponds to the `read` function pointer in `struct file_operations`.
fn read(
/// Corresponds to the `read` and `read_iter` function pointers in `struct file_operations`.
fn read<T: IoBufferWriter>(
&self,
_file: &File,
_data: &mut UserSlicePtrWriter,
_data: &mut T,
_offset: u64,
) -> KernelResult<usize> {
Err(Error::EINVAL)
}

/// Writes data from userspace to this file.
/// Writes data from the caller's buffer to this file.
///
/// Corresponds to the `write` function pointer in `struct file_operations`.
fn write(&self, _data: &mut UserSlicePtrReader, _offset: u64) -> KernelResult<usize> {
/// Corresponds to the `write` and `write_iter` function pointers in `struct file_operations`.
fn write<T: IoBufferReader>(
&self,
_file: &File,
_data: &mut T,
_offset: u64,
) -> KernelResult<usize> {
Err(Error::EINVAL)
}

Expand Down
10 changes: 7 additions & 3 deletions samples/rust/rust_miscdev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ use kernel::{
io_buffer::{IoBufferReader, IoBufferWriter},
miscdev,
sync::{CondVar, Mutex},
user_ptr::{UserSlicePtrReader, UserSlicePtrWriter},
Error,
};

Expand Down Expand Up @@ -74,7 +73,7 @@ impl FileOperations for Token {

kernel::declare_file_operations!(read, write);

fn read(&self, _: &File, data: &mut UserSlicePtrWriter, offset: u64) -> KernelResult<usize> {
fn read<T: IoBufferWriter>(&self, _: &File, data: &mut T, offset: u64) -> KernelResult<usize> {
// Succeed if the caller doesn't provide a buffer or if not at the start.
if data.is_empty() || offset != 0 {
return Ok(0);
Expand Down Expand Up @@ -102,7 +101,12 @@ impl FileOperations for Token {
Ok(1)
}

fn write(&self, data: &mut UserSlicePtrReader, _offset: u64) -> KernelResult<usize> {
fn write<T: IoBufferReader>(
&self,
_: &File,
data: &mut T,
_offset: u64,
) -> KernelResult<usize> {
{
let mut inner = self.shared.inner.lock();

Expand Down
15 changes: 12 additions & 3 deletions samples/rust/rust_random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ use kernel::{
file_operations::{File, FileOperations},
io_buffer::{IoBufferReader, IoBufferWriter},
prelude::*,
user_ptr::{UserSlicePtrReader, UserSlicePtrWriter},
};

#[derive(Default)]
Expand All @@ -21,7 +20,12 @@ struct RandomFile;
impl FileOperations for RandomFile {
kernel::declare_file_operations!(read, write);

fn read(&self, file: &File, buf: &mut UserSlicePtrWriter, _offset: u64) -> KernelResult<usize> {
fn read<T: IoBufferWriter>(
&self,
file: &File,
buf: &mut T,
_offset: u64,
) -> KernelResult<usize> {
let total_len = buf.len();
let mut chunkbuf = [0; 256];

Expand All @@ -39,7 +43,12 @@ impl FileOperations for RandomFile {
Ok(total_len)
}

fn write(&self, buf: &mut UserSlicePtrReader, _offset: u64) -> KernelResult<usize> {
fn write<T: IoBufferReader>(
&self,
_file: &File,
buf: &mut T,
_offset: u64,
) -> KernelResult<usize> {
let total_len = buf.len();
let mut chunkbuf = [0; 256];
while !buf.is_empty() {
Expand Down
9 changes: 7 additions & 2 deletions samples/rust/rust_semaphore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl FileOperations for FileState {

declare_file_operations!(read, write, ioctl);

fn read(&self, _: &File, data: &mut UserSlicePtrWriter, offset: u64) -> KernelResult<usize> {
fn read<T: IoBufferWriter>(&self, _: &File, data: &mut T, offset: u64) -> KernelResult<usize> {
if data.is_empty() || offset > 0 {
return Ok(0);
}
Expand All @@ -94,7 +94,12 @@ impl FileOperations for FileState {
Ok(1)
}

fn write(&self, data: &mut UserSlicePtrReader, _offset: u64) -> KernelResult<usize> {
fn write<T: IoBufferReader>(
&self,
_: &File,
data: &mut T,
_offset: u64,
) -> KernelResult<usize> {
{
let mut inner = self.shared.inner.lock();
inner.count = inner.count.saturating_add(data.len());
Expand Down

0 comments on commit 4e2d67e

Please sign in to comment.