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
Changes from 3 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
82 changes: 54 additions & 28 deletions lib/propolis/src/hw/virtio/p9fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

use std::collections::HashMap;
use std::convert::TryInto;
use std::fs;
use std::io::{Read, Seek};
use std::fs::{self, File};
use std::mem::size_of;
use std::num::NonZeroU16;
use std::os::unix::ffi::OsStrExt;
Expand Down Expand Up @@ -332,7 +331,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 +365,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 +377,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, 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 +949,54 @@ pub(crate) fn write_error(ecode: u32, chain: &mut Chain, mem: &MemCtx) {
let buf = out.as_mut_slice();
write_buf(buf, chain, mem);
}

fn p9_write_file(
file: &File,
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.
#[repr(C, packed)]
#[derive(Copy, Clone)]
struct Header {
size: u32,
typ: u8,
tag: u16,
count: u32,
}

let size = size_of::<Header>() + count;

let h = Header {
size: size as u32,
typ: MessageType::Rread as u8,
tag: 0,
count: count as u32,
};

chain.write(&h, mem);

// Send the header to the guest from the buffer constructed above. Then
// send the actual file data
let mut done = 0;
let _total = chain.for_remaining_type(false, |addr, len| {
let mut copied = 0;
pfmooney marked this conversation as resolved.
Show resolved Hide resolved
let addr = addr.offset::<u8>(copied);
let sub_mapping = mem.writable_region(&GuestRegion(addr, len)).unwrap();

let len = usize::min(len, 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