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 2 commits
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
81 changes: 54 additions & 27 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 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 Expand Up @@ -974,3 +950,54 @@ pub(crate) fn write_error(ecode: u32, chain: &mut Chain, mem: &MemCtx) {
let buf = out.as_mut_slice();
write_buf(buf, chain, mem);
}

pub(crate) fn p9_write_file(
pfmooney marked this conversation as resolved.
Show resolved Hide resolved
file: &impl std::os::fd::AsRawFd,
pfmooney marked this conversation as resolved.
Show resolved Hide resolved
chain: &mut Chain,
mem: &MemCtx,
count: usize,
offset: i64,
) {
// 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 = size_of::<u32>() + // size
size_of::<u8>() + // typ
size_of::<u16>() + // tag
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;
pfmooney marked this conversation as resolved.
Show resolved Hide resolved
if !header_done {
mem.write_from(addr, &header, header.len()).unwrap();
header_done = true;
remain -= header.len();
copied += header.len();
}
pfmooney marked this conversation as resolved.
Show resolved Hide resolved
let addr = GuestAddr(addr.0 + copied as u64);
pfmooney marked this conversation as resolved.
Show resolved Hide resolved
let sub_mapping =
mem.direct_writable_region(&GuestRegion(addr, remain)).unwrap();
pfmooney marked this conversation as resolved.
Show resolved Hide resolved

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)
});
}
1 change: 0 additions & 1 deletion lib/propolis/src/hw/virtio/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,6 @@ pub mod migrate {
}
}

#[cfg(feature = "falcon")]
pfmooney marked this conversation as resolved.
Show resolved Hide resolved
pub(crate) fn write_buf(buf: &[u8], chain: &mut Chain, mem: &MemCtx) {
// more copy pasta from Chain::write b/c like Chain:read a
// statically sized type is expected.
Expand Down
Loading