Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement p9fs read as direct host file to guest mem write #572

Merged
merged 4 commits into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 4 additions & 28 deletions lib/propolis/src/hw/virtio/p9fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
use std::collections::HashMap;
use std::convert::TryInto;
use std::fs;
use std::io::{Read, Seek};
use std::mem::size_of;
use std::num::NonZeroU16;
use std::os::fd::AsRawFd;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::fs::MetadataExt;
use std::path::PathBuf;
Expand All @@ -21,7 +21,7 @@ use crate::vmm::MemCtx;

use super::bits::*;
use super::pci::{PciVirtio, PciVirtioState};
use super::queue::{write_buf, Chain, VirtQueue, VirtQueues};
use super::queue::{p9_write_file, write_buf, Chain, VirtQueue, VirtQueues};
use super::VirtioDevice;

use ispf::WireSize;
Expand Down Expand Up @@ -332,7 +332,7 @@ impl HostFSHandler {
mem: &MemCtx,
msize: u32,
) {
let mut file = match fid.file {
let file = match fid.file {
Some(ref f) => f,
None => {
// the file is not open
Expand Down Expand Up @@ -366,15 +366,6 @@ impl HostFSHandler {
return write_buf(buf, chain, mem);
}

match file.seek(std::io::SeekFrom::Start(msg.offset)) {
Err(e) => {
let ecode = e.raw_os_error().unwrap_or(0);
warn!(self.log, "read: seek: {:?}: {:?}", &fid.pathbuf, e,);
return write_error(ecode as u32, chain, mem);
}
Ok(_) => {}
}

let read_count = u32::min(msize, msg.count);

let space_left = read_count as usize
Expand All @@ -387,22 +378,7 @@ impl HostFSHandler {
let buflen =
std::cmp::min(space_left, (metadata.len() - msg.offset) as usize);

let mut content: Vec<u8> = vec![0; buflen];

match file.read_exact(content.as_mut_slice()) {
Err(e) => {
let ecode = e.raw_os_error().unwrap_or(0);
warn!(self.log, "read: exact: {:?}: {:?}", &fid.pathbuf, e,);
return write_error(ecode as u32, chain, mem);
}
Ok(()) => {}
}

let response = Rread::new(content);
let mut out = ispf::to_bytes_le(&response).unwrap();
let buf = out.as_mut_slice();

write_buf(buf, chain, mem);
p9_write_file(&file.as_raw_fd(), chain, mem, buflen, msg.offset as i64);
}

fn do_statfs(&self, fid: &mut Fid, chain: &mut Chain, mem: &MemCtx) {
Expand Down
52 changes: 52 additions & 0 deletions lib/propolis/src/hw/virtio/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,3 +770,55 @@ pub(crate) fn write_buf(buf: &[u8], chain: &mut Chain, mem: &MemCtx) {
}
});
}

#[cfg(feature = "falcon")]
pub(crate) fn p9_write_file(
file: &impl std::os::fd::AsRawFd,
chain: &mut Chain,
mem: &MemCtx,
count: usize,
offset: i64,
) {
pfmooney marked this conversation as resolved.
Show resolved Hide resolved
// Form the rread header. Unfortunately we can't do this with the Rread
// structure because the count is baked into the data field which is tied
// to the length of the vector and filling that vector is what we're
// explicitly trying to avoid here.
let sz = mem::size_of::<u32>() + // size
mem::size_of::<u8>() + // typ
mem::size_of::<u16>() + // tag
mem::size_of::<u32>() + // data.count
count; // data
let mut header = Vec::with_capacity(11);
header.extend_from_slice(&(sz as u32).to_le_bytes());
header.push(p9ds::proto::MessageType::Rread as u8);
header.extend_from_slice(&0u16.to_le_bytes());
header.extend_from_slice(&(count as u32).to_le_bytes());

// Send the header to the guest from the buffer constructed above. Then
// send the actual file data
let mut header_done = false;
let mut done = 0;
let _total = chain.for_remaining_type(false, |addr, len| {
let mut remain = len;
let mut copied = 0;
if !header_done {
mem.write_from(addr, &header, header.len()).unwrap();
header_done = true;
remain -= header.len();
copied += header.len();
}
let addr = GuestAddr(addr.0 + copied as u64);
let sub_mapping =
mem.direct_writable_region(&GuestRegion(addr, remain)).unwrap();

let len = usize::min(remain, count);
let off = offset + done as i64;
let mapped = sub_mapping.pread(file, len, off).unwrap();
copied += mapped;
done += mapped;

let need_more = done < count;

(copied, need_more)
});
}
Loading