@@ -114,6 +114,21 @@ pub trait SectorRead {
114
114
fn read ( & self , sector : u64 , data : & mut [ u8 ] ) -> Result < ( ) , Error > ;
115
115
}
116
116
117
+ pub trait SectorWrite {
118
+ /// Write a single sector (512 bytes) from the block device. `data` must be
119
+ /// exactly 512 bytes long.
120
+ fn write ( & self , sector : u64 , data : & mut [ u8 ] ) -> Result < ( ) , Error > ;
121
+ fn flush ( & self ) -> Result < ( ) , Error > ;
122
+ }
123
+
124
+ #[ cfg( not( test) ) ]
125
+ #[ derive( PartialEq , Copy , Clone ) ]
126
+ enum RequestType {
127
+ Read = 0 ,
128
+ Write = 1 ,
129
+ Flush = 4 ,
130
+ }
131
+
117
132
#[ cfg( not( test) ) ]
118
133
impl < ' a > VirtioBlockDevice < ' a > {
119
134
pub fn new ( transport : & ' a mut VirtioTransport ) -> VirtioBlockDevice < ' a > {
@@ -208,12 +223,16 @@ impl<'a> VirtioBlockDevice<'a> {
208
223
u64:: from ( self . transport . read_device_config ( 0 ) )
209
224
| u64:: from ( self . transport . read_device_config ( 4 ) ) << 32
210
225
}
211
- }
212
226
213
- #[ cfg( not( test) ) ]
214
- impl < ' a > SectorRead for VirtioBlockDevice < ' a > {
215
- fn read ( & self , sector : u64 , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
216
- assert_eq ! ( 512 , data. len( ) ) ;
227
+ fn request (
228
+ & self ,
229
+ sector : u64 ,
230
+ data : Option < & mut [ u8 ] > ,
231
+ request : RequestType ,
232
+ ) -> Result < ( ) , Error > {
233
+ if request != RequestType :: Flush {
234
+ assert_eq ! ( 512 , data. as_ref( ) . unwrap( ) . len( ) ) ;
235
+ }
217
236
218
237
const VIRTQ_DESC_F_NEXT : u16 = 1 ;
219
238
const VIRTQ_DESC_F_WRITE : u16 = 2 ;
@@ -223,7 +242,7 @@ impl<'a> SectorRead for VirtioBlockDevice<'a> {
223
242
const VIRTIO_BLK_S_UNSUPP : u8 = 2 ;
224
243
225
244
let header = BlockRequestHeader {
226
- request : 0 ,
245
+ request : request as u32 ,
227
246
reserved : 0 ,
228
247
sector,
229
248
} ;
@@ -242,9 +261,17 @@ impl<'a> SectorRead for VirtioBlockDevice<'a> {
242
261
243
262
let mut d = & mut state. descriptors [ next_desc] ;
244
263
let next_desc = ( next_desc + 1 ) % QUEUE_SIZE ;
245
- d. addr = data. as_ptr ( ) as u64 ;
246
- d. length = core:: mem:: size_of :: < [ u8 ; 512 ] > ( ) as u32 ;
247
- d. flags = VIRTQ_DESC_F_NEXT | VIRTQ_DESC_F_WRITE ;
264
+ if request != RequestType :: Flush {
265
+ d. addr = data. unwrap ( ) . as_ptr ( ) as u64 ;
266
+ d. length = core:: mem:: size_of :: < [ u8 ; 512 ] > ( ) as u32 ;
267
+ }
268
+
269
+ d. flags = VIRTQ_DESC_F_NEXT
270
+ | if request == RequestType :: Read {
271
+ VIRTQ_DESC_F_WRITE
272
+ } else {
273
+ 0
274
+ } ;
248
275
d. next = next_desc as u16 ;
249
276
250
277
let mut d = & mut state. descriptors [ next_desc] ;
@@ -279,3 +306,21 @@ impl<'a> SectorRead for VirtioBlockDevice<'a> {
279
306
}
280
307
}
281
308
}
309
+
310
+ #[ cfg( not( test) ) ]
311
+ impl < ' a > SectorRead for VirtioBlockDevice < ' a > {
312
+ fn read ( & self , sector : u64 , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
313
+ self . request ( sector, Some ( data) , RequestType :: Read )
314
+ }
315
+ }
316
+
317
+ #[ cfg( not( test) ) ]
318
+ impl < ' a > SectorWrite for VirtioBlockDevice < ' a > {
319
+ fn write ( & self , sector : u64 , data : & mut [ u8 ] ) -> Result < ( ) , Error > {
320
+ self . request ( sector, Some ( data) , RequestType :: Write )
321
+ }
322
+
323
+ fn flush ( & self ) -> Result < ( ) , Error > {
324
+ self . request ( 0 , None , RequestType :: Flush )
325
+ }
326
+ }
0 commit comments