Skip to content

[scorpio]: Diff for overlay. draw inode & path (v0.5) . #543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 28, 2024
Merged
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
54 changes: 0 additions & 54 deletions scorpio/src/dicfuse/model.rs
Original file line number Diff line number Diff line change
@@ -1,54 +0,0 @@
use std::fmt::Display;

use serde::{Deserialize, Serialize};
#[derive(Debug,Deserialize, Serialize,Clone,Default)]
pub struct GPath{
path:Vec<String>
}

#[allow(unused)]

impl GPath{
pub fn new() -> GPath{
GPath{
path:Vec::new()
}
}
pub fn push(&mut self, path:String){
self.path.push(path);
}
pub fn name(&self) -> String{
self.path.last().unwrap().clone()
}

}

impl From<String> for GPath{
fn from(mut s: String) -> GPath {
if s.starts_with('/'){
s.remove(0);
}
GPath {
path: s.split('/').map(String::from).collect(),
}
}
}


impl Display for GPath{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.path.join("/"))
}
}

#[cfg(test)]
mod tests{
use super::GPath;

#[test]
fn test_from_string(){
let path = String::from("/release");
let gapth = GPath::from(path);
assert_eq!(gapth.to_string(),String::from("release"))
}
}
2 changes: 1 addition & 1 deletion scorpio/src/dicfuse/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use fuse_backend_rs::api::filesystem::DirEntry;
use crate::fuse::READONLY_INODE;

use super::fuse::{self, default_dic_entry, default_file_entry};
use super::model::GPath;
use crate::util::GPath;
const MEGA_TREE_URL: &str = "localhost:8000";//TODO: make it configable
const UNKNOW_INODE: u64 = 0; // illegal inode number;
const INODE_FILE :&str ="file";
Expand Down
2 changes: 1 addition & 1 deletion scorpio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod overlayfs;
//mod store;
mod fuse;
mod dicfuse;

mod util;

use std::sync::Arc;
use std::io::Result;
Expand Down
70 changes: 44 additions & 26 deletions scorpio/src/overlayfs/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use fuse_backend_rs::api::filesystem::{Context, DirEntry, Entry};
use std::sync::Arc;
use std::{cell::RefCell, io::Result, rc::Rc};
use std::collections::VecDeque;
use crate::util::GPath;

