@@ -70,6 +70,10 @@ impl CachedPage {
70
70
unsafe { core:: slice:: from_raw_parts_mut ( data_ptr, Size4KiB :: SIZE as usize ) }
71
71
}
72
72
73
+ fn data_addr ( & self ) -> PhysAddr {
74
+ self . page . start_address ( )
75
+ }
76
+
73
77
fn make_key ( device : Weak < dyn CachedAccess > , offset : usize ) -> PageCacheKey {
74
78
( device. as_ptr ( ) as * const u8 as usize , offset)
75
79
}
@@ -107,12 +111,10 @@ impl Cache<PageCacheKey, CachedPage> {
107
111
let device = device. upgrade ( ) . expect ( "page_cache: device dropped" ) ;
108
112
109
113
let aligned_offset = align_down ( offset as u64 , Size4KiB :: SIZE ) as usize ;
114
+ let sector = aligned_offset / device. block_size ( ) ;
110
115
111
116
device
112
- // FIXME(perf,mem): internally read_block makes use of the DMA API (cc drivers::nvme::dma), which in turn
113
- // allocates another frame in order to make sure the destination buffer is DMA capable. In this
114
- // case, this is not required since we have already allocated a DMA capable frame.
115
- . read_block ( aligned_offset / device. block_size ( ) , page. data_mut ( ) )
117
+ . read_dma ( sector, page. data_addr ( ) , Size4KiB :: SIZE as usize )
116
118
. expect ( "page_cache: failed to read block" ) ;
117
119
118
120
PAGE_CACHE . make_item_cached ( page)
@@ -122,6 +124,8 @@ impl Cache<PageCacheKey, CachedPage> {
122
124
pub trait BlockDeviceInterface : Send + Sync {
123
125
fn block_size ( & self ) -> usize ;
124
126
127
+ fn read_dma ( & self , sector : usize , start : PhysAddr , size : usize ) -> Option < usize > ;
128
+
125
129
fn read_block ( & self , sector : usize , dest : & mut [ MaybeUninit < u8 > ] ) -> Option < usize > ;
126
130
fn write_block ( & self , sector : usize , buf : & [ u8 ] ) -> Option < usize > ;
127
131
}
@@ -147,6 +151,33 @@ pub trait CachedAccess: BlockDeviceInterface {
147
151
148
152
Some ( loc)
149
153
}
154
+
155
+ /// Writes the given data to the device at the given offset and returns the
156
+ /// number of bytes written.
157
+ ///
158
+ /// ## Notes
159
+ ///
160
+ /// * This function does **not** sync the written data to the disk.
161
+ fn write ( & self , mut offset : usize , buffer : & [ u8 ] ) -> Option < usize > {
162
+ let mut loc = 0 ;
163
+
164
+ while loc < buffer. len ( ) {
165
+ let page = PAGE_CACHE . get_page ( self . sref ( ) , offset) ;
166
+
167
+ let page_offset = offset % Size4KiB :: SIZE as usize ;
168
+ let size = core:: cmp:: min ( Size4KiB :: SIZE as usize - page_offset, buffer. len ( ) - loc) ;
169
+
170
+ MaybeUninit :: write_slice (
171
+ & mut page. data_mut ( ) [ page_offset..page_offset + size] ,
172
+ & buffer[ loc..loc + size] ,
173
+ ) ;
174
+
175
+ loc += size;
176
+ offset += align_down ( offset as u64 + Size4KiB :: SIZE , Size4KiB :: SIZE ) as usize ;
177
+ }
178
+
179
+ Some ( loc)
180
+ }
150
181
}
151
182
152
183
static BLOCK_DEVS : Mutex < BTreeMap < usize , Arc < BlockDevice > > > = Mutex :: new ( BTreeMap :: new ( ) ) ;
@@ -189,6 +220,10 @@ impl BlockDeviceInterface for BlockDevice {
189
220
self . dev . block_size ( )
190
221
}
191
222
223
+ fn read_dma ( & self , sector : usize , start : PhysAddr , size : usize ) -> Option < usize > {
224
+ self . dev . read_dma ( sector, start, size)
225
+ }
226
+
192
227
fn read_block ( & self , sector : usize , dest : & mut [ MaybeUninit < u8 > ] ) -> Option < usize > {
193
228
self . dev . read_block ( sector, dest)
194
229
}
@@ -249,17 +284,25 @@ impl BlockDeviceInterface for PartitionBlockDevice {
249
284
self . device . read_block ( self . offset + sector, dest)
250
285
}
251
286
252
- fn block_size ( & self ) -> usize {
253
- self . device . block_size ( )
254
- }
255
-
256
287
fn write_block ( & self , sector : usize , buf : & [ u8 ] ) -> Option < usize > {
257
288
if sector >= self . size {
258
289
return None ;
259
290
}
260
291
261
292
self . device . write_block ( self . offset + sector, buf)
262
293
}
294
+
295
+ fn read_dma ( & self , sector : usize , start : PhysAddr , size : usize ) -> Option < usize > {
296
+ if sector >= self . size {
297
+ return None ;
298
+ }
299
+
300
+ self . device . read_dma ( self . offset + sector, start, size)
301
+ }
302
+
303
+ fn block_size ( & self ) -> usize {
304
+ self . device . block_size ( )
305
+ }
263
306
}
264
307
265
308
impl CachedAccess for PartitionBlockDevice {
0 commit comments