diff --git a/CHANGELOG.md b/CHANGELOG.md index 65097f657ef..635a1881bc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,9 @@ and this project adheres to - [#4028](https://github.com/firecracker-microvm/firecracker/pull/4028): Firecracker now creates the log and metrics files if they do not exist, simplifying the launch of Firecracker by removing a manual step. +- [#5516](https://github.com/firecracker-microvm/firecracker/pull/5516): Balloon + stat now supports guest kernel >= 6.12. Now we have a metric to analyze the + memory performance. ### Deprecated diff --git a/src/vmm/src/devices/virtio/balloon/device.rs b/src/vmm/src/devices/virtio/balloon/device.rs index f0ecf77bc9e..e4e46e41a82 100644 --- a/src/vmm/src/devices/virtio/balloon/device.rs +++ b/src/vmm/src/devices/virtio/balloon/device.rs @@ -19,9 +19,11 @@ use super::{ BALLOON_DEV_ID, BALLOON_NUM_QUEUES, BALLOON_QUEUE_SIZES, DEFLATE_INDEX, INFLATE_INDEX, MAX_PAGE_COMPACT_BUFFER, MAX_PAGES_IN_DESC, MIB_TO_4K_PAGES, STATS_INDEX, VIRTIO_BALLOON_F_DEFLATE_ON_OOM, VIRTIO_BALLOON_F_STATS_VQ, VIRTIO_BALLOON_PFN_SHIFT, - VIRTIO_BALLOON_S_AVAIL, VIRTIO_BALLOON_S_CACHES, VIRTIO_BALLOON_S_HTLB_PGALLOC, - VIRTIO_BALLOON_S_HTLB_PGFAIL, VIRTIO_BALLOON_S_MAJFLT, VIRTIO_BALLOON_S_MEMFREE, - VIRTIO_BALLOON_S_MEMTOT, VIRTIO_BALLOON_S_MINFLT, VIRTIO_BALLOON_S_SWAP_IN, + VIRTIO_BALLOON_S_ALLOC_STALL, VIRTIO_BALLOON_S_ASYNC_RECLAIM, VIRTIO_BALLOON_S_ASYNC_SCAN, + VIRTIO_BALLOON_S_AVAIL, VIRTIO_BALLOON_S_CACHES, VIRTIO_BALLOON_S_DIRECT_RECLAIM, + VIRTIO_BALLOON_S_DIRECT_SCAN, VIRTIO_BALLOON_S_HTLB_PGALLOC, VIRTIO_BALLOON_S_HTLB_PGFAIL, + VIRTIO_BALLOON_S_MAJFLT, VIRTIO_BALLOON_S_MEMFREE, VIRTIO_BALLOON_S_MEMTOT, + VIRTIO_BALLOON_S_MINFLT, VIRTIO_BALLOON_S_OOM_KILL, VIRTIO_BALLOON_S_SWAP_IN, VIRTIO_BALLOON_S_SWAP_OUT, }; use crate::devices::virtio::balloon::BalloonError; @@ -133,6 +135,24 @@ pub struct BalloonStats { /// in the guest. #[serde(skip_serializing_if = "Option::is_none")] pub hugetlb_failures: Option, + /// OOM killer invocations. since linux v6.12. + #[serde(skip_serializing_if = "Option::is_none")] + pub oom_kill: Option, + /// Stall count of memory allocatoin. since linux v6.12. + #[serde(skip_serializing_if = "Option::is_none")] + pub alloc_stall: Option, + /// Amount of memory scanned asynchronously. since linux v6.12. + #[serde(skip_serializing_if = "Option::is_none")] + pub async_scan: Option, + /// Amount of memory scanned directly. since linux v6.12. + #[serde(skip_serializing_if = "Option::is_none")] + pub direct_scan: Option, + /// Amount of memory reclaimed asynchronously. since linux v6.12. + #[serde(skip_serializing_if = "Option::is_none")] + pub async_reclaim: Option, + /// Amount of memory reclaimed directly. since linux v6.12. + #[serde(skip_serializing_if = "Option::is_none")] + pub direct_reclaim: Option, } impl BalloonStats { @@ -149,6 +169,12 @@ impl BalloonStats { VIRTIO_BALLOON_S_CACHES => self.disk_caches = val, VIRTIO_BALLOON_S_HTLB_PGALLOC => self.hugetlb_allocations = val, VIRTIO_BALLOON_S_HTLB_PGFAIL => self.hugetlb_failures = val, + VIRTIO_BALLOON_S_OOM_KILL => self.oom_kill = val, + VIRTIO_BALLOON_S_ALLOC_STALL => self.alloc_stall = val, + VIRTIO_BALLOON_S_ASYNC_SCAN => self.async_scan = val, + VIRTIO_BALLOON_S_DIRECT_SCAN => self.direct_scan = val, + VIRTIO_BALLOON_S_ASYNC_RECLAIM => self.async_reclaim = val, + VIRTIO_BALLOON_S_DIRECT_RECLAIM => self.direct_reclaim = val, _ => { return Err(BalloonError::MalformedPayload); } @@ -694,6 +720,12 @@ pub(crate) mod tests { disk_caches: Some(0), hugetlb_allocations: Some(0), hugetlb_failures: Some(0), + oom_kill: None, + alloc_stall: None, + async_scan: None, + direct_scan: None, + async_reclaim: None, + direct_reclaim: None, }; let mut stat = BalloonStat { @@ -730,6 +762,24 @@ pub(crate) mod tests { stat.tag = VIRTIO_BALLOON_S_HTLB_PGFAIL; stats.update_with_stat(&stat).unwrap(); assert_eq!(stats.hugetlb_failures, Some(1)); + stat.tag = VIRTIO_BALLOON_S_OOM_KILL; + stats.update_with_stat(&stat).unwrap(); + assert_eq!(stats.oom_kill, Some(1)); + stat.tag = VIRTIO_BALLOON_S_ALLOC_STALL; + stats.update_with_stat(&stat).unwrap(); + assert_eq!(stats.alloc_stall, Some(1)); + stat.tag = VIRTIO_BALLOON_S_ASYNC_SCAN; + stats.update_with_stat(&stat).unwrap(); + assert_eq!(stats.async_scan, Some(1)); + stat.tag = VIRTIO_BALLOON_S_DIRECT_SCAN; + stats.update_with_stat(&stat).unwrap(); + assert_eq!(stats.direct_scan, Some(1)); + stat.tag = VIRTIO_BALLOON_S_ASYNC_RECLAIM; + stats.update_with_stat(&stat).unwrap(); + assert_eq!(stats.async_reclaim, Some(1)); + stat.tag = VIRTIO_BALLOON_S_DIRECT_RECLAIM; + stats.update_with_stat(&stat).unwrap(); + assert_eq!(stats.direct_reclaim, Some(1)); } #[test] diff --git a/src/vmm/src/devices/virtio/balloon/mod.rs b/src/vmm/src/devices/virtio/balloon/mod.rs index 33020e0ddec..51032d22882 100644 --- a/src/vmm/src/devices/virtio/balloon/mod.rs +++ b/src/vmm/src/devices/virtio/balloon/mod.rs @@ -53,7 +53,7 @@ pub const STATS_INDEX: usize = 2; const VIRTIO_BALLOON_F_STATS_VQ: u32 = 1; // Enable statistics. const VIRTIO_BALLOON_F_DEFLATE_ON_OOM: u32 = 2; // Deflate balloon on OOM. -// The statistics tags. +// The statistics tags. defined in linux "include/uapi/linux/virtio_balloon.h". const VIRTIO_BALLOON_S_SWAP_IN: u16 = 0; const VIRTIO_BALLOON_S_SWAP_OUT: u16 = 1; const VIRTIO_BALLOON_S_MAJFLT: u16 = 2; @@ -64,6 +64,12 @@ const VIRTIO_BALLOON_S_AVAIL: u16 = 6; const VIRTIO_BALLOON_S_CACHES: u16 = 7; const VIRTIO_BALLOON_S_HTLB_PGALLOC: u16 = 8; const VIRTIO_BALLOON_S_HTLB_PGFAIL: u16 = 9; +const VIRTIO_BALLOON_S_OOM_KILL: u16 = 10; +const VIRTIO_BALLOON_S_ALLOC_STALL: u16 = 11; +const VIRTIO_BALLOON_S_ASYNC_SCAN: u16 = 12; +const VIRTIO_BALLOON_S_DIRECT_SCAN: u16 = 13; +const VIRTIO_BALLOON_S_ASYNC_RECLAIM: u16 = 14; +const VIRTIO_BALLOON_S_DIRECT_RECLAIM: u16 = 15; /// Balloon device related errors. #[derive(Debug, thiserror::Error, displaydoc::Display)] diff --git a/src/vmm/src/devices/virtio/balloon/persist.rs b/src/vmm/src/devices/virtio/balloon/persist.rs index e92356c394e..805ee1138f2 100644 --- a/src/vmm/src/devices/virtio/balloon/persist.rs +++ b/src/vmm/src/devices/virtio/balloon/persist.rs @@ -41,6 +41,12 @@ pub struct BalloonStatsState { disk_caches: Option, hugetlb_allocations: Option, hugetlb_failures: Option, + oom_kill: Option, + alloc_stall: Option, + async_scan: Option, + direct_scan: Option, + async_reclaim: Option, + direct_reclaim: Option, } impl BalloonStatsState { @@ -56,6 +62,12 @@ impl BalloonStatsState { disk_caches: stats.disk_caches, hugetlb_allocations: stats.hugetlb_allocations, hugetlb_failures: stats.hugetlb_failures, + oom_kill: stats.oom_kill, + alloc_stall: stats.alloc_stall, + async_scan: stats.async_scan, + direct_scan: stats.direct_scan, + async_reclaim: stats.async_reclaim, + direct_reclaim: stats.direct_reclaim, } } @@ -75,6 +87,12 @@ impl BalloonStatsState { disk_caches: self.disk_caches, hugetlb_allocations: self.hugetlb_allocations, hugetlb_failures: self.hugetlb_failures, + oom_kill: self.oom_kill, + alloc_stall: self.alloc_stall, + async_scan: self.async_scan, + direct_scan: self.direct_scan, + async_reclaim: self.async_reclaim, + direct_reclaim: self.direct_reclaim, } } } @@ -166,7 +184,6 @@ impl Persist<'_> for Balloon { #[cfg(test)] mod tests { - use super::*; use crate::devices::virtio::device::VirtioDevice; use crate::devices::virtio::test_utils::{default_interrupt, default_mem};