Skip to content

Commit b5debef

Browse files
jiangliubergwolf
authored andcommitted
ptfs: switch to new implementation from util.rs
1. switch to new implementation from util.rs. 2. move helpers into util.rs 3. split out config.rs for configuration information. 4. move os compatibility related data structs into os_compat.rs Signed-off-by: Jiang Liu <[email protected]>
1 parent 1dc15e0 commit b5debef

File tree

9 files changed

+694
-687
lines changed

9 files changed

+694
-687
lines changed

src/passthrough/config.rs

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
// Copyright (C) 2020-2022 Alibaba Cloud. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
use std::str::FromStr;
5+
use std::time::Duration;
6+
7+
/// The caching policy that the file system should report to the FUSE client. By default the FUSE
8+
/// protocol uses close-to-open consistency. This means that any cached contents of the file are
9+
/// invalidated the next time that file is opened.
10+
#[derive(Debug, Default, Clone, Eq, PartialEq)]
11+
pub enum CachePolicy {
12+
/// The client should never cache file data and all I/O should be directly forwarded to the
13+
/// server. This policy must be selected when file contents may change without the knowledge of
14+
/// the FUSE client (i.e., the file system does not have exclusive access to the directory).
15+
Never,
16+
17+
/// The client is free to choose when and how to cache file data. This is the default policy and
18+
/// uses close-to-open consistency as described in the enum documentation.
19+
#[default]
20+
Auto,
21+
22+
/// The client should always cache file data. This means that the FUSE client will not
23+
/// invalidate any cached data that was returned by the file system the last time the file was
24+
/// opened. This policy should only be selected when the file system has exclusive access to the
25+
/// directory.
26+
Always,
27+
}
28+
29+
impl FromStr for CachePolicy {
30+
type Err = &'static str;
31+
32+
fn from_str(s: &str) -> Result<Self, Self::Err> {
33+
match s {
34+
"never" | "Never" | "NEVER" | "none" | "None" | "NONE" => Ok(CachePolicy::Never),
35+
"auto" | "Auto" | "AUTO" => Ok(CachePolicy::Auto),
36+
"always" | "Always" | "ALWAYS" => Ok(CachePolicy::Always),
37+
_ => Err("invalid cache policy"),
38+
}
39+
}
40+
}
41+
42+
/// Options that configure the behavior of the passthrough fuse file system.
43+
#[derive(Debug, Clone, Eq, PartialEq)]
44+
pub struct Config {
45+
/// How long the FUSE client should consider file and directory attributes to be valid. If the
46+
/// attributes of a file or directory can only be modified by the FUSE client (i.e., the file
47+
/// system has exclusive access), then this should be set to a large value.
48+
///
49+
/// The default value for this option is 5 seconds.
50+
pub attr_timeout: Duration,
51+
52+
/// How long the FUSE client should consider directory entries to be valid. If the contents of a
53+
/// directory can only be modified by the FUSE client (i.e., the file system has exclusive
54+
/// access), then this should be a large value.
55+
///
56+
/// The default value for this option is 5 seconds.
57+
pub entry_timeout: Duration,
58+
59+
/// Same as `attr_timeout`, override `attr_timeout` config, but only take effect on directories
60+
/// when specified. This is useful to set different timeouts for directories and regular files.
61+
pub dir_attr_timeout: Option<Duration>,
62+
63+
/// Same as `entry_timeout`, override `entry_timeout` config, but only take effect on
64+
/// directories when specified. This is useful to set different timeouts for directories and
65+
/// regular files.
66+
pub dir_entry_timeout: Option<Duration>,
67+
68+
/// The caching policy the file system should use. See the documentation of `CachePolicy` for
69+
/// more details.
70+
pub cache_policy: CachePolicy,
71+
72+
/// Whether the file system should enable writeback caching. This can improve performance as it
73+
/// allows the FUSE client to cache and coalesce multiple writes before sending them to the file
74+
/// system. However, enabling this option can increase the risk of data corruption if the file
75+
/// contents can change without the knowledge of the FUSE client (i.e., the server does **NOT**
76+
/// have exclusive access). Additionally, the file system should have read access to all files
77+
/// in the directory it is serving as the FUSE client may send read requests even for files
78+
/// opened with `O_WRONLY`.
79+
///
80+
/// Therefore callers should only enable this option when they can guarantee that: 1) the file
81+
/// system has exclusive access to the directory and 2) the file system has read permissions for
82+
/// all files in that directory.
83+
///
84+
/// The default value for this option is `false`.
85+
pub writeback: bool,
86+
87+
/// The path of the root directory.
88+
///
89+
/// The default is `/`.
90+
pub root_dir: String,
91+
92+
/// Whether the file system should support Extended Attributes (xattr). Enabling this feature may
93+
/// have a significant impact on performance, especially on write parallelism. This is the result
94+
/// of FUSE attempting to remove the special file privileges after each write request.
95+
///
96+
/// The default value for this options is `false`.
97+
pub xattr: bool,
98+
99+
/// To be compatible with Vfs and PseudoFs, PassthroughFs needs to prepare
100+
/// root inode before accepting INIT request.
101+
///
102+
/// The default value for this option is `true`.
103+
pub do_import: bool,
104+
105+
/// Control whether no_open is allowed.
106+
///
107+
/// The default value for this option is `false`.
108+
pub no_open: bool,
109+
110+
/// Control whether no_opendir is allowed.
111+
///
112+
/// The default value for this option is `false`.
113+
pub no_opendir: bool,
114+
115+
/// Control whether kill_priv_v2 is enabled.
116+
///
117+
/// The default value for this option is `false`.
118+
pub killpriv_v2: bool,
119+
120+
/// Whether to use file handles to reference inodes. We need to be able to open file
121+
/// descriptors for arbitrary inodes, and by default that is done by storing an `O_PATH` FD in
122+
/// `InodeData`. Not least because there is a maximum number of FDs a process can have open
123+
/// users may find it preferable to store a file handle instead, which we can use to open an FD
124+
/// when necessary.
125+
/// So this switch allows to choose between the alternatives: When set to `false`, `InodeData`
126+
/// will store `O_PATH` FDs. Otherwise, we will attempt to generate and store a file handle
127+
/// instead.
128+
///
129+
/// The default is `false`.
130+
pub inode_file_handles: bool,
131+
132+
/// Control whether readdir/readdirplus requests return zero dirent to client, as if the
133+
/// directory is empty even if it has children.
134+
pub no_readdir: bool,
135+
136+
/// Control whether to refuse operations which modify the size of the file. For a share memory
137+
/// file mounted from host, seal_size can prohibit guest to increase the size of
138+
/// share memory file to attack the host.
139+
pub seal_size: bool,
140+
141+
/// Whether count mount ID or not when comparing two inodes. By default we think two inodes
142+
/// are same if their inode number and st_dev are the same. When `enable_mntid` is set as
143+
/// 'true', inode's mount ID will be taken into account as well. For example, bindmount the
144+
/// same file into virtiofs' source dir, the two bindmounted files will be identified as two
145+
/// different inodes when this option is true, so the don't share pagecache.
146+
///
147+
/// The default value for this option is `false`.
148+
pub enable_mntid: bool,
149+
150+
/// What size file supports dax
151+
/// * If dax_file_size == None, DAX will disable to all files.
152+
/// * If dax_file_size == 0, DAX will enable all files.
153+
/// * If dax_file_size == N, DAX will enable only when the file size is greater than or equal
154+
/// to N Bytes.
155+
pub dax_file_size: Option<u64>,
156+
157+
/// Reduce memory consumption by directly use host inode when possible.
158+
///
159+
/// When set to false, a virtual inode number will be allocated for each file managed by
160+
/// the passthroughfs driver. A map is used to maintain the relationship between virtual
161+
/// inode numbers and host file objects.
162+
/// When set to true, the host inode number will be directly used as virtual inode number
163+
/// if it's less than the threshold (1 << 47), so reduce memory consumed by the map.
164+
/// A virtual inode number will still be allocated and maintained if the host inode number
165+
/// is bigger than the threshold.
166+
/// The default value for this option is `false`.
167+
pub use_host_ino: bool,
168+
}
169+
170+
impl Default for Config {
171+
fn default() -> Self {
172+
Config {
173+
entry_timeout: Duration::from_secs(5),
174+
attr_timeout: Duration::from_secs(5),
175+
cache_policy: Default::default(),
176+
writeback: false,
177+
root_dir: String::from("/"),
178+
xattr: false,
179+
do_import: true,
180+
no_open: false,
181+
no_opendir: false,
182+
killpriv_v2: false,
183+
inode_file_handles: false,
184+
no_readdir: false,
185+
seal_size: false,
186+
enable_mntid: false,
187+
dax_file_size: None,
188+
dir_entry_timeout: None,
189+
dir_attr_timeout: None,
190+
use_host_ino: false,
191+
}
192+
}
193+
}

