Skip to content

Commit 98f59b6

Browse files
committed
transport: refine doc for FileVolatileSlice
Refine doc for FileVolatileSlice. Signed-off-by: Jiang Liu <[email protected]>
1 parent 0e71a87 commit 98f59b6

File tree

1 file changed

+88
-42
lines changed

1 file changed

+88
-42
lines changed

src/transport/file_volatile_slice.rs

Lines changed: 88 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,25 @@
22
//
33
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
44

5-
//! vm-memory 0.6.0 added Bitmap support, which caused some interfaces
6-
//! to not compile with the extra BitmapSlice generic parameter. So added
7-
//! a FileVolatileSlice which is used for volatile access. And mask out
8-
//! BitmapSlice so that FileSystem interfaces don't have to pass BitmapSlice
9-
//! generic parameters.
10-
//! Dirty page tracking is handled in IoBuffers.
5+
//! Helper structures to work around limitations of the `vm-memory` crate.
6+
//!
7+
//! The vm-memory v0.6.0 introduced support of dirty page tracking by using `Bitmap`, which adds a
8+
//! generic type parameters to several APIs. That's a breaking change and makes the rust compiler
9+
//! fail to compile our code. So introduce [FileVolatileSlice] to mask out the `BitmapSlice`
10+
//! generic type parameter.
11+
//!
12+
//! Dirty page tracking is handled at higher level in `IoBuffers`.
13+
1114
use std::io::{Read, Write};
1215
use std::marker::PhantomData;
1316
use std::sync::atomic::Ordering;
14-
use std::{error, fmt, result};
17+
use std::{error, fmt};
1518

1619
use vm_memory::{
1720
bitmap::BitmapSlice, volatile_memory::Error as VError, AtomicAccess, Bytes, VolatileSlice,
1821
};
1922

