Skip to content

Commit

Permalink
runtime-rs: check the update memory size
Browse files Browse the repository at this point in the history
check the update memory size greater than default max memory size

Fixes:#6875
Signed-off-by: Zhongtao Hu <zhongtaohu.tim@linux.alibaba.com>
  • Loading branch information
Tim-0731-Hzt committed Dec 12, 2023
1 parent af399a0 commit 327ec15
Show file tree
Hide file tree
Showing 12 changed files with 83 additions and 102 deletions.
4 changes: 2 additions & 2 deletions src/libs/kata-types/src/capabilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub enum CapabilityBits {
/// hypervisor supports hybrid-vsock
HybridVsockSupport,
/// hypervisor supports memory hotplug probe interface
GuestMemoryHotplugProbe,
GuestMemoryProbe,
}

/// Capabilities describe a virtcontainers hypervisor capabilities through a bit mask.
Expand Down Expand Up @@ -81,7 +81,7 @@ impl Capabilities {

/// is_mem_hotplug_probe_supported tells if the hypervisor supports hotplug probe interface
pub fn is_mem_hotplug_probe_supported(&self) -> bool {
self.flags.and(CapabilityBits::GuestMemoryHotplugProbe) != 0
self.flags.and(CapabilityBits::GuestMemoryProbe) != 0
}
}

