Skip to content

Commit

Permalink
Merge pull request #7697 from lisongqian/feat/balloon_metrics
Browse files Browse the repository at this point in the history
dragonball: add metrics support for balloon device
  • Loading branch information
studychao committed Oct 25, 2023
2 parents 328ba0d + dce365d commit 29d8633
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 3 deletions.
50 changes: 47 additions & 3 deletions src/dragonball/src/dbs_virtio_devices/src/balloon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ use dbs_interrupt::{InterruptNotifier, NoopNotifier};
use dbs_utils::epoll_manager::{
EpollManager, EventOps, EventSet, Events, MutEventSubscriber, SubscriberId,
};
use dbs_utils::metric::{IncMetric, SharedIncMetric, SharedStoreMetric, StoreMetric};
use log::{debug, error, info, trace};
use serde::Serialize;
use virtio_bindings::bindings::virtio_blk::VIRTIO_F_VERSION_1;
use virtio_queue::{QueueOwnedT, QueueSync, QueueT};
use vm_memory::{
Expand Down Expand Up @@ -88,6 +90,25 @@ const PAGE_REPORTING_CAPACITY: u16 = 128;
#[derive(Debug, thiserror::Error)]
pub enum BalloonError {}

/// Balloon Device associated metrics.
#[derive(Default, Serialize)]
pub struct BalloonDeviceMetrics {
/// Number of times when handling events on a balloon device.
pub event_count: SharedIncMetric,
/// Number of times when activate failed on a balloon device.
pub activate_fails: SharedIncMetric,
/// Number of balloon device inflations.
pub inflate_count: SharedIncMetric,
/// Number of balloon device deflations.
pub deflate_count: SharedIncMetric,
/// Memory size(mb) of balloon device.
pub balloon_size_mb: SharedStoreMetric,
/// Number of balloon device reportions
pub reporting_count: SharedIncMetric,
/// Number of times when handling events on a balloon device failed.
pub event_fails: SharedIncMetric,
}

pub type BalloonResult<T> = std::result::Result<T, BalloonError>;

// Got from include/uapi/linux/virtio_balloon.h
Expand All @@ -113,12 +134,14 @@ pub struct BalloonEpollHandler<
pub(crate) deflate: VirtioQueueConfig<Q>,
pub(crate) reporting: Option<VirtioQueueConfig<Q>>,
balloon_config: Arc<Mutex<VirtioBalloonConfig>>,
metrics: Arc<BalloonDeviceMetrics>,
}

