@@ -10,8 +10,7 @@ use alloc::{
10
10
} ;
11
11
use axerrno:: { LinuxError , LinuxResult } ;
12
12
use axfs:: fops:: DirEntry ;
13
- use axio:: PollState ;
14
- use axio:: SeekFrom ;
13
+ use axio:: { PollState , SeekFrom } ;
15
14
use axsync:: { Mutex , MutexGuard } ;
16
15
use linux_raw_sys:: general:: S_IFDIR ;
17
16
@@ -20,174 +19,240 @@ use super::{
20
19
page_cache:: { PageCache , page_cache_manager} ,
21
20
} ;
22
21
23
- /// File wrapper for `axfs::fops::File`.
24
- pub struct File {
25
- inner : Option < Arc < Mutex < axfs:: fops:: File > > > ,
26
- path : String ,
27
- is_direct : bool ,
28
- cache : Weak < PageCache > ,
29
- offset : AtomicUsize ,
30
- size : AtomicUsize ,
22
+ /// File wrapper for `axfs::fops::File` with two variants.
23
+ pub enum File {
24
+ Direct {
25
+ path : String ,
26
+ inner : Arc < Mutex < axfs:: fops:: File > > ,
27
+ } ,
28
+ Cached {
29
+ path : String ,
30
+ size : AtomicUsize ,
31
+ offset : AtomicUsize ,
32
+ cache : Weak < PageCache > ,
33
+ } ,
31
34
}
32
35
33
36
impl File {
34
- pub fn new (
35
- inner : Option < Arc < Mutex < axfs:: fops:: File > > > ,
36
- path : String ,
37
- is_direct : bool ,
38
- cache : Weak < PageCache > ,
39
- ) -> Self {
40
- debug ! ( "Starry-api open file {}" , path) ;
37
+ pub fn new_file_direct ( path : String , inner : Arc < Mutex < axfs:: fops:: File > > ) -> Self {
41
38
let size = {
42
- if is_direct {
43
- let inner = inner. clone ( ) . unwrap ( ) ;
44
- let inner = inner. lock ( ) ;
45
- let metadata = inner. get_attr ( ) . unwrap ( ) ;
46
- metadata. size ( ) as usize
47
- } else {
48
- let cache = cache. upgrade ( ) . unwrap ( ) ;
49
- cache. get_file_size ( )
50
- }
39
+ let inner = inner. clone ( ) ;
40
+ let inner = inner. lock ( ) ;
41
+ let metadata = inner. get_attr ( ) . unwrap ( ) ;
42
+ metadata. size ( ) as usize
51
43
} ;
52
- Self {
44
+ File :: Direct {
45
+ path,
53
46
inner,
47
+ }
48
+ }
49
+
50
+ pub fn new_file_cached ( path : String , cache : Weak < PageCache > ) -> Self {
51
+ let size = {
52
+ let cache = cache. upgrade ( ) . unwrap ( ) ;
53
+ cache. file_size ( )
54
+ } ;
55
+ File :: Cached {
54
56
path,
55
- is_direct,
56
- cache,
57
- offset : AtomicUsize :: new ( 0 ) ,
58
57
size : AtomicUsize :: new ( size) ,
58
+ offset : AtomicUsize :: new ( 0 ) ,
59
+ cache,
59
60
}
60
61
}
61
62
62
- pub fn get_cache ( & self ) -> Arc < PageCache > {
63
- self . cache . upgrade ( ) . unwrap ( )
63
+ pub fn size ( & self ) -> usize {
64
+ match self {
65
+ File :: Direct { inner, .. } => {
66
+ let inner = inner. lock ( ) ;
67
+ inner. get_attr ( ) . unwrap ( ) . size ( ) as usize
68
+ } ,
69
+ File :: Cached { size, .. } => {
70
+ size. load ( Ordering :: Relaxed )
71
+ }
72
+ }
64
73
}
65
74
66
- pub fn get_size ( & self ) -> usize {
67
- self . size . load ( Ordering :: SeqCst )
75
+ pub fn offset ( & self ) -> usize {
76
+ match self {
77
+ File :: Direct { .. } => {
78
+ panic ! ( "Please use seek for File::Direc" ) ;
79
+ } ,
80
+ File :: Cached { offset, .. } => {
81
+ offset. load ( Ordering :: Relaxed )
82
+ }
83
+ }
68
84
}
69
85
70
86
/// Get the path of the file.
71
- pub fn path ( & self ) -> & str {
72
- & self . path
87
+ pub fn path ( & self ) -> & String {
88
+ match self {
89
+ File :: Direct { path, .. } | File :: Cached { path, .. } => path,
90
+ }
73
91
}
74
92
75
- /// Get the inner node of the file.
93
+ /// Get the cache of the file. Only available in File::Cached.
94
+ pub fn cache ( & self ) -> Arc < PageCache > {
95
+ match self {
96
+ File :: Direct { .. } => {
97
+ panic ! ( "File::Direct doesn't have cache." ) ;
98
+ }
99
+ File :: Cached { cache, .. } => cache. upgrade ( ) . unwrap ( ) ,
100
+ }
101
+ }
102
+
103
+ /// Get the inner node of the file. Only available in File::Direct.
76
104
fn inner ( & self ) -> MutexGuard < axfs:: fops:: File > {
77
- self . inner . as_ref ( ) . unwrap ( ) . lock ( )
105
+ match self {
106
+ File :: Direct { inner, .. } => inner. lock ( ) ,
107
+ File :: Cached { .. } => {
108
+ panic ! ( "File::Cached doesn't have inner." ) ;
109
+ }
110
+ }
78
111
}
79
112
80
113
pub fn seek ( & self , pos : SeekFrom ) -> LinuxResult < isize > {
81
- if self . is_direct {
82
- match self . inner ( ) . seek ( pos) {
83
- Ok ( pos) => return Ok ( pos as isize ) ,
84
- Err ( e) => {
85
- error ! ( "Seek failed: {}" , e) ;
86
- return Err ( LinuxError :: EINVAL ) ;
114
+ match self {
115
+ File :: Direct { .. } => {
116
+ let mut inner = self . inner ( ) ;
117
+ match inner. seek ( pos) {
118
+ Ok ( pos) => Ok ( pos as isize ) ,
119
+ Err ( e) => {
120
+ error ! ( "Seek failed: {}" , e) ;
121
+ Err ( LinuxError :: EINVAL )
122
+ }
87
123
}
88
124
}
125
+ File :: Cached { offset, .. } => {
126
+ let size = self . size ( ) as u64 ;
127
+ let offset_val = offset. load ( Ordering :: Relaxed ) as u64 ;
128
+ let new_offset = match pos {
129
+ SeekFrom :: Start ( pos) => Some ( pos) ,
130
+ SeekFrom :: Current ( off) => offset_val. checked_add_signed ( off) ,
131
+ SeekFrom :: End ( off) => size. checked_add_signed ( off) ,
132
+ }
133
+ . unwrap_or ( 0 ) ;
134
+ offset. store ( new_offset as usize , Ordering :: SeqCst ) ;
135
+ Ok ( new_offset as isize )
136
+ }
89
137
}
90
- let size = self . size . load ( Ordering :: SeqCst ) as u64 ;
91
- let offset = self . offset . load ( Ordering :: SeqCst ) as u64 ;
92
- let new_offset = match pos {
93
- SeekFrom :: Start ( pos) => Some ( pos) ,
94
- SeekFrom :: Current ( off) => offset. checked_add_signed ( off) ,
95
- SeekFrom :: End ( off) => size. checked_add_signed ( off) ,
96
- }
97
- . unwrap ( ) ;
98
- self . offset . store ( new_offset as usize , Ordering :: SeqCst ) ;
99
- Ok ( new_offset as isize )
100
138
}
101
139
102
140
pub fn fsync ( & self ) -> LinuxResult < usize > {
103
- if self . is_direct {
104
- return Ok ( 0 ) ;
141
+ match self {
142
+ File :: Direct { .. } => Ok ( 0 ) ,
143
+ File :: Cached { .. } => {
144
+ let cache = self . cache ( ) ;
145
+ Ok ( cache. sync ( ) ?)
146
+ }
105
147
}
106
- let cache = self . get_cache ( ) ;
107
- Ok ( cache. sync ( ) ?)
108
148
}
109
149
110
150
pub fn read_at ( & self , buf : & mut [ u8 ] , offset : usize ) -> LinuxResult < usize > {
111
- if self . is_direct {
112
- return Ok ( self . inner ( ) . read_at ( offset as u64 , buf) ?) ;
151
+ match self {
152
+ File :: Direct { .. } => {
153
+ let inner = self . inner ( ) ;
154
+ Ok ( inner. read_at ( offset as u64 , buf) ?)
155
+ }
156
+ File :: Cached { .. } => {
157
+ let cache = self . cache ( ) ;
158
+ Ok ( cache. read_at ( offset, buf) )
159
+ }
113
160
}
114
-
115
- let cache = self . get_cache ( ) ;
116
- Ok ( cache. read_at ( offset, buf) )
117
161
}
118
162
119
163
pub fn write_at ( & self , buf : & [ u8 ] , offset : usize ) -> LinuxResult < usize > {
120
- if self . is_direct {
121
- return Ok ( self . inner ( ) . write_at ( offset as u64 , buf) ?) ;
164
+ match self {
165
+ File :: Direct { .. } => {
166
+ let inner = self . inner ( ) ;
167
+ Ok ( inner. write_at ( offset as u64 , buf) ?)
168
+ }
169
+ File :: Cached { .. } => {
170
+ let cache = self . cache ( ) ;
171
+ Ok ( cache. write_at ( offset, buf) )
172
+ }
122
173
}
123
-
124
- let cache = self . get_cache ( ) ;
125
- Ok ( cache. write_at ( offset, buf) )
126
174
}
127
175
128
176
pub fn truncate ( & self , offset : usize ) -> LinuxResult < usize > {
129
- if self . is_direct {
130
- self . inner ( ) . truncate ( offset as u64 ) ?;
131
- return Ok ( offset) ;
177
+ match self {
178
+ File :: Direct { .. } => {
179
+ let inner = self . inner ( ) ;
180
+ inner. truncate ( offset as u64 ) ?;
181
+ Ok ( offset)
182
+ }
183
+ File :: Cached { .. } => {
184
+ let cache = self . cache ( ) ;
185
+ Ok ( cache. truncate ( offset) as usize )
186
+ }
132
187
}
133
- let cache = self . get_cache ( ) ;
134
- Ok ( cache. truncate ( offset) as usize )
135
188
}
136
189
}
137
190
138
191
impl Drop for File {
139
192
fn drop ( & mut self ) {
140
- debug ! ( "Starry-api drop file {}" , self . path) ;
141
- if ! self . is_direct {
193
+ debug ! ( "Starry-api drop file {}" , self . path( ) ) ;
194
+ if let File :: Cached { .. } = self {
142
195
let cache_manager = page_cache_manager ( ) ;
143
- cache_manager. close_page_cache ( & self . path ) ;
196
+ cache_manager. close_page_cache ( self . path ( ) ) ;
144
197
}
145
198
}
146
199
}
147
200
148
201
impl FileLike for File {
149
202
fn read ( & self , buf : & mut [ u8 ] ) -> LinuxResult < usize > {
150
- if self . is_direct {
151
- return Ok ( self . inner ( ) . read ( buf) ?) ;
203
+ match self {
204
+ File :: Direct { .. } => {
205
+ let mut inner = self . inner ( ) ;
206
+ Ok ( inner. read ( buf) ?)
207
+ }
208
+ File :: Cached { offset, .. } => {
209
+ let cache = self . cache ( ) ;
210
+ let offset_val = offset. load ( Ordering :: SeqCst ) ;
211
+ let len = cache. read_at ( offset_val, buf) ;
212
+ offset. fetch_add ( len, Ordering :: SeqCst ) ;
213
+ Ok ( len)
214
+ }
152
215
}
153
-
154
- let cache = self . get_cache ( ) ;
155
- let offset = self . offset . load ( Ordering :: SeqCst ) ;
156
- let len = cache. write_at ( offset, buf) ;
157
- self . offset . fetch_add ( len, Ordering :: SeqCst ) ;
158
- Ok ( len)
159
216
}
160
217
161
218
fn write ( & self , buf : & [ u8 ] ) -> LinuxResult < usize > {
162
- if self . is_direct {
163
- return Ok ( self . inner ( ) . write ( buf) ?) ;
219
+ match self {
220
+ File :: Direct { .. } => {
221
+ let mut inner = self . inner ( ) ;
222
+ Ok ( inner. write ( buf) ?)
223
+ }
224
+ File :: Cached { offset, size, .. } => {
225
+ let cache = self . cache ( ) ;
226
+ let offset_val = offset. load ( Ordering :: SeqCst ) ;
227
+ let len = cache. write_at ( offset_val, buf) ;
228
+ offset. fetch_add ( len, Ordering :: SeqCst ) ;
229
+ size. fetch_max ( offset_val + len, Ordering :: SeqCst ) ;
230
+ Ok ( len)
231
+ }
164
232
}
165
-
166
- let cache = self . get_cache ( ) ;
167
- let offset = self . offset . load ( Ordering :: SeqCst ) ;
168
- let len = cache. write_at ( offset, buf) ;
169
- self . offset . fetch_add ( len, Ordering :: SeqCst ) ;
170
- self . size . fetch_max ( offset + len, Ordering :: SeqCst ) ;
171
- Ok ( len)
172
233
}
173
234
174
235
fn stat ( & self ) -> LinuxResult < Kstat > {
175
- if !self . is_direct {
176
- let cache = self . get_cache ( ) ;
177
- return cache. stat ( ) ;
236
+ match self {
237
+ File :: Direct { .. } => {
238
+ let inner = self . inner ( ) ;
239
+ let metadata = inner. get_attr ( ) ?;
240
+ let ty = metadata. file_type ( ) as u8 ;
241
+ let perm = metadata. perm ( ) . bits ( ) as u32 ;
242
+ let size = self . size ( ) ;
243
+ Ok ( Kstat {
244
+ mode : ( ( ty as u32 ) << 12 ) | perm,
245
+ size : size as u64 ,
246
+ blocks : metadata. blocks ( ) ,
247
+ blksize : 512 ,
248
+ ..Default :: default ( )
249
+ } )
250
+ }
251
+ File :: Cached { .. } => {
252
+ let cache = self . cache ( ) ;
253
+ cache. stat ( )
254
+ }
178
255
}
179
-
180
- let metadata = self . inner ( ) . get_attr ( ) ?;
181
- let ty = metadata. file_type ( ) as u8 ;
182
- let perm = metadata. perm ( ) . bits ( ) as u32 ;
183
- let size = self . size . load ( Ordering :: SeqCst ) ;
184
- Ok ( Kstat {
185
- mode : ( ( ty as u32 ) << 12 ) | perm,
186
- size : size as u64 ,
187
- blocks : metadata. blocks ( ) ,
188
- blksize : 512 ,
189
- ..Default :: default ( )
190
- } )
191
256
}
192
257
193
258
fn into_any ( self : Arc < Self > ) -> Arc < dyn Any + Send + Sync > {
0 commit comments