Skip to content

Commit 1f417a3

Browse files
wllenyjbergwolf
authored andcommitted
tokio-uring: temporarily include tokio-uring into common module
Tempoarily include tokio-uring into dbs-fuse, so we could publish dbs-fuse. We will switch to upstream crate once our enhancements have been merged and new version is available. Signed-off-by: wllenyj <[email protected]> Signed-off-by: Jiang Liu <[email protected]>
1 parent 2215bdc commit 1f417a3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+3731
-2
lines changed

Cargo.toml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ log = "0.4.6"
2626
mio = { version = "0.8", features = ["os-poll", "os-ext"]}
2727
nix = "0.24"
2828
lazy_static = "1.4"
29-
tokio-uring = { version = "0.3.0", optional = true }
29+
tokio = { version = "1", optional = true }
3030
vmm-sys-util = { version = "0.9", optional = true }
3131
vm-memory = { version = "0.8", features = ["backend-mmap"] }
3232
virtio-queue = { version = "0.4", optional = true }
@@ -37,16 +37,22 @@ core-foundation-sys = { version = ">=0.8", optional = true }
3737

3838
[target.'cfg(target_os = "linux")'.dependencies]
3939
caps = { version = "0.3", optional = true }
40+
tokio-uring = "0.3.0"
41+
io-uring = { version = "0.5.2", features = ["unstable"] }
42+
socket2 = { version = "0.4.4", features = ["all"] }
43+
scoped-tls = "1.0.0"
44+
slab = "0.4.6"
4045

4146
[dev-dependencies]
4247
futures = { version = "0.3", features = ["thread-pool"]}
4348
stderrlog = "0.5"
4449
vmm-sys-util = "0.9"
4550
vm-memory = { version = "0.8", features = ["backend-mmap", "backend-bitmap"] }
51+
tokio-test = "0.4.2"
4652

