Skip to main content

libfuse_fs/passthrough/
config.rs

1// Copyright (C) 2020-2022 Alibaba Cloud. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4#[cfg(target_os = "macos")]
5use std::num::NonZeroUsize;
6use std::path::PathBuf;
7use std::str::FromStr;
8use std::time::Duration;
9
10use crate::util::mapping::IdMappings;
11use crate::util::whiteout::WhiteoutFormat;
12
13/// The caching policy that the file system should report to the FUSE client. By default the FUSE
14/// protocol uses close-to-open consistency. This means that any cached contents of the file are
15/// invalidated the next time that file is opened.
16#[derive(Debug, Default, Clone, Eq, PartialEq)]
17pub enum CachePolicy {
18    /// The client should never cache file data and all I/O should be directly forwarded to the
19    /// server. This policy must be selected when file contents may change without the knowledge of
20    /// the FUSE client (i.e., the file system does not have exclusive access to the directory).
21    Never,
22
23    /// This is almost same as Never, but it allows page cache of directories, dentries and attr
24    /// cache in guest. In other words, it acts like cache=never for normal files, and like
25    /// cache=always for directories, besides, metadata like dentries and attrs are kept as well.
26    /// This policy can be used if:
27    /// 1. the client wants to use Never policy but it's performance in I/O is not good enough
28    /// 2. the file system has exclusive access to the directory
29    /// 3. cache directory content and other fs metadata can make a difference on performance.
30    Metadata,
31
32    /// The client is free to choose when and how to cache file data. This is the default policy and
33    /// uses close-to-open consistency as described in the enum documentation.
34    #[default]
35    Auto,
36
37    /// The client should always cache file data. This means that the FUSE client will not
38    /// invalidate any cached data that was returned by the file system the last time the file was
39    /// opened. This policy should only be selected when the file system has exclusive access to the
40    /// directory.
41    Always,
42}
43
44impl FromStr for CachePolicy {
45    type Err = &'static str;
46
47    fn from_str(s: &str) -> Result<Self, Self::Err> {
48        match s {
49            "never" | "Never" | "NEVER" | "none" | "None" | "NONE" => Ok(CachePolicy::Never),
50            "metadata" => Ok(CachePolicy::Metadata),
51            "auto" | "Auto" | "AUTO" => Ok(CachePolicy::Auto),
52            "always" | "Always" | "ALWAYS" => Ok(CachePolicy::Always),
53            _ => Err("invalid cache policy"),
54        }
55    }
56}
57
58/// Options that configure the behavior of the passthrough fuse file system.
59#[derive(Debug, Clone, Eq, PartialEq)]
60pub struct Config {
61    /// How long the FUSE client should consider file and directory attributes to be valid. If the
62    /// attributes of a file or directory can only be modified by the FUSE client (i.e., the file
63    /// system has exclusive access), then this should be set to a large value.
64    ///
65    /// The default value for this option is 5 seconds.
66    pub attr_timeout: Duration,
67
68    /// How long the FUSE client should consider directory entries to be valid. If the contents of a
69    /// directory can only be modified by the FUSE client (i.e., the file system has exclusive
70    /// access), then this should be a large value.
71    ///
72    /// The default value for this option is 5 seconds.
73    pub entry_timeout: Duration,
74
75    /// Same as `attr_timeout`, override `attr_timeout` config, but only take effect on directories
76    /// when specified. This is useful to set different timeouts for directories and regular files.
77    pub dir_attr_timeout: Option<Duration>,
78
79    /// Same as `entry_timeout`, override `entry_timeout` config, but only take effect on
80    /// directories when specified. This is useful to set different timeouts for directories and
81    /// regular files.
82    pub dir_entry_timeout: Option<Duration>,
83
84    /// The caching policy the file system should use. See the documentation of `CachePolicy` for
85    /// more details.
86    pub cache_policy: CachePolicy,
87
88    /// Whether the file system should enable writeback caching. This can improve performance as it
89    /// allows the FUSE client to cache and coalesce multiple writes before sending them to the file
90    /// system. However, enabling this option can increase the risk of data corruption if the file
91    /// contents can change without the knowledge of the FUSE client (i.e., the server does **NOT**
92    /// have exclusive access). Additionally, the file system should have read access to all files
93    /// in the directory it is serving as the FUSE client may send read requests even for files
94    /// opened with `O_WRONLY`.
95    ///
96    /// Therefore callers should only enable this option when they can guarantee that: 1) the file
97    /// system has exclusive access to the directory and 2) the file system has read permissions for
98    /// all files in that directory.
99    ///
100    /// The default value for this option is `false`.
101    pub writeback: bool,
102
103    /// The path of the root directory.
104    ///
105    /// The default is `/`.
106    pub root_dir: PathBuf,
107
108    /// Whether the file system should support Extended Attributes (xattr). Enabling this feature may
109    /// have a significant impact on performance, especially on write parallelism. This is the result
110    /// of FUSE attempting to remove the special file privileges after each write request.
111    ///
112    /// The default value for this options is `false`.
113    pub xattr: bool,
114
115    /// To be compatible with Vfs and PseudoFs, PassthroughFs needs to prepare
116    /// root inode before accepting INIT request.
117    ///
118    /// The default value for this option is `true`.
119    pub do_import: bool,
120
121    /// Control whether no_open is allowed.
122    ///
123    /// The default value for this option is `false`.
124    pub no_open: bool,
125
126    /// Control whether no_opendir is allowed.
127    ///
128    /// The default value for this option is `false`.
129    pub no_opendir: bool,
130
131    /// Control whether kill_priv_v2 is enabled.
132    ///
133    /// The default value for this option is `false`.
134    pub killpriv_v2: bool,
135
136    /// Control whether readdir/readdirplus requests return zero dirent to client, as if the
137    /// directory is empty even if it has children.
138    pub no_readdir: bool,
139
140    /// Control whether to refuse operations which modify the size of the file. For a share memory
141    /// file mounted from host, seal_size can prohibit guest to increase the size of
142    /// share memory file to attack the host.
143    pub seal_size: bool,
144
145    /// Whether count mount ID or not when comparing two inodes. By default we think two inodes
146    /// are same if their inode number and st_dev are the same. When `enable_mntid` is set as
147    /// 'true', inode's mount ID will be taken into account as well. For example, bindmount the
148    /// same file into virtiofs' source dir, the two bindmounted files will be identified as two
149    /// different inodes when this option is true, so the don't share pagecache.
150    ///
151    /// The default value for this option is `false`.
152    pub enable_mntid: bool,
153
154    /// What size file supports dax
155    /// * If dax_file_size == None, DAX will disable to all files.
156    /// * If dax_file_size == 0, DAX will enable all files.
157    /// * If dax_file_size == N, DAX will enable only when the file size is greater than or equal
158    ///   to N Bytes.
159    pub dax_file_size: Option<u64>,
160
161    /// Reduce memory consumption by directly use host inode when possible.
162    ///
163    /// When set to false, a virtual inode number will be allocated for each file managed by
164    /// the passthroughfs driver. A map is used to maintain the relationship between virtual
165    /// inode numbers and host file objects.
166    /// When set to true, the host inode number will be directly used as virtual inode number
167    /// if it's less than the threshold (1 << 47), so reduce memory consumed by the map.
168    /// A virtual inode number will still be allocated and maintained if the host inode number
169    /// is bigger than the threshold.
170    /// The default value for this option is `false`.
171    pub use_host_ino: bool,
172
173    /// Whether the file system should honor the O_DIRECT flag. If this option is disabled,
174    /// that flag will be filtered out at `open_inode`.
175    ///
176    /// The default is `true`.
177    pub allow_direct_io: bool,
178
179    pub use_mmap: bool,
180
181    /// The size of the mmap max usage
182    /// The default is `1024 * 1024 * 1024` (1GB).
183    pub max_mmap_size: u64,
184
185    /// UID/GID mapping. Format: `uidmapping=H:T:L[:H2:T2:L2...],gidmapping=H:T:L[:H2:T2:L2...]`
186    pub mapping: IdMappings,
187
188    /// Whiteout format used when this passthrough is layered under overlayfs/unionfs.
189    /// Defaults to `CharDev` on Linux (kernel-overlayfs convention) and to
190    /// `OciWhiteout` on macOS (avoids the root requirement of `mknod` char dev).
191    pub whiteout_format: WhiteoutFormat,
192
193    /// **Experimental configuration knob — semantics not API-stable.**
194    ///
195    /// On macOS, store inode references as path components + lazily-opened
196    /// fds (the `Reopenable` `InodeHandle` variant) instead of always-open
197    /// `O_RDONLY` fds. Lets metadata caching TTLs stay at the crate
198    /// default (5 s) without pinning a real fd per kernel-cached inode.
199    ///
200    /// Lazy is the default and beats the eager fallback by ~2.76× on
201    /// meta-stat in clean same-environment A/B benchmarks. The flag is
202    /// kept as an escape hatch for users who want the eager behaviour
203    /// (e.g. to debug an LRU/path-rewrite issue), but its name and
204    /// semantics may change without notice. Production callers should
205    /// not depend on the eager fallback long-term.
206    ///
207    /// Default on macOS: `true`.
208    #[cfg(target_os = "macos")]
209    pub macos_lazy_inode_fd: bool,
210
211    /// macOS only: hard cap on the number of cached backing fds held by the
212    /// lazy-fd path. When `None` (default), the cap is computed at startup
213    /// as `RLIMIT_NOFILE_soft / 2`. Set explicitly to override (useful for
214    /// tests and constrained environments). Has no effect when
215    /// `macos_lazy_inode_fd == false`.
216    #[cfg(target_os = "macos")]
217    pub macos_lazy_fd_lru_max: Option<NonZeroUsize>,
218}
219
220impl Default for Config {
221    fn default() -> Self {
222        Config {
223            entry_timeout: Duration::from_secs(5),
224            attr_timeout: Duration::from_secs(5),
225            cache_policy: Default::default(),
226            writeback: false,
227            root_dir: PathBuf::from("/"),
228            xattr: false,
229            do_import: true,
230            no_open: false,
231            no_opendir: false,
232            killpriv_v2: false,
233            no_readdir: false,
234            seal_size: false,
235            enable_mntid: false,
236            dax_file_size: None,
237            dir_entry_timeout: None,
238            dir_attr_timeout: None,
239            use_host_ino: false,
240            allow_direct_io: true,
241            use_mmap: false,
242            max_mmap_size: 1024 * 1024 * 1024,
243            mapping: IdMappings::default(),
244            whiteout_format: WhiteoutFormat::default(),
245            #[cfg(target_os = "macos")]
246            macos_lazy_inode_fd: true,
247            #[cfg(target_os = "macos")]
248            macos_lazy_fd_lru_max: None,
249        }
250    }
251}