@@ -26,16 +26,172 @@ use crate::bytes_to_cstr;
2626#[ cfg( any( feature = "vhost-user-fs" , feature = "virtiofs" ) ) ]
2727use crate :: transport:: FsCacheReqHandler ;
2828
29- impl < S : BitmapSlice + Send + Sync > PassthroughFs < S > { }
29+ impl < S : BitmapSlice + Send + Sync > PassthroughFs < S > {
30+ fn open_inode ( & self , inode : Inode , flags : i32 ) -> io:: Result < File > {
31+ let data = self . inode_map . get ( inode) ?;
32+ if !is_safe_inode ( data. mode ) {
33+ Err ( ebadf ( ) )
34+ } else {
35+ let new_flags = self . get_writeback_open_flags ( flags) ;
36+ data. open_file ( new_flags | libc:: O_CLOEXEC )
37+ }
38+ }
39+
40+ fn do_open (
41+ & self ,
42+ inode : Inode ,
43+ flags : u32 ,
44+ fuse_flags : u32 ,
45+ ) -> io:: Result < ( Option < Handle > , OpenOptions , Option < u32 > ) > {
46+ let file = self . open_inode ( inode, flags as i32 ) ?;
47+
48+ let data = HandleData :: new ( inode, file, flags) ;
49+ let handle = self . next_handle . fetch_add ( 1 , Ordering :: Relaxed ) ;
50+ self . handle_map . insert ( handle, data) ;
51+
52+ let mut opts = OpenOptions :: empty ( ) ;
53+ match self . cfg . cache_policy {
54+ // We only set the direct I/O option on files.
55+ CachePolicy :: Never => opts. set (
56+ OpenOptions :: DIRECT_IO ,
57+ flags & ( libc:: O_DIRECTORY as u32 ) == 0 ,
58+ ) ,
59+ CachePolicy :: Metadata => {
60+ if flags & ( libc:: O_DIRECTORY as u32 ) == 0 {
61+ opts |= OpenOptions :: DIRECT_IO ;
62+ } else {
63+ opts |= OpenOptions :: KEEP_CACHE ;
64+ }
65+ }
66+ CachePolicy :: Always => {
67+ opts |= OpenOptions :: KEEP_CACHE ;
68+ }
69+ _ => { }
70+ } ;
71+
72+ Ok ( ( Some ( handle) , opts, None ) )
73+ }
74+
75+ fn do_getattr ( & self , inode : Inode , handle : Option < Handle > ) -> io:: Result < ( LibCStat , Duration ) > {
76+ let st;
77+ let data = self . inode_map . get ( inode) . map_err ( |e| {
78+ error ! ( "fuse: do_getattr ino {} Not find err {:?}" , inode, e) ;
79+ e
80+ } ) ?;
81+
82+ // kernel sends 0 as handle in case of no_open, and it depends on fuse server to handle
83+ // this case correctly.
84+ if !self . no_open . load ( Ordering :: Relaxed ) && handle. is_some ( ) {
85+ // Safe as we just checked handle
86+ let hd = self . handle_map . get ( handle. unwrap ( ) , inode) ?;
87+ st = stat ( hd. get_file ( ) ) ;
88+ } else {
89+ st = data. handle . stat ( ) ;
90+ }
91+
92+ let st = st. map_err ( |e| {
93+ error ! ( "fuse: do_getattr stat failed ino {} err {:?}" , inode, e) ;
94+ e
95+ } ) ?;
96+
97+ Ok ( ( st. st , self . cfg . attr_timeout ) )
98+ }
99+ }
30100
31101impl < S : BitmapSlice + Send + Sync > FileSystem for PassthroughFs < S > {
32102 type Inode = Inode ;
33103 type Handle = Handle ;
34104
105+ fn init ( & self , capable : FsOptions ) -> io:: Result < FsOptions > {
106+ if self . cfg . do_import {
107+ self . import ( ) ?;
108+ }
109+
110+ let mut opts = FsOptions :: FILE_OPS ;
111+
112+ Ok ( opts)
113+ }
114+
35115 fn lookup ( & self , _ctx : & Context , parent : Self :: Inode , name : & CStr ) -> io:: Result < Entry > {
36116 if name. to_bytes_with_nul ( ) . contains ( & SLASH_ASCII ) {
37117 return Err ( einval ( ) ) ;
38118 }
39119 self . do_lookup ( parent, name)
40120 }
121+
122+ fn open (
123+ & self ,
124+ _ctx : & Context ,
125+ inode : Inode ,
126+ flags : u32 ,
127+ fuse_flags : u32 ,
128+ ) -> io:: Result < ( Option < Handle > , OpenOptions , Option < u32 > ) > {
129+ if self . no_open . load ( Ordering :: Relaxed ) {
130+ info ! ( "fuse: open is not supported." ) ;
131+ Err ( enosys ( ) )
132+ } else {
133+ self . do_open ( inode, flags, fuse_flags)
134+ }
135+ }
136+
137+ fn create (
138+ & self ,
139+ ctx : & Context ,
140+ parent : Inode ,
141+ name : & CStr ,
142+ args : CreateIn ,
143+ ) -> io:: Result < ( Entry , Option < Handle > , OpenOptions , Option < u32 > ) > {
144+ self . validate_path_component ( name) ?;
145+
146+ let dir = self . inode_map . get ( parent) ?;
147+ let dir_file = dir. get_file ( ) ?;
148+
149+ let new_file = {
150+ let ( _uid, _gid) = set_creds ( ctx. uid , ctx. gid ) ?;
151+
152+ let flags = self . get_writeback_open_flags ( args. flags as i32 ) ;
153+ Self :: create_file_excl ( & dir_file, name, flags, args. mode & !( args. umask & 0o777 ) ) ?
154+ } ;
155+
156+ let entry = self . do_lookup ( parent, name) ?;
157+ let file = match new_file {
158+ // File didn't exist, now created by create_file_excl()
159+ Some ( f) => f,
160+ // File exists, and args.flags doesn't contain O_EXCL. Now let's open it with
161+ // open_inode().
162+ None => {
163+ let ( _uid, _gid) = set_creds ( ctx. uid , ctx. gid ) ?;
164+ self . open_inode ( entry. inode , args. flags as i32 ) ?
165+ }
166+ } ;
167+
168+ let ret_handle = if !self . no_open . load ( Ordering :: Relaxed ) {
169+ let handle = self . next_handle . fetch_add ( 1 , Ordering :: Relaxed ) ;
170+ let data = HandleData :: new ( entry. inode , file, args. flags ) ;
171+
172+ self . handle_map . insert ( handle, data) ;
173+ Some ( handle)
174+ } else {
175+ None
176+ } ;
177+
178+ let mut opts = OpenOptions :: empty ( ) ;
179+ match self . cfg . cache_policy {
180+ CachePolicy :: Never => opts |= OpenOptions :: DIRECT_IO ,
181+ CachePolicy :: Metadata => opts |= OpenOptions :: DIRECT_IO ,
182+ CachePolicy :: Always => opts |= OpenOptions :: KEEP_CACHE ,
183+ _ => { }
184+ } ;
185+
186+ Ok ( ( entry, ret_handle, opts, None ) )
187+ }
188+
189+ fn getattr (
190+ & self ,
191+ _ctx : & Context ,
192+ inode : Inode ,
193+ handle : Option < Handle > ,
194+ ) -> io:: Result < ( LibCStat , Duration ) > {
195+ self . do_getattr ( inode, handle)
196+ }
41197}
0 commit comments