diff --git a/src/fd/eventfd.rs b/src/fd/eventfd.rs index 945d09d4f0..da2ca923b3 100644 --- a/src/fd/eventfd.rs +++ b/src/fd/eventfd.rs @@ -46,7 +46,7 @@ impl EventFd { #[async_trait] impl ObjectInterface for EventFd { - async fn read(&self, buf: &mut [u8]) -> io::Result { + async fn read(&mut self, buf: &mut [u8]) -> io::Result { let len = mem::size_of::(); if buf.len() < len { @@ -90,7 +90,7 @@ impl ObjectInterface for EventFd { .await } - async fn write(&self, buf: &[u8]) -> io::Result { + async fn write(&mut self, buf: &[u8]) -> io::Result { let len = mem::size_of::(); if buf.len() < len { diff --git a/src/fd/mod.rs b/src/fd/mod.rs index 80d80ae324..158537d408 100644 --- a/src/fd/mod.rs +++ b/src/fd/mod.rs @@ -205,18 +205,18 @@ pub(crate) trait ObjectInterface: Sync + Send { /// `async_read` attempts to read `len` bytes from the object references /// by the descriptor - async fn read(&self, _buf: &mut [u8]) -> io::Result { + async fn read(&mut self, _buf: &mut [u8]) -> io::Result { Err(Errno::Nosys) } /// `async_write` attempts to write `len` bytes to the object references /// by the descriptor - async fn write(&self, _buf: &[u8]) -> io::Result { + async fn write(&mut self, _buf: &[u8]) -> io::Result { Err(Errno::Nosys) } /// `lseek` function repositions the offset of the file descriptor fildes - async fn lseek(&self, _offset: isize, _whence: SeekWhence) -> io::Result { + async fn lseek(&mut self, _offset: isize, _whence: SeekWhence) -> io::Result { Err(Errno::Inval) } @@ -318,12 +318,12 @@ pub(crate) trait ObjectInterface: Sync + Send { } /// Truncates the file - async fn truncate(&self, _size: usize) -> io::Result<()> { + async fn truncate(&mut self, _size: usize) -> io::Result<()> { Err(Errno::Nosys) } /// Changes access permissions to the file - async fn chmod(&self, _access_permission: AccessPermission) -> io::Result<()> { + async fn chmod(&mut self, _access_permission: AccessPermission) -> io::Result<()> { Err(Errno::Nosys) } @@ -340,19 +340,22 @@ pub(crate) fn read(fd: RawFd, buf: &mut [u8]) -> io::Result { return Ok(0); } - block_on(async { obj.read().await.read(buf).await }, None) + block_on(async { obj.write().await.read(buf).await }, None) } pub(crate) fn lseek(fd: RawFd, offset: isize, whence: SeekWhence) -> io::Result { let obj = get_object(fd)?; - block_on(async { obj.read().await.lseek(offset, whence).await }, None) + block_on( + async { obj.write().await.lseek(offset, whence).await }, + None, + ) } pub(crate) fn chmod(fd: RawFd, mode: AccessPermission) -> io::Result<()> { let obj = get_object(fd)?; - block_on(async { obj.read().await.chmod(mode).await }, None) + block_on(async { obj.write().await.chmod(mode).await }, None) } pub(crate) fn write(fd: RawFd, buf: &[u8]) -> io::Result { @@ -362,12 +365,12 @@ pub(crate) fn write(fd: RawFd, buf: &[u8]) -> io::Result { return Ok(0); } - block_on(async { obj.read().await.write(buf).await }, None) + block_on(async { obj.write().await.write(buf).await }, None) } pub(crate) fn truncate(fd: RawFd, length: usize) -> io::Result<()> { let obj = get_object(fd)?; - block_on(async { obj.read().await.truncate(length).await }, None) + block_on(async { obj.write().await.truncate(length).await }, None) } async fn poll_fds(fds: &mut [PollFd]) -> io::Result { diff --git a/src/fd/socket/tcp.rs b/src/fd/socket/tcp.rs index f055ee9d6a..e158d92311 100644 --- a/src/fd/socket/tcp.rs +++ b/src/fd/socket/tcp.rs @@ -189,7 +189,7 @@ impl ObjectInterface for Socket { .await } - async fn read(&self, buffer: &mut [u8]) -> io::Result { + async fn read(&mut self, buffer: &mut [u8]) -> io::Result { future::poll_fn(|cx| { self.with(|socket| { let state = socket.state(); @@ -227,7 +227,7 @@ impl ObjectInterface for Socket { .await } - async fn write(&self, buffer: &[u8]) -> io::Result { + async fn write(&mut self, buffer: &[u8]) -> io::Result { let mut pos: usize = 0; while pos < buffer.len() { diff --git a/src/fd/socket/udp.rs b/src/fd/socket/udp.rs index f1dcade03b..9b8fffe241 100644 --- a/src/fd/socket/udp.rs +++ b/src/fd/socket/udp.rs @@ -189,7 +189,7 @@ impl ObjectInterface for Socket { .map(|(len, endpoint)| (len, Endpoint::Ip(endpoint))) } - async fn read(&self, buffer: &mut [u8]) -> io::Result { + async fn read(&mut self, buffer: &mut [u8]) -> io::Result { future::poll_fn(|cx| { self.with(|socket| { if socket.is_open() { @@ -220,7 +220,7 @@ impl ObjectInterface for Socket { .await } - async fn write(&self, buf: &[u8]) -> io::Result { + async fn write(&mut self, buf: &[u8]) -> io::Result { let endpoint = self.remote_endpoint.ok_or(Errno::Inval)?; let meta = UdpMetadata::from(endpoint); diff --git a/src/fd/socket/vsock.rs b/src/fd/socket/vsock.rs index 949a47112d..e7c4c6501d 100644 --- a/src/fd/socket/vsock.rs +++ b/src/fd/socket/vsock.rs @@ -320,7 +320,7 @@ impl ObjectInterface for Socket { Ok(()) } - async fn read(&self, buffer: &mut [u8]) -> io::Result { + async fn read(&mut self, buffer: &mut [u8]) -> io::Result { let port = self.port; future::poll_fn(|cx| { let mut guard = VSOCK_MAP.lock(); @@ -362,7 +362,7 @@ impl ObjectInterface for Socket { .await } - async fn write(&self, buffer: &[u8]) -> io::Result { + async fn write(&mut self, buffer: &[u8]) -> io::Result { let port = self.port; future::poll_fn(|cx| { let mut guard = VSOCK_MAP.lock(); diff --git a/src/fd/stdio.rs b/src/fd/stdio.rs index f0cac7fb02..39fcd89c9e 100644 --- a/src/fd/stdio.rs +++ b/src/fd/stdio.rs @@ -28,7 +28,7 @@ impl ObjectInterface for GenericStdin { Ok(event & available) } - async fn read(&self, buf: &mut [u8]) -> io::Result { + async fn read(&mut self, buf: &mut [u8]) -> io::Result { future::poll_fn(|cx| { let read_bytes = CONSOLE.lock().read(buf)?; if read_bytes > 0 { @@ -71,7 +71,7 @@ impl ObjectInterface for GenericStdout { Ok(event & available) } - async fn write(&self, buf: &[u8]) -> io::Result { + async fn write(&mut self, buf: &[u8]) -> io::Result { CONSOLE.lock().write(buf) } @@ -103,7 +103,7 @@ impl ObjectInterface for GenericStderr { Ok(event & available) } - async fn write(&self, buf: &[u8]) -> io::Result { + async fn write(&mut self, buf: &[u8]) -> io::Result { CONSOLE.lock().write(buf) } @@ -158,7 +158,7 @@ impl ObjectInterface for UhyveStdout { Ok(event & available) } - async fn write(&self, buf: &[u8]) -> io::Result { + async fn write(&mut self, buf: &[u8]) -> io::Result { let write_params = WriteParams { fd: STDOUT_FILENO, buf: GuestVirtAddr::from_ptr(buf.as_ptr()), @@ -197,7 +197,7 @@ impl ObjectInterface for UhyveStderr { Ok(event & available) } - async fn write(&self, buf: &[u8]) -> io::Result { + async fn write(&mut self, buf: &[u8]) -> io::Result { let write_params = WriteParams { fd: STDERR_FILENO, buf: GuestVirtAddr::from_ptr(buf.as_ptr()), diff --git a/src/fs/mem.rs b/src/fs/mem.rs index 242f9d4b83..95fe350b74 100644 --- a/src/fs/mem.rs +++ b/src/fs/mem.rs @@ -59,7 +59,7 @@ impl ObjectInterface for RomFileInterface { Ok(ret) } - async fn read(&self, buf: &mut [u8]) -> io::Result { + async fn read(&mut self, buf: &mut [u8]) -> io::Result { { let microseconds = arch::kernel::systemtime::now_micros(); let t = timespec::from_usec(microseconds as i64); @@ -81,7 +81,7 @@ impl ObjectInterface for RomFileInterface { Ok(len) } - async fn lseek(&self, offset: isize, whence: SeekWhence) -> io::Result { + async fn lseek(&mut self, offset: isize, whence: SeekWhence) -> io::Result { // NOTE: Allocations can never be larger than `isize::MAX` bytes. let data_len = self.inner.data.len() as isize; @@ -155,7 +155,7 @@ impl ObjectInterface for RamFileInterface { Ok(event & available) } - async fn read(&self, buf: &mut [u8]) -> io::Result { + async fn read(&mut self, buf: &mut [u8]) -> io::Result { { let microseconds = arch::kernel::systemtime::now_micros(); let t = timespec::from_usec(microseconds as i64); @@ -183,7 +183,7 @@ impl ObjectInterface for RamFileInterface { Ok(len) } - async fn write(&self, buf: &[u8]) -> io::Result { + async fn write(&mut self, buf: &[u8]) -> io::Result { let microseconds = arch::kernel::systemtime::now_micros(); let t = timespec::from_usec(microseconds as i64); let mut guard = self.inner.write().await; @@ -205,7 +205,7 @@ impl ObjectInterface for RamFileInterface { Ok(buf.len()) } - async fn lseek(&self, offset: isize, whence: SeekWhence) -> io::Result { + async fn lseek(&mut self, offset: isize, whence: SeekWhence) -> io::Result { let mut guard = self.inner.write().await; let mut pos_guard = self.pos.lock().await; @@ -239,14 +239,14 @@ impl ObjectInterface for RamFileInterface { Ok(guard.attr) } - async fn truncate(&self, size: usize) -> io::Result<()> { + async fn truncate(&mut self, size: usize) -> io::Result<()> { let mut guard = self.inner.write().await; guard.data.resize(size, 0); guard.attr.st_size = size as i64; Ok(()) } - async fn chmod(&self, access_permission: AccessPermission) -> io::Result<()> { + async fn chmod(&mut self, access_permission: AccessPermission) -> io::Result<()> { let mut guard = self.inner.write().await; guard.attr.st_mode = access_permission; Ok(()) @@ -435,7 +435,7 @@ impl ObjectInterface for MemDirectoryInterface { /// logically the same operation, so we can just use the same fn in the backend. /// Any other offset than 0 is not supported. (Mostly because it doesn't make any sense, as /// userspace applications have no way of knowing valid offsets) - async fn lseek(&self, offset: isize, whence: SeekWhence) -> io::Result { + async fn lseek(&mut self, offset: isize, whence: SeekWhence) -> io::Result { if whence != SeekWhence::Set && offset != 0 { error!("Invalid offset for directory lseek ({offset})"); return Err(Errno::Inval); diff --git a/src/fs/mod.rs b/src/fs/mod.rs index bde91cfe5c..69290e6ca1 100644 --- a/src/fs/mod.rs +++ b/src/fs/mod.rs @@ -467,7 +467,7 @@ pub fn truncate(name: &str, size: usize) -> io::Result<()> { .open(name, OpenOption::O_TRUNC, AccessPermission::empty()) .map_err(|_| Errno::Badf)?; - block_on(async { file.read().await.truncate(size).await }, None) + block_on(async { file.write().await.truncate(size).await }, None) }) } diff --git a/src/fs/uhyve.rs b/src/fs/uhyve.rs index 3a82b6b771..75f0ff7e00 100644 --- a/src/fs/uhyve.rs +++ b/src/fs/uhyve.rs @@ -5,7 +5,6 @@ use alloc::string::String; use alloc::sync::Arc; use alloc::vec::Vec; -use async_lock::Mutex; use async_trait::async_trait; use embedded_io::{ErrorType, Read, Write}; use memory_addresses::VirtAddr; @@ -25,14 +24,25 @@ use crate::io; use crate::syscalls::interfaces::uhyve::uhyve_hypercall; #[derive(Debug)] -struct UhyveFileHandleInner(i32); +struct UhyveFileHandle(i32); -impl UhyveFileHandleInner { +impl UhyveFileHandle { pub fn new(fd: i32) -> Self { Self(fd) } +} - fn lseek(&self, offset: isize, whence: SeekWhence) -> io::Result { +#[async_trait] +impl ObjectInterface for UhyveFileHandle { + async fn read(&mut self, buf: &mut [u8]) -> io::Result { + Read::read(self, buf) + } + + async fn write(&mut self, buf: &[u8]) -> io::Result { + Write::write(self, buf) + } + + async fn lseek(&mut self, offset: isize, whence: SeekWhence) -> io::Result { let mut lseek_params = LseekParams { fd: self.0, offset, @@ -48,11 +58,11 @@ impl UhyveFileHandleInner { } } -impl ErrorType for UhyveFileHandleInner { +impl ErrorType for UhyveFileHandle { type Error = Errno; } -impl Read for UhyveFileHandleInner { +impl Read for UhyveFileHandle { fn read(&mut self, buf: &mut [u8]) -> Result { let mut read_params = ReadParams { fd: self.0, @@ -70,7 +80,7 @@ impl Read for UhyveFileHandleInner { } } -impl Write for UhyveFileHandleInner { +impl Write for UhyveFileHandle { fn write(&mut self, buf: &[u8]) -> Result { let write_params = WriteParams { fd: self.0, @@ -87,7 +97,7 @@ impl Write for UhyveFileHandleInner { } } -impl Drop for UhyveFileHandleInner { +impl Drop for UhyveFileHandle { fn drop(&mut self) { let mut close_params = CloseParams { fd: self.0, ret: 0 }; uhyve_hypercall(Hypercall::FileClose(&mut close_params)); @@ -98,35 +108,6 @@ impl Drop for UhyveFileHandleInner { } } -struct UhyveFileHandle(Arc>); - -impl UhyveFileHandle { - pub fn new(fd: i32) -> Self { - Self(Arc::new(Mutex::new(UhyveFileHandleInner::new(fd)))) - } -} - -#[async_trait] -impl ObjectInterface for UhyveFileHandle { - async fn read(&self, buf: &mut [u8]) -> io::Result { - self.0.lock().await.read(buf) - } - - async fn write(&self, buf: &[u8]) -> io::Result { - self.0.lock().await.write(buf) - } - - async fn lseek(&self, offset: isize, whence: SeekWhence) -> io::Result { - self.0.lock().await.lseek(offset, whence) - } -} - -impl Clone for UhyveFileHandle { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} - #[derive(Debug)] pub(crate) struct UhyveDirectory { prefix: Option, diff --git a/src/fs/virtio_fs.rs b/src/fs/virtio_fs.rs index 4b66cf63ff..54d9f228ed 100644 --- a/src/fs/virtio_fs.rs +++ b/src/fs/virtio_fs.rs @@ -22,7 +22,6 @@ use crate::arch::kernel::mmio::get_filesystem_driver; use crate::drivers::pci::get_filesystem_driver; use crate::drivers::virtio::virtqueue::error::VirtqError; use crate::errno::Errno; -use crate::executor::block_on; use crate::fd::PollEvent; use crate::fs::virtio_fs::ops::SetAttrValidFields; use crate::fs::{ @@ -671,13 +670,13 @@ fn readlink(nid: u64) -> io::Result { } #[derive(Debug)] -struct VirtioFsFileHandleInner { +struct VirtioFsFileHandle { fuse_nid: Option, fuse_fh: Option, offset: usize, } -impl VirtioFsFileHandleInner { +impl VirtioFsFileHandle { pub fn new() -> Self { Self { fuse_nid: None, @@ -686,6 +685,28 @@ impl VirtioFsFileHandleInner { } } + fn set_attr(&mut self, attr: FileAttr, valid: SetAttrValidFields) -> io::Result { + debug!("virtio-fs setattr"); + + let nid = self.fuse_nid.ok_or(Errno::Io)?; + let fh = self.fuse_fh.ok_or(Errno::Io)?; + + let (cmd, rsp_payload_len) = ops::Setattr::create(nid, fh, attr, valid); + let rsp = get_filesystem_driver() + .ok_or(Errno::Nosys)? + .lock() + .send_command(cmd, rsp_payload_len)?; + + if rsp.headers.out_header.error < 0 { + return Err(Errno::Io); + } + + Ok(rsp.headers.op_header.attr.into()) + } +} + +#[async_trait] +impl ObjectInterface for VirtioFsFileHandle { async fn poll(&self, events: PollEvent) -> io::Result { static KH: AtomicU64 = AtomicU64::new(0); let kh = KH.fetch_add(1, Ordering::SeqCst); @@ -725,7 +746,15 @@ impl VirtioFsFileHandleInner { .await } - fn lseek(&mut self, offset: isize, whence: SeekWhence) -> io::Result { + async fn read(&mut self, buf: &mut [u8]) -> io::Result { + Read::read(self, buf) + } + + async fn write(&mut self, buf: &[u8]) -> io::Result { + Write::write(self, buf) + } + + async fn lseek(&mut self, offset: isize, whence: SeekWhence) -> io::Result { debug!("virtio-fs lseek: offset: {offset}, whence: {whence:?}"); // Seek on FUSE file systems seems to be a little odd: All reads are referenced from the @@ -766,7 +795,7 @@ impl VirtioFsFileHandleInner { } } - fn fstat(&mut self) -> io::Result { + async fn fstat(&self) -> io::Result { debug!("virtio-fs getattr"); let nid = self.fuse_nid.ok_or(Errno::Io)?; @@ -785,31 +814,32 @@ impl VirtioFsFileHandleInner { Ok(rsp.headers.op_header.attr.into()) } - fn set_attr(&mut self, attr: FileAttr, valid: SetAttrValidFields) -> io::Result { - debug!("virtio-fs setattr"); - - let nid = self.fuse_nid.ok_or(Errno::Io)?; - let fh = self.fuse_fh.ok_or(Errno::Io)?; + async fn truncate(&mut self, size: usize) -> io::Result<()> { + let attr = FileAttr { + st_size: size.try_into().unwrap(), + ..FileAttr::default() + }; - let (cmd, rsp_payload_len) = ops::Setattr::create(nid, fh, attr, valid); - let rsp = get_filesystem_driver() - .ok_or(Errno::Nosys)? - .lock() - .send_command(cmd, rsp_payload_len)?; + self.set_attr(attr, SetAttrValidFields::FATTR_SIZE) + .map(|_| ()) + } - if rsp.headers.out_header.error < 0 { - return Err(Errno::Io); - } + async fn chmod(&mut self, access_permission: AccessPermission) -> io::Result<()> { + let attr = FileAttr { + st_mode: access_permission, + ..FileAttr::default() + }; - Ok(rsp.headers.op_header.attr.into()) + self.set_attr(attr, SetAttrValidFields::FATTR_MODE) + .map(|_| ()) } } -impl ErrorType for VirtioFsFileHandleInner { +impl ErrorType for VirtioFsFileHandle { type Error = Errno; } -impl Read for VirtioFsFileHandleInner { +impl Read for VirtioFsFileHandle { fn read(&mut self, buf: &mut [u8]) -> Result { let mut len = buf.len(); if len > MAX_READ_LEN { @@ -840,7 +870,7 @@ impl Read for VirtioFsFileHandleInner { } } -impl Write for VirtioFsFileHandleInner { +impl Write for VirtioFsFileHandle { fn write(&mut self, buf: &[u8]) -> Result { debug!("virtio-fs write!"); let mut truncated_len = buf.len(); @@ -882,7 +912,7 @@ impl Write for VirtioFsFileHandleInner { } } -impl Drop for VirtioFsFileHandleInner { +impl Drop for VirtioFsFileHandle { fn drop(&mut self) { let Some(fuse_nid) = self.fuse_nid else { return; @@ -901,70 +931,6 @@ impl Drop for VirtioFsFileHandleInner { } } -struct VirtioFsFileHandle(Arc>); - -impl VirtioFsFileHandle { - pub fn new() -> Self { - Self(Arc::new(Mutex::new(VirtioFsFileHandleInner::new()))) - } -} - -#[async_trait] -impl ObjectInterface for VirtioFsFileHandle { - async fn poll(&self, event: PollEvent) -> io::Result { - self.0.lock().await.poll(event).await - } - - async fn read(&self, buf: &mut [u8]) -> io::Result { - self.0.lock().await.read(buf) - } - - async fn write(&self, buf: &[u8]) -> io::Result { - self.0.lock().await.write(buf) - } - - async fn lseek(&self, offset: isize, whence: SeekWhence) -> io::Result { - self.0.lock().await.lseek(offset, whence) - } - - async fn fstat(&self) -> io::Result { - self.0.lock().await.fstat() - } - - async fn truncate(&self, size: usize) -> io::Result<()> { - let attr = FileAttr { - st_size: size.try_into().unwrap(), - ..FileAttr::default() - }; - - self.0 - .lock() - .await - .set_attr(attr, SetAttrValidFields::FATTR_SIZE) - .map(|_| ()) - } - - async fn chmod(&self, access_permission: AccessPermission) -> io::Result<()> { - let attr = FileAttr { - st_mode: access_permission, - ..FileAttr::default() - }; - - self.0 - .lock() - .await - .set_attr(attr, SetAttrValidFields::FATTR_MODE) - .map(|_| ()) - } -} - -impl Clone for VirtioFsFileHandle { - fn clone(&self) -> Self { - warn!("VirtioFsFileHandle: clone not tested"); - Self(self.0.clone()) - } -} - pub struct VirtioFsDirectoryHandle { name: Option, read_position: Mutex, @@ -1088,7 +1054,7 @@ impl ObjectInterface for VirtioFsDirectoryHandle { /// logically the same operation, so we can just use the same fn in the backend. /// Any other offset than 0 is not supported. (Mostly because it doesn't make any sense, as /// userspace applications have no way of knowing valid offsets) - async fn lseek(&self, offset: isize, whence: SeekWhence) -> io::Result { + async fn lseek(&mut self, offset: isize, whence: SeekWhence) -> io::Result { if whence != SeekWhence::Set && offset != 0 { error!("Invalid offset for directory lseek ({offset})"); return Err(Errno::Inval); @@ -1307,11 +1273,10 @@ impl VfsNode for VirtioFsDirectory { ))); } - let file = VirtioFsFileHandle::new(); + let mut file = VirtioFsFileHandle::new(); // 1.FUSE_INIT to create session // Already done - let mut file_guard = block_on(async { Ok(file.0.lock().await) }, None)?; // Differentiate between opening and creating new file, since FUSE does not support O_CREAT on open. if opt.contains(OpenOption::O_CREAT) { @@ -1324,29 +1289,27 @@ impl VfsNode for VirtioFsDirectory { .send_command(cmd, rsp_payload_len)?; let inner = rsp.headers.op_header; - file_guard.fuse_nid = Some(inner.entry.nodeid); - file_guard.fuse_fh = Some(inner.open.fh); + file.fuse_nid = Some(inner.entry.nodeid); + file.fuse_fh = Some(inner.open.fh); } else { // 2.FUSE_LOOKUP(FUSE_ROOT_ID, “foo”) -> nodeid - file_guard.fuse_nid = lookup(path); + file.fuse_nid = lookup(path); - if file_guard.fuse_nid.is_none() { + if file.fuse_nid.is_none() { warn!("virtio-fs lookup seems to have failed!"); return Err(Errno::Noent); } // 3.FUSE_OPEN(nodeid, O_RDONLY) -> fh let (cmd, rsp_payload_len) = - ops::Open::create(file_guard.fuse_nid.unwrap(), opt.bits().try_into().unwrap()); + ops::Open::create(file.fuse_nid.unwrap(), opt.bits().try_into().unwrap()); let rsp = get_filesystem_driver() .ok_or(Errno::Nosys)? .lock() .send_command(cmd, rsp_payload_len)?; - file_guard.fuse_fh = Some(rsp.headers.op_header.fh); + file.fuse_fh = Some(rsp.headers.op_header.fh); } - drop(file_guard); - Ok(Arc::new(async_lock::RwLock::new(file))) }