Skip to content

Commit

Permalink
Merge pull request #687 from Ivanbeethoven/main
Browse files Browse the repository at this point in the history
[scorpio]: Umount API & some bugsfix
  • Loading branch information
genedna authored Nov 13, 2024
2 parents 3294f70 + e1dda6d commit 1b2f427
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 59 deletions.
76 changes: 59 additions & 17 deletions scorpio/src/deamon/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use crate::manager::fetch::fetch;
use crate::manager::ScorpioManager;
use crate::util::GPath;

const SUCCESS: &str = "Success";
const FAIL : &str = "Fail";

#[derive(Debug, Deserialize, Serialize)]
struct MountRequest {
Expand All @@ -24,8 +26,7 @@ struct MountResponse {
mount: MountInfo,
message: String,
}

#[derive(Debug, Deserialize, Serialize)]
#[derive(Debug, Deserialize, Serialize,Default)]
struct MountInfo {
hash: String,
path: String,
Expand Down Expand Up @@ -91,32 +92,54 @@ pub async fn deamon_main(fuse:Arc<MegaFuse>,manager:ScorpioManager) {
axum::serve(listener, app).await.unwrap()
}

/// Mount a dictionary by path , like "/path/to/dic" or "path/to/dic"
async fn mount_handler(
State(state): State<ScoState>, // 注入共享状态
State(state): State<ScoState>,
req: axum::Json<MountRequest>,
) -> axum::Json<MountResponse> {

// transform by GPath , is case of wrong format.
let mono_path = GPath::from(req.path.clone()).to_string();
let inode = state.fuse.get_inode(&mono_path).await;
// get inode by this path .
let inode = match state.fuse.get_inode(&mono_path).await{
Ok(a) => a,
Err(err) => return axum::Json(MountResponse {
status: FAIL.into(),
mount: MountInfo::default(),
message: format!("Wrong Mono Path.err:{}",err),
}),
};
// return fail if this inode is mounted.
if state.fuse.is_mount(inode).await{
return axum::Json(MountResponse {
status: FAIL.into(),
mount: MountInfo::default(),
message: "The target is mounted.".to_string(),
})
}

let mut ml = state.manager.lock().await;
let store_path = ml.store_path.clone();
// fetch the dionary node info from mono.
let work_dir = fetch(&mut ml,inode, mono_path).await;
let store_path = PathBuf::from(store_path).join(&work_dir.hash);
// checkout / mount this dictionary.
state.fuse.overlay_mount(inode, store_path).await;
// init before user operation.
let _ = state.fuse.init(Request::default()).await;

// 在这里可以访问 state.fuse 或 state.manager
let mount_info = MountInfo{
hash:work_dir.hash,
path: work_dir.path,
inode,
};
axum::Json(MountResponse {
status: "success".to_string(),
status: SUCCESS.into(),
mount: mount_info,
message: "Directory mounted successfully".to_string(),
})
}

/// Get all mounted dictionary .
async fn mounts_handler(State(state): State<ScoState>) -> axum::Json<MountsResponse> {
let manager = state.manager.lock().await;
let re = manager.works.iter().map(|word_dir| MountInfo{
Expand All @@ -127,25 +150,44 @@ async fn mounts_handler(State(state): State<ScoState>) -> axum::Json<MountsRespo


axum::Json(MountsResponse {
status: "success".to_string(),
status: SUCCESS.into(),
mounts: re,
})
}

async fn umount_handler(
State(_state): State<ScoState>,
_req: axum::Json<UmountRequest>,
State(state): State<ScoState>,
req: axum::Json<UmountRequest>,
) -> axum::Json<UmountResponse> {
// 在这里访问 state 进行卸载逻辑
axum::Json(UmountResponse {
status: "success".to_string(),
message: "Directory unmounted successfully".to_string(),
})


let handle;
if let Some(inode) = req.inode{
handle= state.fuse.overlay_umount_byinode(inode).await;
}else if let Some(path) = &req.path{
handle = state.fuse.overlay_umount_bypath(path).await;
}else{
return axum::Json(UmountResponse {
status: FAIL.into(),
message: "Need a inode or path.".to_string(),
})
}
match handle {
Ok(_) => axum::Json(UmountResponse {
status: SUCCESS.into(),
message: "Directory unmounted successfully".to_string(),
}),
Err(err) => axum::Json(UmountResponse {
status: FAIL.into(),
message:format!("Umount process error :{}.",err),
}),
}

}

async fn config_handler(State(state): State<ScoState>) -> axum::Json<ConfigResponse> {
let t = state.manager.lock().await;
// 使用 state 访问配置逻辑

let config_info = ConfigInfo {
mega_url: t.url.clone(),
mount_path: t.mount_path.clone(),
Expand All @@ -154,7 +196,7 @@ async fn config_handler(State(state): State<ScoState>) -> axum::Json<ConfigRespo
drop(t);

axum::Json(ConfigResponse {
status: "success".to_string(),
status: SUCCESS.into(),
config: config_info,
})
}
Expand Down
9 changes: 7 additions & 2 deletions scorpio/src/fuse/async_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,18 @@ use super::MegaFuse;
/// 2. if inodes is a overlay fs root ,find it from the hashmap
/// 3. if inode from one overlay, find it by batch number.
macro_rules! call_fuse_function {

// &self -> MegaFuse::Self
// &func -> fuse_func , like `lookup` ,`init` , 'getattr'....
// $req -> Request
// $inode:expr -> Inode number . almost every func have this arg
// $($args:expr),* -> All other args
($self:ident,$func:ident, $req:expr , $inode:expr, $($args:expr),*) => {
if let Some(ovl_inode) = $self.inodes_alloc.get_ovl_inode($inode/READONLY_INODE).await {
if let Some(ovl_inode_root) = $self.overlayfs.lock().await.get(&ovl_inode){
println!(" overlay child inode root");
ovl_inode_root.$func($req,$inode,$($args),*).await
}else{
panic!("can't find fs by inode");
$self.dic.$func($req,$inode,$($args),*).await
}
}else if let Some(ovl_inode_root) = $self.overlayfs.lock().await.get(&$inode){
println!(" overlay inode root");
Expand All @@ -29,6 +33,7 @@ macro_rules! call_fuse_function {
println!(" readonly inode root");
$self.dic.$func($req,$inode,$($args),*).await
}else{
//TODO : don't panic, return error .
panic!("can't find fs by inode");
}
};
Expand Down
23 changes: 17 additions & 6 deletions scorpio/src/fuse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use inode_alloc::InodeAlloc;
use tokio::sync::Mutex;


use std::{collections::HashMap, path::{Path, PathBuf}, sync::Arc};
use std::{collections::HashMap, io::Error, path::{Path, PathBuf}, sync::Arc};
use crate::{dicfuse::Dicfuse, manager::ScorpioManager, overlayfs::{config, OverlayFs}, passthrough::new_passthroughfs_layer};

mod inode_alloc;
Expand Down Expand Up @@ -83,14 +83,25 @@ impl MegaFuse{
self.overlayfs.lock().await.insert(inode, Arc::new(overlayfs));
}

pub async fn overlay_un_mount<P: AsRef<Path>>(&self, store_path: P) -> std::io::Result<()>{

pub async fn overlay_umount_byinode(&self, inode:u64) -> std::io::Result<()>{
if !self.is_mount(inode).await{
return Err( Error::new(std::io::ErrorKind::NotFound, "Overlay filesystem not mounted"))
}
self.overlayfs.lock().await.remove(&inode);
Ok(())
}

pub async fn get_inode(&self,path:&str) -> u64{
let item = self.dic.store.get_by_path(path).await;
item.unwrap().get_inode()
pub async fn overlay_umount_bypath(&self, path:&str)-> std::io::Result<()>{
let item = self.dic.store.get_by_path(path).await?;
let inode = item.get_inode();
self.overlay_umount_byinode(inode).await
}
pub async fn get_inode(&self,path:&str) ->std::io::Result<u64>{
let item = self.dic.store.get_by_path(path).await?;
Ok(item.get_inode())
}
pub async fn is_mount(&self,inode:u64) -> bool{
self.overlayfs.lock().await.get(&inode).is_some()
}
pub async fn async_init(&self){
self.dic.store.async_import().await;
Expand Down
36 changes: 2 additions & 34 deletions scorpio/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ async fn main() {
manager.check().await;
let fuse_interface = MegaFuse::new_from_manager(&manager).await;

let mountpoint =OsStr::new("/home/luxian/dic") ;
let mountpoint =OsStr::new(&manager.mount_path) ;
let mut mount_handle = mount_filesystem(fuse_interface.clone(), mountpoint).await;
let handle = &mut mount_handle;

Expand All @@ -38,40 +38,8 @@ async fn main() {
tokio::select! {
res = handle => res.unwrap(),
_ = signal::ctrl_c() => {
println!("unmount....");
mount_handle.unmount().await.unwrap()
}
};
// init_runtime( Handle::current() );
// println!("Hello, world!");
// let config_path = "config.toml";
// let mut manager = ScorpioManager::from_toml(config_path).unwrap();
// manager.check().await;
// let fuse_interface = MegaFuse::new_from_manager(&manager);

// //run(fuse_interface.clone(), &manager.mount_path)
// let mut se = FuseSession::new(Path::new(&manager.mount_path), "dic", "", false).unwrap();
// se.mount().unwrap();
// let ch = se.new_channel().unwrap();
// let server = Arc::new(Server::new(fuse_interface.clone()));
// let mut fuse_server = FuseServer { server, ch };
// // Spawn server thread
// let handle = tokio::task::spawn_blocking( move || {
// fuse_server.svc_loop()
// });

// // 在tokio运行时中执行deamon_main函数

// deamon_main(fuse_interface,manager).await;

// // Wait for termination signal
// let mut signals = Signals::new(TERM_SIGNALS).unwrap();
// println!("Signals start");
// if let Some(_sig) = signals.forever().next() {
// //pass
// }
// // Unmount and wake up
// se.umount().unwrap();
// se.wake().unwrap();
// // Join server thread
// let _ = handle.await;
}

1 comment on commit 1b2f427

@vercel
Copy link

@vercel vercel bot commented on 1b2f427 Nov 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

mega – ./

mega-git-main-gitmono.vercel.app
mega-gitmono.vercel.app
www.gitmega.dev
gitmega.dev

Please sign in to comment.