Skip to content

Commit 7822b81

Browse files
committed
compiling
1 parent c199401 commit 7822b81

File tree

6 files changed

+423
-159
lines changed

6 files changed

+423
-159
lines changed

rust/kernel/bindings_helper.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include <linux/errname.h>
77
#include <linux/fs.h>
88
#include <linux/module.h>
9-
#include <linux/proc_fs.h>
109
#include <linux/random.h>
1110
#include <linux/seq_file.h>
1211
#include <linux/slab.h>

rust/kernel/debugfs.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! TODOABK: finish doc
4+
5+
use core::{
6+
marker::{PhantomData, Sync},
7+
ptr,
8+
};
9+
10+
use crate::{bindings, c_types, error, str::CStr, types::PointerWrapper, Result};
11+
12+
/// TODOABK: finish doc
13+
pub struct DebugFsDirEntry<T: PointerWrapper> {
14+
dentry: *mut bindings::dentry,
15+
data: *mut c_types::c_void,
16+
_wrapper: PhantomData<T>,
17+
}
18+
19+
// TODOABK: safety
20+
unsafe impl<T: PointerWrapper> Sync for DebugFsDirEntry<T> {}
21+
22+
impl<T: PointerWrapper> DebugFsDirEntry<T> {
23+
pub(crate) unsafe fn create_file(
24+
name: &CStr,
25+
data: T,
26+
fops: &'static bindings::file_operations,
27+
) -> Result<Self> {
28+
let name = name.as_char_ptr();
29+
let data = data.into_pointer() as *mut _;
30+
let dentry_ptr = error::from_kernel_err_ptr(unsafe {
31+
bindings::debugfs_create_file(name, 0, ptr::null_mut(), data, fops)
32+
});
33+
match dentry_ptr {
34+
Err(err) => {
35+
drop(unsafe { T::from_pointer(data) });
36+
Err(err)
37+
}
38+
Ok(dentry) => Ok(DebugFsDirEntry {
39+
dentry,
40+
data,
41+
_wrapper: PhantomData,
42+
}),
43+
}
44+
}
45+
}
46+
47+
impl<T: PointerWrapper> Drop for DebugFsDirEntry<T> {
48+
fn drop(&mut self) {
49+
// TODOABK: safety
50+
unsafe {
51+
bindings::debugfs_remove(self.dentry);
52+
}
53+
// SAFETY: `self.data` was created by a call to `T::into_pointer`.
54+
unsafe { drop(T::from_pointer(self.data)) }
55+
}
56+
}

rust/kernel/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ pub mod chrdev;
4848
#[cfg(CONFIG_COMMON_CLK)]
4949
pub mod clk;
5050
pub mod cred;
51+
#[cfg(CONFIG_DEBUG_FS)]
52+
pub mod debugfs;
5153
pub mod device;
5254
pub mod driver;
5355
mod error;
@@ -75,9 +77,6 @@ mod build_assert;
7577
pub mod prelude;
7678
pub mod print;
7779

78-
#[cfg(CONFIG_PROC_FS)]
79-
pub mod proc_fs;
80-
8180
pub mod random;
8281
pub mod seq_file;
8382
mod static_assert;

rust/kernel/seq_file.rs

Lines changed: 82 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,18 @@
1313
#![cfg(CONFIG_PROC_FS)]
1414

1515
use core::{
16-
iter::{Iterator, Peekable},
16+
fmt::{self, Display},
1717
marker::PhantomData,
18-
mem,
19-
ops::{Deref, DerefMut},
20-
ptr,
18+
mem, ptr,
2119
};
2220

23-
use crate::{bindings, c_str, c_types, str::CStr, types::PointerWrapper, Result};
21+
use crate::{
22+
bindings, c_str, c_types,
23+
debugfs::DebugFsDirEntry,
24+
str::{CStr, CString},
25+
types::PointerWrapper,
26+
Result,
27+
};
2428

