mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-08-21 23:41:15 +00:00
vhost_user_block: Implement and use worker shutdown
Add a kill EventFD and use this to shutdown the worker thread when the backend terminates. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
e619fe6b01
commit
7ca691fc2f
@ -14,6 +14,7 @@ extern crate vhost_user_backend;
|
|||||||
extern crate vm_virtio;
|
extern crate vm_virtio;
|
||||||
|
|
||||||
use epoll;
|
use epoll;
|
||||||
|
use libc::EFD_NONBLOCK;
|
||||||
use log::*;
|
use log::*;
|
||||||
use qcow::{self, ImageType, QcowFile};
|
use qcow::{self, ImageType, QcowFile};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@ -21,7 +22,7 @@ use std::fs::OpenOptions;
|
|||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::io::{Seek, SeekFrom, Write};
|
use std::io::{Seek, SeekFrom, Write};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::os::unix::fs::OpenOptionsExt;
|
use std::os::unix::{fs::OpenOptionsExt, io::AsRawFd};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
@ -33,6 +34,7 @@ use vhost_user_backend::{VhostUserBackend, VhostUserDaemon, Vring, VringWorker};
|
|||||||
use virtio_bindings::bindings::virtio_blk::*;
|
use virtio_bindings::bindings::virtio_blk::*;
|
||||||
use vm_memory::{Bytes, GuestMemoryError, GuestMemoryMmap};
|
use vm_memory::{Bytes, GuestMemoryError, GuestMemoryMmap};
|
||||||
use vm_virtio::block::{build_disk_image_id, Request};
|
use vm_virtio::block::{build_disk_image_id, Request};
|
||||||
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
const QUEUE_SIZE: usize = 1024;
|
const QUEUE_SIZE: usize = 1024;
|
||||||
const SECTOR_SHIFT: u8 = 9;
|
const SECTOR_SHIFT: u8 = 9;
|
||||||
@ -65,6 +67,10 @@ pub enum Error {
|
|||||||
ParseBlkNumQueuesParam(std::num::ParseIntError),
|
ParseBlkNumQueuesParam(std::num::ParseIntError),
|
||||||
/// Failed to handle event other than input event.
|
/// Failed to handle event other than input event.
|
||||||
HandleEventNotEpollIn,
|
HandleEventNotEpollIn,
|
||||||
|
/// Failed to create kill eventfd
|
||||||
|
CreateKillEventFd(io::Error),
|
||||||
|
/// Failed to handle unknown event.
|
||||||
|
HandleEventUnknownEvent,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
impl fmt::Display for Error {
|
||||||
@ -89,6 +95,7 @@ pub struct VhostUserBlkBackend {
|
|||||||
disk_nsectors: u64,
|
disk_nsectors: u64,
|
||||||
config: virtio_blk_config,
|
config: virtio_blk_config,
|
||||||
rdonly: bool,
|
rdonly: bool,
|
||||||
|
kill_evt: EventFd,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VhostUserBlkBackend {
|
impl VhostUserBlkBackend {
|
||||||
@ -129,6 +136,7 @@ impl VhostUserBlkBackend {
|
|||||||
disk_nsectors: nsectors,
|
disk_nsectors: nsectors,
|
||||||
config,
|
config,
|
||||||
rdonly,
|
rdonly,
|
||||||
|
kill_evt: EventFd::new(EFD_NONBLOCK).map_err(Error::CreateKillEventFd)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,6 +185,13 @@ impl VhostUserBlkBackend {
|
|||||||
pub fn set_vring_worker(&mut self, vring_worker: Option<Arc<VringWorker>>) {
|
pub fn set_vring_worker(&mut self, vring_worker: Option<Arc<VringWorker>>) {
|
||||||
self.vring_worker = vring_worker;
|
self.vring_worker = vring_worker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_kill_event(&self) -> (u16, EventFd) {
|
||||||
|
(
|
||||||
|
self.config.num_queues as u16,
|
||||||
|
self.kill_evt.try_clone().unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VhostUserBackend for VhostUserBlkBackend {
|
impl VhostUserBackend for VhostUserBlkBackend {
|
||||||
@ -221,14 +236,21 @@ impl VhostUserBackend for VhostUserBlkBackend {
|
|||||||
|
|
||||||
debug!("event received: {:?}", device_event);
|
debug!("event received: {:?}", device_event);
|
||||||
|
|
||||||
let mut vring = vrings[device_event as usize].write().unwrap();
|
// Kill event is the index after the last queue
|
||||||
|
let kill_index = self.config.num_queues;
|
||||||
|
match device_event {
|
||||||
|
event if event == kill_index => Ok(true),
|
||||||
|
q if device_event < self.config.num_queues => {
|
||||||
|
let mut vring = vrings[q as usize].write().unwrap();
|
||||||
if self.process_queue(&mut vring) {
|
if self.process_queue(&mut vring) {
|
||||||
debug!("signalling queue");
|
debug!("signalling queue");
|
||||||
vring.signal_used_queue().unwrap();
|
vring.signal_used_queue().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
_ => Err(Error::HandleEventUnknownEvent.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_config(&self, _offset: u32, _size: u32) -> Vec<u8> {
|
fn get_config(&self, _offset: u32, _size: u32) -> Vec<u8> {
|
||||||
// self.config is a statically allocated virtio_blk_config
|
// self.config is a statically allocated virtio_blk_config
|
||||||
@ -334,6 +356,15 @@ pub fn start_block_backend(backend_command: &str) {
|
|||||||
debug!("blk_daemon is created!\n");
|
debug!("blk_daemon is created!\n");
|
||||||
|
|
||||||
let vring_worker = blk_daemon.get_vring_worker();
|
let vring_worker = blk_daemon.get_vring_worker();
|
||||||
|
let (kill_index, kill_evt_fd) = blk_backend.read().unwrap().get_kill_event();
|
||||||
|
if let Err(e) = vring_worker.register_listener(
|
||||||
|
kill_evt_fd.as_raw_fd(),
|
||||||
|
epoll::Events::EPOLLIN,
|
||||||
|
u64::from(kill_index),
|
||||||
|
) {
|
||||||
|
error!("Failed to register listener for kill event: {:?}", e);
|
||||||
|
process::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
blk_backend
|
blk_backend
|
||||||
.write()
|
.write()
|
||||||
@ -341,12 +372,18 @@ pub fn start_block_backend(backend_command: &str) {
|
|||||||
.set_vring_worker(Some(vring_worker));
|
.set_vring_worker(Some(vring_worker));
|
||||||
|
|
||||||
if let Err(e) = blk_daemon.start() {
|
if let Err(e) = blk_daemon.start() {
|
||||||
println!(
|
error!(
|
||||||
"failed to start daemon for vhost-user-blk with error: {:?}\n",
|
"Failed to start daemon for vhost-user-block with error: {:?}\n",
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
blk_daemon.wait().unwrap();
|
if let Err(e) = blk_daemon.wait() {
|
||||||
|
error!("Error from the main thread: {:?}", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(e) = kill_evt_fd.write(1) {
|
||||||
|
error!("Error shutting down worker thread: {:?}", e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user