Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 74 additions & 5 deletions project/libfuse-fs/examples/overlayfs_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

use clap::Parser;
use libfuse_fs::overlayfs::{OverlayArgs, mount_fs};
use libfuse_fs::util::bind_mount::{BindMount, BindMountManager};
use tokio::signal;
use tracing::debug;
use tracing::{debug, info, error};

#[derive(Parser, Debug)]
#[command(author, version, about = "OverlayFS example for integration tests")]
Expand All @@ -28,6 +29,9 @@ struct Args {
mapping: Option<String>,
#[arg(long)]
allow_other: bool,
/// Bind mounts in format "source:target" (repeatable)
#[arg(long = "bind")]
bind_mounts: Vec<String>,
}

fn set_log() {
Expand All @@ -44,9 +48,27 @@ async fn main() {
set_log();
debug!("Starting overlay filesystem with args: {:?}", args);

// Parse bind mounts
let bind_specs: Result<Vec<BindMount>, _> = args
.bind_mounts
.iter()
.map(|s| BindMount::parse(s))
.collect();

let bind_specs = match bind_specs {
Ok(specs) => specs,
Err(e) => {
error!("Failed to parse bind mount specifications: {}", e);
std::process::exit(1);
}
};

// Create bind mount manager
let bind_manager = BindMountManager::new(&args.mountpoint);

let mut mount_handle = mount_fs(OverlayArgs {
name: None::<String>,
mountpoint: args.mountpoint,
mountpoint: args.mountpoint.clone(),
lowerdir: args.lowerdir,
upperdir: args.upperdir,
mapping: args.mapping,
Expand All @@ -55,11 +77,58 @@ async fn main() {
})
.await;

let handle = &mut mount_handle;
// Mount bind mounts after the overlay filesystem is mounted
if !bind_specs.is_empty() {
info!("Cleaning up any existing bind mounts from previous runs...");
if let Err(e) = bind_manager.cleanup_existing_mounts(&bind_specs).await {
error!("Failed to cleanup existing mounts: {}", e);
}

info!("Mounting {} bind mount(s)", bind_specs.len());
if let Err(e) = bind_manager.mount_all(&bind_specs).await {
error!("Failed to mount bind mounts: {}", e);
// Unmount the overlay filesystem
mount_handle.unmount().await.unwrap();
std::process::exit(1);
}
}

tokio::select! {
res = handle => res.unwrap(),
res = &mut mount_handle => {
if let Err(e) = res {
error!("Overlay filesystem error: {:?}", e);
}
info!("Cleaning up...");
// Unmount bind mounts first
if let Err(e) = bind_manager.unmount_all().await {
error!("Failed to unmount bind mounts: {}", e);
}
},
_ = signal::ctrl_c() => {
mount_handle.unmount().await.unwrap();
info!("Received SIGINT signal, cleaning up...");
// Unmount bind mounts first
if let Err(e) = bind_manager.unmount_all().await {
error!("Failed to unmount bind mounts: {}", e);
}
// Then unmount the overlay filesystem
if let Err(e) = mount_handle.unmount().await {
error!("Failed to unmount overlay filesystem: {}", e);
}
}
_ = async {
use tokio::signal::unix::{signal, SignalKind};
let mut term = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM handler");
term.recv().await
} => {
info!("Received SIGTERM signal, cleaning up...");
// Unmount bind mounts first
if let Err(e) = bind_manager.unmount_all().await {
error!("Failed to unmount bind mounts: {}", e);
}
// Then unmount the overlay filesystem
if let Err(e) = mount_handle.unmount().await {
error!("Failed to unmount overlay filesystem: {}", e);
}
}
}
}
77 changes: 73 additions & 4 deletions project/libfuse-fs/examples/passthrough.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ use clap::Parser;
use libfuse_fs::passthrough::{
PassthroughArgs, new_passthroughfs_layer, newlogfs::LoggingFileSystem,
};
use libfuse_fs::util::bind_mount::{BindMount, BindMountManager};
use rfuse3::{MountOptions, raw::Session};
use std::ffi::OsString;
use tokio::signal;
use tracing::debug;
use tracing::{debug, info, error};

#[derive(Parser, Debug)]
#[command(
Expand All @@ -32,6 +33,9 @@ struct Args {
options: Option<String>,
#[arg(long)]
allow_other: bool,
/// Bind mounts in format "source:target" (repeatable)
#[arg(long = "bind")]
bind_mounts: Vec<String>,
}

fn set_log() {
Expand All @@ -48,6 +52,24 @@ async fn main() {
set_log();
debug!("Starting passthrough filesystem with args: {:?}", args);

// Parse bind mounts
let bind_specs: Result<Vec<BindMount>, _> = args
.bind_mounts
.iter()
.map(|s| BindMount::parse(s))
.collect();

let bind_specs = match bind_specs {
Ok(specs) => specs,
Err(e) => {
error!("Failed to parse bind mount specifications: {}", e);
std::process::exit(1);
}
};

// Create bind mount manager
let bind_manager = BindMountManager::new(&args.mountpoint);

let fs = new_passthroughfs_layer(PassthroughArgs {
root_dir: args.rootdir,
mapping: args.options,
Expand Down Expand Up @@ -81,11 +103,58 @@ async fn main() {
.expect("Privileged mount failed")
};

let handle = &mut mount_handle;
// Mount bind mounts after the passthrough filesystem is mounted
if !bind_specs.is_empty() {
info!("Cleaning up any existing bind mounts from previous runs...");
if let Err(e) = bind_manager.cleanup_existing_mounts(&bind_specs).await {
error!("Failed to cleanup existing mounts: {}", e);
}

info!("Mounting {} bind mount(s)", bind_specs.len());
if let Err(e) = bind_manager.mount_all(&bind_specs).await {
error!("Failed to mount bind mounts: {}", e);
// Unmount the passthrough filesystem
mount_handle.unmount().await.unwrap();
std::process::exit(1);
}
}

tokio::select! {
res = handle => res.unwrap(),
res = &mut mount_handle => {
if let Err(e) = res {
error!("Passthrough filesystem error: {:?}", e);
}
info!("Cleaning up...");
// Unmount bind mounts first
if let Err(e) = bind_manager.unmount_all().await {
error!("Failed to unmount bind mounts: {}", e);
}
},
_ = signal::ctrl_c() => {
mount_handle.unmount().await.unwrap();
info!("Received SIGINT signal, cleaning up...");
// Unmount bind mounts first
if let Err(e) = bind_manager.unmount_all().await {
error!("Failed to unmount bind mounts: {}", e);
}
// Then unmount the passthrough filesystem
if let Err(e) = mount_handle.unmount().await {
error!("Failed to unmount passthrough filesystem: {}", e);
}
}
_ = async {
use tokio::signal::unix::{signal, SignalKind};
let mut term = signal(SignalKind::terminate()).expect("Failed to setup SIGTERM handler");
term.recv().await
} => {
info!("Received SIGTERM signal, cleaning up...");
// Unmount bind mounts first
if let Err(e) = bind_manager.unmount_all().await {
error!("Failed to unmount bind mounts: {}", e);
}
// Then unmount the passthrough filesystem
if let Err(e) = mount_handle.unmount().await {
error!("Failed to unmount passthrough filesystem: {}", e);
}
}
}
}
2 changes: 1 addition & 1 deletion project/libfuse-fs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub mod overlayfs;
pub mod passthrough;
mod server;
pub mod unionfs;
mod util;
pub mod util;

// Test utilities (only compiled during tests)
#[cfg(test)]
Expand Down
Loading