Skip to content

Commit

Permalink
Implement the foreground option for the mount command
Browse files Browse the repository at this point in the history
Inspired by cberner/fuser#179 (comment)
The program exits when ctrl-c is pressed or when the filesystem is
unmounted (e.g. fusermount -u <mountpoint>)

Note that this issue zargony/fuse-rs#151
prevents using the destroy callback for notifying us that the filesystem
was unmounted, so we use the drop callback as a workaround.

Signed-off-by: Ariel Miculas <[email protected]>
  • Loading branch information
ariel-miculas committed Nov 4, 2022
1 parent e92c671 commit 35be14f
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 20 deletions.
43 changes: 36 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions exe/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ anyhow = "*"
nix = "*"
clap = { version = "4.0.18", features = ["derive"] }
daemonize = "0.4"
ctrlc = "3.2.0"
format = { path = "../format" }
builder = { path = "../builder" }
oci = { path = "../oci" }
Expand Down
34 changes: 26 additions & 8 deletions exe/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use builder::build_initial_rootfs;
use daemonize::Daemonize;
use extractor::extract_rootfs;
use oci::Image;
use reader::mount;
use reader::{mount, spawn_mount};

#[derive(Parser)]
#[command(author, version, about)]
Expand Down Expand Up @@ -35,6 +35,8 @@ struct Mount {
oci_dir: String,
tag: String,
mountpoint: String,
#[arg(short, long)]
foreground: bool,
}

#[derive(Args)]
Expand All @@ -55,17 +57,33 @@ fn main() -> anyhow::Result<()> {
image.add_tag(b.tag, desc).map_err(|e| e.into())
}
SubCommand::Mount(m) => {
// TODO: add --foreground option?
let oci_dir = Path::new(&m.oci_dir);
let image = Image::new(oci_dir)?;
let mountpoint = Path::new(&m.mountpoint);
let stdout = File::create("/tmp/puzzlefs.out")?;
let stderr = File::create("/tmp/puzzlefs.err")?;
let daemonize = Daemonize::new().stdout(stdout).stderr(stderr);

match daemonize.start() {
Ok(_) => mount(&image, &m.tag, mountpoint)?,
Err(e) => eprintln!("Error, {}", e),
if m.foreground {
let (send, recv) = std::sync::mpsc::channel();
let send_ctrlc = send.clone();

ctrlc::set_handler(move || {
println!("puzzlefs unmounted");
send_ctrlc.send(()).unwrap();
})
.unwrap();

let fuse_thread_finished = send;
let _guard = spawn_mount(&image, &m.tag, mountpoint, Some(fuse_thread_finished))?;
// This blocks until either ctrl-c is pressed or the filesystem is unmounted
let () = recv.recv().unwrap();
} else {
let stdout = File::create("/tmp/puzzlefs.out")?;
let stderr = File::create("/tmp/puzzlefs.err")?;
let daemonize = Daemonize::new().stdout(stdout).stderr(stderr);

match daemonize.start() {
Ok(_) => mount(&image, &m.tag, mountpoint)?,
Err(e) => eprintln!("Error, {}", e),
}
}

Ok(())
Expand Down
18 changes: 15 additions & 3 deletions reader/src/fuse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use super::puzzlefs::{file_read, Inode, InodeMode, PuzzleFS};

pub struct Fuse<'a> {
pfs: PuzzleFS<'a>,
sender: Option<std::sync::mpsc::Sender<()>>,
// TODO: LRU cache inodes or something. I had problems fiddling with the borrow checker for the
// cache, so for now we just do each lookup every time.
}
Expand All @@ -36,8 +37,8 @@ fn mode_to_fuse_type(inode: &Inode) -> Result<FileType> {
}

impl<'a> Fuse<'a> {
pub fn new(pfs: PuzzleFS<'a>) -> Fuse<'a> {
Fuse { pfs }
pub fn new(pfs: PuzzleFS<'a>, sender: Option<std::sync::mpsc::Sender<()>>) -> Fuse<'a> {
Fuse { pfs, sender }
}

fn _lookup(&mut self, parent: u64, name: &OsStr) -> Result<FileAttr> {
Expand Down Expand Up @@ -106,6 +107,17 @@ impl<'a> Fuse<'a> {
}
}

impl Drop for Fuse<'_> {
fn drop(&mut self) {
// This code should be in the destroy function inside the Filesystem implementation
// Unfortunately, destroy is not getting called: https://github.com/zargony/fuse-rs/issues/151
// This is fixed in fuser, which we're not using right now: https://github.com/cberner/fuser/issues/153
if let Some(sender) = &self.sender {
sender.send(()).unwrap();
}
}
}

impl Filesystem for Fuse<'_> {
fn init(&mut self, _req: &Request) -> std::result::Result<(), c_int> {
Ok(())
Expand Down Expand Up @@ -463,7 +475,7 @@ mod tests {
let rootfs_desc = build_test_fs(Path::new("../builder/test/test-1"), &image).unwrap();
image.add_tag("test".to_string(), rootfs_desc).unwrap();
let mountpoint = tempdir().unwrap();
let _bg = crate::spawn_mount(&image, "test", Path::new(mountpoint.path())).unwrap();
let _bg = crate::spawn_mount(&image, "test", Path::new(mountpoint.path()), None).unwrap();
let ents = fs::read_dir(mountpoint.path())
.unwrap()
.collect::<io::Result<Vec<fs::DirEntry>>>()
Expand Down
5 changes: 3 additions & 2 deletions reader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub use walk::WalkPuzzleFS;

pub fn mount(image: &Image, tag: &str, mountpoint: &Path) -> Result<()> {
let pfs = PuzzleFS::open(image, tag)?;
let fuse = Fuse::new(pfs);
let fuse = Fuse::new(pfs, None);
fuse_ffi::mount(fuse, &mountpoint, &[])?;
Ok(())
}
Expand All @@ -25,8 +25,9 @@ pub fn spawn_mount<'a>(
image: &'a Image,
tag: &str,
mountpoint: &Path,
sender: Option<std::sync::mpsc::Sender<()>>,
) -> Result<fuse_ffi::BackgroundSession<'a>> {
let pfs = PuzzleFS::open(image, tag)?;
let fuse = Fuse::new(pfs);
let fuse = Fuse::new(pfs, sender);
unsafe { Ok(fuse_ffi::spawn_mount(fuse, &mountpoint, &[])?) }
}

0 comments on commit 35be14f

Please sign in to comment.