mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-21 20:15:21 +00:00
vm-virtio: block: Ensure backing file consistency
Correctly implement the virtio specification by setting the writeback field on the request based on the algorithm in the spec. TEST=Boot with hypervisor-firmware with CH in verbose mode. See info level messages saying cache mode is writethrough in firmware (no support for flush or WCE). Once in the Linux kernel see messages that mode is writeback. Fixes: #1216 Fixes: #680 Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
dc66eee8f0
commit
9101bdd7a9
@ -610,6 +610,7 @@ struct BlockEpollHandler<T: DiskFile> {
|
||||
kill_evt: EventFd,
|
||||
pause_evt: EventFd,
|
||||
event_idx: bool,
|
||||
writeback: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl<T: DiskFile> BlockEpollHandler<T> {
|
||||
@ -622,7 +623,9 @@ impl<T: DiskFile> BlockEpollHandler<T> {
|
||||
for avail_desc in queue.iter(&mem) {
|
||||
let len;
|
||||
match Request::parse(&avail_desc, &mem) {
|
||||
Ok(request) => {
|
||||
Ok(mut request) => {
|
||||
request.set_writeback(self.writeback.load(Ordering::SeqCst));
|
||||
|
||||
let mut disk_image_locked = self.disk_image.lock().unwrap();
|
||||
let mut disk_image = disk_image_locked.deref_mut();
|
||||
let status = match request.execute(
|
||||
@ -931,6 +934,7 @@ pub struct Block<T: DiskFile> {
|
||||
pause_evt: Option<EventFd>,
|
||||
paused: Arc<AtomicBool>,
|
||||
queue_size: Vec<u16>,
|
||||
writeback: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@ -966,7 +970,8 @@ impl<T: DiskFile> Block<T> {
|
||||
|
||||
let mut avail_features = (1u64 << VIRTIO_F_VERSION_1)
|
||||
| (1u64 << VIRTIO_BLK_F_FLUSH)
|
||||
| (1u64 << VIRTIO_RING_F_EVENT_IDX);
|
||||
| (1u64 << VIRTIO_RING_F_EVENT_IDX)
|
||||
| (1u64 << VIRTIO_BLK_F_CONFIG_WCE);
|
||||
|
||||
if iommu {
|
||||
avail_features |= 1u64 << VIRTIO_F_IOMMU_PLATFORM;
|
||||
@ -979,6 +984,7 @@ impl<T: DiskFile> Block<T> {
|
||||
let disk_nsectors = disk_size / SECTOR_SIZE;
|
||||
let mut config = VirtioBlockConfig {
|
||||
capacity: disk_nsectors,
|
||||
writeback: 1,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
@ -1002,6 +1008,7 @@ impl<T: DiskFile> Block<T> {
|
||||
pause_evt: None,
|
||||
paused: Arc::new(AtomicBool::new(false)),
|
||||
queue_size: vec![queue_size; num_queues],
|
||||
writeback: Arc::new(AtomicBool::new(true)),
|
||||
})
|
||||
}
|
||||
|
||||
@ -1024,6 +1031,27 @@ impl<T: DiskFile> Block<T> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update_writeback(&mut self) {
|
||||
// Use writeback from config if VIRTIO_BLK_F_CONFIG_WCE
|
||||
let writeback =
|
||||
if self.acked_features & 1 << VIRTIO_BLK_F_CONFIG_WCE == 1 << VIRTIO_BLK_F_CONFIG_WCE {
|
||||
self.config.writeback == 1
|
||||
} else {
|
||||
// Else check if VIRTIO_BLK_F_FLUSH negotiated
|
||||
self.acked_features & 1 << VIRTIO_BLK_F_FLUSH == 1 << VIRTIO_BLK_F_FLUSH
|
||||
};
|
||||
|
||||
info!(
|
||||
"Changing cache mode to {}",
|
||||
if writeback {
|
||||
"writeback"
|
||||
} else {
|
||||
"writethrough"
|
||||
}
|
||||
);
|
||||
self.writeback.store(writeback, Ordering::SeqCst);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: DiskFile> Drop for Block<T> {
|
||||
@ -1085,6 +1113,7 @@ impl<T: 'static + DiskFile + Send> VirtioDevice for Block<T> {
|
||||
}
|
||||
let (_, right) = config_slice.split_at_mut(offset as usize);
|
||||
right.copy_from_slice(&data[..]);
|
||||
self.update_writeback();
|
||||
}
|
||||
|
||||
fn activate(
|
||||
@ -1146,6 +1175,7 @@ impl<T: 'static + DiskFile + Send> VirtioDevice for Block<T> {
|
||||
|
||||
let event_idx = self.acked_features & 1u64 << VIRTIO_RING_F_EVENT_IDX
|
||||
== 1u64 << VIRTIO_RING_F_EVENT_IDX;
|
||||
self.update_writeback();
|
||||
|
||||
let mut epoll_threads = Vec::new();
|
||||
for _ in 0..self.queue_size.len() {
|
||||
@ -1159,6 +1189,7 @@ impl<T: 'static + DiskFile + Send> VirtioDevice for Block<T> {
|
||||
kill_evt: kill_evt.try_clone().unwrap(),
|
||||
pause_evt: pause_evt.try_clone().unwrap(),
|
||||
event_idx,
|
||||
writeback: self.writeback.clone(),
|
||||
};
|
||||
|
||||
handler.queue.set_event_idx(event_idx);
|
||||
|
Loading…
x
Reference in New Issue
Block a user