diff options
author | Florian Klink <flokli@flokli.de> | 2024-04-16T14·03+0300 |
---|---|---|
committer | flokli <flokli@flokli.de> | 2024-04-16T18·45+0000 |
commit | 99bc926d1ebabb9161f9fb1f9d2436031340ca6f (patch) | |
tree | e81e722a78418a4883c3494d726b3e127fbaf0f5 | |
parent | bfd342873c535df3281090a3fe49e3aef6a943b6 (diff) |
fix(tvix/castore/fs): use io::copy to fill kernel-provided buffer r/7948
The docs state we must fill all of the buffer, except on EOF. Change-Id: Id977ba99c0b15132422474ebbf82bb92b79d55ba Reviewed-on: https://cl.tvl.fyi/c/depot/+/11446 Tested-by: BuildkiteCI Reviewed-by: raitobezarius <tvl@lahfa.xyz>
-rw-r--r-- | tvix/castore/src/fs/mod.rs | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/tvix/castore/src/fs/mod.rs b/tvix/castore/src/fs/mod.rs index 0da811528172..59eeb8422828 100644 --- a/tvix/castore/src/fs/mod.rs +++ b/tvix/castore/src/fs/mod.rs @@ -33,7 +33,6 @@ use fuse_backend_rs::api::filesystem::{ }; use futures::StreamExt; use parking_lot::RwLock; -use std::ffi::CStr; use std::sync::Mutex; use std::{ collections::HashMap, @@ -42,11 +41,12 @@ use std::{ sync::{atomic::Ordering, Arc}, time::Duration, }; +use std::{ffi::CStr, io::Cursor}; use tokio::{ io::{AsyncReadExt, AsyncSeekExt}, sync::mpsc, }; -use tracing::{debug, instrument, warn, Span}; +use tracing::{debug, error, instrument, warn, Span}; /// This implements a read-only FUSE filesystem for a tvix-store /// with the passed [BlobService], [DirectoryService] and [RootNodes]. @@ -767,7 +767,16 @@ where Ok::<_, std::io::Error>(buf) })?; - w.write(&buf) + // We cannot use w.write() here, we're required to call write multiple + // times until we wrote the entirety of the buffer (which is `size`, except on EOF). + let buf_len = buf.len(); + let bytes_written = io::copy(&mut Cursor::new(buf), w)?; + if bytes_written != buf_len as u64 { + error!(bytes_written=%bytes_written, "unable to write all of buf to kernel"); + return Err(io::Error::from_raw_os_error(libc::EIO)); + } + + Ok(bytes_written as usize) } #[tracing::instrument(skip_all, fields(rq.inode = inode))] |