use super::{BoxedLayer, OverlayFs};
#[allow(dead_code)]
pub trait FSdiff {
Expand All @@ -12,69 +14,81 @@ pub trait FSdiff {
#[allow(unused)]
impl FSdiff for OverlayFs{
fn diff(&self) {
println!("root work path :{} mount point :{}",self.config.work, self.config.mountpoint);
let upper = match &self.upper_layer{
Some(a) => a.clone(),
None => return ,
};
let _lower = self.lower_layers.clone();
let ctx= Context::new();
let _upper_inodes = traverse_directory(&ctx, upper);
let upper_inodes = traverse_directory(&ctx, upper).unwrap();
// Traverse all modified nodes and search for corresponding files in the lower level file library
for upder_inode in upper_inodes{

println!("inode:{},path:{}",upder_inode.0, upder_inode.1);
}

}
}
// 用于遍历目录的函数
fn traverse_directory(ctx: &Context, fs: Arc<BoxedLayer>) -> Result<Vec<u64>> {

let buffer_size = 1024;
// traverse a file Dictionary and find all inodes.
fn traverse_directory(ctx: &Context, fs: Arc<BoxedLayer>) -> Result<Vec<(u64,GPath)>> {

let mut entrys_inode = Vec::new();
let buffer_size = 1024;
// return diff inodes
let mut entrys_inode: Vec<(u64, GPath)> = Vec::new();
println!("root ino:{}",fs.root_inode());
let dir_inodes = Rc::new(RefCell::new(VecDeque::from([fs.root_inode()])));

// bfs lookup inodes.
let dir_inodes = Rc::new(RefCell::new(VecDeque::from([(fs.root_inode(), GPath::new())])));
let path = Rc::new(RefCell::new(GPath::new())) ;

let mut add_entry = |entry: DirEntry, e:Entry| -> Result<usize> {
println!("inode:{}, type:{}, name:{} ",entry.ino, entry.type_, std::str::from_utf8(entry.name).unwrap());
entrys_inode.push(e.inode);
let node_name = std::str::from_utf8(entry.name).unwrap().to_string();
println!("inode:{}, type:{}, name:{} ",e.inode, entry.type_, node_name);
let mut gpath = path.borrow().clone();
gpath.push(node_name);
entrys_inode.push((e.inode,gpath.clone()));
if entry.type_ == libc::DT_DIR as u32 {
println!("push dir ino:{}", e.inode);
dir_inodes.borrow_mut().push_back(e.inode);
dir_inodes.borrow_mut().push_back((e.inode,gpath.clone()));
}
Ok(1)
};
while !dir_inodes.borrow().is_empty() {
let mut b= dir_inodes.borrow_mut();
let mut b= dir_inodes.borrow_mut();
let current_inode = b.pop_front().unwrap();
*path.borrow_mut() = current_inode.1;
drop(b);
// 调用 readdir 方法来填充条目
let attrs = fs.getattr(ctx,current_inode,None).unwrap();
println!("inode1:{}, inode2:{}", attrs.0.st_ino, current_inode);
let handle = fs.opendir(ctx, current_inode,100352).unwrap().0;
// call the [readdir] func. to fill
let attrs = fs.getattr(ctx,current_inode.0,None).unwrap();
println!("inode1:{}, inode2:{}", attrs.0.st_ino, current_inode.0);
let handle = fs.opendir(ctx, current_inode.0,100352).unwrap().0;
let result = fs.readdirplus(
ctx,
current_inode,
current_inode.0,
handle.unwrap(),
buffer_size as u32,
0,
&mut add_entry,
);
// 处理 result,更新 offset 或进行其他处理
// deeal with result,update offset or ERROR
match result {
Ok(_) => {
// 可以根据需要更新 offset
// offset = 更新后的 offset;
//pass
}
Err(e) => {
// 处理错误
// ERRER pass
return Err(e);
}
}
}

Ok(entrys_inode)
}


#[cfg(test)]
mod tests{
use std::sync::Arc;
use std::{ffi::CStr, sync::Arc};
use fuse_backend_rs::{abi::fuse_abi::FsOptions, api::filesystem::Context};
use crate::passthrough::new_passthroughfs_layer;
use super::traverse_directory;
Expand All @@ -84,9 +98,13 @@ mod tests{
let fs = new_passthroughfs_layer("/home/luxian/megatest/lower").unwrap();
fs.init(FsOptions::empty()).unwrap();
let ctx = Context::new();
let out = traverse_directory(&ctx,Arc::new(fs)).unwrap();
for ino in out{
println!("inode: {}", ino);
}
let afs = Arc::new(fs);
let _out = traverse_directory(&ctx,afs.clone()).unwrap();

let bytes_with_nul: &[u8] = b".\0";
let cstr = CStr::from_bytes_with_nul(bytes_with_nul).expect("CStr creation failed");
let e = afs.lookup(&ctx, afs.root_inode(),cstr).unwrap();
//afs.readdirplus(ctx, inode, handle, size, offset, add_entry);
println!("{:?}",e)
}
}
15 changes: 6 additions & 9 deletions scorpio/src/overlayfs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ pub type Inode = u64;
pub type Handle = u64;
pub const CURRENT_DIR: &str = ".";
pub const PARENT_DIR: &str = "..";

//type BoxedFileSystem = Box<dyn FileSystem<Inode = Inode, Handle = Handle> + Send + Sync>;
pub type BoxedLayer = Box<dyn Layer<Inode = Inode, Handle = Handle> + Send + Sync>;
const INODE_ALLOC_BATCH:u64 = 0x1_0000_0000;
Expand Down Expand Up @@ -484,7 +483,6 @@ impl OverlayInode {
pub fn new() -> Self {
OverlayInode::default()
}

// Allocate new OverlayInode based on one RealInode,
// inode number is always 0 since only OverlayFs has global unique inode allocator.
pub fn new_from_real_inode(name: &str, ino: u64, path: String, real_inode: RealInode) -> Self {
Expand Down Expand Up @@ -2182,6 +2180,7 @@ mod tests {
use std::{path::Path, thread};

use super::*;
use diff::FSdiff;
use fuse_backend_rs::{api::server::Server, transport::{FuseChannel, FuseSession}};
use super::super::passthrough::passthrough;
use signal_hook::{consts::TERM_SIGNALS, iterator::Signals};
Expand Down Expand Up @@ -2251,15 +2250,13 @@ mod tests {
// Set up test environment
let args = Args {
name: "test_overlay".to_string(),
mountpoint: "/tmp/true_temp".to_string(),
lowerdir: vec!["/tmp/lower".to_string()],
upperdir: "/tmp/upper".to_string(),
workdir: "/tmp/workdir".to_string(),
mountpoint: "/home/luxian/megatest/true_temp".to_string(),
lowerdir: vec!["/home/luxian/megatest/lower".to_string()],
upperdir: "/home/luxian/megatest/upper".to_string(),
workdir: "/home/luxian/megatest/workerdir".to_string(),
log_level: "info".to_string(),
};



// Create lower layers
let mut lower_layers = Vec::new();
for lower in &args.lowerdir {
Expand All @@ -2278,7 +2275,7 @@ mod tests {
let overlayfs = OverlayFs::new(Some(upper_layer), lower_layers, config,1).unwrap();
// Import overlayfs
overlayfs.import().unwrap();

overlayfs.diff();
// Create fuse session
let mut se = FuseSession::new(Path::new(&args.mountpoint), &args.name, "", false).unwrap();
se.mount().unwrap();
Expand Down
54 changes: 54 additions & 0 deletions scorpio/src/util/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use std::fmt::Display;

use serde::{Deserialize, Serialize};
#[derive(Debug,Deserialize, Serialize,Clone,Default)]
pub struct GPath{
pub path:Vec<String>
}

#[allow(unused)]

impl GPath{
pub fn new() -> GPath{
GPath{
path:Vec::new()
}
}
pub fn push(&mut self, path:String){
self.path.push(path);
}
pub fn name(&self) -> String{
self.path.last().unwrap().clone()
}

}

impl From<String> for GPath{
fn from(mut s: String) -> GPath {
if s.starts_with('/'){
s.remove(0);
}
GPath {
path: s.split('/').map(String::from).collect(),
}
}
}


impl Display for GPath{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.path.join("/"))
}
}

#[cfg(test)]
mod tests{
use super::GPath;

#[test]
fn test_from_string(){
let path = String::from("/release");
let gapth = GPath::from(path);
assert_eq!(gapth.to_string(),String::from("release"))
}
}
Loading