src/passthrough/file_handle.rs

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ extern "C" {
174174

175175
impl FileHandle {
176176
/// Create a file handle for the given file.
177-
pub fn from_name_at(dir_fd: RawFd, path: &CStr) -> io::Result<Self> {
177+
pub fn from_name_at(dir_fd: &impl AsRawFd, path: &CStr) -> io::Result<Self> {
178178
let mut mount_id: libc::c_int = 0;
179179
let mut c_fh = CFileHandle::new(0);
180180

@@ -186,7 +186,7 @@ impl FileHandle {
186186
// structure of the correct size.
187187
let ret = unsafe {
188188
name_to_handle_at(
189-
dir_fd,
189+
dir_fd.as_raw_fd(),
190190
path.as_ptr(),
191191
c_fh.wrapper.as_mut_fam_struct_ptr(),
192192
&mut mount_id,
@@ -214,7 +214,7 @@ impl FileHandle {
214214
// the automount can be triggered by adding a "/" to the end of the pathname.
215215
let ret = unsafe {
216216
name_to_handle_at(
217-
dir_fd,
217+
dir_fd.as_raw_fd(),
218218
path.as_ptr(),
219219
c_fh.wrapper.as_mut_fam_struct_ptr(),
220220
&mut mount_id,
@@ -259,7 +259,7 @@ impl OpenableFileHandle {
259259
/// If `path` is empty, `reopen_dir` may be invoked to duplicate `dir` with custom
260260
/// `libc::open()` flags.
261261
pub fn from_name_at<F>(
262-
dir_fd: RawFd,
262+
dir_fd: &impl AsRawFd,
263263
path: &CStr,
264264
mount_fds: &MountFds,
265265
reopen_dir: F,
@@ -412,9 +412,8 @@ mod tests {
412412
let dir = File::open(topdir).unwrap();
413413
let filename = CString::new("build.rs").unwrap();
414414

415-
let dir_handle =
416-
FileHandle::from_name_at(dir.as_raw_fd(), &CString::new("").unwrap()).unwrap();
417-
let file_handle = FileHandle::from_name_at(dir.as_raw_fd(), &filename).unwrap();
415+
let dir_handle = FileHandle::from_name_at(&dir, &CString::new("").unwrap()).unwrap();
416+
let file_handle = FileHandle::from_name_at(&dir, &filename).unwrap();
418417

419418
assert_eq!(dir_handle.mnt_id, file_handle.mnt_id);
420419
assert_ne!(
@@ -434,13 +433,11 @@ mod tests {
434433
let filename = CString::new("build.rs").unwrap();
435434
let mount_fds = MountFds::new(None).unwrap();
436435

437-
let file_handle = OpenableFileHandle::from_name_at(
438-
dir.as_raw_fd(),
439-
&filename,
440-
&mount_fds,
441-
|_fd, _flags, _mode| File::open(topdir),
442-
)
443-
.unwrap();
436+
let file_handle =
437+
OpenableFileHandle::from_name_at(&dir, &filename, &mount_fds, |_fd, _flags, _mode| {
438+
File::open(topdir)
439+
})
440+
.unwrap();
444441
assert_eq!(file_handle.handle.mnt_id, file_handle.mount_id());
445442

446443
let mut file = file_handle.open(libc::O_RDONLY).unwrap();

src/passthrough/inode_store.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ mod test {
102102
use super::*;
103103

104104
use std::ffi::CStr;
105+
use std::mem::MaybeUninit;
105106
use std::os::unix::io::{AsRawFd, RawFd};
106107
use std::sync::atomic::Ordering;
107108
use vmm_sys_util::tempfile::TempFile;

0 commit comments

Comments
 (0)