about summary refs log tree commit diff
path: root/tvix/castore/src/fs/mod.rs
diff options
context:
space:
mode:
authorFlorian Klink <flokli@flokli.de>2024-04-16T14·03+0300
committerflokli <flokli@flokli.de>2024-04-16T18·45+0000
commit99bc926d1ebabb9161f9fb1f9d2436031340ca6f (patch)
treee81e722a78418a4883c3494d726b3e127fbaf0f5 /tvix/castore/src/fs/mod.rs
parentbfd342873c535df3281090a3fe49e3aef6a943b6 (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>
Diffstat (limited to 'tvix/castore/src/fs/mod.rs')
-rw-r--r--tvix/castore/src/fs/mod.rs15
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))]