Skip to content
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

Virtual fs refactor #4298

Open
wants to merge 65 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
3446ebe
Refactored files and fs
syrusakbary Nov 7, 2023
7ebdd61
Added NativeFS
syrusakbary Nov 7, 2023
d0bc9e7
Fixed hostfs naming
syrusakbary Nov 7, 2023
22f9f30
Make native use clean_safely for Paths
syrusakbary Nov 7, 2023
1a4b5c4
Fix linting and formatting
syrusakbary Nov 7, 2023
cd7e98b
More linting fixes
syrusakbary Nov 7, 2023
c2d2c38
Improved errors a bit further
syrusakbary Nov 7, 2023
e4785c5
Added new union fs
syrusakbary Nov 8, 2023
5cb8d10
Remove memory fs from WebC
syrusakbary Nov 8, 2023
b911ee4
Simplified webc implementation
syrusakbary Nov 8, 2023
3a6f6bf
Fixed overflow
syrusakbary Nov 8, 2023
09a300d
Fix linting
syrusakbary Nov 8, 2023
55b5a38
Improved a bit the codebase
syrusakbary Nov 9, 2023
31ebe2d
Fixed virtual-fs implementation
syrusakbary Nov 9, 2023
db392b0
Fixed running
syrusakbary Nov 10, 2023
b4b05f4
Fixed new union
syrusakbary Nov 10, 2023
e9749ae
Merge branch 'master' into virtual-fs-refactor
syrusakbary Nov 10, 2023
e7d4cc9
Replace the UnionFS
syrusakbary Nov 10, 2023
0d75a8d
Replace HostFs completely
syrusakbary Nov 10, 2023
a2116ac
Small fixes (including fixing lint)
syrusakbary Nov 10, 2023
18de2d3
Improved union
syrusakbary Nov 10, 2023
c855ef3
Fix union
syrusakbary Nov 10, 2023
8361c6b
Remove unused code
syrusakbary Nov 10, 2023
b3b66d6
Added current_dir to wasi runner
syrusakbary Nov 10, 2023
5e52097
Use dashmap in the workspace
syrusakbary Nov 10, 2023
ec0c871
Removed all dependency hacks
syrusakbary Nov 10, 2023
19140cc
Improved package fetching
syrusakbary Nov 10, 2023
dd875df
Remove unused function
syrusakbary Nov 11, 2023
4e4fe92
Removed a lot of unused code
syrusakbary Nov 11, 2023
5d0ce2e
Move things into workspace
syrusakbary Nov 11, 2023
6d2e724
Remove union_fs (can be easily achieved with memfs)
syrusakbary Nov 11, 2023
fd1fc4c
Fix use in simple wasm modules
syrusakbary Nov 11, 2023
093fa8f
Most tests now fully work
syrusakbary Nov 11, 2023
dd78a69
Removed more unused stuff. Fixed linting
syrusakbary Nov 11, 2023
551f8b5
Merge branch 'master' into virtual-fs-refactor
syrusakbary Nov 11, 2023
cbd6bdf
Improved overlay fs
syrusakbary Nov 11, 2023
3760628
Introduced directory trait
syrusakbary Nov 11, 2023
c33a895
More refactors
syrusakbary Nov 12, 2023
1162406
More fixes and improvements
syrusakbary Nov 12, 2023
daac7fe
Updated cargo
syrusakbary Nov 12, 2023
ef2b31d
Added a unique_id to the VirtualFile and Directory
syrusakbary Nov 13, 2023
a2a4655
Removed ArcFile
syrusakbary Nov 13, 2023
751cbe9
Almost there
syrusakbary Nov 13, 2023
c24da83
Fixed iterator
syrusakbary Nov 13, 2023
ec984b6
Removed FallbackFileSystem
syrusakbary Nov 13, 2023
6e3b544
Fixed a few things on virtual-fs
syrusakbary Nov 13, 2023
850e318
Removed passthru fs from testing
syrusakbary Nov 14, 2023
23e0bbd
More improvements on the virtual fs
syrusakbary Nov 14, 2023
850dac7
WASIX code is now compiling (but doesn’t work)
syrusakbary Nov 14, 2023
68e954a
Improved a bit the tests
syrusakbary Nov 17, 2023
b48bff5
Implemented much improvements in virtual-fs
syrusakbary Nov 18, 2023
892124d
More improvements on virtualfs
syrusakbary Nov 20, 2023
1683b95
Revert "WASIX code is now compiling (but doesn’t work)"
syrusakbary Nov 21, 2023
6593691
Fix chdir
syrusakbary Nov 22, 2023
183ad55
Merge branch 'master' into virtual-fs-refactor
syrusakbary Nov 22, 2023
5eebbb7
Multiple lint fixes
syrusakbary Nov 22, 2023
6873c0f
Fix python
syrusakbary Nov 22, 2023
d6b0ee0
Fixed small bugs
syrusakbary Nov 22, 2023
9e8e0b8
Use latest webc package
syrusakbary Nov 22, 2023
41a071f
Fixed mounting
syrusakbary Nov 22, 2023
7da34d5
Fix tests
syrusakbary Nov 22, 2023
5fb577f
Fix overlay test
syrusakbary Nov 22, 2023
239c322
Removed union fs wast tests
syrusakbary Nov 22, 2023
03c9517
Fixed WASIX envs
syrusakbary Nov 24, 2023
2b766e8
Added wasi.fyi tests
syrusakbary Nov 24, 2023
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
4 changes: 2 additions & 2 deletions lib/c-api/src/wasm_c_api/wasi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use std::sync::Arc;
#[cfg(feature = "webc_runner")]
use wasmer_api::{AsStoreMut, Imports, Module};
use wasmer_wasix::{
default_fs_backing, get_wasi_version,
get_wasi_version,
runtime::task_manager::{tokio::TokioTaskManager, InlineWaker},
virtual_fs::AsyncReadExt,
virtual_fs::VirtualFile,
Expand Down Expand Up @@ -55,7 +55,7 @@ pub unsafe extern "C" fn wasi_config_new(
inherit_stdout: true,
inherit_stderr: true,
inherit_stdin: true,
builder: WasiEnv::builder(prog_name).fs(default_fs_backing()),
builder: WasiEnv::builder(prog_name),
runtime: Some(runtime),
}))
}
Expand Down
7 changes: 4 additions & 3 deletions lib/cli/src/commands/run/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,12 +228,13 @@ impl Run {
) -> Result<(), Error> {
let mut runner = wasmer_wasix::runners::wcgi::WcgiRunner::new();

let root_fs = self.wasi.get_fs()?;
runner
.config()
.args(self.args.clone())
.addr(self.wcgi.addr)
.envs(self.wasi.env_vars.clone())
.map_directories(self.wasi.mapped_dirs.clone())
.with_fs(root_fs)
.callbacks(Callbacks::new(self.wcgi.addr))
.inject_packages(uses);
*runner.config().capabilities() = self.wasi.capabilities();
Expand Down Expand Up @@ -298,8 +299,8 @@ impl Run {
.with_args(&self.args)
.with_injected_packages(packages)
.with_envs(self.wasi.env_vars.clone())
.with_fs(self.wasi.get_fs()?)
.with_mapped_host_commands(self.wasi.build_mapped_commands()?)
.with_mapped_directories(self.wasi.build_mapped_directories()?)
.with_forward_host_env(self.wasi.forward_host_env)
.with_capabilities(self.wasi.capabilities());

Expand All @@ -316,7 +317,7 @@ impl Run {
) -> Result<(), Error> {
let program_name = wasm_path.display().to_string();

let runner = self.build_wasi_runner(&runtime)?;
let mut runner = self.build_wasi_runner(&runtime)?;
runner.run_wasm(
runtime,
&program_name,
Expand Down
234 changes: 61 additions & 173 deletions lib/cli/src/commands/run/wasi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ use bytes::Bytes;
use clap::Parser;
use tokio::runtime::Handle;
use url::Url;
use virtual_fs::{DeviceFile, FileSystem, PassthruFileSystem, RootFileSystemBuilder};
use virtual_fs::host_fs::FileSystem as HostFileSystem;
use virtual_fs::{DeviceFile, FileSystem, RootFileSystemBuilder};
use wasmer::{Engine, Function, Instance, Memory32, Memory64, Module, RuntimeError, Store, Value};
use wasmer_registry::wasmer_env::WasmerEnv;
use wasmer_wasix::{
bin_factory::BinaryPackage,
capabilities::Capabilities,
default_fs_backing, get_wasi_versions,
get_wasi_versions,
http::HttpClient,
os::{tty_sys::SysTty, TtyBridge},
rewind_ext,
Expand Down Expand Up @@ -125,7 +126,7 @@ pub struct RunProperties {

#[allow(dead_code)]
impl Wasi {
const MAPPED_CURRENT_DIR_DEFAULT_PATH: &'static str = "/mnt/host";
const MAPPED_CURRENT_DIR_DEFAULT_PATH: &'static str = "/home";

pub fn map_dir(&mut self, alias: &str, target_on_disk: PathBuf) {
self.mapped_dirs.push(MappedDirectory {
Expand Down Expand Up @@ -193,115 +194,13 @@ impl Wasi {
.map_commands(map_commands);

let mut builder = {
// If we preopen anything from the host then shallow copy it over
let root_fs = RootFileSystemBuilder::new()
.with_tty(Box::new(DeviceFile::new(__WASI_STDIN_FILENO)))
.build();

let mut mapped_dirs = Vec::new();

// Process the --dirs flag and merge it with --mapdir.
let mut have_current_dir = false;
for dir in &self.pre_opened_directories {
let mapping = if dir == Path::new(".") {
if have_current_dir {
bail!("Cannot pre-open the current directory twice: --dir=. must only be specified once");
}
have_current_dir = true;

let current_dir =
std::env::current_dir().context("could not determine current directory")?;

MappedDirectory {
host: current_dir,
guest: Self::MAPPED_CURRENT_DIR_DEFAULT_PATH.to_string(),
}
} else {
let resolved = dir.canonicalize().with_context(|| {
format!(
"could not canonicalize path for argument '--dir {}'",
dir.display()
)
})?;

if &resolved != dir {
bail!(
"Invalid argument '--dir {}': path must either be absolute, or '.'",
dir.display(),
);
}

let guest = resolved
.to_str()
.with_context(|| {
format!(
"invalid argument '--dir {}': path must be valid utf-8",
dir.display(),
)
})?
.to_string();

MappedDirectory {
host: resolved,
guest,
}
};

mapped_dirs.push(mapping);
}

for MappedDirectory { host, guest } in &self.mapped_dirs {
let resolved_host = host.canonicalize().with_context(|| {
format!(
"could not canonicalize path for argument '--mapdir {}:{}'",
host.display(),
guest,
)
})?;

let mapping = if guest == "." {
if have_current_dir {
bail!("Cannot pre-open the current directory twice: '--mapdir=?:.' / '--dir=.' must only be specified once");
}
have_current_dir = true;

MappedDirectory {
host: resolved_host,
guest: Self::MAPPED_CURRENT_DIR_DEFAULT_PATH.to_string(),
}
} else {
MappedDirectory {
host: resolved_host,
guest: guest.clone(),
}
};
mapped_dirs.push(mapping);
}

if !mapped_dirs.is_empty() {
let fs_backing: Arc<dyn FileSystem + Send + Sync> =
Arc::new(PassthruFileSystem::new(default_fs_backing()));
for MappedDirectory { host, guest } in self.mapped_dirs.clone() {
let host = if !host.is_absolute() {
Path::new("/").join(host)
} else {
host
};
root_fs.mount(guest.into(), &fs_backing, host)?;
}
}

let root_fs = self.get_fs()?;
// Open the root of the new filesystem
let b = builder
.sandbox_fs(root_fs)
.preopen_dir(Path::new("/"))
.unwrap();

if have_current_dir {
b.map_dir(".", Self::MAPPED_CURRENT_DIR_DEFAULT_PATH)?
} else {
b.map_dir(".", "/")?
}
b
};

*builder.capabilities_mut() = self.capabilities();
Expand All @@ -317,85 +216,74 @@ impl Wasi {
Ok(builder)
}

pub fn build_mapped_directories(&self) -> Result<Vec<MappedDirectory>, anyhow::Error> {
let mut mapped_dirs = Vec::new();

// Process the --dirs flag and merge it with --mapdir.
let mut have_current_dir = false;
for dir in &self.pre_opened_directories {
let mapping = if dir == Path::new(".") {
if have_current_dir {
bail!("Cannot pre-open the current directory twice: --dir=. must only be specified once");
}
have_current_dir = true;

let current_dir =
std::env::current_dir().context("could not determine current directory")?;

MappedDirectory {
host: current_dir,
guest: Self::MAPPED_CURRENT_DIR_DEFAULT_PATH.to_string(),
}
} else {
let resolved = dir.canonicalize().with_context(|| {
format!(
"could not canonicalize path for argument '--dir {}'",
dir.display()
)
})?;

if &resolved != dir {
bail!(
"Invalid argument '--dir {}': path must either be absolute, or '.'",
dir.display(),
);
}

let guest = resolved
.to_str()
.with_context(|| {
format!(
"invalid argument '--dir {}': path must be valid utf-8",
dir.display(),
pub fn get_fs(&self) -> Result<virtual_fs::TmpFileSystem> {
// If we preopen anything from the host then shallow copy it over
let root_fs = RootFileSystemBuilder::new()
.with_tty(Box::new(DeviceFile::new(__WASI_STDIN_FILENO)))
.build();
let mut mapped_dirs = self.build_mapped_directories()?;
if !mapped_dirs.is_empty() {
for MappedDirectory { host, guest } in mapped_dirs {
let native_fs = HostFileSystem::new(host.canonicalize()?)?;
let fs: Arc<dyn virtual_fs::FileSystem + Send + Sync + 'static> =
Arc::new(native_fs);
root_fs
.mount(guest.clone().into(), &fs, PathBuf::new())
.map_err(|_e| {
anyhow!(
"There has been a collision. \nA folder might be already mounted in {} or it's parent.",
guest
)
})?
.to_string();
.context(format!(
"Could not mount {} in {}",
host.display(),
guest
))
})?;
}
}
Ok(root_fs)
}

MappedDirectory {
host: resolved,
guest,
}
};
fn build_mapped_directories(&self) -> Result<Vec<MappedDirectory>> {
let mut mapped_dirs = Vec::new();

mapped_dirs.push(mapping);
// Process the --dirs flag and merge it with --mapdir flag.
for dir in &self.pre_opened_directories {
if !dir.is_relative() {
bail!(
"Invalid argument '--dir {}': path must be relative",
dir.display(),
);
}
let guest = PathBuf::from(Self::MAPPED_CURRENT_DIR_DEFAULT_PATH)
.join(dir)
.display()
.to_string();
let host = dir.canonicalize().with_context(|| {
format!(
"could not canonicalize path for argument '--dir {}'",
dir.display()
)
})?;
mapped_dirs.push(MappedDirectory { host, guest });
}

// Process the --mapdir flag.
for MappedDirectory { host, guest } in &self.mapped_dirs {
let resolved_host = host.canonicalize().with_context(|| {
let host = host.canonicalize().with_context(|| {
format!(
"could not canonicalize path for argument '--mapdir {}:{}'",
host.display(),
guest,
)
})?;
let guest = PathBuf::from(Self::MAPPED_CURRENT_DIR_DEFAULT_PATH)
.join(guest)
.display()
.to_string();

let mapping = if guest == "." {
if have_current_dir {
bail!("Cannot pre-open the current directory twice: '--mapdir=?:.' / '--dir=.' must only be specified once");
}
have_current_dir = true;

MappedDirectory {
host: resolved_host,
guest: Self::MAPPED_CURRENT_DIR_DEFAULT_PATH.to_string(),
}
} else {
MappedDirectory {
host: resolved_host,
guest: guest.clone(),
}
};
mapped_dirs.push(mapping);
mapped_dirs.push(MappedDirectory { host, guest });
}

Ok(mapped_dirs)
Expand Down
3 changes: 2 additions & 1 deletion lib/virtual-fs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ tokio = { version = "1", features = ["io-util", "rt"], default_features = false

[features]
default = ["host-fs", "webc-fs", "static-fs"]
host-fs = ["libc", "fs_extra", "filetime", "tokio/fs", "tokio/io-std", "tokio/rt"]
host-fs = ["libc", "fs_extra", "filetime", "tokio/fs", "tokio/io-std", "tokio/rt", "native-fs"]
native-fs = ["libc", "fs_extra", "filetime", "tokio/fs", "tokio/io-std", "tokio/rt"]
webc-fs = ["webc", "anyhow"]
static-fs = ["webc", "anyhow"]
enable-serde = ["typetag"]
Expand Down
Loading