@@ -301,6 +301,47 @@ pub struct PassthroughFs {
301
301
302
302
impl PassthroughFs {
303
303
pub fn new ( cfg : Config ) -> io:: Result < PassthroughFs > {
304
+ // Initialze inodes with root directory already open
305
+ let inodes = {
306
+ let mut inodes = MultikeyBTreeMap :: new ( ) ;
307
+
308
+ let root = CString :: new ( cfg. root_dir . as_str ( ) ) . expect ( "CString::new failed" ) ;
309
+
310
+ // Safe because this doesn't modify any memory and we check the return value.
311
+ // We use `O_PATH` because we just want this for traversing the directory tree
312
+ // and not for actually reading the contents.
313
+ let fd = unsafe {
314
+ libc:: openat (
315
+ libc:: AT_FDCWD ,
316
+ root. as_ptr ( ) ,
317
+ libc:: O_PATH | libc:: O_NOFOLLOW | libc:: O_CLOEXEC ,
318
+ )
319
+ } ;
320
+ if fd < 0 {
321
+ return Err ( io:: Error :: last_os_error ( ) ) ;
322
+ }
323
+
324
+ // Safe because we just opened this fd above.
325
+ let f = unsafe { File :: from_raw_fd ( fd) } ;
326
+
327
+ let st = stat ( & f) ?;
328
+
329
+ // Not sure why the root inode gets a refcount of 2 but that's what libfuse does.
330
+ inodes. insert (
331
+ fuse:: ROOT_ID ,
332
+ InodeAltKey {
333
+ ino : st. st_ino ,
334
+ dev : st. st_dev ,
335
+ } ,
336
+ Arc :: new ( InodeData {
337
+ inode : fuse:: ROOT_ID ,
338
+ file : f,
339
+ refcount : AtomicU64 :: new ( 2 ) ,
340
+ } ) ,
341
+ ) ;
342
+ inodes
343
+ } ;
344
+
304
345
let fd = if let Some ( fd) = cfg. proc_sfd_rawfd {
305
346
fd
306
347
} else {
@@ -326,7 +367,7 @@ impl PassthroughFs {
326
367
let proc_self_fd = unsafe { File :: from_raw_fd ( fd) } ;
327
368
328
369
Ok ( PassthroughFs {
329
- inodes : RwLock :: new ( MultikeyBTreeMap :: new ( ) ) ,
370
+ inodes : RwLock :: new ( inodes ) ,
330
371
next_inode : AtomicU64 :: new ( fuse:: ROOT_ID + 2 ) ,
331
372
init_inode : fuse:: ROOT_ID + 1 ,
332
373
@@ -683,48 +724,11 @@ impl FileSystem for PassthroughFs {
683
724
type Handle = Handle ;
684
725
685
726
fn init ( & self , capable : FsOptions ) -> io:: Result < FsOptions > {
686
- let root = CString :: new ( self . cfg . root_dir . as_str ( ) ) . expect ( "CString::new failed" ) ;
687
-
688
- // Safe because this doesn't modify any memory and we check the return value.
689
- // We use `O_PATH` because we just want this for traversing the directory tree
690
- // and not for actually reading the contents.
691
- let fd = unsafe {
692
- libc:: openat (
693
- libc:: AT_FDCWD ,
694
- root. as_ptr ( ) ,
695
- libc:: O_PATH | libc:: O_NOFOLLOW | libc:: O_CLOEXEC ,
696
- )
697
- } ;
698
- if fd < 0 {
699
- return Err ( io:: Error :: last_os_error ( ) ) ;
700
- }
701
-
702
- // Safe because we just opened this fd above.
703
- let f = unsafe { File :: from_raw_fd ( fd) } ;
704
-
705
- let st = stat ( & f) ?;
706
-
707
727
// Safe because this doesn't modify any memory and there is no need to check the return
708
728
// value because this system call always succeeds. We need to clear the umask here because
709
729
// we want the client to be able to set all the bits in the mode.
710
730
unsafe { libc:: umask ( 0o000 ) } ;
711
731
712
- let mut inodes = self . inodes . write ( ) . unwrap ( ) ;
713
-
714
- // Not sure why the root inode gets a refcount of 2 but that's what libfuse does.
715
- inodes. insert (
716
- fuse:: ROOT_ID ,
717
- InodeAltKey {
718
- ino : st. st_ino ,
719
- dev : st. st_dev ,
720
- } ,
721
- Arc :: new ( InodeData {
722
- inode : fuse:: ROOT_ID ,
723
- file : f,
724
- refcount : AtomicU64 :: new ( 2 ) ,
725
- } ) ,
726
- ) ;
727
-
728
732
let mut opts = FsOptions :: DO_READDIRPLUS | FsOptions :: READDIRPLUS_AUTO ;
729
733
if self . cfg . writeback && capable. contains ( FsOptions :: WRITEBACK_CACHE ) {
730
734
opts |= FsOptions :: WRITEBACK_CACHE ;
0 commit comments