From 81eb1055c06418f756e12d35b03bbf4fd54aae9a Mon Sep 17 00:00:00 2001 From: zjregee Date: Sat, 24 Aug 2024 22:05:14 +0800 Subject: [PATCH] feat: change cmd entrance --- .github/workflows/behavior_test.yml | 4 +- Cargo.lock | 110 ++++++++++++++++++++-------- Cargo.toml | 10 ++- README.md | 17 +++-- src/filesystem.rs | 20 ++++- src/main.rs | 73 +++++++++--------- 6 files changed, 149 insertions(+), 85 deletions(-) diff --git a/.github/workflows/behavior_test.yml b/.github/workflows/behavior_test.yml index 112c118..bbc8f10 100644 --- a/.github/workflows/behavior_test.yml +++ b/.github/workflows/behavior_test.yml @@ -18,8 +18,8 @@ jobs: - name: Run Behavior Test env: - KIND: fs - ROOT: ${{ github.workspace }}/.github/scripts + OVFS_SOCKET_PATH: /tmp/vfsd.sock + OVFS_BACKEND: fs://?root=${{ github.workspace }}/.github/scripts run: | cargo run --manifest-path ../../Cargo.toml --release & chmod +x ./install_and_run_vm.sh diff --git a/Cargo.lock b/Cargo.lock index bccb70f..6667882 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,9 +58,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" @@ -211,6 +211,46 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "clap" +version = "4.5.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + [[package]] name = "colorchoice" version = "1.0.1" @@ -316,9 +356,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.3" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" dependencies = [ "anstream", "anstyle", @@ -727,13 +767,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -745,16 +786,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "object" version = "0.32.2" @@ -772,9 +803,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opendal" -version = "0.47.3" +version = "0.49.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac4826fe3d5482a49b92955b0f6b06ce45b46ec84484176588209bfbf996870" +checksum = "ba615070686c8781ce97376fdafca29d7c42f47b31d2230d7c8c1642ec823950" dependencies = [ "anyhow", "async-trait", @@ -791,7 +822,7 @@ dependencies = [ "md-5", "once_cell", "percent-encoding", - "quick-xml", + "quick-xml 0.36.1", "reqsign", "reqwest", "serde", @@ -816,6 +847,7 @@ version = "0.1.0" dependencies = [ "anyhow", "bitflags 1.3.2", + "clap", "env_logger", "futures", "libc", @@ -824,6 +856,7 @@ dependencies = [ "sharded-slab", "snafu", "tokio", + "url", "vhost", "vhost-user-backend", "virtio-bindings", @@ -887,9 +920,19 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.31.0" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86e446ed58cef1bbfe847bc2fda0e2e4ea9f0e57b90c507d4781292590d72a4e" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "quick-xml" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +checksum = "96a05e2e8efddfa51a84ca47cec303fac86c8541b686d37cac5efc0e094417bc" dependencies = [ "memchr", "serde", @@ -965,9 +1008,9 @@ checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqsign" -version = "0.15.2" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70fe66d4cd0b5ed9b1abbfe639bf6baeaaf509f7da2d51b31111ba945be59286" +checksum = "03dd4ba7c3901dd43e6b8c7446a760d45bc1ea4301002e1a6fa48f97c3a796fa" dependencies = [ "anyhow", "async-trait", @@ -981,7 +1024,7 @@ dependencies = [ "http", "log", "percent-encoding", - "quick-xml", + "quick-xml 0.35.0", "rand", "reqwest", "rust-ini", @@ -1254,6 +1297,12 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" version = "2.5.0" @@ -1323,18 +1372,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.39.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "pin-project-lite", "socket2", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1456,9 +1504,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", diff --git a/Cargo.toml b/Cargo.toml index 4a19659..a6d54c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,14 +6,16 @@ edition = "2021" [dependencies] anyhow = { version = "1.0.86", features = ["std"] } bitflags = "1.2" -env_logger = "0.11.3" +clap = { version = "4.5.16", features = ["derive", "env"] } +env_logger = "0.11.5" futures = "0.3.30" libc = "0.2.139" log = "0.4.22" -opendal = { version = "0.47.3", features = ["services-fs", "services-s3"] } +opendal = { version = "0.49.1", features = ["services-fs", "services-s3"] } sharded-slab = "0.1.7" -snafu = "0.8.3" -tokio = { version = "1.37.0", features = ["rt-multi-thread"] } +snafu = "0.8.4" +tokio = { version = "1.39.3", features = ["rt-multi-thread"] } +url = "2.5.2" vhost = "0.10.0" vhost-user-backend = "0.13.1" virtio-bindings = { version = "0.2.1", features = ["virtio-v5_0_0"] } diff --git a/README.md b/README.md index d134a5d..2f9c70a 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # OVFS, OpenDAL File System via Virtio -OVFS is a backend implementation of VirtioFS. It provides a filesystem interface for VMs based on [Apache OpenDAL](https://github.com/apache/opendal), aiming to accelerate VMs IO performance by VirtIO and seamlessly connect with various storage backends. +OVFS is a backend implementation of VirtioFS. It provides a filesystem interface for VMs based on [OpenDAL](https://github.com/apache/opendal), aiming to accelerate VMs IO performance by VirtIO and seamlessly connect with various storage backends. ![OVFS Architecture](./docs/proposal/media/architecture.png) @@ -14,15 +14,15 @@ The following components are required: ### Install QEMU and VMs ```shell -sudo apt-get -y qemu # debian/ubuntu +$ sudo apt-get -y qemu # debian/ubuntu ``` Download and install the VM, taking Ubuntu as an example: ```shell -wget https://releases.ubuntu.com/20.04/ubuntu-20.04.6-live-server-amd64.iso -truncate -s 10G image.img -sudo qemu-system-x86_64 -enable-kvm -smp 2 -m 4G \ +$ wget https://releases.ubuntu.com/20.04/ubuntu-20.04.6-live-server-amd64.iso +$ truncate -s 10G image.img +$ sudo qemu-system-x86_64 -enable-kvm -smp 2 -m 4G \ -cdrom ubuntu-20.04.6-live-server-amd64.iso \ -drive file=image.img,format=raw,cache=none,if=virtio \ -boot d @@ -37,15 +37,18 @@ host# cargo run --release ``` `backend-url` is the URL that includes the scheme and parameters of the service used, in the following format: -- fs://?root= + +```markdown +- fs://?root= - s3://?root=&bucket=&endpoint=®ion=&access_key_id=&secret_access_key= +``` Run the VM through QEMU and create a VirtioFS device: ```shell host# sudo qemu-system-x86_64 --enable-kvm -smp 2 \ -m 4G -object memory-backend-file,id=mem,size=4G,mem-path=/dev/shm,share=on -numa node,memdev=mem \ - -chardev socket,id=char0,path=/tmp/vfsd.sock -device vhost-user-fs-pci,queue-size=1024,chardev=char0,tag=myfs \ + -chardev socket,id=char0,path= -device vhost-user-fs-pci,queue-size=1024,chardev=char0,tag= \ -drive file=image.img,format=raw,cache=none,if=virtio \ -net user,hostfwd=tcp::2222-:22 -net nic \ -nographic -boot c diff --git a/src/filesystem.rs b/src/filesystem.rs index 0aae358..e6a9d5e 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -359,8 +359,9 @@ impl Filesystem { None => return Filesystem::reply_error(in_header.unique, w, libc::ENOENT), }; - let mut opened_file_writer = self.opened_files_writer.lock().unwrap(); - opened_file_writer.remove(&path); + if self.rt.block_on(self.do_release_writer(&path)).is_err() { + return Filesystem::reply_error(in_header.unique, w, libc::EIO); + } Filesystem::reply_ok(None::, None, in_header.unique, w) } @@ -792,6 +793,21 @@ impl Filesystem { Ok(()) } + async fn do_release_writer(&self, path: &str) -> Result<()> { + let mut opened_file_writer = self.opened_files_writer.lock().unwrap(); + let inner_writer = opened_file_writer + .get_mut(path) + .ok_or(Error::from(libc::EIO))?; + inner_writer + .writer + .close() + .await + .map_err(|err| Error::from(err))?; + opened_file_writer.remove(path); + + Ok(()) + } + async fn do_delete(&self, path: &str) -> Result<()> { self.core .delete(path) diff --git a/src/main.rs b/src/main.rs index 8aecbb7..c04d9ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,15 @@ -use std::env; use std::io; use std::process::exit; +use std::str::FromStr; use std::sync::Arc; use std::sync::RwLock; +use clap::Parser; use log::error; -use log::info; use log::warn; -use opendal::services::Fs; -use opendal::services::S3; use opendal::Operator; +use opendal::Scheme; +use url::Url; use vhost::vhost_user::message::VhostUserProtocolFeatures; use vhost::vhost_user::message::VhostUserVirtioFeatures; use vhost::vhost_user::Backend; @@ -238,40 +238,38 @@ impl VhostUserBackend for VhostUserFsBackend { } } -fn init_operator() -> Operator { - let kind = env::var("KIND").unwrap(); - if kind == "fs" { - let root = env::var("ROOT").unwrap(); - let mut builder = Fs::default(); - builder.root(&root); - Operator::new(builder) - .expect("failed to build operator") - .finish() - } else { - let bucket = env::var("BUCKET").unwrap(); - let endpoint = env::var("ENDPOINT").unwrap(); - let access_key_id = env::var("ACCESS_KEY_ID").unwrap(); - let secret_access_key = env::var("SECRET_ACCESS_KEY").unwrap(); - let region = env::var("REGION").unwrap(); - let mut builder = S3::default(); - builder.bucket(&bucket); - builder.endpoint(&endpoint); - builder.access_key_id(&access_key_id); - builder.secret_access_key(&secret_access_key); - builder.region(®ion); - Operator::new(builder) - .expect("failed to build operator") - .finish() - } +#[derive(Parser, Debug)] +#[command(version, about)] +struct Config { + #[arg(env = "OVFS_SOCKET_PATH", index = 1)] + socket_path: String, + + #[arg(env = "OVFS_BACKEND", index = 2)] + backend: Url, } fn main() { env_logger::init(); - let socket = "/tmp/vfsd.sock"; - let operator = init_operator(); - let listener = Listener::new(socket, true).unwrap(); - let fs = Filesystem::new(operator); + let cfg = Config::parse(); + if cfg.backend.has_host() { + log::warn!("backend host will be ignored"); + } + + let scheme_str = cfg.backend.scheme(); + let op_args = cfg.backend.query_pairs().into_owned(); + + let scheme = match Scheme::from_str(scheme_str) { + Ok(Scheme::Custom(_)) | Err(_) => { + log::error!("invalid backend scheme: {}", scheme_str); + return; + } + Ok(s) => s, + }; + let backend = Operator::via_iter(scheme, op_args).unwrap(); + + let listener = Listener::new(cfg.socket_path, true).unwrap(); + let fs = Filesystem::new(backend); let fs_backend = Arc::new(VhostUserFsBackend::new(fs).unwrap()); let mut daemon = VhostUserDaemon::new( @@ -282,15 +280,13 @@ fn main() { .unwrap(); if let Err(e) = daemon.start(listener) { - error!("[Main] failed to start daemon: {:?}", e); + error!("failed to start daemon: {:?}", e); exit(1); } - info!("[Main] daemon started"); if let Err(e) = daemon.wait() { - error!("[Main] failed to wait for daemon: {:?}", e); + error!("failed to wait for daemon: {:?}", e); } - info!("[Main] daemon shutdown"); let kill_event_fd = fs_backend .thread @@ -300,7 +296,6 @@ fn main() { .try_clone() .unwrap(); if let Err(e) = kill_event_fd.write(1) { - error!("[Main] failed to shutdown worker thread: {:?}", e); + error!("failed to shutdown worker thread: {:?}", e); } - info!("[Main] worker thread shutdown"); }