4753
[features]
4854
default = ["fusedev"]
49-
async-io = ["async-trait", "futures", "tokio-uring"]
55+
async-io = ["async-trait", "futures", "tokio/fs", "tokio/net", "tokio/sync", "tokio/rt"]
5056
fusedev = ["vmm-sys-util", "caps", "core-foundation-sys"]
5157
virtiofs = ["virtio-queue", "caps"]
5258
vhost-user-fs = ["virtiofs", "vhost", "caps"]

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,10 @@ impl FuseServer {
9393
This project is licensed under
9494
- [Apache License](http://www.apache.org/licenses/LICENSE-2.0), Version 2.0
9595
- [BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
96+
97+
Source code under [src/tokio-uring] is temporarily copied from [tokio-uring](https://github.com/tokio-rs/tokio-uring)
98+
with modifications, which is licensed under [MIT](https://github.com/tokio-rs/tokio-uring/blob/master/LICENSE).
99+
100+
We will use `crate.io` directly instead of this temporary copy when the pendding PRs is merged.
101+
https://github.com/tokio-rs/tokio-uring/pull/87
102+
https://github.com/tokio-rs/tokio-uring/pull/88

src/common/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,10 @@
66
77
pub mod file_buf;
88
pub mod file_traits;
9+
10+
// Temporarily include all source code tokio-uring.
11+
// Will switch to upstream once our enhancement have been merged and new version available.
12+
#[cfg(all(feature = "async-io", target_os = "linux"))]
13+
pub mod tokio_uring;
14+
#[cfg(all(feature = "async-io", target_os = "linux"))]
15+
pub(crate) use self::tokio_uring::{buf, driver, fs, future, BufResult};

src/common/tokio_uring/buf/io_buf.rs

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
use crate::buf::Slice;
2+
3+
use std::ops;
4+
5+
/// An `io-uring` compatible buffer.
6+
///
7+
/// The `IoBuf` trait is implemented by buffer types that can be passed to
8+
/// io-uring operations. Users will not need to use this trait directly, except
9+
/// for the [`slice`] method.
10+
///
11+
/// # Slicing
12+
///
13+
/// Because buffers are passed by ownership to the runtime, Rust's slice API
14+
/// (`&buf[..]`) cannot be used. Instead, `tokio-uring` provides an owned slice
15+
/// API: [`slice()`]. The method takes ownership fo the buffer and returns a
16+
/// `Slice<Self>` type that tracks the requested offset.
17+
///
18+
/// # Implementation notes
19+
///
20+
/// Buffers passed to `io-uring` operations must reference a stable memory
21+
/// region. While the runtime holds ownership to a buffer, the pointer returned
22+
/// by `stable_ptr` must remain valid even if the `IoBuf` value is moved.
23+
///
24+
/// [`slice()`]: IoBuf::slice
25+
pub unsafe trait IoBuf: Unpin + 'static {
26+
/// Returns a raw pointer to the vector’s buffer.
27+
///
28+
/// This method is to be used by the `tokio-uring` runtime and it is not
29+
/// expected for users to call it directly.
30+
///
31+
/// The implementation must ensure that, while the `tokio-uring` runtime
32+
/// owns the value, the pointer returned by `stable_ptr` **does not**
33+
/// change.
34+
fn stable_ptr(&self) -> *const u8;
35+
36+
/// Number of initialized bytes.
37+
///
38+
/// This method is to be used by the `tokio-uring` runtime and it is not
39+
/// expected for users to call it directly.
40+
///
41+
/// For `Vec`, this is identical to `len()`.
42+
fn bytes_init(&self) -> usize;
43+
44+
/// Total size of the buffer, including uninitialized memory, if any.
45+
///
46+
/// This method is to be used by the `tokio-uring` runtime and it is not
47+
/// expected for users to call it directly.
48+
///
49+
/// For `Vec`, this is identical to `capacity()`.
50+
fn bytes_total(&self) -> usize;
51+
52+
/// Returns a view of the buffer with the specified range.
53+
///
54+
/// This method is similar to Rust's slicing (`&buf[..]`), but takes
55+
/// ownership of the buffer.
56+
///
57+
/// # Examples
58+
///
59+
/// ```
60+
/// use tokio_uring::buf::IoBuf;
61+
///
62+
/// let buf = b"hello world".to_vec();
63+
/// buf.slice(5..10);
64+
/// ```
65+
fn slice(self, range: impl ops::RangeBounds<usize>) -> Slice<Self>
66+
where
67+
Self: Sized,
68+
{
69+
use core::ops::Bound;
70+
71+
let begin = match range.start_bound() {
72+
Bound::Included(&n) => n,
73+
Bound::Excluded(&n) => n + 1,
74+
Bound::Unbounded => 0,
75+
};
76+
77+
assert!(begin < self.bytes_total());
78+
79+
let end = match range.end_bound() {
80+
Bound::Included(&n) => n.checked_add(1).expect("out of range"),
81+
Bound::Excluded(&n) => n,
82+
Bound::Unbounded => self.bytes_total(),
83+
};
84+
85+
assert!(end <= self.bytes_total());
86+
assert!(begin <= self.bytes_init());
87+
88+
Slice::new(self, begin, end)
89+
}
90+
}
91+
92+
unsafe impl IoBuf for Vec<u8> {
93+
fn stable_ptr(&self) -> *const u8 {
94+
self.as_ptr()
95+
}
96+
97+
fn bytes_init(&self) -> usize {
98+
self.len()
99+
}
100+
101+
fn bytes_total(&self) -> usize {
102+
self.capacity()
103+
}
104+
}
105+
106+
unsafe impl IoBuf for &'static [u8] {
107+
fn stable_ptr(&self) -> *const u8 {
108+
self.as_ptr()
109+
}
110+
111+
fn bytes_init(&self) -> usize {
112+
<[u8]>::len(self)
113+
}
114+
115+
fn bytes_total(&self) -> usize {
116+
self.bytes_init()
117+
}
118+
}
119+
120+
unsafe impl IoBuf for &'static str {
121+
fn stable_ptr(&self) -> *const u8 {
122+
self.as_ptr()
123+
}
124+
125+
fn bytes_init(&self) -> usize {
126+
<str>::len(self)
127+
}
128+
129+
fn bytes_total(&self) -> usize {
130+
self.bytes_init()
131+
}
132+
}
133+
134+
#[cfg(feature = "bytes")]
135+
unsafe impl IoBuf for bytes::Bytes {
136+
fn stable_ptr(&self) -> *const u8 {
137+
self.as_ptr()
138+
}
139+
140+
fn bytes_init(&self) -> usize {
141+
self.len()
142+
}
143+
144+
fn bytes_total(&self) -> usize {
145+
self.len()
146+
}
147+
}
148+
149+
#[cfg(feature = "bytes")]
150+
unsafe impl IoBuf for bytes::BytesMut {
151+
fn stable_ptr(&self) -> *const u8 {
152+
self.as_ptr()
153+
}
154+
155+
fn bytes_init(&self) -> usize {
156+
self.len()
157+
}
158+
159+
fn bytes_total(&self) -> usize {
160+
self.capacity()
161+
}
162+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use crate::buf::IoBuf;
2+
3+
/// A mutable`io-uring` compatible buffer.
4+
///
5+
/// The `IoBufMut` trait is implemented by buffer types that can be passed to
6+
/// io-uring operations. Users will not need to use this trait directly.
7+
///
8+
/// # Implementation notes
9+
///
10+
/// Buffers passed to `io-uring` operations must reference a stable memory
11+
/// region. While the runtime holds ownership to a buffer, the pointer returned
12+
/// by `stable_mut_ptr` must remain valid even if the `IoBufMut` value is moved.
13+
pub unsafe trait IoBufMut: IoBuf {
14+
/// Returns a raw mutable pointer to the vector’s buffer.
15+
///
16+
/// This method is to be used by the `tokio-uring` runtime and it is not
17+
/// expected for users to call it directly.
18+
///
19+
/// The implementation must ensure that, while the `tokio-uring` runtime
20+
/// owns the value, the pointer returned by `stable_mut_ptr` **does not**
21+
/// change.
22+
fn stable_mut_ptr(&mut self) -> *mut u8;
23+
24+
/// Updates the number of initialized bytes.
25+
///
26+
/// The specified `pos` becomes the new value returned by
27+
/// `IoBuf::bytes_init`.
28+
///
29+
/// # Safety
30+
///
31+
/// The caller must ensure that all bytes starting at `stable_mut_ptr()` up
32+
/// to `pos` are initialized and owned by the buffer.
33+
unsafe fn set_init(&mut self, pos: usize);
34+
}
35+
36+
unsafe impl IoBufMut for Vec<u8> {
37+
fn stable_mut_ptr(&mut self) -> *mut u8 {
38+
self.as_mut_ptr()
39+
}
40+
41+
unsafe fn set_init(&mut self, init_len: usize) {
42+
if self.len() < init_len {
43+
self.set_len(init_len);
44+
}
45+
}
46+
}
47+
48+
#[cfg(feature = "bytes")]
49+
unsafe impl IoBufMut for bytes::BytesMut {
50+
fn stable_mut_ptr(&mut self) -> *mut u8 {
51+
self.as_mut_ptr()
52+
}
53+
54+
unsafe fn set_init(&mut self, init_len: usize) {
55+
if self.len() < init_len {
56+
self.set_len(init_len);
57+
}
58+
}
59+
}

src/common/tokio_uring/buf/mod.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//! Utilities for working with buffers.
2+
//!
3+
//! `io-uring` APIs require passing ownership of buffers to the runtime. The
4+
//! crate defines [`IoBuf`] and [`IoBufMut`] traits which are implemented by buffer
5+
//! types that respect the `io-uring` contract.
6+
7+
mod io_buf;
8+
pub use io_buf::IoBuf;
9+
10+
mod io_buf_mut;
11+
pub use io_buf_mut::IoBufMut;
12+
13+
mod slice;
14+
pub use slice::Slice;
15+
16+
pub(crate) fn deref(buf: &impl IoBuf) -> &[u8] {
17+
// Safety: the `IoBuf` trait is marked as unsafe and is expected to be
18+
// implemented correctly.
19+
unsafe { std::slice::from_raw_parts(buf.stable_ptr(), buf.bytes_init()) }
20+
}
21+
22+
pub(crate) fn deref_mut(buf: &mut impl IoBufMut) -> &mut [u8] {
23+
// Safety: the `IoBufMut` trait is marked as unsafe and is expected to be
24+
// implemented correct.
25+
unsafe { std::slice::from_raw_parts_mut(buf.stable_mut_ptr(), buf.bytes_init()) }
26+
}

0 commit comments

Comments
 (0)