mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-11-04 19:11:11 +00:00
virtio-balloon: Add memory_actual_size to vm.info to show memory actual size
The virtio-balloon change the memory size is asynchronous. VirtioBalloonConfig.actual of balloon device show current balloon size. This commit add memory_actual_size to vm.info to show memory actual size. Signed-off-by: Hui Zhu <teawater@antfin.com>
This commit is contained in:
parent
9dffc5da5c
commit
c75f8b2f89
@ -47,9 +47,6 @@ const INFLATE_QUEUE_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 2;
|
||||
// New descriptors are pending on the virtio queue.
|
||||
const DEFLATE_QUEUE_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 3;
|
||||
|
||||
// Page shift in the host.
|
||||
const PAGE_SHIFT: u32 = 12;
|
||||
|
||||
// Size of a PFN in the balloon interface.
|
||||
const VIRTIO_BALLOON_PFN_SHIFT: u64 = 12;
|
||||
|
||||
@ -78,7 +75,7 @@ pub enum Error {
|
||||
}
|
||||
|
||||
// Got from include/uapi/linux/virtio_balloon.h
|
||||
#[repr(C, packed)]
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
struct VirtioBalloonConfig {
|
||||
// Number of pages host wants Guest to give up.
|
||||
@ -87,6 +84,9 @@ struct VirtioBalloonConfig {
|
||||
actual: u32,
|
||||
}
|
||||
|
||||
const CONFIG_ACTUAL_OFFSET: u64 = 4;
|
||||
const CONFIG_ACTUAL_SIZE: usize = 4;
|
||||
|
||||
// Safe because it only has data and has no implicit padding.
|
||||
unsafe impl ByteValued for VirtioBalloonConfig {}
|
||||
|
||||
@ -207,7 +207,7 @@ impl BalloonEpollHandler {
|
||||
let res = unsafe {
|
||||
libc::madvise(
|
||||
hva as *mut libc::c_void,
|
||||
(1 << PAGE_SHIFT) as libc::size_t,
|
||||
(1 << VIRTIO_BALLOON_PFN_SHIFT) as libc::size_t,
|
||||
advice,
|
||||
)
|
||||
};
|
||||
@ -258,7 +258,8 @@ impl EpollHelperHandler for BalloonEpollHandler {
|
||||
let mut signal_error = false;
|
||||
let r = {
|
||||
let mut config = self.config.lock().unwrap();
|
||||
config.num_pages = (self.resize_receiver.get_size() >> PAGE_SHIFT) as u32;
|
||||
config.num_pages =
|
||||
(self.resize_receiver.get_size() >> VIRTIO_BALLOON_PFN_SHIFT) as u32;
|
||||
if let Err(e) = self.signal(&VirtioInterruptType::Config, None) {
|
||||
signal_error = true;
|
||||
Err(e)
|
||||
@ -321,7 +322,7 @@ impl Balloon {
|
||||
let avail_features = 1u64 << VIRTIO_F_VERSION_1;
|
||||
|
||||
let mut config = VirtioBalloonConfig::default();
|
||||
config.num_pages = (size >> PAGE_SHIFT) as u32;
|
||||
config.num_pages = (size >> VIRTIO_BALLOON_PFN_SHIFT) as u32;
|
||||
|
||||
Ok(Balloon {
|
||||
common: VirtioCommon {
|
||||
@ -341,6 +342,11 @@ impl Balloon {
|
||||
pub fn resize(&self, size: u64) -> Result<(), Error> {
|
||||
self.resize.work(size)
|
||||
}
|
||||
|
||||
// Get the actual size of the virtio-balloon.
|
||||
pub fn get_actual(&self) -> u64 {
|
||||
(self.config.lock().unwrap().actual as u64) << VIRTIO_BALLOON_PFN_SHIFT
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Balloon {
|
||||
@ -373,6 +379,20 @@ impl VirtioDevice for Balloon {
|
||||
self.read_config_from_slice(self.config.lock().unwrap().as_slice(), offset, data);
|
||||
}
|
||||
|
||||
fn write_config(&mut self, offset: u64, data: &[u8]) {
|
||||
// The "actual" field is the only mutable field
|
||||
if offset != CONFIG_ACTUAL_OFFSET || data.len() != CONFIG_ACTUAL_SIZE {
|
||||
error!(
|
||||
"Attempt to write to read-only field: offset {:x} length {}",
|
||||
offset,
|
||||
data.len()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
self.write_config_helper(self.config.lock().unwrap().as_mut_slice(), offset, data);
|
||||
}
|
||||
|
||||
fn activate(
|
||||
&mut self,
|
||||
mem: GuestMemoryAtomic<GuestMemoryMmap>,
|
||||
|
@ -176,6 +176,28 @@ pub trait VirtioDevice: Send {
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper to allow common implementation of write_config
|
||||
fn write_config_helper(&self, config: &mut [u8], offset: u64, data: &[u8]) {
|
||||
let config_len = config.len() as u64;
|
||||
let data_len = data.len() as u64;
|
||||
if offset + data_len > config_len {
|
||||
error!(
|
||||
"Out-of-bound access to configuration: config_len = {} offset = {:x} length = {} for {}",
|
||||
config_len,
|
||||
offset,
|
||||
data_len,
|
||||
self.device_type()
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(end) = offset.checked_add(config.len() as u64) {
|
||||
let mut offset_config =
|
||||
&mut config[offset as usize..std::cmp::min(end, config_len) as usize];
|
||||
offset_config.write_all(data).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait providing address translation the same way a physical DMA remapping
|
||||
|
@ -145,6 +145,7 @@ pub type ApiResult<T> = std::result::Result<T, ApiError>;
|
||||
pub struct VmInfo {
|
||||
pub config: Arc<Mutex<VmConfig>>,
|
||||
pub state: VmState,
|
||||
pub memory_actual_size: u64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
|
@ -360,6 +360,9 @@ components:
|
||||
state:
|
||||
type: string
|
||||
enum: [Created, Running, Shutdown, Paused]
|
||||
memory_actual_size:
|
||||
type: integer
|
||||
format: int64
|
||||
description: Virtual Machine information
|
||||
|
||||
VmCounters:
|
||||
|
@ -534,6 +534,24 @@ impl MemoryConfig {
|
||||
zones,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn total_size(&self) -> u64 {
|
||||
let mut size = self.size;
|
||||
if let Some(hotplugged_size) = self.hotplugged_size {
|
||||
size += hotplugged_size;
|
||||
}
|
||||
|
||||
if let Some(zones) = &self.zones {
|
||||
for zone in zones.iter() {
|
||||
size += zone.size;
|
||||
if let Some(hotplugged_size) = zone.hotplugged_size {
|
||||
size += hotplugged_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MemoryConfig {
|
||||
|
@ -465,9 +465,17 @@ impl Vmm {
|
||||
None => VmState::Created,
|
||||
};
|
||||
|
||||
let config = Arc::clone(config);
|
||||
|
||||
let mut memory_actual_size = config.lock().unwrap().memory.total_size();
|
||||
if let Some(vm) = &self.vm {
|
||||
memory_actual_size -= vm.get_balloon_actual();
|
||||
}
|
||||
|
||||
Ok(VmInfo {
|
||||
config: Arc::clone(config),
|
||||
config,
|
||||
state,
|
||||
memory_actual_size,
|
||||
})
|
||||
}
|
||||
None => Err(VmError::VmNotCreated),
|
||||
|
@ -1236,6 +1236,14 @@ impl MemoryManager {
|
||||
Ok(balloon_size)
|
||||
}
|
||||
|
||||
pub fn get_balloon_actual(&self) -> u64 {
|
||||
if let Some(balloon) = &self.balloon {
|
||||
return balloon.lock().unwrap().get_actual();
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
/// In case this function resulted in adding a new memory region to the
|
||||
/// guest memory, the new region is returned to the caller. The virtio-mem
|
||||
/// use case never adds a new region as the whole hotpluggable memory has
|
||||
|
@ -1493,6 +1493,11 @@ impl Vm {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets the actual size of the balloon.
|
||||
pub fn get_balloon_actual(&self) -> u64 {
|
||||
self.memory_manager.lock().unwrap().get_balloon_actual()
|
||||
}
|
||||
}
|
||||
|
||||
impl Pausable for Vm {
|
||||
|
Loading…
Reference in New Issue
Block a user