From 44b8c25b60821dc2b5914f49be884609ed47d191 Mon Sep 17 00:00:00 2001 From: Brian Olsen Date: Fri, 29 Sep 2023 17:40:11 +0200 Subject: [PATCH] fuse_t_session: Correctly handle EOF The fuse-t session uses a socket pair for communication but wasn't correctly handling EOF and so when trying to gracefully unmount it would just hang. This change simply deals with EOF in the channel and returns None when it occurs during header read and an error otherwise. Signed-off-by: Brian Olsen --- src/transport/fusedev/fuse_t_session.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/transport/fusedev/fuse_t_session.rs b/src/transport/fusedev/fuse_t_session.rs index 8509b4ccb..fce534877 100644 --- a/src/transport/fusedev/fuse_t_session.rs +++ b/src/transport/fusedev/fuse_t_session.rs @@ -9,6 +9,7 @@ //! A FUSE session can have multiple FUSE channels so that FUSE requests are handled in parallel. use std::fs::File; +use std::io; use std::mem::size_of; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use std::os::unix::prelude::CommandExt; @@ -259,12 +260,16 @@ impl FuseChannel { }) } - fn read(&mut self, len: usize, offset: usize) -> Result<()> { + fn read(&mut self, len: usize, offset: usize) -> Result { let read_buf = &mut self.buf[offset..offset + len]; let mut total: usize = 0; let fd = self.file.as_raw_fd(); while total < len { match read(fd, read_buf) { + Ok(0) => { + trace!("Read EOF"); + return Ok(true); + } Ok(size) => { total += size; } @@ -286,7 +291,7 @@ impl FuseChannel { } Errno::ENODEV => { info!("fuse filesystem umounted"); - return Ok(()); + return Ok(true); } e => { warn! {"read fuse dev failed on fd {}: {}", fd, e}; @@ -295,7 +300,7 @@ impl FuseChannel { }, } } - Ok(()) + Ok(false) } /// Get next available FUSE request from the underlying fuse device file. @@ -316,12 +321,17 @@ impl FuseChannel { let fd = self.file.as_raw_fd(); let size = size_of::(); // read header - self.read(size, 0)?; + if self.read(size, 0)? { + return Ok(None); + } let in_header = InHeader::from_slice(&self.buf[0..size]); let header_len = in_header.unwrap().len as usize; let should_read_size = header_len - size; - if should_read_size > 0 { - self.read(should_read_size, size)?; + if should_read_size > 0 && !self.read(should_read_size, size)? { + return Err(IoError(io::Error::new( + io::ErrorKind::UnexpectedEof, + "Unexpected EOF", + ))); } drop(result);