Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 23 additions & 38 deletions src/devices/src/virtio/balloon/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use utils::eventfd::EventFd;
use vm_memory::{ByteValued, GuestMemory, GuestMemoryMmap};

use super::super::{
ActivateError, ActivateResult, BalloonError, DeviceState, Queue as VirtQueue, VirtioDevice,
ActivateError, ActivateResult, BalloonError, DeviceQueue, DeviceState, QueueConfig,
VirtioDevice,
};
use super::{defs, defs::uapi};
use crate::virtio::InterruptTransport;
Expand Down Expand Up @@ -45,8 +46,7 @@ pub struct VirtioBalloonConfig {
unsafe impl ByteValued for VirtioBalloonConfig {}

pub struct Balloon {
pub(crate) queues: Vec<VirtQueue>,
pub(crate) queue_events: Vec<EventFd>,
pub(crate) queues: Option<Vec<DeviceQueue>>,
pub(crate) avail_features: u64,
pub(crate) acked_features: u64,
pub(crate) activate_evt: EventFd,
Expand All @@ -55,35 +55,18 @@ pub struct Balloon {
}

impl Balloon {
pub(crate) fn with_queues(queues: Vec<VirtQueue>) -> super::Result<Balloon> {
let mut queue_events = Vec::new();
for _ in 0..queues.len() {
queue_events
.push(EventFd::new(utils::eventfd::EFD_NONBLOCK).map_err(BalloonError::EventFd)?);
}

let config = VirtioBalloonConfig::default();

pub fn new() -> super::Result<Balloon> {
Ok(Balloon {
queues,
queue_events,
queues: None,
avail_features: AVAIL_FEATURES,
acked_features: 0,
activate_evt: EventFd::new(utils::eventfd::EFD_NONBLOCK)
.map_err(BalloonError::EventFd)?,
device_state: DeviceState::Inactive,
config,
config: VirtioBalloonConfig::default(),
})
}

pub fn new() -> super::Result<Balloon> {
let queues: Vec<VirtQueue> = defs::QUEUE_SIZES
.iter()
.map(|&max_size| VirtQueue::new(max_size))
.collect();
Self::with_queues(queues)
}

pub fn id(&self) -> &str {
defs::BALLOON_DEV_ID
}
Expand All @@ -96,9 +79,13 @@ impl Balloon {
DeviceState::Inactive => unreachable!(),
};

let queues = self
.queues
.as_mut()
.expect("queues should exist when activated");
let mut have_used = false;

while let Some(head) = self.queues[FRQ_INDEX].pop(mem) {
while let Some(head) = queues[FRQ_INDEX].queue.pop(mem) {
let index = head.index;
for desc in head.into_iter() {
let host_addr = mem.get_host_address(desc.addr).unwrap();
Expand All @@ -116,7 +103,7 @@ impl Balloon {
}

have_used = true;
if let Err(e) = self.queues[FRQ_INDEX].add_used(mem, index, 0) {
if let Err(e) = queues[FRQ_INDEX].queue.add_used(mem, index, 0) {
error!("failed to add used elements to the queue: {e:?}");
}
}
Expand Down Expand Up @@ -146,16 +133,8 @@ impl VirtioDevice for Balloon {
"balloon"
}

fn queues(&self) -> &[VirtQueue] {
&self.queues
}

fn queues_mut(&mut self) -> &mut [VirtQueue] {
&mut self.queues
}

fn queue_events(&self) -> &[EventFd] {
&self.queue_events
fn queue_config(&self) -> &[QueueConfig] {
&defs::QUEUE_CONFIG
}

fn read_config(&self, offset: u64, mut data: &mut [u8]) {
Expand All @@ -180,12 +159,17 @@ impl VirtioDevice for Balloon {
);
}

fn activate(&mut self, mem: GuestMemoryMmap, interrupt: InterruptTransport) -> ActivateResult {
if self.queues.len() != defs::NUM_QUEUES {
fn activate(
&mut self,
mem: GuestMemoryMmap,
interrupt: InterruptTransport,
queues: Vec<DeviceQueue>,
) -> ActivateResult {
if queues.len() != defs::NUM_QUEUES {
error!(
"Cannot perform activate. Expected {} queue(s), got {}",
defs::NUM_QUEUES,
self.queues.len()
queues.len()
);
return Err(ActivateError::BadActivate);
}
Expand All @@ -195,6 +179,7 @@ impl VirtioDevice for Balloon {
return Err(ActivateError::BadActivate);
}

self.queues = Some(queues);
self.device_state = DeviceState::Activated(mem, interrupt);

Ok(())
Expand Down
59 changes: 24 additions & 35 deletions src/devices/src/virtio/balloon/event_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ use super::device::{Balloon, DFQ_INDEX, FRQ_INDEX, IFQ_INDEX, PHQ_INDEX, STQ_IND
use crate::virtio::device::VirtioDevice;

impl Balloon {
fn queue_event(&self, idx: usize) -> &std::sync::Arc<utils::eventfd::EventFd> {
&self.queues.as_ref().expect("queues should exist")[idx].event
}

pub(crate) fn handle_ifq_event(&mut self, event: &EpollEvent) {
error!("balloon: unsupported inflate queue event");

Expand All @@ -16,7 +20,7 @@ impl Balloon {
return;
}

if let Err(e) = self.queue_events[IFQ_INDEX].read() {
if let Err(e) = self.queue_event(IFQ_INDEX).read() {
error!("Failed to read balloon inflate queue event: {e:?}");
}
}
Expand All @@ -30,7 +34,7 @@ impl Balloon {
return;
}

if let Err(e) = self.queue_events[DFQ_INDEX].read() {
if let Err(e) = self.queue_event(DFQ_INDEX).read() {
error!("Failed to read balloon inflate queue event: {e:?}");
}
}
Expand All @@ -44,7 +48,7 @@ impl Balloon {
return;
}

if let Err(e) = self.queue_events[STQ_INDEX].read() {
if let Err(e) = self.queue_event(STQ_INDEX).read() {
error!("Failed to read balloon stats queue event: {e:?}");
}
}
Expand All @@ -58,7 +62,7 @@ impl Balloon {
return;
}

if let Err(e) = self.queue_events[PHQ_INDEX].read() {
if let Err(e) = self.queue_event(PHQ_INDEX).read() {
error!("Failed to read balloon page-hinting queue event: {e:?}");
}
}
Expand All @@ -72,7 +76,7 @@ impl Balloon {
return;
}

if let Err(e) = self.queue_events[FRQ_INDEX].read() {
if let Err(e) = self.queue_event(FRQ_INDEX).read() {
error!("Failed to read balloon free-page reporting queue event: {e:?}");
} else if self.process_frq() {
self.device_state.signal_used_queue();
Expand All @@ -93,11 +97,8 @@ impl Balloon {

event_manager
.register(
self.queue_events[IFQ_INDEX].as_raw_fd(),
EpollEvent::new(
EventSet::IN,
self.queue_events[IFQ_INDEX].as_raw_fd() as u64,
),
self.queue_event(IFQ_INDEX).as_raw_fd(),
EpollEvent::new(EventSet::IN, self.queue_event(IFQ_INDEX).as_raw_fd() as u64),
self_subscriber.clone(),
)
.unwrap_or_else(|e| {
Expand All @@ -106,11 +107,8 @@ impl Balloon {

event_manager
.register(
self.queue_events[DFQ_INDEX].as_raw_fd(),
EpollEvent::new(
EventSet::IN,
self.queue_events[DFQ_INDEX].as_raw_fd() as u64,
),
self.queue_event(DFQ_INDEX).as_raw_fd(),
EpollEvent::new(EventSet::IN, self.queue_event(DFQ_INDEX).as_raw_fd() as u64),
self_subscriber.clone(),
)
.unwrap_or_else(|e| {
Expand All @@ -119,11 +117,8 @@ impl Balloon {

event_manager
.register(
self.queue_events[STQ_INDEX].as_raw_fd(),
EpollEvent::new(
EventSet::IN,
self.queue_events[STQ_INDEX].as_raw_fd() as u64,
),
self.queue_event(STQ_INDEX).as_raw_fd(),
EpollEvent::new(EventSet::IN, self.queue_event(STQ_INDEX).as_raw_fd() as u64),
self_subscriber.clone(),
)
.unwrap_or_else(|e| {
Expand All @@ -132,11 +127,8 @@ impl Balloon {

event_manager
.register(
self.queue_events[PHQ_INDEX].as_raw_fd(),
EpollEvent::new(
EventSet::IN,
self.queue_events[PHQ_INDEX].as_raw_fd() as u64,
),
self.queue_event(PHQ_INDEX).as_raw_fd(),
EpollEvent::new(EventSet::IN, self.queue_event(PHQ_INDEX).as_raw_fd() as u64),
self_subscriber.clone(),
)
.unwrap_or_else(|e| {
Expand All @@ -145,11 +137,8 @@ impl Balloon {

event_manager
.register(
self.queue_events[FRQ_INDEX].as_raw_fd(),
EpollEvent::new(
EventSet::IN,
self.queue_events[FRQ_INDEX].as_raw_fd() as u64,
),
self.queue_event(FRQ_INDEX).as_raw_fd(),
EpollEvent::new(EventSet::IN, self.queue_event(FRQ_INDEX).as_raw_fd() as u64),
self_subscriber.clone(),
)
.unwrap_or_else(|e| {
Expand All @@ -167,11 +156,11 @@ impl Balloon {
impl Subscriber for Balloon {
fn process(&mut self, event: &EpollEvent, event_manager: &mut EventManager) {
let source = event.fd();
let ifq = self.queue_events[IFQ_INDEX].as_raw_fd();
let dfq = self.queue_events[DFQ_INDEX].as_raw_fd();
let stq = self.queue_events[STQ_INDEX].as_raw_fd();
let phq = self.queue_events[PHQ_INDEX].as_raw_fd();
let frq = self.queue_events[FRQ_INDEX].as_raw_fd();
let ifq = self.queue_event(IFQ_INDEX).as_raw_fd();
let dfq = self.queue_event(DFQ_INDEX).as_raw_fd();
let stq = self.queue_event(STQ_INDEX).as_raw_fd();
let phq = self.queue_event(PHQ_INDEX).as_raw_fd();
let frq = self.queue_event(FRQ_INDEX).as_raw_fd();
let activate_evt = self.activate_evt.as_raw_fd();

if self.is_activated() {
Expand Down
5 changes: 4 additions & 1 deletion src/devices/src/virtio/balloon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ pub use self::defs::uapi::VIRTIO_ID_BALLOON as TYPE_BALLOON;
pub use self::device::Balloon;

mod defs {
use super::super::QueueConfig;

pub const BALLOON_DEV_ID: &str = "virtio_balloon";
pub const NUM_QUEUES: usize = 5;
pub const QUEUE_SIZES: &[u16] = &[256; NUM_QUEUES];
pub const QUEUE_SIZE: u16 = 256;
pub static QUEUE_CONFIG: [QueueConfig; NUM_QUEUES] = [QueueConfig::new(QUEUE_SIZE); NUM_QUEUES];

pub mod uapi {
pub const VIRTIO_F_VERSION_1: u32 = 32;
Expand Down
40 changes: 15 additions & 25 deletions src/devices/src/virtio/block/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ use vm_memory::{ByteValued, GuestMemoryMmap};

use super::worker::BlockWorker;
use super::{
super::{ActivateResult, DeviceState, Queue, VirtioDevice, TYPE_BLOCK},
Error, QUEUE_SIZES, SECTOR_SHIFT, SECTOR_SIZE,
super::{ActivateResult, DeviceQueue, DeviceState, QueueConfig, VirtioDevice, TYPE_BLOCK},
Error, NUM_QUEUES, QUEUE_CONFIG, SECTOR_SHIFT, SECTOR_SIZE,
};

use crate::virtio::{
Expand Down Expand Up @@ -216,8 +216,6 @@ pub struct Block {
config: VirtioBlkConfig,

// Transport related fields.
pub(crate) queues: Vec<Queue>,
pub(crate) queue_evts: [EventFd; 1],
pub(crate) device_state: DeviceState,

// Implementation specific fields.
Expand Down Expand Up @@ -302,10 +300,6 @@ impl Block {
avail_features |= 1u64 << VIRTIO_BLK_F_RO;
};

let queue_evts = [EventFd::new(EFD_NONBLOCK)?];

let queues = QUEUE_SIZES.iter().map(|&s| Queue::new(s)).collect();

let config = VirtioBlkConfig {
capacity: disk_properties.nsectors(),
size_max: 0,
Expand All @@ -330,8 +324,6 @@ impl Block {
disk_image_id,
avail_features,
acked_features: 0u64,
queue_evts,
queues,
device_state: DeviceState::Inactive,
worker_thread: None,
worker_stopfd: EventFd::new(EFD_NONBLOCK)?,
Expand Down Expand Up @@ -363,16 +355,8 @@ impl VirtioDevice for Block {
"block"
}

fn queues(&self) -> &[Queue] {
&self.queues
}

fn queues_mut(&mut self) -> &mut [Queue] {
&mut self.queues
}

fn queue_events(&self) -> &[EventFd] {
&self.queue_evts
fn queue_config(&self) -> &[QueueConfig] {
&QUEUE_CONFIG
}

fn avail_features(&self) -> u64 {
Expand Down Expand Up @@ -409,13 +393,20 @@ impl VirtioDevice for Block {
self.device_state.is_activated()
}

fn activate(&mut self, mem: GuestMemoryMmap, interrupt: InterruptTransport) -> ActivateResult {
fn activate(
&mut self,
mem: GuestMemoryMmap,
interrupt: InterruptTransport,
queues: Vec<DeviceQueue>,
) -> ActivateResult {
if self.worker_thread.is_some() {
panic!("virtio_blk: worker thread already exists");
}

let event_idx: bool = (self.acked_features & (1 << VIRTIO_RING_F_EVENT_IDX)) != 0;
self.queues[0].set_event_idx(event_idx);
let [blk_q]: [_; NUM_QUEUES] = queues.try_into().map_err(|_| {
error!("Cannot perform activate. Expected {} queue(s)", NUM_QUEUES);
ActivateError::BadActivate
})?;

let disk = match self.disk.take() {
Some(d) => d,
Expand All @@ -428,8 +419,7 @@ impl VirtioDevice for Block {
};

let worker = BlockWorker::new(
self.queues[0].clone(),
self.queue_evts[0].try_clone().unwrap(),
blk_q,
interrupt.clone(),
mem.clone(),
disk,
Expand Down
6 changes: 4 additions & 2 deletions src/devices/src/virtio/block/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ pub use self::device::{Block, CacheType};

use vm_memory::GuestMemoryError;

use super::QueueConfig;

pub const CONFIG_SPACE_SIZE: usize = 8;
pub const SECTOR_SHIFT: u8 = 9;
pub const SECTOR_SIZE: u64 = (0x01_u64) << SECTOR_SHIFT;
pub const QUEUE_SIZE: u16 = 256;
const QUEUE_SIZE: u16 = 256;
pub const NUM_QUEUES: usize = 1;
pub const QUEUE_SIZES: &[u16] = &[QUEUE_SIZE];
pub static QUEUE_CONFIG: [QueueConfig; NUM_QUEUES] = [QueueConfig::new(QUEUE_SIZE)];

#[derive(Debug)]
pub enum Error {
Expand Down
Loading
Loading