From af949ab268a5a6ca8f78f668e0a8431b64efbcf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 4 Mar 2026 14:30:13 +0100 Subject: [PATCH 1/5] refactor(fs): don't implement Clone for file handles Arcs to this type can be cloned instead. --- src/fs/uhyve.rs | 6 ------ src/fs/virtio_fs.rs | 7 ------- 2 files changed, 13 deletions(-) diff --git a/src/fs/uhyve.rs b/src/fs/uhyve.rs index 3a82b6b771..5ca3ee3658 100644 --- a/src/fs/uhyve.rs +++ b/src/fs/uhyve.rs @@ -121,12 +121,6 @@ impl ObjectInterface for UhyveFileHandle { } } -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..217b4ea565 100644 --- a/src/fs/virtio_fs.rs +++ b/src/fs/virtio_fs.rs @@ -958,13 +958,6 @@ impl ObjectInterface for VirtioFsFileHandle { } } -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, From 93fed35202ccce99426951bba9d54615f1ec3dae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 4 Mar 2026 14:21:27 +0100 Subject: [PATCH 2/5] refactor(fd): make read, write, lseek, truncate, chmod mutable --- src/fd/eventfd.rs | 4 ++-- src/fd/mod.rs | 23 +++++++++++++---------- src/fd/socket/tcp.rs | 4 ++-- src/fd/socket/udp.rs | 4 ++-- src/fd/socket/vsock.rs | 4 ++-- src/fd/stdio.rs | 10 +++++----- src/fs/mem.rs | 16 ++++++++-------- src/fs/mod.rs | 2 +- src/fs/uhyve.rs | 6 +++--- src/fs/virtio_fs.rs | 12 ++++++------ 10 files changed, 44 insertions(+), 41 deletions(-) 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 5ca3ee3658..23c76b2906 100644 --- a/src/fs/uhyve.rs +++ b/src/fs/uhyve.rs @@ -108,15 +108,15 @@ impl UhyveFileHandle { #[async_trait] impl ObjectInterface for UhyveFileHandle { - async fn read(&self, buf: &mut [u8]) -> io::Result { + async fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.lock().await.read(buf) } - async fn write(&self, buf: &[u8]) -> io::Result { + async fn write(&mut self, buf: &[u8]) -> io::Result { self.0.lock().await.write(buf) } - async fn lseek(&self, offset: isize, whence: SeekWhence) -> io::Result { + async fn lseek(&mut self, offset: isize, whence: SeekWhence) -> io::Result { self.0.lock().await.lseek(offset, whence) } } diff --git a/src/fs/virtio_fs.rs b/src/fs/virtio_fs.rs index 217b4ea565..502f0c58d8 100644 --- a/src/fs/virtio_fs.rs +++ b/src/fs/virtio_fs.rs @@ -915,15 +915,15 @@ impl ObjectInterface for VirtioFsFileHandle { self.0.lock().await.poll(event).await } - async fn read(&self, buf: &mut [u8]) -> io::Result { + async fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.lock().await.read(buf) } - async fn write(&self, buf: &[u8]) -> io::Result { + async fn write(&mut self, buf: &[u8]) -> io::Result { self.0.lock().await.write(buf) } - async fn lseek(&self, offset: isize, whence: SeekWhence) -> io::Result { + async fn lseek(&mut self, offset: isize, whence: SeekWhence) -> io::Result { self.0.lock().await.lseek(offset, whence) } @@ -931,7 +931,7 @@ impl ObjectInterface for VirtioFsFileHandle { self.0.lock().await.fstat() } - async fn truncate(&self, size: usize) -> io::Result<()> { + async fn truncate(&mut self, size: usize) -> io::Result<()> { let attr = FileAttr { st_size: size.try_into().unwrap(), ..FileAttr::default() @@ -944,7 +944,7 @@ impl ObjectInterface for VirtioFsFileHandle { .map(|_| ()) } - async fn chmod(&self, access_permission: AccessPermission) -> io::Result<()> { + async fn chmod(&mut self, access_permission: AccessPermission) -> io::Result<()> { let attr = FileAttr { st_mode: access_permission, ..FileAttr::default() @@ -1081,7 +1081,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); From e982398fc4f2c6cc3ae06288c735968cbbc9a5c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 4 Mar 2026 14:26:23 +0100 Subject: [PATCH 3/5] refactor(virtio-fs): implement truncate, chmod directly --- src/fs/virtio_fs.rs | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/fs/virtio_fs.rs b/src/fs/virtio_fs.rs index 502f0c58d8..eadb56e0ac 100644 --- a/src/fs/virtio_fs.rs +++ b/src/fs/virtio_fs.rs @@ -785,6 +785,26 @@ impl VirtioFsFileHandleInner { Ok(rsp.headers.op_header.attr.into()) } + fn truncate(&mut self, size: usize) -> io::Result<()> { + let attr = FileAttr { + st_size: size.try_into().unwrap(), + ..FileAttr::default() + }; + + self.set_attr(attr, SetAttrValidFields::FATTR_SIZE) + .map(|_| ()) + } + + fn chmod(&mut self, access_permission: AccessPermission) -> io::Result<()> { + let attr = FileAttr { + st_mode: access_permission, + ..FileAttr::default() + }; + + self.set_attr(attr, SetAttrValidFields::FATTR_MODE) + .map(|_| ()) + } + fn set_attr(&mut self, attr: FileAttr, valid: SetAttrValidFields) -> io::Result { debug!("virtio-fs setattr"); @@ -932,29 +952,11 @@ impl ObjectInterface for VirtioFsFileHandle { } async fn truncate(&mut 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(|_| ()) + self.0.lock().await.truncate(size) } async fn chmod(&mut 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(|_| ()) + self.0.lock().await.chmod(access_permission) } } From 1ae743be4f5389b32569714332e3f04b903ae670 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 4 Mar 2026 14:36:57 +0100 Subject: [PATCH 4/5] refactor(virtio-fs): group ObjectInterface methods --- src/fs/virtio_fs.rs | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/fs/virtio_fs.rs b/src/fs/virtio_fs.rs index eadb56e0ac..b2cd362898 100644 --- a/src/fs/virtio_fs.rs +++ b/src/fs/virtio_fs.rs @@ -686,6 +686,27 @@ 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()) + } +} + +impl VirtioFsFileHandleInner { async fn poll(&self, events: PollEvent) -> io::Result { static KH: AtomicU64 = AtomicU64::new(0); let kh = KH.fetch_add(1, Ordering::SeqCst); @@ -804,25 +825,6 @@ impl VirtioFsFileHandleInner { self.set_attr(attr, SetAttrValidFields::FATTR_MODE) .map(|_| ()) } - - 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()) - } } impl ErrorType for VirtioFsFileHandleInner { From 8c7cdcfa1fe3b66e0a2f7bd9e23cde1b9339af28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Wed, 4 Mar 2026 15:07:12 +0100 Subject: [PATCH 5/5] refactor(fs): implement ObjectInterface without inner lock --- src/fs/uhyve.rs | 49 ++++++++++--------------- src/fs/virtio_fs.rs | 88 ++++++++++++++------------------------------- 2 files changed, 45 insertions(+), 92 deletions(-) diff --git a/src/fs/uhyve.rs b/src/fs/uhyve.rs index 23c76b2906..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) } +} + +#[async_trait] +impl ObjectInterface for UhyveFileHandle { + async fn read(&mut self, buf: &mut [u8]) -> io::Result { + Read::read(self, buf) + } - fn lseek(&self, offset: isize, whence: SeekWhence) -> io::Result { + 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,29 +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(&mut self, buf: &mut [u8]) -> io::Result { - self.0.lock().await.read(buf) - } - - async fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.lock().await.write(buf) - } - - async fn lseek(&mut self, offset: isize, whence: SeekWhence) -> io::Result { - self.0.lock().await.lseek(offset, whence) - } -} - #[derive(Debug)] pub(crate) struct UhyveDirectory { prefix: Option, diff --git a/src/fs/virtio_fs.rs b/src/fs/virtio_fs.rs index b2cd362898..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, @@ -706,7 +705,8 @@ impl VirtioFsFileHandleInner { } } -impl VirtioFsFileHandleInner { +#[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); @@ -746,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 @@ -787,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)?; @@ -806,7 +814,7 @@ impl VirtioFsFileHandleInner { Ok(rsp.headers.op_header.attr.into()) } - fn truncate(&mut self, size: usize) -> io::Result<()> { + async fn truncate(&mut self, size: usize) -> io::Result<()> { let attr = FileAttr { st_size: size.try_into().unwrap(), ..FileAttr::default() @@ -816,7 +824,7 @@ impl VirtioFsFileHandleInner { .map(|_| ()) } - fn chmod(&mut self, access_permission: AccessPermission) -> io::Result<()> { + async fn chmod(&mut self, access_permission: AccessPermission) -> io::Result<()> { let attr = FileAttr { st_mode: access_permission, ..FileAttr::default() @@ -827,11 +835,11 @@ impl VirtioFsFileHandleInner { } } -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 { @@ -862,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(); @@ -904,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; @@ -923,45 +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(&mut self, buf: &mut [u8]) -> io::Result { - self.0.lock().await.read(buf) - } - - async fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.lock().await.write(buf) - } - - async fn lseek(&mut 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(&mut self, size: usize) -> io::Result<()> { - self.0.lock().await.truncate(size) - } - - async fn chmod(&mut self, access_permission: AccessPermission) -> io::Result<()> { - self.0.lock().await.chmod(access_permission) - } -} - pub struct VirtioFsDirectoryHandle { name: Option, read_position: Mutex, @@ -1304,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) { @@ -1321,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))) }