20-
/// `FileVolatileSlice` related errors.
23+
/// [`FileVolatileSlice`] related errors.
2124
#[allow(missing_docs)]
2225
#[derive(Debug)]
2326
pub enum Error {
@@ -45,24 +48,51 @@ impl fmt::Display for Error {
4548

4649
impl error::Error for Error {}
4750

48-
/// Result of volatile memory operations.
49-
pub type Result<T> = result::Result<T, Error>;
50-
51-
/// A adapter in order to mask the BitmapSlice generic parameter.
51+
/// An adapter structure to work around limitations of the `vm-memory` crate.
52+
///
53+
/// It solves the compilation failure by masking out the
54+
/// [`vm_memory::BitmapSlice`](https://docs.rs/vm-memory/latest/vm_memory/bitmap/trait.BitmapSlice.html)
55+
/// generic type parameter of
56+
/// [`vm_memory::VolatileSlice`](https://docs.rs/vm-memory/latest/vm_memory/volatile_memory/struct.VolatileSlice.html)
5257
#[derive(Clone, Copy, Debug)]
5358
pub struct FileVolatileSlice<'a> {
5459
addr: *mut u8,
5560
size: usize,
5661
phantom: PhantomData<&'a u8>,
5762
}
5863

64+
// Safe because the field `FileVolatileSlice::addr` is used as data buffer.
5965
unsafe impl<'a> Sync for FileVolatileSlice<'a> {}
6066

6167
impl<'a> FileVolatileSlice<'a> {
62-
/// Create a new instance
68+
/// Create a new instance of [`FileVolatileSlice`] from a raw pointer.
6369
///
6470
/// # Safety
65-
/// This function is the same as VolatileSlice::new.
71+
/// To use this safely, the caller must guarantee that the memory at addr is size bytes long
72+
/// and is available for the duration of the lifetime of the new [FileVolatileSlice].
73+
/// The caller must also guarantee that all other users of the given chunk of memory are using
74+
/// volatile accesses.
75+
///
76+
/// ### Example
77+
/// ```rust
78+
/// # use fuse_backend_rs::transport::FileVolatileSlice;
79+
/// # use vm_memory::bytes::Bytes;
80+
/// # use std::sync::atomic::Ordering;
81+
/// let mut buffer = [0u8; 1024];
82+
/// let s = unsafe { FileVolatileSlice::new(buffer.as_mut_ptr(), buffer.len()) };
83+
///
84+
/// {
85+
/// let o: u32 = s.load(0x10, Ordering::Acquire).unwrap();
86+
/// assert_eq!(o, 0);
87+
/// s.store(1u8, 0x10, Ordering::Release).unwrap();
88+
///
89+
/// let s2 = s.as_volatile_slice();
90+
/// let s3 = FileVolatileSlice::new_from_volatile_slice(&s2);
91+
/// assert_eq!(s3.len(), 1024);
92+
/// }
93+
///
94+
/// assert_eq!(buffer[0x10], 1);
95+
/// ```
6696
pub unsafe fn new(addr: *mut u8, size: usize) -> Self {
6797
Self {
6898
addr,
@@ -71,34 +101,37 @@ impl<'a> FileVolatileSlice<'a> {
71101
}
72102
}
73103

74-
/// Create a new FileVolatileSlice from VolatileSlice, but don't have bitmap.
75-
/// The caller needs to ensure that dirty pages are marked.
104+
/// Create a new [`FileVolatileSlice`] from [`VolatileSlice`](https://docs.rs/vm-memory/latest/vm_memory/volatile_memory/struct.VolatileSlice.html)
105+
/// and strip off the [`BitmapSlice`](https://docs.rs/vm-memory/latest/vm_memory/bitmap/trait.BitmapSlice.html) generic type parameter.
106+
///
107+
/// The caller needs to handle dirty page tracking for the data buffer.
76108
pub fn new_from_volatile_slice<S: BitmapSlice>(s: &VolatileSlice<'a, S>) -> Self {
77109
unsafe { Self::new(s.as_ptr(), s.len()) }
78110
}
79111

80-
/// Create a new VolatileSlice
112+
/// Create a [`vm_memory::VolatileSlice`](https://docs.rs/vm-memory/latest/vm_memory/volatile_memory/struct.VolatileSlice.html)
113+
/// from [FileVolatileSlice] without dirty page tracking.
81114
pub fn as_volatile_slice(&self) -> VolatileSlice<'_, ()> {
82115
unsafe { VolatileSlice::new(self.as_ptr(), self.len()) }
83116
}
84117

85-
/// Returns a pointer to the beginning of the slice.
118+
/// Return a pointer to the start of the slice.
86119
pub fn as_ptr(&self) -> *mut u8 {
87120
self.addr
88121
}
89122

90-
/// Gets the size of this slice.
123+
/// Get the size of the slice.
91124
pub fn len(&self) -> usize {
92125
self.size
93126
}
94127

95-
/// Checks if the slice is empty.
128+
/// Check if the slice is empty.
96129
pub fn is_empty(&self) -> bool {
97130
self.size == 0
98131
}
99132

100-
/// Returns a subslice of this FileVolatileSlice starting at `offset`.
101-
pub fn offset(&self, count: usize) -> Result<Self> {
133+
/// Return a subslice of this [FileVolatileSlice] starting at `offset`.
134+
pub fn offset(&self, count: usize) -> Result<Self, Error> {
102135
let new_addr = (self.addr as usize)
103136
.checked_add(count)
104137
.ok_or(Error::Overflow {
@@ -116,65 +149,78 @@ impl<'a> FileVolatileSlice<'a> {
116149
impl<'a> Bytes<usize> for FileVolatileSlice<'a> {
117150
type E = VError;
118151

119-
fn write(&self, buf: &[u8], addr: usize) -> result::Result<usize, Self::E> {
152+
fn write(&self, buf: &[u8], addr: usize) -> Result<usize, Self::E> {
120153
VolatileSlice::write(&self.as_volatile_slice(), buf, addr)
121154
}
122155

123-
fn read(&self, buf: &mut [u8], addr: usize) -> result::Result<usize, Self::E> {
156+
fn read(&self, buf: &mut [u8], addr: usize) -> Result<usize, Self::E> {
124157
VolatileSlice::read(&self.as_volatile_slice(), buf, addr)
125158
}
126159

127-
fn write_slice(&self, buf: &[u8], addr: usize) -> result::Result<(), Self::E> {
160+
fn write_slice(&self, buf: &[u8], addr: usize) -> Result<(), Self::E> {
128161
VolatileSlice::write_slice(&self.as_volatile_slice(), buf, addr)
129162
}
130163

131-
fn read_slice(&self, buf: &mut [u8], addr: usize) -> result::Result<(), Self::E> {
164+
fn read_slice(&self, buf: &mut [u8], addr: usize) -> Result<(), Self::E> {
132165
VolatileSlice::write_slice(&self.as_volatile_slice(), buf, addr)
133166
}
134167

135-
fn read_from<F>(&self, addr: usize, src: &mut F, count: usize) -> result::Result<usize, Self::E>
168+
fn read_from<F>(&self, addr: usize, src: &mut F, count: usize) -> Result<usize, Self::E>
136169
where
137170
F: Read,
138171
{
139172
VolatileSlice::read_from(&self.as_volatile_slice(), addr, src, count)
140173
}
141174

142-
fn read_exact_from<F>(
143-
&self,
144-
addr: usize,
145-
src: &mut F,
146-
count: usize,
147-
) -> result::Result<(), Self::E>
175+
fn read_exact_from<F>(&self, addr: usize, src: &mut F, count: usize) -> Result<(), Self::E>
148176
where
149177
F: Read,
150178
{
151179
VolatileSlice::read_exact_from(&self.as_volatile_slice(), addr, src, count)
152180
}
153181

154-
fn write_to<F>(&self, addr: usize, dst: &mut F, count: usize) -> result::Result<usize, Self::E>
182+
fn write_to<F>(&self, addr: usize, dst: &mut F, count: usize) -> Result<usize, Self::E>
155183
where
156184
F: Write,
157185
{
158186
VolatileSlice::write_to(&self.as_volatile_slice(), addr, dst, count)
159187
}
160188

161-
fn write_all_to<F>(&self, addr: usize, dst: &mut F, count: usize) -> result::Result<(), Self::E>
189+
fn write_all_to<F>(&self, addr: usize, dst: &mut F, count: usize) -> Result<(), Self::E>
162190
where
163191
F: Write,
164192
{
165193
VolatileSlice::write_all_to(&self.as_volatile_slice(), addr, dst, count)
166194
}
167195

168-
fn store<T: AtomicAccess>(
169-
&self,
170-
val: T,
171-
addr: usize,
172-
order: Ordering,
173-
) -> result::Result<(), Self::E> {
196+
fn store<T: AtomicAccess>(&self, val: T, addr: usize, order: Ordering) -> Result<(), Self::E> {
174197
VolatileSlice::store(&self.as_volatile_slice(), val, addr, order)
175198
}
176199

177-
fn load<T: AtomicAccess>(&self, addr: usize, order: Ordering) -> result::Result<T, Self::E> {
200+
fn load<T: AtomicAccess>(&self, addr: usize, order: Ordering) -> Result<T, Self::E> {
178201
VolatileSlice::load(&self.as_volatile_slice(), addr, order)
179202
}
180203
}
204+
205+
#[cfg(test)]
206+
mod tests {
207+
use super::*;
208+
209+
#[test]
210+
fn test_new_file_volatile_slice() {
211+
let mut buffer = [0u8; 1024];
212+
let s = unsafe { FileVolatileSlice::new(buffer.as_mut_ptr(), buffer.len()) };
213+
214+
let o: u32 = s.load(0x10, Ordering::Acquire).unwrap();
215+
assert_eq!(o, 0);
216+
s.store(1u8, 0x10, Ordering::Release).unwrap();
217+
218+
let s2 = s.as_volatile_slice();
219+
let s3 = FileVolatileSlice::new_from_volatile_slice(&s2);
220+
assert_eq!(s3.len(), 1024);
221+
222+
assert!(s3.offset(2048).is_err());
223+
224+
assert_eq!(buffer[0x10], 1);
225+
}
226+
}

0 commit comments

Comments
 (0)