2529
/// Rust equivalent of the [`seq_operations`] interface on the C side.
2630
///
@@ -54,22 +58,30 @@ use crate::{bindings, c_str, c_types, str::CStr, types::PointerWrapper, Result};
5458
/// [`seq_operations`]: ../../../include/linux/seq_file.h
5559
pub trait SeqOperations {
5660
/// Type produced on each iteration.
57-
type Item;
58-
59-
/// Type created when the seq file is opened.
60-
type Iterator: Iterator<Item = Self::Item>;
61+
type Item: Display;
6162

6263
/// Wrapper used to store a pointer to `Self` on the C side.
63-
type DataWrapper: PointerWrapper + Deref<Target = Self>;
64+
type DataWrapper: PointerWrapper;
6465

6566
/// Wrapper used to store a pointer to the iterator on the C side.
66-
type IteratorWrapper: PointerWrapper + DerefMut<Target = Peekable<Self::Iterator>>;
67+
type IteratorWrapper: PointerWrapper;
68+
69+
/// TODOABK
70+
type OpenData: PointerWrapper + Sync;
6771

6872
/// Called once each time the `seq_file` is opened.
69-
fn start(&self) -> Result<Self::IteratorWrapper>;
73+
fn start(data: &Self::DataWrapper) -> Option<Self::IteratorWrapper>;
7074

71-
/// How the item will be displayed to the reader.
72-
fn display(item: &Self::Item) -> &str;
75+
/// TODOABK: docs
76+
fn next(iterator: &mut Self::IteratorWrapper) -> bool;
77+
78+
/// TODOABK: docs
79+
fn current(iterator: &Self::IteratorWrapper) -> Option<Self::Item>;
80+
81+
/// TODOABK: docs
82+
fn open<'a>(
83+
open_data: <Self::OpenData as PointerWrapper>::Borrowed<'a>,
84+
) -> Result<Self::DataWrapper>;
7385
}
7486

