summaryrefslogtreecommitdiff
path: root/src/fuse/session.rs
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2022-01-04 03:51:32 -0600
committerAlejandro Soto <alejandro@34project.org>2022-01-04 03:51:32 -0600
commit1c02eebc71a0ede4e75fea516920697850bbe030 (patch)
tree3a54355a5e34d5539fe413e0e3b17a8e9b832601 /src/fuse/session.rs
parentb5c8846482d5309fac92c7ab94d4f53690b201b4 (diff)
Implement unmount
Diffstat (limited to '')
-rw-r--r--src/fuse/session.rs57
1 files changed, 52 insertions, 5 deletions
diff --git a/src/fuse/session.rs b/src/fuse/session.rs
index d7b6501..55fedcb 100644
--- a/src/fuse/session.rs
+++ b/src/fuse/session.rs
@@ -4,6 +4,7 @@ use std::{
marker::PhantomData,
ops::ControlFlow,
os::unix::io::{IntoRawFd, RawFd},
+ path::PathBuf,
sync::{Arc, Mutex},
};
@@ -22,6 +23,7 @@ use bytemuck::bytes_of;
use smallvec::SmallVec;
use crate::{
+ mount::{unmount_sync, MountError},
proto::{self, InHeader, Structured},
util::{page_size, DumbFd, OutputChain},
Errno, FuseError, FuseResult,
@@ -34,6 +36,7 @@ use super::{
pub struct Start {
session_fd: DumbFd,
+ mountpoint: PathBuf,
}
pub struct Session {
@@ -42,6 +45,7 @@ pub struct Session {
buffers: Mutex<Vec<Buffer>>,
buffer_semaphore: Arc<Semaphore>,
buffer_pages: usize,
+ mountpoint: Mutex<Option<PathBuf>>,
}
pub struct Endpoint<'a> {
@@ -93,6 +97,15 @@ impl Session {
}
}
+ pub fn unmount_sync(&self) -> Result<(), MountError> {
+ let mountpoint = self.mountpoint.lock().unwrap().take();
+ if let Some(mountpoint) = &mountpoint {
+ unmount_sync(mountpoint)?;
+ }
+
+ Ok(())
+ }
+
pub(crate) fn ok(&self, unique: u64, output: OutputChain<'_>) -> FuseResult<()> {
self.send(unique, 0, output)
}
@@ -212,6 +225,24 @@ impl Session {
}
}
+impl Drop for Start {
+ fn drop(&mut self) {
+ if !self.mountpoint.as_os_str().is_empty() {
+ let _ = unmount_sync(&self.mountpoint);
+ }
+ }
+}
+
+impl Drop for Session {
+ fn drop(&mut self) {
+ if let Some(mountpoint) = self.mountpoint.get_mut().unwrap().take() {
+ let _ = unmount_sync(&mountpoint);
+ }
+
+ drop(DumbFd(*self.session_fd.get_ref())); // Close
+ }
+}
+
impl<'o> Dispatch<'o> {
pub fn op(self) -> Op<'o> {
use Dispatch::*;
@@ -253,7 +284,11 @@ impl Endpoint<'_> {
let mut readable = tokio::select! {
readable = session_fd.readable() => readable?,
- _ = session_fd.writable() => return Ok(ControlFlow::Break(())),
+
+ _ = session_fd.writable() => {
+ self.session.mountpoint.lock().unwrap().take();
+ return Ok(ControlFlow::Break(()));
+ }
};
let mut read = |fd: &AsyncFd<RawFd>| read(*fd.get_ref(), buffer);
@@ -264,6 +299,7 @@ impl Endpoint<'_> {
match result {
// Interrupted
+ //TODO: libfuse docs say that this has some side effects
Err(error) if error.kind() == std::io::ErrorKind::NotFound => continue,
result => break result,
@@ -330,11 +366,12 @@ impl Endpoint<'_> {
}
impl Start {
- pub async fn start<F>(self, mut init: F) -> FuseResult<Arc<Session>>
+ pub async fn start<F>(mut self, mut init: F) -> FuseResult<Arc<Session>>
where
F: FnOnce(Op<'_, ops::Init>) -> Done<'_>,
{
- let session_fd = self.session_fd.into_raw_fd();
+ let mountpoint = std::mem::take(&mut self.mountpoint);
+ let session_fd = self.session_fd.take().into_raw_fd();
let flags = OFlag::O_NONBLOCK | OFlag::O_LARGEFILE;
fcntl(session_fd, FcntlArg::F_SETFL(flags)).unwrap();
@@ -353,6 +390,7 @@ impl Start {
buffers: Mutex::new(buffers),
buffer_semaphore: Arc::new(Semaphore::new(buffer_count)),
buffer_pages,
+ mountpoint: Mutex::new(Some(mountpoint)),
};
let mut init_buffer = session.buffers.get_mut().unwrap().pop().unwrap();
@@ -368,8 +406,17 @@ impl Start {
}
}
- pub(crate) fn new(session_fd: DumbFd) -> Self {
- Start { session_fd }
+ pub fn unmount_sync(mut self) -> Result<(), MountError> {
+ // This prevents Start::drop() from unmounting a second time
+ let mountpoint = std::mem::take(&mut self.mountpoint);
+ unmount_sync(&mountpoint)
+ }
+
+ pub(crate) fn new(session_fd: DumbFd, mountpoint: PathBuf) -> Self {
+ Start {
+ session_fd,
+ mountpoint,
+ }
}
}