Expand Down
14 changes: 7 additions & 7 deletions src/libs/kata-types/src/config/hypervisor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,13 @@ pub struct MemoryInfo {
#[serde(default)]
pub default_memory: u32,

/// Default maximum memory in MiB per SB / VM
/// unspecified or == 0 --> will be set to the actual amount of physical RAM
/// > 0 <= amount of physical RAM --> will be set to the specified number
/// > amount of physical RAM --> will be set to the actual amount of physical RAM
#[serde(default)]
pub default_maxmemory: u32,

/// Default memory slots per SB/VM.
///
/// This is will determine the times that memory will be hotadded to sandbox/VM.
Expand Down Expand Up @@ -653,13 +660,6 @@ pub struct MemoryInfo {
/// If swap_in_bytes and memory_limit_in_bytes is not set, the size should be default_memory.
#[serde(default)]
pub enable_guest_swap: bool,

/// Default maximum memory in MiB per SB / VM
/// unspecified or == 0 --> will be set to the actual amount of physical RAM
/// > 0 <= amount of physical RAM --> will be set to the specified number
/// > amount of physical RAM --> will be set to the actual amount of physical RAM
#[serde(default)]
pub default_maxmemory: u32,
}

impl MemoryInfo {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@ impl CloudHypervisorInner {
todo!()
}

pub(crate) fn resize_memory(&self, _req_mem_mb: u32) -> Result<(u32, MemoryConfig)> {
pub(crate) fn resize_memory(&self, _new_mem_mb: u32) -> Result<(u32, MemoryConfig)> {
todo!()
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/runtime-rs/crates/hypervisor/src/ch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,9 @@ impl Hypervisor for CloudHypervisor {
inner.guest_memory_block_size_mb()
}

async fn resize_memory(&self, req_mem_mb: u32) -> Result<(u32, MemoryConfig)> {
async fn resize_memory(&self, new_mem_mb: u32) -> Result<(u32, MemoryConfig)> {
let inner = self.inner.read().await;
inner.resize_memory(req_mem_mb)
inner.resize_memory(new_mem_mb)
}
}

Expand Down
76 changes: 52 additions & 24 deletions src/runtime-rs/crates/hypervisor/src/dragonball/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ use std::{collections::HashSet, fs::create_dir_all};

const DRAGONBALL_KERNEL: &str = "vmlinux";
const DRAGONBALL_ROOT_FS: &str = "rootfs";

const BALLOON_DEVICE_ID: &str = "balloon0";
const MEM_DEVICE_ID: &str = "memmr0";
#[derive(Debug)]
pub struct DragonballInner {
/// sandbox id
Expand Down Expand Up @@ -76,6 +77,9 @@ pub struct DragonballInner {

/// the hotplug memory size
pub(crate) mem_hotplug_size_mb: u32,

/// the balloon size
pub(crate) balloon_size: u32,
}

impl DragonballInner {
Expand All @@ -85,7 +89,8 @@ impl DragonballInner {
CapabilityBits::BlockDeviceSupport
| CapabilityBits::BlockDeviceHotplugSupport
| CapabilityBits::FsSharingSupport
| CapabilityBits::HybridVsockSupport,
| CapabilityBits::HybridVsockSupport
| CapabilityBits::GuestMemoryProbe,
);
DragonballInner {
id: "".to_string(),
Expand All @@ -102,6 +107,7 @@ impl DragonballInner {
capabilities,
guest_memory_block_size_mb: 0,
mem_hotplug_size_mb: 0,
balloon_size: 0,
}
}

Expand Down Expand Up @@ -349,33 +355,53 @@ impl DragonballInner {
Ok((old_vcpus, new_vcpus))
}

pub(crate) fn resize_memory(&mut self, req_mem_mb: u32) -> Result<(u32, MemoryConfig)> {
pub(crate) fn resize_memory(&mut self, new_mem_mb: u32) -> Result<(u32, MemoryConfig)> {
// check the invalid request memory
if new_mem_mb > self.hypervisor_config().memory_info.default_maxmemory
&& self.hypervisor_config().memory_info.default_maxmemory > 0
{
warn!(
sl!(),
"memory size unchanged, the request memory size {} is greater than the max memory size {}",
new_mem_mb, self.hypervisor_config().memory_info.default_maxmemory
);

return Ok((
0,
MemoryConfig {
..Default::default()
},
));
}

let had_mem_mb = self.config.memory_info.default_memory + self.mem_hotplug_size_mb;
match req_mem_mb.cmp(&had_mem_mb) {
match new_mem_mb.cmp(&had_mem_mb) {
Ordering::Greater => {
// clean virtio-ballon device before hotplug memory, resize to 0
let balloon_config = BalloonDeviceConfigInfo {
balloon_id: "balloon0".to_owned(),
size_mib: 0,
use_shared_irq: None,
use_generic_irq: None,
f_deflate_on_oom: false,
f_reporting: false,
};
self.vmm_instance
.insert_balloon_device(balloon_config)
.context("failed to insert balloon device")?;
if self.balloon_size > 0 {
let balloon_config = BalloonDeviceConfigInfo {
balloon_id: BALLOON_DEVICE_ID.to_owned(),
size_mib: 0,
use_shared_irq: None,
use_generic_irq: None,
f_deflate_on_oom: false,
f_reporting: false,
};
self.vmm_instance
.insert_balloon_device(balloon_config)
.context("failed to insert balloon device")?;
}

// update the hotplug size
self.mem_hotplug_size_mb = req_mem_mb - self.config.memory_info.default_memory;
self.mem_hotplug_size_mb = new_mem_mb - self.config.memory_info.default_memory;
self.balloon_size = 0;

// insert a new memory device
let add_mem_mb = req_mem_mb - had_mem_mb;
let add_mem_mb = new_mem_mb - had_mem_mb;
self.vmm_instance.insert_mem_device(MemDeviceConfigInfo {
mem_id: format!("mem{}", self.mem_hotplug_size_mb),
mem_id: MEM_DEVICE_ID.to_owned(),
size_mib: add_mem_mb as u64,
capacity_mib: add_mem_mb as u64,
multi_region: false,
multi_region: true,
host_numa_node_id: None,
guest_numa_node_id: None,
use_shared_irq: None,
Expand All @@ -384,15 +410,16 @@ impl DragonballInner {
}
Ordering::Less => {
// we only use one balloon device here, and resize it to release memory
// the operation we do here is inserting a new balloon0 device or resizing it
// the operation we do here is inserting a new BALLOON_DEVICE_ID device or resizing it
let balloon_config = BalloonDeviceConfigInfo {
balloon_id: "balloon0".to_owned(),
size_mib: (had_mem_mb - req_mem_mb) as u64,
balloon_id: BALLOON_DEVICE_ID.to_owned(),
size_mib: (had_mem_mb - new_mem_mb) as u64,
use_shared_irq: None,
use_generic_irq: None,
f_deflate_on_oom: false,
f_reporting: false,
};
self.balloon_size = had_mem_mb - new_mem_mb;
self.vmm_instance
.insert_balloon_device(balloon_config)
.context("failed to insert balloon device")?;
Expand All @@ -407,7 +434,7 @@ impl DragonballInner {
};

Ok((
req_mem_mb,
new_mem_mb,
MemoryConfig {
..Default::default()
},
Expand Down Expand Up @@ -476,6 +503,7 @@ impl Persist for DragonballInner {
capabilities: Capabilities::new(),
guest_memory_block_size_mb: 0,
mem_hotplug_size_mb: 0,
balloon_size: 0,
})
}
}
4 changes: 2 additions & 2 deletions src/runtime-rs/crates/hypervisor/src/dragonball/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,9 @@ impl Hypervisor for Dragonball {
inner.guest_memory_block_size_mb()
}

async fn resize_memory(&self, req_mem_mb: u32) -> Result<(u32, MemoryConfig)> {
async fn resize_memory(&self, new_mem_mb: u32) -> Result<(u32, MemoryConfig)> {
let mut inner = self.inner.write().await;
inner.resize_memory(req_mem_mb)
inner.resize_memory(new_mem_mb)
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/runtime-rs/crates/hypervisor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ pub trait Hypervisor: std::fmt::Debug + Send + Sync {
async fn save_vm(&self) -> Result<()>;
async fn resume_vm(&self) -> Result<()>;
async fn resize_vcpu(&self, old_vcpus: u32, new_vcpus: u32) -> Result<(u32, u32)>; // returns (old_vcpus, new_vcpus)
async fn resize_memory(&self, req_mem_mb: u32) -> Result<(u32, MemoryConfig)>;
async fn resize_memory(&self, new_mem_mb: u32) -> Result<(u32, MemoryConfig)>;

// device manager
async fn add_device(&self, device: DeviceType) -> Result<DeviceType>;
Expand Down
2 changes: 1 addition & 1 deletion src/runtime-rs/crates/hypervisor/src/qemu/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ impl QemuInner {
todo!()
}

pub(crate) fn resize_memory(&self, _req_mem_mb: u32) -> Result<(u32, MemoryConfig)> {
pub(crate) fn resize_memory(&self, _new_mem_mb: u32) -> Result<(u32, MemoryConfig)> {
todo!()
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/runtime-rs/crates/hypervisor/src/qemu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,8 @@ impl Hypervisor for Qemu {
inner.guest_memory_block_size_mb()
}

async fn resize_memory(&self, req_mem_mb: u32) -> Result<(u32, MemoryConfig)> {
async fn resize_memory(&self, new_mem_mb: u32) -> Result<(u32, MemoryConfig)> {
let inner = self.inner.read().await;
inner.resize_memory(req_mem_mb)
inner.resize_memory(new_mem_mb)
}
}
69 changes: 11 additions & 58 deletions src/runtime-rs/crates/resource/src/cpu_mem/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use std::sync::Arc;

use anyhow::{Context, Ok, Result};
use hypervisor::Hypervisor;
use kata_types::config::TomlConfig;
use oci::LinuxResources;
use tokio::sync::RwLock;

Expand All @@ -21,31 +20,17 @@ pub const MIB_TO_BYTES_SHIFT: i32 = 20;

#[derive(Default, Debug, Clone)]
pub struct MemResource {
/// Current memory
pub(crate) current_mem: Arc<RwLock<u32>>,

/// Default memory
pub(crate) orig_toml_default_mem: u32,

/// MemResource of each container
pub(crate) container_mem_resources: Arc<RwLock<HashMap<String, LinuxResources>>>,

/// Use guest swap
pub(crate) use_guest_swap: bool,
}

impl MemResource {
pub fn new(config: Arc<TomlConfig>, init_size_manager: InitialSizeManager) -> Result<Self> {
let hypervisor_name = config.runtime.hypervisor_name.clone();
let hypervisor_config = config
.hypervisor
.get(&hypervisor_name)
.context("failed to get hypervisor")?;

pub fn new(init_size_manager: InitialSizeManager) -> Result<Self> {
Ok(Self {
current_mem: Arc::new(RwLock::new(hypervisor_config.memory_info.default_memory)),
container_mem_resources: Arc::new(RwLock::new(HashMap::new())),
use_guest_swap: hypervisor_config.memory_info.enable_guest_swap,
orig_toml_default_mem: init_size_manager.get_orig_toml_default_mem(),
})
}
Expand All @@ -61,36 +46,23 @@ impl MemResource {
.await
.context("update container memory resources")?;
// the unit here is MB
let (mut mem_sb_mb, need_pod_swap, swap_sb_mb) = self
.total_mems(self.use_guest_swap)
let mut mem_sb_mb = self
.total_mems()
.await
.context("failed to calculate total memory requirement for containers")?;
mem_sb_mb += self.orig_toml_default_mem;
if need_pod_swap {
mem_sb_mb += swap_sb_mb;
}
info!(sl!(), "calculate mem_sb_mb {}", mem_sb_mb);

let curr_mem = self
.do_update_mem_resource(mem_sb_mb, swap_sb_mb, hypervisor)
let _curr_mem = self
.do_update_mem_resource(mem_sb_mb, hypervisor)
.await
.context("failed to update_mem_resource")?;

self.update_current_mem(curr_mem).await;
Ok(())
}

async fn update_current_mem(&self, new_mem: u32) {
let mut current_mem = self.current_mem.write().await;
*current_mem = new_mem;
}

async fn total_mems(&self, use_guest_swap: bool) -> Result<(u32, bool, u32)> {
// sb stands for sandbox
async fn total_mems(&self) -> Result<u32> {
let mut mem_sandbox = 0;
let mut need_pod_swap = false;
let mut swap_sandbox = 0;

let resources = self.container_mem_resources.read().await;

for (_, r) in resources.iter() {
Expand All @@ -100,36 +72,17 @@ impl MemResource {

if let Some(memory) = &r.memory {
// set current_limit to 0 if memory limit is not set to container
let current_limit = memory.limit.map_or(0, |limit| {
let _current_limit = memory.limit.map_or(0, |limit| {
mem_sandbox += limit as u64;
info!(sl!(), "memory sb: {}, memory limit: {}", mem_sandbox, limit);
limit
});

if let Some(swappiness) = memory.swappiness {
if swappiness > 0 && use_guest_swap {
if let Some(swap) = memory.swap {
if swap > current_limit {
swap_sandbox = swap.saturating_sub(current_limit);
}
}
// if current_limit is 0, the container will have access to the entire memory available on the host system
// so we add swap for this
else if current_limit == 0 {
need_pod_swap = true;
} else {
swap_sandbox += current_limit;
}
}
}
// TODO support memory guest swap
// https://github.com/kata-containers/kata-containers/issues/7293
}
}

Ok((
(mem_sandbox >> MIB_TO_BYTES_SHIFT) as u32,
need_pod_swap,
(swap_sandbox >> MIB_TO_BYTES_SHIFT) as u32,
))
Ok((mem_sandbox >> MIB_TO_BYTES_SHIFT) as u32)
}

// update container_cpu_resources field
Expand All @@ -156,10 +109,10 @@ impl MemResource {
async fn do_update_mem_resource(
&self,
new_mem: u32,
_swap_sz_mb: u32,
hypervisor: &dyn Hypervisor,
) -> Result<u32> {
info!(sl!(), "requesting vmm to update memory to {:?}", new_mem);

let (new_memory, _mem_config) = hypervisor
.resize_memory(new_mem)
.await
Expand Down
2 changes: 1 addition & 1 deletion src/runtime-rs/crates/resource/src/manager_inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl ResourceManagerInner {

let cgroups_resource = CgroupsResource::new(sid, &toml_config)?;
let cpu_resource = CpuResource::new(toml_config.clone())?;
let mem_resource = MemResource::new(toml_config.clone(), init_size_manager)?;
let mem_resource = MemResource::new(init_size_manager)?;
Ok(Self {
sid: sid.to_string(),
toml_config,
Expand Down

0 comments on commit 327ec15

Please sign in to comment.