@@ -301,6 +301,47 @@ pub struct PassthroughFs {
301301
302302impl PassthroughFs {
303303 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+
304345 let fd = if let Some ( fd) = cfg. proc_sfd_rawfd {
305346 fd
306347 } else {
@@ -326,7 +367,7 @@ impl PassthroughFs {
326367 let proc_self_fd = unsafe { File :: from_raw_fd ( fd) } ;
327368
328369 Ok ( PassthroughFs {
329- inodes : RwLock :: new ( MultikeyBTreeMap :: new ( ) ) ,
370+ inodes : RwLock :: new ( inodes ) ,
330371 next_inode : AtomicU64 :: new ( fuse:: ROOT_ID + 2 ) ,
331372 init_inode : fuse:: ROOT_ID + 1 ,
332373
@@ -683,48 +724,11 @@ impl FileSystem for PassthroughFs {
683724 type Handle = Handle ;
684725
685726 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-
707727 // Safe because this doesn't modify any memory and there is no need to check the return
708728 // value because this system call always succeeds. We need to clear the umask here because
709729 // we want the client to be able to set all the bits in the mode.
710730 unsafe { libc:: umask ( 0o000 ) } ;
711731
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-
728732 let mut opts = FsOptions :: DO_READDIRPLUS | FsOptions :: READDIRPLUS_AUTO ;
729733 if self . cfg . writeback && capable. contains ( FsOptions :: WRITEBACK_CACHE ) {
730734 opts |= FsOptions :: WRITEBACK_CACHE ;
0 commit comments