@@ -27,34 +27,32 @@ use std::sync::atomic::{AtomicBool, AtomicU32, AtomicU64, AtomicU8, Ordering};
27
27
use std:: sync:: { Arc , Mutex , MutexGuard , RwLock , RwLockWriteGuard } ;
28
28
use std:: time:: Duration ;
29
29
30
- use vm_memory:: ByteValued ;
30
+ use vm_memory:: { bitmap :: BitmapSlice , ByteValued } ;
31
31
32
+ use self :: file_handle:: { FileHandle , MountFds } ;
33
+ use self :: inode_store:: InodeStore ;
32
34
use crate :: abi:: fuse_abi as fuse;
33
35
use crate :: abi:: fuse_abi:: Opcode ;
34
36
use crate :: api:: filesystem:: Entry ;
35
37
use crate :: api:: {
36
38
validate_path_component, BackendFileSystem , CURRENT_DIR_CSTR , EMPTY_CSTR , PARENT_DIR_CSTR ,
37
39
PROC_SELF_FD_CSTR , SLASH_ASCII , VFS_MAX_INO ,
38
40
} ;
39
- use crate :: passthrough:: inode_store:: InodeStore ;
40
- use crate :: BitmapSlice ;
41
41
42
42
#[ cfg( feature = "async-io" ) ]
43
43
mod async_io;
44
44
mod file_handle;
45
45
mod inode_store;
46
46
mod sync_io;
47
47
48
- use file_handle:: { FileHandle , MountFds } ;
49
-
50
48
type Inode = u64 ;
51
49
type Handle = u64 ;
52
50
53
51
/// Maximum host inode number supported by passthroughfs
54
- pub const MAX_HOST_INO : u64 = 0x7fff_ffff_ffff ;
52
+ const MAX_HOST_INO : u64 = 0x7fff_ffff_ffff ;
55
53
56
54
/// the 56th bit used to set the inode to 1 indicates virtual inode
57
- pub const USE_VIRTUAL_INODE_MASK : u64 = 1 << 55 ;
55
+ const VIRTUAL_INODE_FLAG : u64 = 1 << 55 ;
58
56
59
57
/// Used to form a pair of dev and mntid as the key of the map
60
58
#[ derive( Clone , Copy , Default , PartialOrd , Ord , PartialEq , Eq , Debug ) ]
@@ -83,10 +81,9 @@ impl UniqueInodeGenerator {
83
81
}
84
82
85
83
fn get_unique_inode ( & self , alt_key : & InodeAltKey ) -> io:: Result < libc:: ino64_t > {
86
- let id: DevMntIDPair = DevMntIDPair ( alt_key. dev , alt_key. mnt ) ;
87
- let mut id_map_guard = self . dev_mntid_map . lock ( ) . unwrap ( ) ;
88
-
89
84
let unique_id = {
85
+ let id: DevMntIDPair = DevMntIDPair ( alt_key. dev , alt_key. mnt ) ;
86
+ let mut id_map_guard = self . dev_mntid_map . lock ( ) . unwrap ( ) ;
90
87
match id_map_guard. entry ( id) {
91
88
btree_map:: Entry :: Occupied ( v) => * v. get ( ) ,
92
89
btree_map:: Entry :: Vacant ( v) => {
@@ -112,7 +109,7 @@ impl UniqueInodeGenerator {
112
109
format ! ( "the virtual inode excess {}" , MAX_HOST_INO ) ,
113
110
) ) ;
114
111
}
115
- self . next_virtual_inode . fetch_add ( 1 , Ordering :: Relaxed ) | USE_VIRTUAL_INODE_MASK
112
+ self . next_virtual_inode . fetch_add ( 1 , Ordering :: Relaxed ) | VIRTUAL_INODE_FLAG
116
113
} ;
117
114
118
115
Ok ( ( unique_id as u64 ) << 47 | inode)
@@ -464,34 +461,34 @@ impl FromStr for CachePolicy {
464
461
/// Options that configure the behavior of the passthrough fuse file system.
465
462
#[ derive( Debug , Clone , Eq , PartialEq ) ]
466
463
pub struct Config {
464
+ /// How long the FUSE client should consider file and directory attributes to be valid. If the
465
+ /// attributes of a file or directory can only be modified by the FUSE client (i.e., the file
466
+ /// system has exclusive access), then this should be set to a large value.
467
+ ///
468
+ /// The default value for this option is 5 seconds.
469
+ pub attr_timeout : Duration ,
470
+
467
471
/// How long the FUSE client should consider directory entries to be valid. If the contents of a
468
472
/// directory can only be modified by the FUSE client (i.e., the file system has exclusive
469
473
/// access), then this should be a large value.
470
474
///
471
475
/// The default value for this option is 5 seconds.
472
476
pub entry_timeout : Duration ,
473
477
474
- /// How long the FUSE client should consider file and directory attributes to be valid. If the
475
- /// attributes of a file or directory can only be modified by the FUSE client (i.e., the file
476
- /// system has exclusive access), then this should be set to a large value.
477
- ///
478
- /// The default value for this option is 5 seconds.
479
- pub attr_timeout : Duration ,
478
+ /// Same as `attr_timeout`, override `attr_timeout` config, but only take effect on directories
479
+ /// when specified. This is useful to set different timeouts for directories and regular files.
480
+ pub dir_attr_timeout : Option < Duration > ,
480
481
481
482
/// Same as `entry_timeout`, override `entry_timeout` config, but only take effect on
482
483
/// directories when specified. This is useful to set different timeouts for directories and
483
484
/// regular files.
484
485
pub dir_entry_timeout : Option < Duration > ,
485
486
486
- /// Same as `attr_timeout`, override `attr_timeout` config, but only take effect on directories
487
- /// when specified. This is useful to set different timeouts for directories and regular files.
488
- pub dir_attr_timeout : Option < Duration > ,
489
-
490
487
/// The caching policy the file system should use. See the documentation of `CachePolicy` for
491
488
/// more details.
492
489
pub cache_policy : CachePolicy ,
493
490
494
- /// Whether the file system should enabled writeback caching. This can improve performance as it
491
+ /// Whether the file system should enable writeback caching. This can improve performance as it
495
492
/// allows the FUSE client to cache and coalesce multiple writes before sending them to the file
496
493
/// system. However, enabling this option can increase the risk of data corruption if the file
497
494
/// contents can change without the knowledge of the FUSE client (i.e., the server does **NOT**
@@ -792,23 +789,14 @@ impl<S: BitmapSlice + Send + Sync> PassthroughFs<S> {
792
789
return Err ( io:: Error :: last_os_error ( ) ) ;
793
790
}
794
791
795
- // Safe because we know buf len
796
- unsafe {
797
- buf. set_len ( buf_read as usize ) ;
798
- }
792
+ // Safe because we trust the value returned by kernel.
793
+ unsafe { buf. set_len ( buf_read as usize ) } ;
794
+ buf. shrink_to_fit ( ) ;
799
795
800
- if ( buf_read as usize ) < buf. capacity ( ) {
801
- buf. shrink_to_fit ( ) ;
802
-
803
- return Ok ( PathBuf :: from ( OsString :: from_vec ( buf) ) ) ;
804
- }
805
-
806
- error ! (
807
- "fuse: readlinkat return value {} is greater than libc::PATH_MAX({})" ,
808
- buf_read,
809
- libc:: PATH_MAX
810
- ) ;
811
- Err ( io:: Error :: from_raw_os_error ( libc:: EOVERFLOW ) )
796
+ // Be careful:
797
+ // - readlink() does not append a terminating null byte to buf
798
+ // - OsString instances are not NUL terminated
799
+ return Ok ( PathBuf :: from ( OsString :: from_vec ( buf) ) ) ;
812
800
}
813
801
814
802
/// Get the file pathname corresponding to the Inode
@@ -1320,6 +1308,15 @@ macro_rules! scoped_cred {
1320
1308
scoped_cred ! ( ScopedUid , libc:: uid_t, libc:: SYS_setresuid ) ;
1321
1309
scoped_cred ! ( ScopedGid , libc:: gid_t, libc:: SYS_setresgid ) ;
1322
1310
1311
+ fn set_creds (
1312
+ uid : libc:: uid_t ,
1313
+ gid : libc:: gid_t ,
1314
+ ) -> io:: Result < ( Option < ScopedUid > , Option < ScopedGid > ) > {
1315
+ // We have to change the gid before we change the uid because if we change the uid first then we
1316
+ // lose the capability to change the gid. However changing back can happen in any order.
1317
+ ScopedGid :: new ( gid) . and_then ( |gid| Ok ( ( ScopedUid :: new ( uid) ?, gid) ) )
1318
+ }
1319
+
1323
1320
struct CapFsetid { }
1324
1321
1325
1322
impl Drop for CapFsetid {
@@ -1345,15 +1342,6 @@ fn drop_cap_fsetid() -> io::Result<Option<CapFsetid>> {
1345
1342
Ok ( Some ( CapFsetid { } ) )
1346
1343
}
1347
1344
1348
- fn set_creds (
1349
- uid : libc:: uid_t ,
1350
- gid : libc:: gid_t ,
1351
- ) -> io:: Result < ( Option < ScopedUid > , Option < ScopedGid > ) > {
1352
- // We have to change the gid before we change the uid because if we change the uid first then we
1353
- // lose the capability to change the gid. However changing back can happen in any order.
1354
- ScopedGid :: new ( gid) . and_then ( |gid| Ok ( ( ScopedUid :: new ( uid) ?, gid) ) )
1355
- }
1356
-
1357
1345
fn ebadf ( ) -> io:: Error {
1358
1346
io:: Error :: from_raw_os_error ( libc:: EBADF )
1359
1347
}
0 commit comments