impl<AS: DbsGuestAddressSpace, Q: QueueT + Send, R: GuestMemoryRegion>
BalloonEpollHandler<AS, Q, R>
{
fn process_reporting_queue(&mut self) -> bool {
self.metrics.reporting_count.inc();
if let Some(queue) = &mut self.reporting {
if let Err(e) = queue.consume_event() {
error!("Failed to get reporting queue event: {:?}", e);
Expand Down Expand Up @@ -234,7 +257,11 @@ impl<AS: DbsGuestAddressSpace, Q: QueueT + Send, R: GuestMemoryRegion>

fn process_queue(&mut self, idx: u32) -> bool {
let conf = &mut self.config;

match idx {
INFLATE_QUEUE_AVAIL_EVENT => self.metrics.inflate_count.inc(),
DEFLATE_QUEUE_AVAIL_EVENT => self.metrics.deflate_count.inc(),
_ => {}
}
let queue = match idx {
INFLATE_QUEUE_AVAIL_EVENT => &mut self.inflate,
DEFLATE_QUEUE_AVAIL_EVENT => &mut self.deflate,
Expand Down Expand Up @@ -481,14 +508,17 @@ where
BALLOON_DRIVER_NAME,
idx
);
self.metrics.event_count.inc();
match idx {
INFLATE_QUEUE_AVAIL_EVENT | DEFLATE_QUEUE_AVAIL_EVENT => {
if !self.process_queue(idx) {
self.metrics.event_fails.inc();
error!("{}: Failed to handle {} queue", BALLOON_DRIVER_NAME, idx);
}
}
REPORTING_QUEUE_AVAIL_EVENT => {
if !self.process_reporting_queue() {
self.metrics.event_fails.inc();
error!("Failed to handle reporting queue");
}
}
Expand Down Expand Up @@ -518,6 +548,7 @@ pub struct Balloon<AS: GuestAddressSpace> {
pub(crate) device_change_notifier: Arc<dyn InterruptNotifier>,
pub(crate) subscriber_id: Option<SubscriberId>,
pub(crate) phantom: PhantomData<AS>,
metrics: Arc<BalloonDeviceMetrics>,
}

#[derive(Copy, Clone, Debug, Default, PartialEq)]
Expand Down Expand Up @@ -556,10 +587,12 @@ impl<AS: GuestAddressSpace> Balloon<AS> {
device_change_notifier: Arc::new(NoopNotifier::new()),
subscriber_id: None,
phantom: PhantomData,
metrics: Arc::new(BalloonDeviceMetrics::default()),
})
}

pub fn set_size(&self, size_mb: u64) -> Result<()> {
self.metrics.balloon_size_mb.store(size_mb as usize);
let num_pages = mib_to_page_number(size_mb);

let balloon_config = &mut self.config.lock().unwrap();
Expand All @@ -574,6 +607,10 @@ impl<AS: GuestAddressSpace> Balloon<AS> {

Ok(())
}

pub fn metrics(&self) -> Arc<BalloonDeviceMetrics> {
self.metrics.clone()
}
}

impl<AS, Q, R> VirtioDevice<AS, Q, R> for Balloon<AS>
Expand Down Expand Up @@ -649,7 +686,12 @@ where
}

fn activate(&mut self, mut config: VirtioDeviceConfig<AS, Q, R>) -> ActivateResult {
self.device_info.check_queue_sizes(&config.queues)?;
self.device_info
.check_queue_sizes(&config.queues)
.map_err(|e| {
self.metrics.activate_fails.inc();
e
})?;
self.device_change_notifier = config.device_change_notifier.clone();

trace!(
Expand All @@ -671,6 +713,7 @@ where
deflate,
reporting,
balloon_config: self.config.clone(),
metrics: self.metrics.clone(),
});

self.subscriber_id = Some(self.device_info.register_event_handler(handler));
Expand Down Expand Up @@ -731,13 +774,14 @@ pub(crate) mod tests {
let deflate = VirtioQueueConfig::create(128, 0).unwrap();
let reporting = Some(VirtioQueueConfig::create(128, 0).unwrap());
let balloon_config = Arc::new(Mutex::new(VirtioBalloonConfig::default()));

let metrics = Arc::new(BalloonDeviceMetrics::default());
BalloonEpollHandler {
config,
inflate,
deflate,
reporting,
balloon_config,
metrics,
}
}

Expand Down
18 changes: 18 additions & 0 deletions src/dragonball/src/device_manager/balloon_dev_mgr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::address_space_manager::GuestAddressSpaceImpl;
use crate::config_manager::{ConfigItem, DeviceConfigInfo, DeviceConfigInfos};
use crate::device_manager::DbsMmioV2Device;
use crate::device_manager::{DeviceManager, DeviceMgrError, DeviceOpContext};
use crate::metric::METRICS;

// The flag of whether to use the shared irq.
const USE_SHARED_IRQ: bool = true;
Expand Down Expand Up @@ -175,6 +176,11 @@ impl BalloonDeviceMgr {
)
.map_err(BalloonDeviceError::CreateBalloonDevice)?,
);
METRICS
.write()
.unwrap()
.balloon
.insert(balloon_cfg.balloon_id.clone(), device.metrics());

let mmio_dev =
DeviceManager::create_mmio_virtio_device_with_device_change_notification(
Expand Down Expand Up @@ -220,6 +226,11 @@ impl BalloonDeviceMgr {
},
)
.map_err(BalloonDeviceError::CreateBalloonDevice)?;
METRICS
.write()
.unwrap()
.balloon
.insert(info.config.balloon_id.clone(), device.metrics());
let mmio_dev =
DeviceManager::create_mmio_virtio_device_with_device_change_notification(
Box::new(device),
Expand Down Expand Up @@ -275,6 +286,13 @@ impl Default for BalloonDeviceMgr {
}
}

impl Drop for BalloonDeviceMgr {
// todo: move METIRCS oprations to remove_device. issue #8207.
fn drop(&mut self) {
METRICS.write().unwrap().balloon.clear();
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
7 changes: 7 additions & 0 deletions src/dragonball/src/metric.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ use std::collections::HashMap;
use std::sync::{Arc, RwLock};

use dbs_utils::metric::SharedIncMetric;
#[cfg(feature = "virtio-balloon")]
use dbs_virtio_devices::balloon::BalloonDeviceMetrics;
use lazy_static::lazy_static;
use serde::Serialize;

Expand Down Expand Up @@ -52,6 +54,8 @@ pub struct SignalMetrics {
}

/// Structure storing all metrics while enforcing serialization support on them.
/// The type of the device metrics is HashMap<DeviceId, Arc<DeviceMetrics>> and the type of
/// non-device metrics is XXMetrics.
#[derive(Default, Serialize)]
pub struct DragonballMetrics {
/// Metrics related to a vcpu's functioning.
Expand All @@ -60,6 +64,9 @@ pub struct DragonballMetrics {
pub seccomp: SeccompMetrics,
/// Metrics related to signals.
pub signals: SignalMetrics,
#[cfg(feature = "virtio-balloon")]
/// Metrics related to balloon device.
pub balloon: HashMap<String, Arc<BalloonDeviceMetrics>>,
}

#[cfg(test)]
Expand Down

0 comments on commit 29d8633

Please sign in to comment.