Skip to content

Commit dfa67aa

Browse files
Merge branch 'deepseek-ai:main' into main
2 parents dc38d27 + f9a4291 commit dfa67aa

18 files changed

+696
-505
lines changed

Cargo.lock

+191-20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
[workspace]
22
members = [
33
"src/client/trash_cleaner",
4-
"src/storage/chunk_engine"
4+
"src/storage/chunk_engine",
5+
"src/lib/rs/hf3fs-usrbio-sys"
6+
]
7+
default-members = [
8+
"src/client/trash_cleaner",
9+
"src/storage/chunk_engine",
510
]
611
resolver = "2"
712

813
[workspace.package]
914
authors = ["dev <noreply@deepseek.com>"]
1015
edition = "2021"
1116
license = "MIT"
12-
rust-version = "1.75.0" # MSRV
17+
rust-version = "1.85.0" # MSRV
1318

1419
[profile.release-cmake]
1520
debug = true

src/common/net/Listener.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ namespace hf3fs::net {
3333
static bool checkNicType(std::string_view nic, Address::Type type) {
3434
switch (type) {
3535
case Address::TCP:
36-
return nic.starts_with("en") || nic.starts_with("eth") || nic.starts_with("bond");
36+
return nic.starts_with("en") || nic.starts_with("eth") || nic.starts_with("bond") || nic.starts_with("xgbe");
3737
case Address::IPoIB:
3838
return nic.starts_with("ib");
3939
case Address::RDMA:
40-
return nic.starts_with("en") || nic.starts_with("eth") || nic.starts_with("bond");
40+
return nic.starts_with("en") || nic.starts_with("eth") || nic.starts_with("bond") || nic.starts_with("xgbe");
4141
case Address::LOCAL:
4242
return nic.starts_with("lo");
4343
default:

src/lib/api/CMakeLists.txt

+7
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
11
target_add_lib(hf3fs_api client-lib-common storage-client numa rt)
22
target_add_shared_lib(hf3fs_api_shared client-lib-common storage-client numa rt)
3+
4+
add_custom_command(
5+
TARGET hf3fs_api_shared
6+
POST_BUILD
7+
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"
8+
COMMENT "linking usrbio library to rust binding lib dir"
9+
)

src/lib/api/hf3fs_usrbio.h

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
extern "C" {
55
#endif
66

7+
#include <stdbool.h>
78
#include <stdint.h>
89
#include <sys/types.h>
910

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "hf3fs-usrbio-sys"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
shared_memory = "0.12.4"
8+
uuid = { version = "1.13.2", features = ["v4"] }
9+
10+
[build-dependencies]
11+
bindgen = "0.71"

src/lib/rs/hf3fs-usrbio-sys/README

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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.

src/lib/rs/hf3fs-usrbio-sys/build.rs

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
use std::env;
2+
use std::path::PathBuf;
3+
4+
fn main() {
5+
let topdir = env::var("CARGO_MANIFEST_DIR").unwrap();
6+
println!("cargo::rustc-link-search=native={}/lib", topdir);
7+
println!("cargo::rustc-link-lib=hf3fs_api_shared");
8+
9+
let bindings = bindgen::Builder::default()
10+
.header(PathBuf::from(topdir).join("../../api/hf3fs_usrbio.h").display().to_string())
11+
.clang_arg("-std=c99")
12+
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
13+
.generate()
14+
.expect("Unable to generate bindings");
15+
16+
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
17+
bindings
18+
.write_to_file(out_path.join("bindings.rs"))
19+
.expect("Couldn't write bindings!");
20+
}

src/lib/rs/hf3fs-usrbio-sys/lib/.dummy

Whitespace-only changes.
+279
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
#![allow(non_upper_case_globals)]
2+
#![allow(non_camel_case_types)]
3+
#![allow(non_snake_case)]
4+
5+
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
6+
7+
use std::ffi::CString;
8+
use std::mem::{size_of, transmute};
9+
use std::ops::{Range, RangeInclusive};
10+
use std::os::fd::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
11+
use std::os::unix::fs;
12+
use std::ptr;
13+
use std::time::{Duration, SystemTime, UNIX_EPOCH};
14+
15+
use shared_memory::Shmem;
16+
use uuid::Uuid;
17+
18+
impl Default for hf3fs_iov {
19+
fn default() -> Self {
20+
Self {
21+
base: ptr::null_mut(),
22+
iovh: ptr::null_mut(),
23+
id: [0; 16],
24+
mount_point: [0; 256],
25+
size: 0,
26+
block_size: 0,
27+
numa: 0,
28+
}
29+
}
30+
}
31+
pub struct Iov(hf3fs_iov);
32+
33+
unsafe impl Send for Iov {}
34+
unsafe impl Sync for Iov {}
35+
36+
impl Iov {
37+
pub fn wrap(mountpoint: &str, shm: &Shmem, numa: i32) -> Result<Self, i32> {
38+
let id = Uuid::new_v4();
39+
let targ = format!("/dev/shm/{}", shm.get_os_id());
40+
let link = format!(
41+
"{}/3fs-virt/iovs/{}",
42+
mountpoint,
43+
id.as_hyphenated().to_string()
44+
);
45+
fs::symlink(&targ, &link).expect(&format!("failed to create symlink for shm {}", targ));
46+
47+
let mut iov = hf3fs_iov::default();
48+
let mp = CString::new(mountpoint)
49+
.expect("failed to alloc mountpoint string")
50+
.into_raw();
51+
let r = unsafe {
52+
hf3fs_iovwrap(
53+
&mut iov as *mut _,
54+
shm.as_ptr() as *mut _,
55+
id.as_bytes().as_ptr(),
56+
mp,
57+
shm.len(),
58+
0,
59+
numa,
60+
)
61+
};
62+
if r == 0 {
63+
Ok(Self(iov))
64+
} else {
65+
Err(r)
66+
}
67+
}
68+
}
69+
70+
pub struct Ior {
71+
ior: hf3fs_ior,
72+
}
73+
74+
unsafe impl Send for Ior {}
75+
76+
impl Ior {
77+
pub fn create(
78+
mountpoint: &str,
79+
for_read: bool,
80+
entries: i32,
81+
iodepth: i32,
82+
timeout: i32,
83+
numa: i32,
84+
flags: u64,
85+
) -> Result<Self, i32> {
86+
let mut ior = hf3fs_ior {
87+
iov: hf3fs_iov::default(),
88+
iorh: ptr::null_mut(),
89+
mount_point: [0; 256],
90+
for_read: true,
91+
io_depth: 0,
92+
priority: 0,
93+
timeout: 0,
94+
flags: 0,
95+
};
96+
let mp = CString::new(mountpoint)
97+
.expect("failed to alloc mountpoint string")
98+
.into_raw();
99+
let r = unsafe {
100+
hf3fs_iorcreate4(
101+
&mut ior as *mut _,
102+
mp,
103+
entries,
104+
for_read,
105+
iodepth,
106+
timeout,
107+
numa,
108+
flags,
109+
)
110+
};
111+
if r == 0 {
112+
Ok(Self { ior })
113+
} else {
114+
Err(r)
115+
}
116+
}
117+
pub fn prepare<T>(
118+
&self,
119+
iov: &Iov,
120+
bufrng: Range<usize>,
121+
fd: &RegisteredFd,
122+
file_off: usize,
123+
extra: T,
124+
) -> Result<(), i32> {
125+
let io = Box::new(PreparedIo {
126+
buf: iov.0.base,
127+
extra,
128+
result: 0,
129+
});
130+
let r = unsafe {
131+
hf3fs_prep_io(
132+
&self.ior as *const _,
133+
&iov.0 as *const _,
134+
self.ior.for_read,
135+
iov.0.base.add(bufrng.start) as *mut _,
136+
fd.0.as_raw_fd(),
137+
file_off,
138+
(bufrng.end - bufrng.start) as _,
139+
Box::into_raw(io) as *const _,
140+
)
141+
};
142+
if r >= 0 {
143+
Ok(())
144+
} else {
145+
Err(r)
146+
}
147+
}
148+
pub fn submit(&self) {
149+
unsafe {
150+
hf3fs_submit_ios(&self.ior as *const _);
151+
}
152+
}
153+
pub fn poll<T>(
154+
&self,
155+
wanted: RangeInclusive<usize>,
156+
timeout_in_ms: u64,
157+
) -> Vec<Box<PreparedIo<T>>> {
158+
let dl = SystemTime::now() + Duration::from_millis(timeout_in_ms);
159+
let ts = dl.duration_since(UNIX_EPOCH).unwrap();
160+
let to = timespec {
161+
tv_sec: ts.as_secs() as _,
162+
tv_nsec: ts.subsec_nanos() as _,
163+
};
164+
let arr: __BindgenOpaqueArray<u8, { size_of::<timespec>() }> = unsafe { transmute(to) };
165+
let pto = &arr as *const __BindgenOpaqueArray<u8, { size_of::<timespec>() }>;
166+
167+
let min = *wanted.start();
168+
let max = *wanted.end();
169+
let mut cqes = Vec::with_capacity(max);
170+
cqes.resize(max, hf3fs_cqe::default());
171+
let n = unsafe {
172+
hf3fs_wait_for_ios(
173+
&self.ior as *const _,
174+
cqes.as_mut_ptr(),
175+
max as _,
176+
min as _,
177+
pto as _,
178+
)
179+
};
180+
(0..n)
181+
.map(|i| {
182+
let cqe: &hf3fs_cqe = &cqes[i as usize];
183+
let mut io = unsafe { Box::from_raw(cqe.userdata as *mut PreparedIo<T>) };
184+
io.result = cqe.result;
185+
io
186+
})
187+
.collect()
188+
}
189+
}
190+
191+
impl Drop for Ior {
192+
fn drop(&mut self) {
193+
unsafe {
194+
hf3fs_iordestroy(&mut self.ior as *mut _);
195+
}
196+
}
197+
}
198+
199+
impl Default for hf3fs_cqe {
200+
fn default() -> Self {
201+
Self {
202+
index: 0,
203+
reserved: 0,
204+
result: 0,
205+
userdata: ptr::null_mut(),
206+
}
207+
}
208+
}
209+
210+
pub struct RegisteredFd(OwnedFd);
211+
212+
impl RegisteredFd {
213+
fn register(fd: RawFd) -> Self {
214+
unsafe {
215+
hf3fs_reg_fd(fd as _, 0);
216+
Self(OwnedFd::from_raw_fd(fd))
217+
}
218+
}
219+
pub fn open_and_register<P: AsRef<std::path::Path>>(path: P) -> std::io::Result<Self> {
220+
std::fs::File::open(path).map(|f| Self::register(f.into_raw_fd()))
221+
}
222+
}
223+
224+
impl Drop for RegisteredFd {
225+
fn drop(&mut self) {
226+
unsafe {
227+
hf3fs_dereg_fd(self.0.as_raw_fd());
228+
}
229+
}
230+
}
231+
232+
pub struct PreparedIo<T> {
233+
pub buf: *mut u8,
234+
pub extra: T,
235+
pub result: i64,
236+
}
237+
238+
#[repr(C)]
239+
struct timespec {
240+
tv_sec: i64,
241+
tv_nsec: i64,
242+
}
243+
244+
#[cfg(test)]
245+
mod tests {
246+
use super::*;
247+
use shared_memory::*;
248+
249+
#[test]
250+
fn test_io() {
251+
let shm = ShmemConf::new()
252+
.os_id("/123")
253+
.size(10 << 10)
254+
.create()
255+
.unwrap();
256+
let iov = Iov::wrap("/3fs/test", &shm, 0).unwrap();
257+
258+
let ior = Ior::create(
259+
"/3fs/test",
260+
true,
261+
1000,
262+
0,
263+
1000,
264+
-1,
265+
HF3FS_IOR_FORBID_READ_HOLES as _,
266+
)
267+
.unwrap();
268+
let fp = "/3fs/test";
269+
let fd = RegisteredFd::open_and_register(fp).unwrap();
270+
ior.prepare(&iov, 0..52, &fd, 0, (1u64, 2usize, 3usize))
271+
.unwrap();
272+
ior.submit();
273+
let rs = ior.poll::<(u64, usize, usize)>(1..=1, 1000);
274+
assert_eq!(rs.len(), 1);
275+
println!("{:?} {}", rs[0].extra, rs[0].result);
276+
assert_eq!(rs[0].extra, (1u64, 2usize, 3usize));
277+
assert_eq!(rs[0].result, 52);
278+
}
279+
}

tests/fuse/config/admin_cli.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ cluster_id = '${FS_CLUSTER}'
44
default_pkey_index = ${PKEY_INDEX}
55

66
[fdb]
7-
clusterFile = '${FDB_UNITTEST_CLUSTER}'
7+
clusterFile = '${FDB_TEST_CLUSTER}'
88

99
[mgmtd_client]
1010
mgmtd_server_addresses = [ 'RDMA://${ADDRESS}:${MGMTD_PORT}' ]

0 commit comments

Comments
 (0)