@@ -16,7 +16,7 @@ use core::{
16
16
iter:: { Iterator , Peekable } ,
17
17
marker:: PhantomData ,
18
18
mem,
19
- ops:: { Deref , DerefMut } ,
19
+ ops:: DerefMut ,
20
20
ptr,
21
21
} ;
22
22
@@ -30,7 +30,7 @@ use crate::{bindings, c_str, c_types, str::CStr, types::PointerWrapper, Result};
30
30
/// #![feature(allocator_api)]
31
31
///
32
32
/// use core::iter::Peekable;
33
- /// use kernel::{Error, Result, seq_file};
33
+ /// use kernel::{Error, Result, seq_file, UnsafeReference };
34
34
///
35
35
/// struct Data(&'static [String]);
36
36
///
@@ -40,8 +40,8 @@ use crate::{bindings, c_str, c_types, str::CStr, types::PointerWrapper, Result};
40
40
/// type DataWrapper = Box<Self>;
41
41
/// type IteratorWrapper = Box<Peekable<Self::Iterator>>;
42
42
///
43
- /// fn start(&self ) -> Result<Self::IteratorWrapper> {
44
- /// let iter = self .0.iter();
43
+ /// fn start(data: UnsafeReference<Data> ) -> Result<Self::IteratorWrapper> {
44
+ /// let iter = data .0.iter();
45
45
/// Box::try_new(iter.peekable()).map_err(|_| Error::ENOMEM)
46
46
/// }
47
47
///
@@ -56,17 +56,20 @@ pub trait SeqOperations {
56
56
/// Type produced on each iteration.
57
57
type Item ;
58
58
59
- /// Type created when the seq file is opened.
59
+ /// Type created when the seq file is read and then iterated through to
60
+ /// produce the file's contents.
60
61
type Iterator : Iterator < Item = Self :: Item > ;
61
62
62
- /// Wrapper used to store a pointer to `Self` on the C side.
63
- type DataWrapper : PointerWrapper + Deref < Target = Self > ;
63
+ /// Wrapper used to store a pointer to the data on the C side.
64
+ type DataWrapper : PointerWrapper ;
64
65
65
66
/// Wrapper used to store a pointer to the iterator on the C side.
66
67
type IteratorWrapper : PointerWrapper + DerefMut < Target = Peekable < Self :: Iterator > > ;
67
68
68
- /// Called once each time the `seq_file` is opened.
69
- fn start ( & self ) -> Result < Self :: IteratorWrapper > ;
69
+ /// Called once each time the `seq_file` is read.
70
+ fn start (
71
+ data : <Self :: DataWrapper as PointerWrapper >:: Borrowed ,
72
+ ) -> Result < Self :: IteratorWrapper > ;
70
73
71
74
/// How the item will be displayed to the reader.
72
75
fn display ( item : & Self :: Item ) -> & str ;
@@ -153,15 +156,15 @@ extern "C" fn start_callback<T: SeqOperations>(
153
156
m : * mut bindings:: seq_file ,
154
157
pos : * mut bindings:: loff_t ,
155
158
) -> * mut c_types:: c_void {
156
- // SAFETY: This function will be called by opening a proc file generated
159
+ // SAFETY: This function will be called by reading a proc file generated
157
160
// from `proc_create_seq_private` on the C side with data created via
158
- // `T::DataWrapper::into_pointer`. We don't move the data in the wrapper
159
- // so the pointer will remain valid for later calls.
160
- let data_wrapper =
161
- unsafe { T :: DataWrapper :: from_pointer ( bindings :: PDE_DATA ( ( * ( * m ) . file ) . f_inode ) ) } ;
162
- let iterator = data_wrapper . start ( ) . ok ( ) ;
163
- // Data is still used in the `proc_dir_entry`.
164
- mem :: forget ( data_wrapper ) ;
161
+ // `T::DataWrapper::into_pointer`. The data will not be destroyed until
162
+ // the proc_dir_entry is destroyed and that operation will wait for all
163
+ // readers to finish, so the data will be valid for the entire borrow. No
164
+ // mutable borrows will be created because this is the only point at which
165
+ // the data is accessed (other than when it is freed).
166
+ let data = unsafe { T :: DataWrapper :: borrow ( bindings :: PDE_DATA ( ( * ( * m ) . file ) . f_inode ) ) } ;
167
+ let iterator = T :: start ( data ) . ok ( ) ;
165
168
// SAFETY: The caller guarantees that `pos` points to a valid `loff_t`.
166
169
let pos = unsafe { * pos } ;
167
170
match iterator {
0 commit comments