Skip to content

Commit cd969b5

Browse files
authored
Merge pull request torvalds#617 from wedsonaf/file-opener
rust: simplify file operations by removing `FileOpener`
2 parents 00bb9f4 + 6b7165b commit cd969b5

File tree

10 files changed

+83
-98
lines changed

10 files changed

+83
-98
lines changed

drivers/android/process.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use kernel::{
55
bindings, c_types,
66
cred::Credential,
77
file::File,
8-
file_operations::{FileOpener, FileOperations, IoctlCommand, IoctlHandler, PollTable},
8+
file_operations::{FileOperations, IoctlCommand, IoctlHandler, PollTable},
99
io_buffer::{IoBufferReader, IoBufferWriter},
1010
linked_list::List,
1111
pages::Pages,
@@ -806,17 +806,16 @@ impl IoctlHandler for Process {
806806
}
807807
}
808808

809-
impl FileOpener<Ref<Context>> for Process {
810-
fn open(ctx: &Ref<Context>, file: &File) -> Result<Self::Wrapper> {
811-
Self::new(ctx.clone(), file.cred().clone())
812-
}
813-
}
814-
815809
impl FileOperations for Process {
816810
type Wrapper = Ref<Self>;
811+
type OpenData = Ref<Context>;
817812

818813
kernel::declare_file_operations!(ioctl, compat_ioctl, mmap, poll);
819814

815+
fn open(ctx: &Ref<Context>, file: &File) -> Result<Self::Wrapper> {
816+
Self::new(ctx.clone(), file.cred().clone())
817+
}
818+
820819
fn release(obj: Self::Wrapper, _file: &File) {
821820
// Mark this process as dead. We'll do the same for the threads later.
822821
obj.inner.lock().is_dead = true;

drivers/android/rust_binder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,13 @@ const fn ptr_align(value: usize) -> usize {
102102
unsafe impl Sync for BinderModule {}
103103

104104
struct BinderModule {
105-
_reg: Pin<Box<Registration<Ref<Context>>>>,
105+
_reg: Pin<Box<Registration<process::Process>>>,
106106
}
107107

108108
impl KernelModule for BinderModule {
109109
fn init(name: &'static CStr, _module: &'static kernel::ThisModule) -> Result<Self> {
110110
let ctx = Context::new()?;
111-
let reg = Registration::new_pinned::<process::Process>(name, None, ctx)?;
111+
let reg = Registration::new_pinned(name, None, ctx)?;
112112
Ok(Self { _reg: reg })
113113
}
114114
}

drivers/char/hw_random/bcm2835_rng_rust.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@ module! {
1818
license: b"GPL v2",
1919
}
2020

21-
#[derive(Default)]
2221
struct RngDevice;
2322

2423
impl FileOperations for RngDevice {
2524
kernel::declare_file_operations!(read);
2625

26+
fn open(_open_data: &(), _file: &File) -> Result<Self::Wrapper> {
27+
Ok(Box::try_new(RngDevice)?)
28+
}
29+
2730
fn read(_: &Self, _: &File, data: &mut impl IoBufferWriter, offset: u64) -> Result<usize> {
2831
// Succeed if the caller doesn't provide a buffer or if not at the start.
2932
if data.is_empty() || offset != 0 {
@@ -38,12 +41,11 @@ impl FileOperations for RngDevice {
3841
struct RngDriver;
3942

4043
impl PlatformDriver for RngDriver {
41-
type DrvData = Pin<Box<miscdev::Registration<()>>>;
44+
type DrvData = Pin<Box<miscdev::Registration<RngDevice>>>;
4245

4346
fn probe(device_id: i32) -> Result<Self::DrvData> {
4447
pr_info!("probing discovered hwrng with id {}\n", device_id);
45-
let drv_data =
46-
miscdev::Registration::new_pinned::<RngDevice>(c_str!("rust_hwrng"), None, ())?;
48+
let drv_data = miscdev::Registration::new_pinned(c_str!("rust_hwrng"), None, ())?;
4749
Ok(drv_data)
4850
}
4951

rust/kernel/chrdev.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ impl<const N: usize> Registration<{ N }> {
134134
/// Registers a character device.
135135
///
136136
/// You may call this once per device type, up to `N` times.
137-
pub fn register<T: file_operations::FileOpener<()>>(self: Pin<&mut Self>) -> Result {
137+
pub fn register<T: file_operations::FileOperations<OpenData = ()>>(
138+
self: Pin<&mut Self>,
139+
) -> Result {
138140
// SAFETY: We must ensure that we never move out of `this`.
139141
let this = unsafe { self.get_unchecked_mut() };
140142
if this.inner.is_none() {
@@ -177,13 +179,8 @@ impl<const N: usize> Registration<{ N }> {
177179
}
178180
}
179181

180-
impl<const N: usize> file_operations::FileOpenAdapter for Registration<{ N }> {
181-
type Arg = ();
182-
183-
unsafe fn convert(
184-
_inode: *mut bindings::inode,
185-
_file: *mut bindings::file,
186-
) -> *const Self::Arg {
182+
impl<const N: usize> file_operations::FileOpenAdapter<()> for Registration<{ N }> {
183+
unsafe fn convert(_inode: *mut bindings::inode, _file: *mut bindings::file) -> *const () {
187184
// TODO: Update the SAFETY comment on the call to `FileOperationsVTable::build` above once
188185
// this is updated to retrieve state.
189186
&()

rust/kernel/file_operations.rs

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub enum SeekFrom {
8686
///
8787
/// The returned value of `A::convert` must be a valid non-null pointer and
8888
/// `T:open` must return a valid non-null pointer on an `Ok` result.
89-
unsafe extern "C" fn open_callback<A: FileOpenAdapter, T: FileOpener<A::Arg>>(
89+
unsafe extern "C" fn open_callback<A: FileOpenAdapter<T::OpenData>, T: FileOperations>(
9090
inode: *mut bindings::inode,
9191
file: *mut bindings::file,
9292
) -> c_types::c_int {
@@ -312,7 +312,7 @@ unsafe extern "C" fn poll_callback<T: FileOperations>(
312312

313313
pub(crate) struct FileOperationsVtable<A, T>(marker::PhantomData<A>, marker::PhantomData<T>);
314314

315-
impl<A: FileOpenAdapter, T: FileOpener<A::Arg>> FileOperationsVtable<A, T> {
315+
impl<A: FileOpenAdapter<T::OpenData>, T: FileOperations> FileOperationsVtable<A, T> {
316316
const VTABLE: bindings::file_operations = bindings::file_operations {
317317
open: Some(open_callback::<A, T>),
318318
release: Some(release_callback::<T>),
@@ -568,10 +568,7 @@ impl IoctlCommand {
568568
/// Trait for extracting file open arguments from kernel data structures.
569569
///
570570
/// This is meant to be implemented by registration managers.
571-
pub trait FileOpenAdapter {
572-
/// The type of argument this adapter extracts.
573-
type Arg;
574-
571+
pub trait FileOpenAdapter<T: Sync> {
575572
/// Converts untyped data stored in [`struct inode`] and [`struct file`] (when [`struct
576573
/// file_operations::open`] is called) into the given type. For example, for `miscdev`
577574
/// devices, a pointer to the registered [`struct miscdev`] is stored in [`struct
@@ -582,27 +579,7 @@ pub trait FileOpenAdapter {
582579
/// This function must be called only when [`struct file_operations::open`] is being called for
583580
/// a file that was registered by the implementer. The returned pointer must be valid and
584581
/// not-null.
585-
unsafe fn convert(_inode: *mut bindings::inode, _file: *mut bindings::file)
586-
-> *const Self::Arg;
587-
}
588-
589-
/// Trait for implementers of kernel files.
590-
///
591-
/// In addition to the methods in [`FileOperations`], implementers must also provide
592-
/// [`FileOpener::open`] with a customised argument. This allows a single implementation of
593-
/// [`FileOperations`] to be used for different types of registrations, for example, `miscdev` and
594-
/// `chrdev`.
595-
pub trait FileOpener<T: ?Sized>: FileOperations {
596-
/// Creates a new instance of this file.
597-
///
598-
/// Corresponds to the `open` function pointer in `struct file_operations`.
599-
fn open(context: &T, file: &File) -> Result<Self::Wrapper>;
600-
}
601-
602-
impl<T: FileOperations<Wrapper = Box<T>> + Default> FileOpener<()> for T {
603-
fn open(_: &(), _file: &File) -> Result<Self::Wrapper> {
604-
Ok(Box::try_new(T::default())?)
605-
}
582+
unsafe fn convert(_inode: *mut bindings::inode, _file: *mut bindings::file) -> *const T;
606583
}
607584

608585
/// Corresponds to the kernel's `struct file_operations`.
@@ -619,6 +596,14 @@ pub trait FileOperations: Send + Sync + Sized + 'static {
619596
/// The pointer type that will be used to hold ourselves.
620597
type Wrapper: PointerWrapper = Box<Self>;
621598

599+
/// The type of the context data passed to [`FileOperations::open`].
600+
type OpenData: Sync = ();
601+
602+
/// Creates a new instance of this file.
603+
///
604+
/// Corresponds to the `open` function pointer in `struct file_operations`.
605+
fn open(context: &Self::OpenData, file: &File) -> Result<Self::Wrapper>;
606+
622607
/// Cleans up after the last reference to the file goes away.
623608
///
624609
/// Note that the object is moved, so it will be freed automatically unless the implementation

rust/kernel/miscdev.rs

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,28 @@
88
99
use crate::bindings;
1010
use crate::error::{Error, Result};
11-
use crate::file_operations::{FileOpenAdapter, FileOpener, FileOperationsVtable};
11+
use crate::file_operations::{FileOpenAdapter, FileOperations, FileOperationsVtable};
1212
use crate::{str::CStr, KernelModule, ThisModule};
1313
use alloc::boxed::Box;
14-
use core::marker::{PhantomData, PhantomPinned};
14+
use core::marker::PhantomPinned;
1515
use core::{mem::MaybeUninit, pin::Pin};
1616

1717
/// A registration of a miscellaneous device.
1818
///
1919
/// # Invariants
2020
///
2121
/// `Context` is always initialised when `registered` is `true`, and not initialised otherwise.
22-
pub struct Registration<T: Sync = ()> {
22+
pub struct Registration<T: FileOperations> {
2323
registered: bool,
2424
mdev: bindings::miscdevice,
2525
_pin: PhantomPinned,
2626

2727
/// Context initialised on construction and made available to all file instances on
28-
/// [`FileOpener::open`].
29-
open_data: MaybeUninit<T>,
28+
/// [`FileOperations::open`].
29+
open_data: MaybeUninit<T::OpenData>,
3030
}
3131

32-
impl<T: Sync> Registration<T> {
32+
impl<T: FileOperations> Registration<T> {
3333
/// Creates a new [`Registration`] but does not register it yet.
3434
///
3535
/// It is allowed to move.
@@ -46,25 +46,25 @@ impl<T: Sync> Registration<T> {
4646
/// Registers a miscellaneous device.
4747
///
4848
/// Returns a pinned heap-allocated representation of the registration.
49-
pub fn new_pinned<F: FileOpener<T>>(
49+
pub fn new_pinned(
5050
name: &'static CStr,
5151
minor: Option<i32>,
52-
open_data: T,
52+
open_data: T::OpenData,
5353
) -> Result<Pin<Box<Self>>> {
5454
let mut r = Pin::from(Box::try_new(Self::new())?);
55-
r.as_mut().register::<F>(name, minor, open_data)?;
55+
r.as_mut().register(name, minor, open_data)?;
5656
Ok(r)
5757
}
5858

5959
/// Registers a miscellaneous device with the rest of the kernel.
6060
///
6161
/// It must be pinned because the memory block that represents the registration is
6262
/// self-referential. If a minor is not given, the kernel allocates a new one if possible.
63-
pub fn register<F: FileOpener<T>>(
63+
pub fn register(
6464
self: Pin<&mut Self>,
6565
name: &'static CStr,
6666
minor: Option<i32>,
67-
open_data: T,
67+
open_data: T::OpenData,
6868
) -> Result {
6969
// SAFETY: We must ensure that we never move out of `this`.
7070
let this = unsafe { self.get_unchecked_mut() };
@@ -74,7 +74,7 @@ impl<T: Sync> Registration<T> {
7474
}
7575

7676
// SAFETY: The adapter is compatible with `misc_register`.
77-
this.mdev.fops = unsafe { FileOperationsVtable::<Self, F>::build() };
77+
this.mdev.fops = unsafe { FileOperationsVtable::<Self, T>::build() };
7878
this.mdev.name = name.as_char_ptr();
7979
this.mdev.minor = minor.unwrap_or(bindings::MISC_DYNAMIC_MINOR as i32);
8080

@@ -98,16 +98,17 @@ impl<T: Sync> Registration<T> {
9898
}
9999
}
100100

101-
impl<T: Sync> Default for Registration<T> {
101+
impl<T: FileOperations> Default for Registration<T> {
102102
fn default() -> Self {
103103
Self::new()
104104
}
105105
}
106106

107-
impl<T: Sync> FileOpenAdapter for Registration<T> {
108-
type Arg = T;
109-
110-
unsafe fn convert(_inode: *mut bindings::inode, file: *mut bindings::file) -> *const Self::Arg {
107+
impl<T: FileOperations> FileOpenAdapter<T::OpenData> for Registration<T> {
108+
unsafe fn convert(
109+
_inode: *mut bindings::inode,
110+
file: *mut bindings::file,
111+
) -> *const T::OpenData {
111112
// SAFETY: the caller must guarantee that `file` is valid.
112113
let reg = crate::container_of!(unsafe { (*file).private_data }, Self, mdev);
113114

@@ -120,14 +121,13 @@ impl<T: Sync> FileOpenAdapter for Registration<T> {
120121

121122
// SAFETY: The only method is `register()`, which requires a (pinned) mutable `Registration`, so it
122123
// is safe to pass `&Registration` to multiple threads because it offers no interior mutability.
123-
unsafe impl<T: Sync> Sync for Registration<T> {}
124+
unsafe impl<T: FileOperations> Sync for Registration<T> {}
124125

125126
// SAFETY: All functions work from any thread. So as long as the `Registration::open_data` is
126-
// `Send`, so is `Registration<T>`. `T` needs to be `Sync` because it's a requirement of
127-
// `Registration<T>`.
128-
unsafe impl<T: Send + Sync> Send for Registration<T> {}
127+
// `Send`, so is `Registration<T>`.
128+
unsafe impl<T: FileOperations> Send for Registration<T> where T::OpenData: Send {}
129129

130-
impl<T: Sync> Drop for Registration<T> {
130+
impl<T: FileOperations> Drop for Registration<T> {
131131
/// Removes the registration from the kernel if it has completed successfully before.
132132
fn drop(&mut self) {
133133
if self.registered {
@@ -142,17 +142,15 @@ impl<T: Sync> Drop for Registration<T> {
142142
}
143143
}
144144

145-
/// Kernel module that exposes a single miscdev device implemented by `F`.
146-
pub struct Module<F: FileOpener<()>> {
147-
_dev: Pin<Box<Registration>>,
148-
_p: PhantomData<F>,
145+
/// Kernel module that exposes a single miscdev device implemented by `T`.
146+
pub struct Module<T: FileOperations<OpenData = ()>> {
147+
_dev: Pin<Box<Registration<T>>>,
149148
}
150149

151-
impl<F: FileOpener<()>> KernelModule for Module<F> {
150+
impl<T: FileOperations<OpenData = ()>> KernelModule for Module<T> {
152151
fn init(name: &'static CStr, _module: &'static ThisModule) -> Result<Self> {
153152
Ok(Self {
154-
_p: PhantomData,
155-
_dev: Registration::new_pinned::<F>(name, None, ())?,
153+
_dev: Registration::new_pinned(name, None, ())?,
156154
})
157155
}
158156
}

samples/rust/rust_chrdev.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#![feature(allocator_api, global_asm)]
77

88
use kernel::prelude::*;
9-
use kernel::{chrdev, file_operations::FileOperations};
9+
use kernel::{chrdev, file, file_operations::FileOperations};
1010

1111
module! {
1212
type: RustChrdev,
@@ -16,11 +16,14 @@ module! {
1616
license: b"GPL v2",
1717
}
1818

19-
#[derive(Default)]
2019
struct RustFile;
2120

2221
impl FileOperations for RustFile {
2322
kernel::declare_file_operations!();
23+
24+
fn open(_shared: &(), _file: &file::File) -> Result<Self::Wrapper> {
25+
Ok(Box::try_new(RustFile)?)
26+
}
2427
}
2528

2629
struct RustChrdev {

samples/rust/rust_miscdev.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use kernel::prelude::*;
99
use kernel::{
1010
file::File,
11-
file_operations::{FileOpener, FileOperations},
11+
file_operations::FileOperations,
1212
io_buffer::{IoBufferReader, IoBufferWriter},
1313
miscdev,
1414
sync::{CondVar, Mutex, Ref, RefBorrow, UniqueRef},
@@ -55,18 +55,16 @@ impl SharedState {
5555
}
5656

5757
struct Token;
58-
59-
impl FileOpener<Ref<SharedState>> for Token {
60-
fn open(shared: &Ref<SharedState>, _file: &File) -> Result<Self::Wrapper> {
61-
Ok(shared.clone())
62-
}
63-
}
64-
6558
impl FileOperations for Token {
6659
type Wrapper = Ref<SharedState>;
60+
type OpenData = Ref<SharedState>;
6761

6862
kernel::declare_file_operations!(read, write);
6963

64+
fn open(shared: &Ref<SharedState>, _file: &File) -> Result<Self::Wrapper> {
65+
Ok(shared.clone())
66+
}
67+
7068
fn read(
7169
shared: RefBorrow<'_, SharedState>,
7270
_: &File,
@@ -127,7 +125,7 @@ impl FileOperations for Token {
127125
}
128126

129127
struct RustMiscdev {
130-
_dev: Pin<Box<miscdev::Registration<Ref<SharedState>>>>,
128+
_dev: Pin<Box<miscdev::Registration<Token>>>,
131129
}
132130

133131
impl KernelModule for RustMiscdev {
@@ -137,7 +135,7 @@ impl KernelModule for RustMiscdev {
137135
let state = SharedState::try_new()?;
138136

139137
Ok(RustMiscdev {
140-
_dev: miscdev::Registration::new_pinned::<Token>(name, None, state)?,
138+
_dev: miscdev::Registration::new_pinned(name, None, state)?,
141139
})
142140
}
143141
}

0 commit comments

Comments
 (0)