7587
extern "C" fn stop_callback<T: SeqOperations>(
@@ -105,21 +117,18 @@ extern "C" fn next_callback<T: SeqOperations>(
105117
*pos += 1;
106118
}
107119

108-
if iterator.next().is_none() {
109-
return ptr::null_mut();
110-
}
111-
112-
match iterator.peek() {
113-
Some(_next) => T::IteratorWrapper::into_pointer(iterator) as *mut _,
114-
None => ptr::null_mut(),
120+
if !T::next(&mut iterator) {
121+
ptr::null_mut()
122+
} else {
123+
T::IteratorWrapper::into_pointer(iterator) as *mut _
115124
}
116125
}
117126

118127
extern "C" fn show_callback<T: SeqOperations>(
119128
m: *mut bindings::seq_file,
120129
v: *mut c_types::c_void,
121130
) -> c_types::c_int {
122-
const FORMAT: &CStr = c_str!("%.*s");
131+
const FORMAT: &CStr = c_str!("%pA");
123132
if v.is_null() {
124133
return 0;
125134
}
@@ -128,18 +137,16 @@ extern "C" fn show_callback<T: SeqOperations>(
128137
// or pointer generated by `T::IteratorWrapper::into_pointer`. We
129138
// checked for null pointers above. The iterator is forgotten below
130139
// so the pointer on the C side stays valid.
131-
let mut iterator = unsafe { T::IteratorWrapper::from_pointer(v) };
132-
if let Some(item) = iterator.peek() {
133-
let s = T::display(item);
140+
let iterator = unsafe { T::IteratorWrapper::from_pointer(v) };
141+
if let Some(item) = T::current(&iterator) {
134142
// SAFETY: Calling a C function. `FORMAT` is null terminated because
135143
// it comes from a `CStr`. `s` does not need to be null terminated
136144
// because we are only printing the first `s.len()` bytes.
137145
unsafe {
138146
bindings::seq_printf(
139147
m,
140-
FORMAT.as_char_ptr(),
141-
s.len(),
142-
s.as_ptr() as *const u8 as *const c_types::c_char,
148+
(FORMAT as *const _) as *const _,
149+
(&format_args!("{}", item) as *const _) as *const _,
143150
);
144151
}
145152
}
@@ -158,55 +165,64 @@ extern "C" fn start_callback<T: SeqOperations>(
158165
// `T::DataWrapper::into_pointer`. We don't move the data in the wrapper
159166
// so the pointer will remain valid for later calls.
160167
let data_wrapper = unsafe { T::DataWrapper::from_pointer((*m).private) };
161-
let iterator = data_wrapper.start().ok();
168+
let iterator = T::start(&data_wrapper);
162169
// Data is still used in the `proc_dir_entry`.
163170
mem::forget(data_wrapper);
164171
// SAFETY: The caller guarantees that `pos` points to a valid `loff_t`.
165172
let pos = unsafe { *pos };
166173
match iterator {
167174
Some(mut wrapper) => {
168175
for _ in 0..pos {
169-
if wrapper.next().is_none() {
176+
if !T::next(&mut wrapper) {
170177
return ptr::null_mut();
171178
}
172179
}
173-
match wrapper.peek() {
174-
Some(_next) => T::IteratorWrapper::into_pointer(wrapper) as *mut _,
175-
None => ptr::null_mut(),
176-
}
180+
T::IteratorWrapper::into_pointer(wrapper) as *mut _
177181
}
178182
None => ptr::null_mut(),
179183
}
180184
}
181185

182186
pub(crate) struct SeqFileOperationsVTable<T>(PhantomData<T>);
183187

184-
impl<T: SeqOperations> SeqFileOperationsVTable<T> {
188+
impl<'a, T, D: 'a> SeqFileOperationsVTable<T>
189+
where
190+
T: SeqOperations<DataWrapper = D>,
191+
D: PointerWrapper,
192+
{
185193
const SEQ_VTABLE: bindings::seq_operations = bindings::seq_operations {
186194
start: Some(start_callback::<T>),
187195
stop: Some(stop_callback::<T>),
188196
next: Some(next_callback::<T>),
189197
show: Some(show_callback::<T>),
190198
};
191199

192-
// TODOABK: safety
193-
pub(crate) const unsafe fn seq_build() -> &'static bindings::seq_operations {
194-
&Self::SEQ_VTABLE
195-
}
196-
197200
extern "C" fn open_callback(
198201
inode: *mut bindings::inode,
199202
file: *mut bindings::file,
200203
) -> c_types::c_int {
201204
// TODOABK: docs
202-
unsafe {
203-
bindings::seq_open_private(
205+
let result = unsafe {
206+
bindings::seq_open(
204207
file,
205208
&Self::SEQ_VTABLE as *const _ as *mut bindings::seq_operations,
206-
// TODOABK: how to convert safely?
207-
mem::size_of::<T::DataWrapper>() as i32,
208209
)
210+
};
211+
if result != 0 {
212+
// Close file?
213+
return result;
209214
}
215+
216+
let open_data = unsafe { T::OpenData::borrow((*inode).i_private) };
217+
218+
let data_wrapper = match T::open(open_data) {
219+
Ok(data) => data,
220+
Err(err) => return err.to_kernel_errno(),
221+
};
222+
223+
unsafe { *((*file).private_data as *mut bindings::seq_file) }.private =
224+
data_wrapper.into_pointer() as *mut _;
225+
result
210226
}
211227

212228
const VTABLE: bindings::file_operations = bindings::file_operations {
@@ -244,9 +260,27 @@ impl<T: SeqOperations> SeqFileOperationsVTable<T> {
244260
write: None,
245261
write_iter: None,
246262
};
263+
}
247264

248-
// TODOABK: safety
249-
pub(crate) const unsafe fn build() -> &'static bindings::file_operations {
250-
&Self::VTABLE
251-
}
265+
/// TODOABK: docs
266+
pub struct SeqFileDebugFsDirEntry<T: SeqOperations> {
267+
_debugfs_entry: DebugFsDirEntry<T::DataWrapper>,
268+
}
269+
270+
/// TODOABK: finish doc
271+
pub fn debugfs_create_file<'a, T, D: 'a>(
272+
name: fmt::Arguments<'_>,
273+
data: D,
274+
) -> Result<SeqFileDebugFsDirEntry<T>>
275+
where
276+
T: SeqOperations<DataWrapper = D>,
277+
D: PointerWrapper + Clone,
278+
{
279+
let name = CString::try_from_fmt(name)?;
280+
let debugfs_entry = unsafe {
281+
DebugFsDirEntry::create_file(&name, data, &SeqFileOperationsVTable::<T>::VTABLE)
282+
}?;
283+
Ok(SeqFileDebugFsDirEntry {
284+
_debugfs_entry: debugfs_entry,
285+
})
252286
}

0 commit comments

Comments
 (0)