mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-08-21 23:41:15 +00:00
vhost-user-blk: Device support multiple queues
The previous code only support one queue, and we need to support MQ in vhost user block device. This patch can work with SPDK with MQ setting. Signed-off-by: Yang Zhong <yang.zhong@intel.com>
This commit is contained in:
parent
839f3a74ff
commit
1038a07dd6
@ -64,6 +64,10 @@ impl Blk {
|
|||||||
avail_features |= 1 << VIRTIO_BLK_F_CONFIG_WCE;
|
avail_features |= 1 << VIRTIO_BLK_F_CONFIG_WCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if vu_cfg.num_queues > 1 {
|
||||||
|
avail_features |= 1 << VIRTIO_BLK_F_MQ;
|
||||||
|
}
|
||||||
|
|
||||||
// Set vhost-user owner.
|
// Set vhost-user owner.
|
||||||
vhost_user_blk
|
vhost_user_blk
|
||||||
.set_owner()
|
.set_owner()
|
||||||
@ -95,7 +99,17 @@ impl Blk {
|
|||||||
.set_protocol_features(protocol_features)
|
.set_protocol_features(protocol_features)
|
||||||
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
.map_err(Error::VhostUserSetProtocolFeatures)?;
|
||||||
}
|
}
|
||||||
|
// Get the max queues number from backend, and the queue number set
|
||||||
|
// should be less than this max queue number.
|
||||||
|
let max_queues_num = vhost_user_blk
|
||||||
|
.get_queue_num()
|
||||||
|
.map_err(Error::VhostUserGetQueueMaxNum)?;
|
||||||
|
|
||||||
|
if vu_cfg.num_queues > max_queues_num as usize {
|
||||||
|
error!("vhost-user-blk has queue number: {} larger than the max queue number: {} backend allowed\n",
|
||||||
|
vu_cfg.num_queues, max_queues_num);
|
||||||
|
return Err(Error::BadQueueNum);
|
||||||
|
}
|
||||||
let config_len = mem::size_of::<VirtioBlockConfig>();
|
let config_len = mem::size_of::<VirtioBlockConfig>();
|
||||||
let config_space: Vec<u8> = vec![0u8; config_len as usize];
|
let config_space: Vec<u8> = vec![0u8; config_len as usize];
|
||||||
let (_, config_space) = vhost_user_blk
|
let (_, config_space) = vhost_user_blk
|
||||||
@ -113,6 +127,15 @@ impl Blk {
|
|||||||
config.num_queues = vu_cfg.num_queues as u16;
|
config.num_queues = vu_cfg.num_queues as u16;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send set_vring_base here, since it could tell backends, like SPDK,
|
||||||
|
// how many virt queues to be handled, which backend required to know
|
||||||
|
// at early stage.
|
||||||
|
for i in 0..vu_cfg.num_queues {
|
||||||
|
vhost_user_blk
|
||||||
|
.set_vring_base(i, 0)
|
||||||
|
.map_err(Error::VhostUserSetVringBase)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(Blk {
|
Ok(Blk {
|
||||||
vhost_user_blk,
|
vhost_user_blk,
|
||||||
kill_evt: None,
|
kill_evt: None,
|
||||||
@ -246,7 +269,7 @@ impl VirtioDevice for Blk {
|
|||||||
}
|
}
|
||||||
self.queue_evts = Some(tmp_queue_evts);
|
self.queue_evts = Some(tmp_queue_evts);
|
||||||
|
|
||||||
let vu_interrupt_list = setup_vhost_user(
|
let mut vu_interrupt_list = setup_vhost_user(
|
||||||
&mut self.vhost_user_blk,
|
&mut self.vhost_user_blk,
|
||||||
mem.load().as_ref(),
|
mem.load().as_ref(),
|
||||||
queues,
|
queues,
|
||||||
@ -256,25 +279,29 @@ impl VirtioDevice for Blk {
|
|||||||
)
|
)
|
||||||
.map_err(ActivateError::VhostUserBlkSetup)?;
|
.map_err(ActivateError::VhostUserBlkSetup)?;
|
||||||
|
|
||||||
let mut handler = VhostUserEpollHandler::<SlaveReqHandler>::new(VhostUserEpollConfig {
|
|
||||||
interrupt_cb,
|
|
||||||
kill_evt,
|
|
||||||
pause_evt,
|
|
||||||
vu_interrupt_list,
|
|
||||||
slave_req_handler: None,
|
|
||||||
});
|
|
||||||
|
|
||||||
let paused = self.paused.clone();
|
|
||||||
let mut epoll_threads = Vec::new();
|
let mut epoll_threads = Vec::new();
|
||||||
thread::Builder::new()
|
for _ in 0..vu_interrupt_list.len() {
|
||||||
.name("vhost_user_blk".to_string())
|
let mut interrupt_list_sub: Vec<(Option<EventFd>, Queue)> = Vec::with_capacity(1);
|
||||||
.spawn(move || handler.run(paused))
|
interrupt_list_sub.push(vu_interrupt_list.remove(0));
|
||||||
.map(|thread| epoll_threads.push(thread))
|
|
||||||
.map_err(|e| {
|
|
||||||
error!("failed to clone virtio epoll thread: {}", e);
|
|
||||||
ActivateError::BadActivate
|
|
||||||
})?;
|
|
||||||
|
|
||||||
|
let mut handler = VhostUserEpollHandler::<SlaveReqHandler>::new(VhostUserEpollConfig {
|
||||||
|
interrupt_cb: interrupt_cb.clone(),
|
||||||
|
kill_evt: kill_evt.try_clone().unwrap(),
|
||||||
|
pause_evt: pause_evt.try_clone().unwrap(),
|
||||||
|
vu_interrupt_list: interrupt_list_sub,
|
||||||
|
slave_req_handler: None,
|
||||||
|
});
|
||||||
|
|
||||||
|
let paused = self.paused.clone();
|
||||||
|
thread::Builder::new()
|
||||||
|
.name("vhost_user_blk".to_string())
|
||||||
|
.spawn(move || handler.run(paused))
|
||||||
|
.map(|thread| epoll_threads.push(thread))
|
||||||
|
.map_err(|e| {
|
||||||
|
error!("failed to clone virtio epoll thread: {}", e);
|
||||||
|
ActivateError::BadActivate
|
||||||
|
})?;
|
||||||
|
}
|
||||||
self.epoll_threads = Some(epoll_threads);
|
self.epoll_threads = Some(epoll_threads);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -55,6 +55,8 @@ pub enum Error {
|
|||||||
VhostUserConnect(vhost_rs::Error),
|
VhostUserConnect(vhost_rs::Error),
|
||||||
/// Get features failed.
|
/// Get features failed.
|
||||||
VhostUserGetFeatures(VhostError),
|
VhostUserGetFeatures(VhostError),
|
||||||
|
/// Get queue max number failed.
|
||||||
|
VhostUserGetQueueMaxNum(VhostError),
|
||||||
/// Get protocol features failed.
|
/// Get protocol features failed.
|
||||||
VhostUserGetProtocolFeatures(VhostError),
|
VhostUserGetProtocolFeatures(VhostError),
|
||||||
/// Vhost-user Backend not support vhost-user protocol.
|
/// Vhost-user Backend not support vhost-user protocol.
|
||||||
|
Loading…
Reference in New Issue
Block a user