@@ -86,6 +86,78 @@ pub trait BlockDevice {
86
86
fn num_blocks ( & self ) -> Result < BlockCount , Self :: Error > ;
87
87
}
88
88
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
+
89
161
/// The linear numeric address of a block (or sector).
90
162
///
91
163
/// The first block on a disk gets `BlockIdx(0)` (which usually contains the
0 commit comments