@@ -70,6 +70,10 @@ impl CachedPage {
7070 unsafe { core:: slice:: from_raw_parts_mut ( data_ptr, Size4KiB :: SIZE as usize ) }
7171 }
7272
73+ fn data_addr ( & self ) -> PhysAddr {
74+ self . page . start_address ( )
75+ }
76+
7377 fn make_key ( device : Weak < dyn CachedAccess > , offset : usize ) -> PageCacheKey {
7478 ( device. as_ptr ( ) as * const u8 as usize , offset)
7579 }
@@ -107,12 +111,10 @@ impl Cache<PageCacheKey, CachedPage> {
107111 let device = device. upgrade ( ) . expect ( "page_cache: device dropped" ) ;
108112
109113 let aligned_offset = align_down ( offset as u64 , Size4KiB :: SIZE ) as usize ;
114+ let sector = aligned_offset / device. block_size ( ) ;
110115
111116 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 )
116118 . expect ( "page_cache: failed to read block" ) ;
117119
118120 PAGE_CACHE . make_item_cached ( page)
@@ -122,6 +124,8 @@ impl Cache<PageCacheKey, CachedPage> {
122124pub trait BlockDeviceInterface : Send + Sync {
123125 fn block_size ( & self ) -> usize ;
124126
127+ fn read_dma ( & self , sector : usize , start : PhysAddr , size : usize ) -> Option < usize > ;
128+
125129 fn read_block ( & self , sector : usize , dest : & mut [ MaybeUninit < u8 > ] ) -> Option < usize > ;
126130 fn write_block ( & self , sector : usize , buf : & [ u8 ] ) -> Option < usize > ;
127131}
@@ -147,6 +151,33 @@ pub trait CachedAccess: BlockDeviceInterface {
147151
148152 Some ( loc)
149153 }
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+ }
150181}
151182
152183static BLOCK_DEVS : Mutex < BTreeMap < usize , Arc < BlockDevice > > > = Mutex :: new ( BTreeMap :: new ( ) ) ;
@@ -189,6 +220,10 @@ impl BlockDeviceInterface for BlockDevice {
189220 self . dev . block_size ( )
190221 }
191222
223+ fn read_dma ( & self , sector : usize , start : PhysAddr , size : usize ) -> Option < usize > {
224+ self . dev . read_dma ( sector, start, size)
225+ }
226+
192227 fn read_block ( & self , sector : usize , dest : & mut [ MaybeUninit < u8 > ] ) -> Option < usize > {
193228 self . dev . read_block ( sector, dest)
194229 }
@@ -249,17 +284,25 @@ impl BlockDeviceInterface for PartitionBlockDevice {
249284 self . device . read_block ( self . offset + sector, dest)
250285 }
251286
252- fn block_size ( & self ) -> usize {
253- self . device . block_size ( )
254- }
255-
256287 fn write_block ( & self , sector : usize , buf : & [ u8 ] ) -> Option < usize > {
257288 if sector >= self . size {
258289 return None ;
259290 }
260291
261292 self . device . write_block ( self . offset + sector, buf)
262293 }
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+ }
263306}
264307
265308impl CachedAccess for PartitionBlockDevice {
0 commit comments