Skip to content

Commit 7381a97

Browse files
committed
block: Add support for writing and flushing to block device
Refactor the common code and add a SectorWrite trait in order to support writing and flushing blocks on the device. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
1 parent f899ec8 commit 7381a97

File tree

1 file changed

+54
-9
lines changed

1 file changed

+54
-9
lines changed

src/block.rs

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,21 @@ pub trait SectorRead {
114114
fn read(&self, sector: u64, data: &mut [u8]) -> Result<(), Error>;
115115
}
116116

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+
117132
#[cfg(not(test))]
118133
impl<'a> VirtioBlockDevice<'a> {
119134
pub fn new(transport: &'a mut VirtioTransport) -> VirtioBlockDevice<'a> {
@@ -208,12 +223,16 @@ impl<'a> VirtioBlockDevice<'a> {
208223
u64::from(self.transport.read_device_config(0))
209224
| u64::from(self.transport.read_device_config(4)) << 32
210225
}
211-
}
212226

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+
}
217236

218237
const VIRTQ_DESC_F_NEXT: u16 = 1;
219238
const VIRTQ_DESC_F_WRITE: u16 = 2;
@@ -223,7 +242,7 @@ impl<'a> SectorRead for VirtioBlockDevice<'a> {
223242
const VIRTIO_BLK_S_UNSUPP: u8 = 2;
224243

225244
let header = BlockRequestHeader {
226-
request: 0,
245+
request: request as u32,
227246
reserved: 0,
228247
sector,
229248
};
@@ -242,9 +261,17 @@ impl<'a> SectorRead for VirtioBlockDevice<'a> {
242261

243262
let mut d = &mut state.descriptors[next_desc];
244263
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+
};
248275
d.next = next_desc as u16;
249276

250277
let mut d = &mut state.descriptors[next_desc];
@@ -279,3 +306,21 @@ impl<'a> SectorRead for VirtioBlockDevice<'a> {
279306
}
280307
}
281308
}
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

Comments
 (0)