From 99bc926d1ebabb9161f9fb1f9d2436031340ca6f Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Tue, 16 Apr 2024 17:03:23 +0300 Subject: [PATCH] fix(tvix/castore/fs): use io::copy to fill kernel-provided buffer 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 --- tvix/castore/src/fs/mod.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tvix/castore/src/fs/mod.rs b/tvix/castore/src/fs/mod.rs index 0da811528..59eeb8422 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))]