mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-05 21:15:45 +00:00
vmm: Create shared memory region for virtio-fs
When the cache_size parameter from virtio-fs device is not empty, the VMM creates a dedicated memory region where the shared files will be memory mapped by the virtio-fs device. Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
parent
74225ab5b3
commit
3c29c47783
@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
use super::Error as DeviceError;
|
use super::Error as DeviceError;
|
||||||
use super::{ActivateError, ActivateResult, Queue, VirtioDevice, VirtioDeviceType};
|
use super::{ActivateError, ActivateResult, Queue, VirtioDevice, VirtioDeviceType};
|
||||||
use crate::{VirtioInterrupt, VirtioInterruptType, VIRTIO_F_VERSION_1_BITMASK};
|
use crate::{
|
||||||
|
VirtioInterrupt, VirtioInterruptType, VirtioSharedMemoryList, VIRTIO_F_VERSION_1_BITMASK,
|
||||||
|
};
|
||||||
use epoll;
|
use epoll;
|
||||||
use libc::EFD_NONBLOCK;
|
use libc::EFD_NONBLOCK;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
@ -183,7 +185,13 @@ pub struct Fs {
|
|||||||
|
|
||||||
impl Fs {
|
impl Fs {
|
||||||
/// Create a new virtio-fs device.
|
/// Create a new virtio-fs device.
|
||||||
pub fn new(path: &str, tag: &str, req_num_queues: usize, queue_size: u16) -> Result<Fs> {
|
pub fn new(
|
||||||
|
path: &str,
|
||||||
|
tag: &str,
|
||||||
|
req_num_queues: usize,
|
||||||
|
queue_size: u16,
|
||||||
|
_cache_addr: Option<(VirtioSharedMemoryList, u64)>,
|
||||||
|
) -> Result<Fs> {
|
||||||
// Calculate the actual number of queues needed.
|
// Calculate the actual number of queues needed.
|
||||||
let num_queues = NUM_QUEUE_OFFSET + req_num_queues;
|
let num_queues = NUM_QUEUE_OFFSET + req_num_queues;
|
||||||
// Connect to the vhost-user socket.
|
// Connect to the vhost-user socket.
|
||||||
|
@ -56,6 +56,7 @@ use vm_memory::{
|
|||||||
GuestMemoryRegion, GuestUsize,
|
GuestMemoryRegion, GuestUsize,
|
||||||
};
|
};
|
||||||
use vm_virtio::transport::VirtioPciDevice;
|
use vm_virtio::transport::VirtioPciDevice;
|
||||||
|
use vm_virtio::{VirtioSharedMemory, VirtioSharedMemoryList};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
use vmm_sys_util::signal::register_signal_handler;
|
use vmm_sys_util::signal::register_signal_handler;
|
||||||
use vmm_sys_util::terminal::Terminal;
|
use vmm_sys_util::terminal::Terminal;
|
||||||
@ -244,6 +245,9 @@ pub enum DeviceManagerError {
|
|||||||
/// Cannot find a memory range for persistent memory
|
/// Cannot find a memory range for persistent memory
|
||||||
PmemRangeAllocation,
|
PmemRangeAllocation,
|
||||||
|
|
||||||
|
/// Cannot find a memory range for virtio-fs
|
||||||
|
FsRangeAllocation,
|
||||||
|
|
||||||
/// Error creating serial output file
|
/// Error creating serial output file
|
||||||
SerialOutputFileOpen(io::Error),
|
SerialOutputFileOpen(io::Error),
|
||||||
|
|
||||||
@ -261,6 +265,9 @@ pub enum DeviceManagerError {
|
|||||||
|
|
||||||
/// Failed to create the KVM device.
|
/// Failed to create the KVM device.
|
||||||
CreateKvmDevice(io::Error),
|
CreateKvmDevice(io::Error),
|
||||||
|
|
||||||
|
/// Failed to memory map.
|
||||||
|
Mmap(io::Error),
|
||||||
}
|
}
|
||||||
pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>;
|
pub type DeviceManagerResult<T> = result::Result<T, DeviceManagerError>;
|
||||||
|
|
||||||
@ -685,7 +692,14 @@ impl DeviceManager {
|
|||||||
DeviceManager::add_virtio_rng_devices(vm_info, allocator, pci, buses, &interrupt_info)?;
|
DeviceManager::add_virtio_rng_devices(vm_info, allocator, pci, buses, &interrupt_info)?;
|
||||||
|
|
||||||
// Add virtio-fs if required
|
// Add virtio-fs if required
|
||||||
DeviceManager::add_virtio_fs_devices(vm_info, allocator, pci, buses, &interrupt_info)?;
|
DeviceManager::add_virtio_fs_devices(
|
||||||
|
vm_info,
|
||||||
|
allocator,
|
||||||
|
pci,
|
||||||
|
buses,
|
||||||
|
&interrupt_info,
|
||||||
|
&mut mem_slots,
|
||||||
|
)?;
|
||||||
|
|
||||||
// Add virtio-pmem if required
|
// Add virtio-pmem if required
|
||||||
DeviceManager::add_virtio_pmem_devices(
|
DeviceManager::add_virtio_pmem_devices(
|
||||||
@ -820,16 +834,72 @@ impl DeviceManager {
|
|||||||
pci: &mut PciConfigIo,
|
pci: &mut PciConfigIo,
|
||||||
buses: &mut BusInfo,
|
buses: &mut BusInfo,
|
||||||
interrupt_info: &InterruptInfo,
|
interrupt_info: &InterruptInfo,
|
||||||
|
mem_slots: &mut u32,
|
||||||
) -> DeviceManagerResult<()> {
|
) -> DeviceManagerResult<()> {
|
||||||
// Add virtio-fs if required
|
// Add virtio-fs if required
|
||||||
if let Some(fs_list_cfg) = &vm_info.vm_cfg.fs {
|
if let Some(fs_list_cfg) = &vm_info.vm_cfg.fs {
|
||||||
for fs_cfg in fs_list_cfg.iter() {
|
for fs_cfg in fs_list_cfg.iter() {
|
||||||
if let Some(fs_sock) = fs_cfg.sock.to_str() {
|
if let Some(fs_sock) = fs_cfg.sock.to_str() {
|
||||||
|
let mut cache: Option<(VirtioSharedMemoryList, u64)> = None;
|
||||||
|
if let Some(fs_cache) = fs_cfg.cache_size {
|
||||||
|
// The memory needs to be 2MiB aligned in order to support
|
||||||
|
// hugepages.
|
||||||
|
let fs_guest_addr = allocator
|
||||||
|
.allocate_mmio_addresses(
|
||||||
|
None,
|
||||||
|
fs_cache as GuestUsize,
|
||||||
|
Some(0x0020_0000),
|
||||||
|
)
|
||||||
|
.ok_or(DeviceManagerError::FsRangeAllocation)?;
|
||||||
|
|
||||||
|
let addr = unsafe {
|
||||||
|
libc::mmap(
|
||||||
|
null_mut(),
|
||||||
|
fs_cache as usize,
|
||||||
|
libc::PROT_READ | libc::PROT_WRITE,
|
||||||
|
libc::MAP_NORESERVE | libc::MAP_ANONYMOUS | libc::MAP_PRIVATE,
|
||||||
|
-1,
|
||||||
|
0 as libc::off_t,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if addr == libc::MAP_FAILED {
|
||||||
|
return Err(DeviceManagerError::Mmap(io::Error::last_os_error()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mem_region = kvm_userspace_memory_region {
|
||||||
|
slot: *mem_slots as u32,
|
||||||
|
guest_phys_addr: fs_guest_addr.raw_value(),
|
||||||
|
memory_size: fs_cache,
|
||||||
|
userspace_addr: addr as u64,
|
||||||
|
flags: 0,
|
||||||
|
};
|
||||||
|
// Safe because the guest regions are guaranteed not to overlap.
|
||||||
|
let _ = unsafe { vm_info.vm_fd.set_user_memory_region(mem_region) };
|
||||||
|
|
||||||
|
// Increment the KVM slot number
|
||||||
|
*mem_slots += 1;
|
||||||
|
|
||||||
|
let mut region_list = Vec::new();
|
||||||
|
region_list.push(VirtioSharedMemory {
|
||||||
|
offset: 0,
|
||||||
|
len: fs_cache,
|
||||||
|
});
|
||||||
|
cache = Some((
|
||||||
|
VirtioSharedMemoryList {
|
||||||
|
addr: fs_guest_addr,
|
||||||
|
len: fs_cache as GuestUsize,
|
||||||
|
region_list,
|
||||||
|
},
|
||||||
|
addr as u64,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let virtio_fs_device = vm_virtio::Fs::new(
|
let virtio_fs_device = vm_virtio::Fs::new(
|
||||||
fs_sock,
|
fs_sock,
|
||||||
fs_cfg.tag,
|
fs_cfg.tag,
|
||||||
fs_cfg.num_queues,
|
fs_cfg.num_queues,
|
||||||
fs_cfg.queue_size,
|
fs_cfg.queue_size,
|
||||||
|
cache,
|
||||||
)
|
)
|
||||||
.map_err(DeviceManagerError::CreateVirtioFs)?;
|
.map_err(DeviceManagerError::CreateVirtioFs)?;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user