diff --git a/clients/filesystem-fuse/src/gvfs_fileset_fs.rs b/clients/filesystem-fuse/src/gvfs_fileset_fs.rs index cd775b0c1a5..d0686f18a2c 100644 --- a/clients/filesystem-fuse/src/gvfs_fileset_fs.rs +++ b/clients/filesystem-fuse/src/gvfs_fileset_fs.rs @@ -21,10 +21,14 @@ use crate::filesystem::{FileStat, FileSystemCapacity, FileSystemContext, PathFil use crate::gravitino_client::GravitinoClient; use crate::opened_file::{OpenFileFlags, OpenedFile}; use async_trait::async_trait; +use fuse3::Errno; use std::path::{Path, PathBuf}; pub(crate) struct GravitinoFileSystemConfig {} +/// GravitinoFileSystem is a filesystem that is associated with a fileset in Gravitino. +/// It mapping the fileset path to the original data storage path. and delegate the operation +/// to the inner filesystem like S3 GCS, JuiceFS. pub(crate) struct GvfsFilesetFs { fs: Box, client: GravitinoClient, @@ -46,12 +50,15 @@ impl GvfsFilesetFs { } } - fn map_to_raw_path(&self, path: &Path) -> PathBuf { - if path == Path::new("/") { - return self.fileset_location.clone(); - } + fn map_fileset_path_to_raw_path(&self, path: &Path) -> PathBuf { self.fileset_location.join(path) } + + fn map_raw_path_to_fileset_path(&self, path: &Path) -> Result { + path.strip_prefix(&self.fileset_location) + .map_err(|_| Errno::from(libc::EBADF))?; + Ok(path.into()) + } } #[async_trait] @@ -61,47 +68,64 @@ impl PathFileSystem for GvfsFilesetFs { } async fn stat(&self, path: &Path) -> Result { - let raw_path = self.map_to_raw_path(path); - self.fs.stat(&raw_path).await + let raw_path = self.map_fileset_path_to_raw_path(path); + let mut file_stat = self.fs.stat(&raw_path).await?; + file_stat.path = self.map_raw_path_to_fileset_path(&file_stat.path)?; + Ok(file_stat) } async fn read_dir(&self, path: &Path) -> Result> { - let raw_path = self.map_to_raw_path(path); - self.fs.read_dir(&raw_path).await + let raw_path = self.map_fileset_path_to_raw_path(path); + let mut child_filestats = self.fs.read_dir(&raw_path).await?; + for file_stat in child_filestats.iter_mut() { + file_stat.path = self.map_raw_path_to_fileset_path(&file_stat.path)?; + } + Ok(child_filestats) } async fn open_file(&self, path: &Path, flags: OpenFileFlags) -> Result { - let raw_path = self.map_to_raw_path(path); - self.fs.open_file(&raw_path, flags).await + let raw_path = self.map_fileset_path_to_raw_path(path); + let mut opened_file = self.fs.open_file(&raw_path, flags).await?; + opened_file.file_stat.path = + self.map_raw_path_to_fileset_path(&opened_file.file_stat.path)?; + Ok(opened_file) } async fn open_dir(&self, path: &Path, flags: OpenFileFlags) -> Result { - let raw_path = self.map_to_raw_path(path); - self.fs.open_dir(&raw_path, flags).await + let raw_path = self.map_fileset_path_to_raw_path(path); + let mut opened_file = self.fs.open_dir(&raw_path, flags).await?; + opened_file.file_stat.path = + self.map_raw_path_to_fileset_path(&opened_file.file_stat.path)?; + Ok(opened_file) } async fn create_file(&self, path: &Path, flags: OpenFileFlags) -> Result { - let raw_path = self.map_to_raw_path(path); - self.fs.create_file(&raw_path, flags).await + let raw_path = self.map_fileset_path_to_raw_path(path); + let mut opened_file = self.fs.create_file(&raw_path, flags).await?; + opened_file.file_stat.path = + self.map_raw_path_to_fileset_path(&opened_file.file_stat.path)?; + Ok(opened_file) } async fn create_dir(&self, path: &Path) -> Result { - let raw_path = self.map_to_raw_path(path); - self.fs.create_dir(&raw_path).await + let raw_path = self.map_fileset_path_to_raw_path(path); + let mut file_stat = self.fs.create_dir(&raw_path).await?; + file_stat.path = self.map_raw_path_to_fileset_path(&file_stat.path)?; + Ok(file_stat) } async fn set_attr(&self, path: &Path, file_stat: &FileStat, flush: bool) -> Result<()> { - let raw_path = self.map_to_raw_path(path); + let raw_path = self.map_fileset_path_to_raw_path(path); self.fs.set_attr(&raw_path, file_stat, flush).await } async fn remove_file(&self, path: &Path) -> Result<()> { - let raw_path = self.map_to_raw_path(path); + let raw_path = self.map_fileset_path_to_raw_path(path); self.fs.remove_file(&raw_path).await } async fn remove_dir(&self, path: &Path) -> Result<()> { - let raw_path = self.map_to_raw_path(path); + let raw_path = self.map_fileset_path_to_raw_path(path); self.fs.remove_dir(&raw_path).await }