From 3eaeba4b5585ef5f8b98563f38de0bbceed3523d Mon Sep 17 00:00:00 2001 From: Jose Carlos Venegas Munoz Date: Wed, 22 Apr 2020 23:10:31 +0000 Subject: [PATCH] vm-virtio: Fix FS_IO callback for virtio-fs FS_IO is part of the actions a vhost-user-fs daemon can ask the VMM to perform on its behalf. It is meant to read/write the content from a file descriptor directly into a guest memory region. This region can either be a RAM region or the dedicated cache region for virtio-fs. The way FS_IO was implemented, it was only expecting the guest physical address provided through the "cache_offset" field to refer to the cache region. Unfortunately, this was only implementing FS_IO partially. This patch extends the existing FS_IO implementation by checking the GPA against the cache region as a first step, but if it is not part of the cache region address range, then we fallback onto searching for a RAM region that could match. If there is a matching RAM region, we retrieve the corresponding host address to let the VMM read/write from/to it. Fixes: #1054 Signed-off-by: Sebastien Boeuf Signed-off-by: Jose Carlos Venegas Munoz --- vm-virtio/src/vhost_user/fs.rs | 40 ++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/vm-virtio/src/vhost_user/fs.rs b/vm-virtio/src/vhost_user/fs.rs index e8debdf5e..6dbde8afa 100644 --- a/vm-virtio/src/vhost_user/fs.rs +++ b/vm-virtio/src/vhost_user/fs.rs @@ -27,8 +27,8 @@ use vhost_rs::vhost_user::{ }; use vhost_rs::VhostBackend; use vm_memory::{ - Address, ByteValued, GuestAddress, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap, - MmapRegion, + Address, ByteValued, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, + GuestMemoryMmap, MmapRegion, }; use vm_migration::{Migratable, MigratableError, Pausable, Snapshottable, Transportable}; use vmm_sys_util::eventfd::EventFd; @@ -39,6 +39,7 @@ struct SlaveReqHandler { cache_offset: GuestAddress, cache_size: u64, mmap_cache_addr: u64, + mem: GuestMemoryAtomic, } impl SlaveReqHandler { @@ -183,18 +184,32 @@ impl VhostUserMasterReqHandler for SlaveReqHandler { let cache_end = self.cache_offset.raw_value() + self.cache_size; let efault = libc::EFAULT; - let offset = gpa - .checked_sub(self.cache_offset.raw_value()) - .ok_or_else(|| io::Error::from_raw_os_error(efault))?; - let end = gpa - .checked_add(fs.len[i]) - .ok_or_else(|| io::Error::from_raw_os_error(efault))?; + let mut ptr = if gpa >= self.cache_offset.raw_value() && gpa < cache_end { + let offset = gpa + .checked_sub(self.cache_offset.raw_value()) + .ok_or_else(|| io::Error::from_raw_os_error(efault))?; + let end = gpa + .checked_add(fs.len[i]) + .ok_or_else(|| io::Error::from_raw_os_error(efault))?; - if gpa < self.cache_offset.raw_value() || gpa >= cache_end || end >= cache_end { - return Err(io::Error::from_raw_os_error(efault)); - } + if end >= cache_end { + return Err(io::Error::from_raw_os_error(efault)); + } + + self.mmap_cache_addr + offset + } else { + self.mem + .memory() + .get_host_address(GuestAddress(gpa)) + .map_err(|e| { + error!( + "Failed to find RAM region associated with guest physical address 0x{:x}: {:?}", + gpa, e + ); + io::Error::from_raw_os_error(efault) + })? as u64 + }; - let mut ptr = self.mmap_cache_addr + offset; while len > 0 { let ret = if (fs.flags[i] & VhostUserFSSlaveMsgFlags::MAP_W) == VhostUserFSSlaveMsgFlags::MAP_W @@ -479,6 +494,7 @@ impl VirtioDevice for Fs { cache_offset: cache.0.addr, cache_size: cache.0.len, mmap_cache_addr: cache.0.host_addr, + mem, })); let req_handler = MasterReqHandler::new(vu_master_req_handler).map_err(|e| {