mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-18 12:06:43 +00:00
Implement flush for virtio-blk
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
197d53c0ab
commit
32572e22d9
@ -83,6 +83,18 @@ impl dyn BlockDevice {
|
|||||||
let bio = create_bio_from_frame(BioType::Write, bid, frame);
|
let bio = create_bio_from_frame(BioType::Write, bid, frame);
|
||||||
bio.submit(self)
|
bio.submit(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Issues a sync request
|
||||||
|
pub fn sync(&self) -> Result<BioStatus, BioEnqueueError> {
|
||||||
|
let bio = Bio::new(
|
||||||
|
BioType::Flush,
|
||||||
|
Sid::from(Bid::from_offset(0)),
|
||||||
|
vec![],
|
||||||
|
Some(general_complete_fn),
|
||||||
|
);
|
||||||
|
let status = bio.submit_and_wait(self)?;
|
||||||
|
Ok(status)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VmIo for dyn BlockDevice {
|
impl VmIo for dyn BlockDevice {
|
||||||
|
@ -63,7 +63,8 @@ impl BlockDevice {
|
|||||||
match request.type_() {
|
match request.type_() {
|
||||||
BioType::Read => self.device.read(request),
|
BioType::Read => self.device.read(request),
|
||||||
BioType::Write => self.device.write(request),
|
BioType::Write => self.device.write(request),
|
||||||
BioType::Flush | BioType::Discard => todo!(),
|
BioType::Flush => self.device.flush(request),
|
||||||
|
BioType::Discard => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,6 +407,58 @@ impl DeviceInner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Flushes any cached data from the guest to the persistent storage on the host.
|
||||||
|
/// This will be ignored if the device doesn't support the `VIRTIO_BLK_F_FLUSH` feature.
|
||||||
|
fn flush(&self, bio_request: BioRequest) {
|
||||||
|
if self.transport.lock().device_features() & BlockFeatures::FLUSH.bits() == 0 {
|
||||||
|
bio_request.bios().for_each(|bio| {
|
||||||
|
bio.complete(BioStatus::Complete);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let id = self.id_allocator.disable_irq().lock().alloc().unwrap();
|
||||||
|
let req_slice = {
|
||||||
|
let req_slice = DmaStreamSlice::new(&self.block_requests, id * REQ_SIZE, REQ_SIZE);
|
||||||
|
let req = BlockReq {
|
||||||
|
type_: ReqType::Flush as _,
|
||||||
|
reserved: 0,
|
||||||
|
sector: bio_request.sid_range().start.to_raw(),
|
||||||
|
};
|
||||||
|
req_slice.write_val(0, &req).unwrap();
|
||||||
|
req_slice.sync().unwrap();
|
||||||
|
req_slice
|
||||||
|
};
|
||||||
|
|
||||||
|
let resp_slice = {
|
||||||
|
let resp_slice = DmaStreamSlice::new(&self.block_responses, id * RESP_SIZE, RESP_SIZE);
|
||||||
|
resp_slice.write_val(0, &BlockResp::default()).unwrap();
|
||||||
|
resp_slice
|
||||||
|
};
|
||||||
|
|
||||||
|
let num_used_descs = 1;
|
||||||
|
loop {
|
||||||
|
let mut queue = self.queue.disable_irq().lock();
|
||||||
|
if num_used_descs > queue.available_desc() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let token = queue
|
||||||
|
.add_dma_buf(&[&req_slice], &[&resp_slice])
|
||||||
|
.expect("add queue failed");
|
||||||
|
if queue.should_notify() {
|
||||||
|
queue.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Records the submitted request
|
||||||
|
let submitted_request = SubmittedRequest::new(id as u16, bio_request, Vec::new());
|
||||||
|
self.submitted_requests
|
||||||
|
.disable_irq()
|
||||||
|
.lock()
|
||||||
|
.insert(token, submitted_request);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Performs DMA mapping for the segments in bio request.
|
/// Performs DMA mapping for the segments in bio request.
|
||||||
fn dma_stream_map(bio_request: &BioRequest) -> Vec<(DmaStream, usize, usize)> {
|
fn dma_stream_map(bio_request: &BioRequest) -> Vec<(DmaStream, usize, usize)> {
|
||||||
let dma_direction = match bio_request.type_() {
|
let dma_direction = match bio_request.type_() {
|
||||||
|
Reference in New Issue
Block a user