mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-02-22 11:22:26 +00:00
vhost-user-fs: handle FS_IO request
Virtiofs's dax window can be used as read/write's source (e.g. mmap a file on virtiofs), but the dax window area is not shared with vhost-user backend, i.e. virtiofs daemon. To make those IO work, addresses of this kind of IO source are routed to VMM via FS_IO requests to perform a read/write from an fd directly to the given GPA. This adds the support of FS_IO request to clh's vhost-user-fs master part. Signed-off-by: Liu Bo <bo.liu@linux.alibaba.com>
This commit is contained in:
parent
f61f78eac6
commit
5c1207c198
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1147,7 +1147,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "vhost"
|
name = "vhost"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/cloud-hypervisor/vhost?branch=dragonball#7d5a205199e3d5594494b3021635a719580fabc8"
|
source = "git+https://github.com/cloud-hypervisor/vhost?branch=dragonball#af264bb39201b175607d7cc517ee2d90b8820dcc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -9,7 +9,7 @@ use crate::{
|
|||||||
ActivateError, ActivateResult, Queue, VirtioDevice, VirtioDeviceType, VirtioInterrupt,
|
ActivateError, ActivateResult, Queue, VirtioDevice, VirtioDeviceType, VirtioInterrupt,
|
||||||
VirtioSharedMemoryList, VIRTIO_F_VERSION_1,
|
VirtioSharedMemoryList, VIRTIO_F_VERSION_1,
|
||||||
};
|
};
|
||||||
use libc::{self, EFD_NONBLOCK};
|
use libc::{self, c_void, off64_t, pread64, pwrite64, EFD_NONBLOCK};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
@ -19,20 +19,23 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
|||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use vhost_rs::vhost_user::message::{
|
use vhost_rs::vhost_user::message::{
|
||||||
VhostUserFSSlaveMsg, VhostUserProtocolFeatures, VhostUserVirtioFeatures,
|
VhostUserFSSlaveMsg, VhostUserFSSlaveMsgFlags, VhostUserProtocolFeatures,
|
||||||
VHOST_USER_FS_SLAVE_ENTRIES,
|
VhostUserVirtioFeatures, VHOST_USER_FS_SLAVE_ENTRIES,
|
||||||
};
|
};
|
||||||
use vhost_rs::vhost_user::{
|
use vhost_rs::vhost_user::{
|
||||||
HandlerResult, Master, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler,
|
HandlerResult, Master, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler,
|
||||||
};
|
};
|
||||||
use vhost_rs::VhostBackend;
|
use vhost_rs::VhostBackend;
|
||||||
use vm_device::{Migratable, MigratableError, Pausable, Snapshotable};
|
use vm_device::{Migratable, MigratableError, Pausable, Snapshotable};
|
||||||
use vm_memory::{ByteValued, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap};
|
use vm_memory::{
|
||||||
|
Address, ByteValued, GuestAddress, GuestAddressSpace, GuestMemoryAtomic, GuestMemoryMmap,
|
||||||
|
};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
const NUM_QUEUE_OFFSET: usize = 1;
|
const NUM_QUEUE_OFFSET: usize = 1;
|
||||||
|
|
||||||
struct SlaveReqHandler {
|
struct SlaveReqHandler {
|
||||||
|
cache_offset: GuestAddress,
|
||||||
cache_size: u64,
|
cache_size: u64,
|
||||||
mmap_cache_addr: u64,
|
mmap_cache_addr: u64,
|
||||||
}
|
}
|
||||||
@ -144,6 +147,68 @@ impl VhostUserMasterReqHandler for SlaveReqHandler {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fs_slave_io(&mut self, fs: &VhostUserFSSlaveMsg, fd: RawFd) -> HandlerResult<()> {
|
||||||
|
debug!("fs_slave_io");
|
||||||
|
|
||||||
|
for i in 0..VHOST_USER_FS_SLAVE_ENTRIES {
|
||||||
|
// Ignore if the length is 0.
|
||||||
|
if fs.len[i] == 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut foffset = fs.fd_offset[i];
|
||||||
|
let mut len = fs.len[i] as usize;
|
||||||
|
let gpa = fs.cache_offset[i];
|
||||||
|
if gpa < self.cache_offset.raw_value()
|
||||||
|
|| gpa >= self.cache_offset.raw_value() + self.cache_size
|
||||||
|
{
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::Other,
|
||||||
|
"gpa is out of cache range",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let offset = gpa
|
||||||
|
.checked_sub(self.cache_offset.raw_value())
|
||||||
|
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "gpa is out of cache range"))?;
|
||||||
|
let mut ptr = self.mmap_cache_addr + offset;
|
||||||
|
|
||||||
|
while len > 0 {
|
||||||
|
let ret = if (fs.flags[i] & VhostUserFSSlaveMsgFlags::MAP_W)
|
||||||
|
== VhostUserFSSlaveMsgFlags::MAP_W
|
||||||
|
{
|
||||||
|
debug!("write: foffset={}, len={}", foffset, len);
|
||||||
|
unsafe { pwrite64(fd, ptr as *const c_void, len as usize, foffset as off64_t) }
|
||||||
|
} else {
|
||||||
|
debug!("read: foffset={}, len={}", foffset, len);
|
||||||
|
unsafe { pread64(fd, ptr as *mut c_void, len as usize, foffset as off64_t) }
|
||||||
|
};
|
||||||
|
|
||||||
|
if ret < 0 {
|
||||||
|
return Err(io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ret == 0 {
|
||||||
|
// EOF
|
||||||
|
return Err(io::Error::new(
|
||||||
|
io::ErrorKind::UnexpectedEof,
|
||||||
|
"failed to access whole buffer",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
len -= ret as usize;
|
||||||
|
foffset += ret as u64;
|
||||||
|
ptr += ret as u64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ret = unsafe { libc::close(fd) };
|
||||||
|
if ret == -1 {
|
||||||
|
return Err(io::Error::last_os_error());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -387,6 +452,7 @@ impl VirtioDevice for Fs {
|
|||||||
let slave_req_handler = if self.slave_req_support {
|
let slave_req_handler = if self.slave_req_support {
|
||||||
if let Some(cache) = self.cache.clone() {
|
if let Some(cache) = self.cache.clone() {
|
||||||
let vu_master_req_handler = Arc::new(Mutex::new(SlaveReqHandler {
|
let vu_master_req_handler = Arc::new(Mutex::new(SlaveReqHandler {
|
||||||
|
cache_offset: cache.0.addr,
|
||||||
cache_size: cache.0.len,
|
cache_size: cache.0.len,
|
||||||
mmap_cache_addr: cache.1,
|
mmap_cache_addr: cache.1,
|
||||||
}));
|
}));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user