use secure_exec_kernel::mount_plugin::{
FileSystemPluginFactory, OpenFileSystemPluginRequest, PluginError,
};
use secure_exec_kernel::mount_table::MountedFileSystem;
use secure_exec_vfs::{FileBlockStore, SqliteMetadataStore};
use serde::Deserialize;
use vfs::adapter::MountedEngineFileSystem;
use vfs::engine::engines::{ChunkedFs, ChunkedFsOptions};
use vfs::engine::CachedMetadataStore;
const DEFAULT_METADATA_CACHE_ENTRIES: usize = 4096;
#[derive(Debug, Clone, Deserialize)]
#[serde(rename_all = "camelCase")]
struct ChunkedLocalMountConfig {
metadata_path: String,
block_root: String,
chunk_size: Option<u32>,
inline_threshold: Option<usize>,
uid: Option<u32>,
gid: Option<u32>,
file_mode: Option<u32>,
dir_mode: Option<u32>,
metadata_cache_entries: Option<usize>,
}
#[derive(Debug)]
pub(crate) struct ChunkedLocalMountPlugin;
impl<Context> FileSystemPluginFactory<Context> for ChunkedLocalMountPlugin {
fn plugin_id(&self) -> &'static str {
"chunked_local"
}
fn open(
&self,
request: OpenFileSystemPluginRequest<'_, Context>,
) -> Result<Box<dyn MountedFileSystem>, PluginError> {
let config: ChunkedLocalMountConfig = serde_json::from_value(request.config.clone())
.map_err(|error| PluginError::invalid_input(error.to_string()))?;
if config.metadata_path.trim().is_empty() {
return Err(PluginError::invalid_input(
"chunked_local mount requires metadataPath",
));
}
if config.block_root.trim().is_empty() {
return Err(PluginError::invalid_input(
"chunked_local mount requires blockRoot",
));
}
let chunk_size = config.chunk_size.unwrap_or(vfs::engine::DEFAULT_CHUNK_SIZE);
if chunk_size == 0 {
return Err(PluginError::invalid_input(
"chunked_local mount requires chunkSize to be greater than zero",
));
}
let inline_threshold = config
.inline_threshold
.unwrap_or(vfs::engine::DEFAULT_INLINE_THRESHOLD);
if inline_threshold > chunk_size as usize {
return Err(PluginError::invalid_input(
"chunked_local mount requires inlineThreshold to be less than or equal to chunkSize",
));
}
let metadata = SqliteMetadataStore::open(config.metadata_path)
.map_err(|error| PluginError::new(error.code(), error.message().to_owned()))?;
let metadata = CachedMetadataStore::new(
metadata,
config
.metadata_cache_entries
.unwrap_or(DEFAULT_METADATA_CACHE_ENTRIES),
);
let blocks = FileBlockStore::new(config.block_root)
.map_err(|error| PluginError::new(error.code(), error.message().to_owned()))?;
let fs = ChunkedFs::with_options(
metadata,
blocks,
ChunkedFsOptions {
inline_threshold,
chunk_size,
uid: config.uid.unwrap_or(0),
gid: config.gid.unwrap_or(0),
file_mode: config.file_mode.unwrap_or(0o644),
dir_mode: config.dir_mode.unwrap_or(0o755),
},
);
Ok(Box::new(MountedEngineFileSystem::new(fs)?))
}
}