@@ -86,6 +86,78 @@ pub trait BlockDevice {
8686 fn num_blocks ( & self ) -> Result < BlockCount , Self :: Error > ;
8787}
8888
89+ /// A caching layer for block devices
90+ ///
91+ /// Caches a single block.
92+ #[ derive( Debug ) ]
93+ pub struct BlockCache < D > {
94+ block_device : D ,
95+ block : [ Block ; 1 ] ,
96+ block_idx : Option < BlockIdx > ,
97+ }
98+
99+ impl < D > BlockCache < D >
100+ where
101+ D : BlockDevice ,
102+ {
103+ /// Create a new block cache
104+ pub fn new ( block_device : D ) -> BlockCache < D > {
105+ BlockCache {
106+ block_device,
107+ block : [ Block :: new ( ) ] ,
108+ block_idx : None ,
109+ }
110+ }
111+
112+ /// Read a block, and return a reference to it.
113+ pub fn read ( & mut self , block_idx : BlockIdx ) -> Result < & Block , D :: Error > {
114+ if self . block_idx != Some ( block_idx) {
115+ self . block_device . read ( & mut self . block , block_idx) ?;
116+ self . block_idx = Some ( block_idx) ;
117+ }
118+ Ok ( & self . block [ 0 ] )
119+ }
120+
121+ /// Read a block, and return a reference to it.
122+ pub fn read_mut ( & mut self , block_idx : BlockIdx ) -> Result < & mut Block , D :: Error > {
123+ if self . block_idx != Some ( block_idx) {
124+ self . block_device . read ( & mut self . block , block_idx) ?;
125+ self . block_idx = Some ( block_idx) ;
126+ }
127+ Ok ( & mut self . block [ 0 ] )
128+ }
129+
130+ /// Write back a block you read with [`Self::read_mut`] and then modified.
131+ pub fn write_back ( & mut self ) -> Result < ( ) , D :: Error > {
132+ self . block_device . write (
133+ & self . block ,
134+ self . block_idx . expect ( "write_back with no read" ) ,
135+ )
136+ }
137+
138+ /// Access a blank sector
139+ pub fn blank_mut ( & mut self , block_idx : BlockIdx ) -> & mut Block {
140+ self . block_idx = Some ( block_idx) ;
141+ for b in self . block [ 0 ] . iter_mut ( ) {
142+ * b = 0 ;
143+ }
144+ & mut self . block [ 0 ]
145+ }
146+
147+ /// Access the block device
148+ pub fn block_device ( & mut self ) -> & mut D {
149+ // invalidate the cache
150+ self . block_idx = None ;
151+ // give them the block device
152+ & mut self . block_device
153+ }
154+
155+ /// Get the block device back
156+ pub fn free ( self ) -> D {
157+ self . block_device
158+ }
159+ }
160+
89161/// The linear numeric address of a block (or sector).
90162///
91163/// The first block on a disk gets `BlockIdx(0)` (which usually contains the
0 commit comments