diff --git a/virtio-devices/src/balloon.rs b/virtio-devices/src/balloon.rs index f68909554..b1dd272de 100644 --- a/virtio-devices/src/balloon.rs +++ b/virtio-devices/src/balloon.rs @@ -51,6 +51,9 @@ const DEFLATE_QUEUE_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 3; // Size of a PFN in the balloon interface. const VIRTIO_BALLOON_PFN_SHIFT: u64 = 12; +// Deflate balloon on OOM +const VIRTIO_BALLOON_F_DEFLATE_ON_OOM: u64 = 2; + #[derive(Debug)] pub enum Error { // Guest gave us bad memory addresses. @@ -319,8 +322,16 @@ pub struct Balloon { impl Balloon { // Create a new virtio-balloon. - pub fn new(id: String, size: u64, seccomp_action: SeccompAction) -> io::Result { - let avail_features = 1u64 << VIRTIO_F_VERSION_1; + pub fn new( + id: String, + size: u64, + deflate_on_oom: bool, + seccomp_action: SeccompAction, + ) -> io::Result { + let mut avail_features = 1u64 << VIRTIO_F_VERSION_1; + if deflate_on_oom { + avail_features |= 1u64 << VIRTIO_BALLOON_F_DEFLATE_ON_OOM; + } let config = VirtioBalloonConfig { num_pages: (size >> VIRTIO_BALLOON_PFN_SHIFT) as u32, diff --git a/vmm/src/api/openapi/cloud-hypervisor.yaml b/vmm/src/api/openapi/cloud-hypervisor.yaml index 49ddf3fbf..cf43d3713 100644 --- a/vmm/src/api/openapi/cloud-hypervisor.yaml +++ b/vmm/src/api/openapi/cloud-hypervisor.yaml @@ -745,6 +745,10 @@ components: size: type: integer format: int64 + deflate_on_oom: + type: boolean + default: false + description: Whether the balloon should deflate when the guest is under memory pressure. FsConfig: required: diff --git a/vmm/src/config.rs b/vmm/src/config.rs index 6e6390e33..2c712f4c3 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -1201,14 +1201,19 @@ impl Default for RngConfig { #[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct BalloonConfig { pub size: u64, + /// Option to deflate the balloon in case the guest is out of memory. + #[serde(default)] + pub deflate_on_oom: bool, } impl BalloonConfig { - pub const SYNTAX: &'static str = "Balloon parameters \"size=\""; + pub const SYNTAX: &'static str = + "Balloon parameters \"size=,deflate_on_oom=on|off\""; pub fn parse(balloon: &str) -> Result { let mut parser = OptionParser::new(); parser.add("size"); + parser.add("deflate_on_oom"); parser.parse(balloon).map_err(Error::ParseBalloon)?; let size = parser @@ -1217,7 +1222,16 @@ impl BalloonConfig { .map(|v| v.0) .unwrap_or(0); - Ok(BalloonConfig { size }) + let deflate_on_oom = parser + .convert::("deflate_on_oom") + .map_err(Error::ParseBalloon)? + .unwrap_or(Toggle(false)) + .0; + + Ok(BalloonConfig { + size, + deflate_on_oom, + }) } } diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index a1196f986..cde9673c7 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -2610,6 +2610,7 @@ impl DeviceManager { virtio_devices::Balloon::new( id.clone(), balloon_config.size, + balloon_config.deflate_on_oom, self.seccomp_action.clone(), ) .map_err(DeviceManagerError::CreateVirtioBalloon)?,