|
| 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 | +} |
0 commit comments