From 6c856acb4baad524e6def1d3381aeded4e491b5a Mon Sep 17 00:00:00 2001 From: "Zhang \"Echaozh\" Yichao" <325050+echaozh@users.noreply.github.com> Date: Thu, 13 Mar 2025 10:28:47 +0800 Subject: [PATCH] Rust binding with an easier to use API (#163) Co-authored-by: Zhang "Echaozh" Yichao --- Cargo.lock | 209 ++++++++++++++++-- Cargo.toml | 5 +- src/lib/api/CMakeLists.txt | 7 + src/lib/api/hf3fs_usrbio.h | 1 + src/lib/rs/hf3fs-usrbio-sys/Cargo.toml | 11 + src/lib/rs/hf3fs-usrbio-sys/README | 1 + src/lib/rs/hf3fs-usrbio-sys/build.rs | 20 ++ src/lib/rs/hf3fs-usrbio-sys/src/lib.rs | 279 +++++++++++++++++++++++++ 8 files changed, 512 insertions(+), 21 deletions(-) create mode 100644 src/lib/rs/hf3fs-usrbio-sys/Cargo.toml create mode 100644 src/lib/rs/hf3fs-usrbio-sys/README create mode 100644 src/lib/rs/hf3fs-usrbio-sys/build.rs create mode 100644 src/lib/rs/hf3fs-usrbio-sys/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 04e0f05..b1d448e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -139,9 +139,29 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash", + "rustc-hash 1.1.0", "shlex", - "syn 2.0.90", + "syn 2.0.100", +] + +[[package]] +name = "bindgen" +version = "0.71.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" +dependencies = [ + "bitflags 2.6.0", + "cexpr", + "clang-sys", + "itertools 0.12.1", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 2.1.1", + "shlex", + "syn 2.0.100", ] [[package]] @@ -344,7 +364,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -485,7 +505,7 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -498,7 +518,7 @@ dependencies = [ "codespan-reporting", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -516,7 +536,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -562,7 +582,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -607,7 +627,19 @@ checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets", ] [[package]] @@ -668,6 +700,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" +[[package]] +name = "hf3fs-usrbio-sys" +version = "0.1.0" +dependencies = [ + "bindgen 0.71.1", + "shared_memory", + "uuid", +] + [[package]] name = "iana-time-zone" version = "0.1.61" @@ -795,7 +836,7 @@ version = "0.16.0+8.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce3d60bc059831dc1c83903fb45c103f75db65c5a7bf22272764d9cc683e348c" dependencies = [ - "bindgen", + "bindgen 0.69.5", "bzip2-sys", "cc", "glob", @@ -872,12 +913,34 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags 1.3.2", + "cc", + "cfg-if", + "libc", + "memoffset", +] + [[package]] name = "nix" version = "0.29.0" @@ -1011,6 +1074,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "prettyplease" +version = "0.2.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1ccf34da56fc294e7d4ccf69a85992b7dfb826b7cf57bac6a70bba3494cc08a" +dependencies = [ + "proc-macro2", + "syn 2.0.100", +] + [[package]] name = "proc-macro-crate" version = "3.2.0" @@ -1089,7 +1162,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom", + "getrandom 0.2.15", ] [[package]] @@ -1175,6 +1248,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustc_version" version = "0.4.1" @@ -1259,7 +1338,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -1292,6 +1371,19 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared_memory" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba8593196da75d9dc4f69349682bd4c2099f8cde114257d1ef7ef1b33d1aba54" +dependencies = [ + "cfg-if", + "libc", + "nix 0.23.2", + "rand", + "win-sys", +] + [[package]] name = "shlex" version = "1.3.0" @@ -1359,9 +1451,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" dependencies = [ "proc-macro2", "quote", @@ -1416,7 +1508,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -1550,7 +1642,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] @@ -1608,7 +1700,7 @@ version = "0.1.0" dependencies = [ "chrono", "libc", - "nix", + "nix 0.29.0", "scopeguard 0.3.3", "serde", "serde_json", @@ -1643,6 +1735,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" +dependencies = [ + "getrandom 0.3.1", +] + [[package]] name = "valuable" version = "0.1.0" @@ -1683,6 +1784,15 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "wasm-bindgen" version = "0.2.97" @@ -1705,7 +1815,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", "wasm-bindgen-shared", ] @@ -1727,7 +1837,7 @@ checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -1748,6 +1858,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "win-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b7b128a98c1cfa201b09eb49ba285887deb3cbe7466a98850eb1adabb452be5" +dependencies = [ + "windows", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1779,6 +1898,19 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45296b64204227616fdbf2614cefa4c236b98ee64dfaaaa435207ed99fe7829f" +dependencies = [ + "windows_aarch64_msvc 0.34.0", + "windows_i686_gnu 0.34.0", + "windows_i686_msvc 0.34.0", + "windows_x86_64_gnu 0.34.0", + "windows_x86_64_msvc 0.34.0", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -1849,6 +1981,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -1861,6 +1999,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -1879,6 +2023,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -1891,6 +2041,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -1915,6 +2071,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -1936,6 +2098,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -1954,7 +2125,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.100", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 32b37e4..3e190c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,8 @@ [workspace] members = [ "src/client/trash_cleaner", - "src/storage/chunk_engine" + "src/storage/chunk_engine", + "src/lib/rs/hf3fs-usrbio-sys" ] resolver = "2" @@ -9,7 +10,7 @@ resolver = "2" authors = ["dev "] edition = "2021" license = "MIT" -rust-version = "1.75.0" # MSRV +rust-version = "1.85.0" # MSRV [profile.release-cmake] debug = true diff --git a/src/lib/api/CMakeLists.txt b/src/lib/api/CMakeLists.txt index b681623..a385736 100644 --- a/src/lib/api/CMakeLists.txt +++ b/src/lib/api/CMakeLists.txt @@ -1,2 +1,9 @@ target_add_lib(hf3fs_api client-lib-common storage-client numa rt) target_add_shared_lib(hf3fs_api_shared client-lib-common storage-client numa rt) + +add_custom_command( + TARGET hf3fs_api_shared + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E create_symlink "${CMAKE_CURRENT_BINARY_DIR}/libhf3fs_api_shared.so" "${CMAKE_SOURCE_DIR}/src/lib/rs/hf3fs-usrbio-sys/lib/libhf3fs_api_shared.so" + COMMENT "linking usrbio library to rust binding lib dir" +) diff --git a/src/lib/api/hf3fs_usrbio.h b/src/lib/api/hf3fs_usrbio.h index d40723d..c8c237e 100644 --- a/src/lib/api/hf3fs_usrbio.h +++ b/src/lib/api/hf3fs_usrbio.h @@ -4,6 +4,7 @@ extern "C" { #endif +#include #include #include diff --git a/src/lib/rs/hf3fs-usrbio-sys/Cargo.toml b/src/lib/rs/hf3fs-usrbio-sys/Cargo.toml new file mode 100644 index 0000000..4534f0e --- /dev/null +++ b/src/lib/rs/hf3fs-usrbio-sys/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "hf3fs-usrbio-sys" +version = "0.1.0" +edition = "2021" + +[dependencies] +shared_memory = "0.12.4" +uuid = { version = "1.13.2", features = ["v4"] } + +[build-dependencies] +bindgen = "0.71" diff --git a/src/lib/rs/hf3fs-usrbio-sys/README b/src/lib/rs/hf3fs-usrbio-sys/README new file mode 100644 index 0000000..dbfcd45 --- /dev/null +++ b/src/lib/rs/hf3fs-usrbio-sys/README @@ -0,0 +1 @@ +Make sure to build the CMake target `hf3fs_api_shared` (the usrbio library) before building this rust binding. The CMake build will link the built library to the `lib` directory, which is a prerequisite of the Cargo build. diff --git a/src/lib/rs/hf3fs-usrbio-sys/build.rs b/src/lib/rs/hf3fs-usrbio-sys/build.rs new file mode 100644 index 0000000..aa682bb --- /dev/null +++ b/src/lib/rs/hf3fs-usrbio-sys/build.rs @@ -0,0 +1,20 @@ +use std::env; +use std::path::PathBuf; + +fn main() { + let topdir = env::var("CARGO_MANIFEST_DIR").unwrap(); + println!("cargo::rustc-link-search=native={}/lib", topdir); + println!("cargo::rustc-link-lib=hf3fs_api_shared"); + + let bindings = bindgen::Builder::default() + .header("include/hf3fs_usrbio.h") + .clang_arg("-std=c99") + .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) + .generate() + .expect("Unable to generate bindings"); + + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); + bindings + .write_to_file(out_path.join("bindings.rs")) + .expect("Couldn't write bindings!"); +} diff --git a/src/lib/rs/hf3fs-usrbio-sys/src/lib.rs b/src/lib/rs/hf3fs-usrbio-sys/src/lib.rs new file mode 100644 index 0000000..64b1984 --- /dev/null +++ b/src/lib/rs/hf3fs-usrbio-sys/src/lib.rs @@ -0,0 +1,279 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] + +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +use std::ffi::CString; +use std::mem::{size_of, transmute}; +use std::ops::{Range, RangeInclusive}; +use std::os::fd::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd, RawFd}; +use std::os::unix::fs; +use std::ptr; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; + +use shared_memory::Shmem; +use uuid::Uuid; + +impl Default for hf3fs_iov { + fn default() -> Self { + Self { + base: ptr::null_mut(), + iovh: ptr::null_mut(), + id: [0; 16], + mount_point: [0; 256], + size: 0, + block_size: 0, + numa: 0, + } + } +} +pub struct Iov(hf3fs_iov); + +unsafe impl Send for Iov {} +unsafe impl Sync for Iov {} + +impl Iov { + pub fn wrap(mountpoint: &str, shm: &Shmem, numa: i32) -> Result { + let id = Uuid::new_v4(); + let targ = format!("/dev/shm/{}", shm.get_os_id()); + let link = format!( + "{}/3fs-virt/iovs/{}", + mountpoint, + id.as_hyphenated().to_string() + ); + fs::symlink(&targ, &link).expect(&format!("failed to create symlink for shm {}", targ)); + + let mut iov = hf3fs_iov::default(); + let mp = CString::new(mountpoint) + .expect("failed to alloc mountpoint string") + .into_raw(); + let r = unsafe { + hf3fs_iovwrap( + &mut iov as *mut _, + shm.as_ptr() as *mut _, + id.as_bytes().as_ptr(), + mp, + shm.len(), + 0, + numa, + ) + }; + if r == 0 { + Ok(Self(iov)) + } else { + Err(r) + } + } +} + +pub struct Ior { + ior: hf3fs_ior, +} + +unsafe impl Send for Ior {} + +impl Ior { + pub fn create( + mountpoint: &str, + for_read: bool, + entries: i32, + iodepth: i32, + timeout: i32, + numa: i32, + flags: u64, + ) -> Result { + let mut ior = hf3fs_ior { + iov: hf3fs_iov::default(), + iorh: ptr::null_mut(), + mount_point: [0; 256], + for_read: true, + io_depth: 0, + priority: 0, + timeout: 0, + flags: 0, + }; + let mp = CString::new(mountpoint) + .expect("failed to alloc mountpoint string") + .into_raw(); + let r = unsafe { + hf3fs_iorcreate4( + &mut ior as *mut _, + mp, + entries, + for_read, + iodepth, + timeout, + numa, + flags, + ) + }; + if r == 0 { + Ok(Self { ior }) + } else { + Err(r) + } + } + pub fn prepare( + &self, + iov: &Iov, + bufrng: Range, + fd: &RegisteredFd, + file_off: usize, + extra: T, + ) -> Result<(), i32> { + let io = Box::new(PreparedIo { + buf: iov.0.base, + extra, + result: 0, + }); + let r = unsafe { + hf3fs_prep_io( + &self.ior as *const _, + &iov.0 as *const _, + self.ior.for_read, + iov.0.base.add(bufrng.start) as *mut _, + fd.0.as_raw_fd(), + file_off, + (bufrng.end - bufrng.start) as _, + Box::into_raw(io) as *const _, + ) + }; + if r >= 0 { + Ok(()) + } else { + Err(r) + } + } + pub fn submit(&self) { + unsafe { + hf3fs_submit_ios(&self.ior as *const _); + } + } + pub fn poll( + &self, + wanted: RangeInclusive, + timeout_in_ms: u64, + ) -> Vec>> { + let dl = SystemTime::now() + Duration::from_millis(timeout_in_ms); + let ts = dl.duration_since(UNIX_EPOCH).unwrap(); + let to = timespec { + tv_sec: ts.as_secs() as _, + tv_nsec: ts.subsec_nanos() as _, + }; + let arr: __BindgenOpaqueArray() }> = unsafe { transmute(to) }; + let pto = &arr as *const __BindgenOpaqueArray() }>; + + let min = *wanted.start(); + let max = *wanted.end(); + let mut cqes = Vec::with_capacity(max); + cqes.resize(max, hf3fs_cqe::default()); + let n = unsafe { + hf3fs_wait_for_ios( + &self.ior as *const _, + cqes.as_mut_ptr(), + max as _, + min as _, + pto as _, + ) + }; + (0..n) + .map(|i| { + let cqe: &hf3fs_cqe = &cqes[i as usize]; + let mut io = unsafe { Box::from_raw(cqe.userdata as *mut PreparedIo) }; + io.result = cqe.result; + io + }) + .collect() + } +} + +impl Drop for Ior { + fn drop(&mut self) { + unsafe { + hf3fs_iordestroy(&mut self.ior as *mut _); + } + } +} + +impl Default for hf3fs_cqe { + fn default() -> Self { + Self { + index: 0, + reserved: 0, + result: 0, + userdata: ptr::null_mut(), + } + } +} + +pub struct RegisteredFd(OwnedFd); + +impl RegisteredFd { + fn register(fd: RawFd) -> Self { + unsafe { + hf3fs_reg_fd(fd as _, 0); + Self(OwnedFd::from_raw_fd(fd)) + } + } + pub fn open_and_register>(path: P) -> std::io::Result { + std::fs::File::open(path).map(|f| Self::register(f.into_raw_fd())) + } +} + +impl Drop for RegisteredFd { + fn drop(&mut self) { + unsafe { + hf3fs_dereg_fd(self.0.as_raw_fd()); + } + } +} + +pub struct PreparedIo { + pub buf: *mut u8, + pub extra: T, + pub result: i64, +} + +#[repr(C)] +struct timespec { + tv_sec: i64, + tv_nsec: i64, +} + +#[cfg(test)] +mod tests { + use super::*; + use shared_memory::*; + + #[test] + fn test_io() { + let shm = ShmemConf::new() + .os_id("/123") + .size(10 << 10) + .create() + .unwrap(); + let iov = Iov::wrap("/3fs/test", &shm, 0).unwrap(); + + let ior = Ior::create( + "/3fs/test", + true, + 1000, + 0, + 1000, + -1, + HF3FS_IOR_FORBID_READ_HOLES as _, + ) + .unwrap(); + let fp = "/3fs/test"; + let fd = RegisteredFd::open_and_register(fp).unwrap(); + ior.prepare(&iov, 0..52, &fd, 0, (1u64, 2usize, 3usize)) + .unwrap(); + ior.submit(); + let rs = ior.poll::<(u64, usize, usize)>(1..=1, 1000); + assert_eq!(rs.len(), 1); + println!("{:?} {}", rs[0].extra, rs[0].result); + assert_eq!(rs[0].extra, (1u64, 2usize, 3usize)); + assert_eq!(rs[0].result, 52); + } +}