@@ -26,16 +26,172 @@ use crate::bytes_to_cstr;
26
26
#[ cfg( any( feature = "vhost-user-fs" , feature = "virtiofs" ) ) ]
27
27
use crate :: transport:: FsCacheReqHandler ;
28
28
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
+ }
30
100
31
101
impl < S : BitmapSlice + Send + Sync > FileSystem for PassthroughFs < S > {
32
102
type Inode = Inode ;
33
103
type Handle = Handle ;
34
104
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
+
35
115
fn lookup ( & self , _ctx : & Context , parent : Self :: Inode , name : & CStr ) -> io:: Result < Entry > {
36
116
if name. to_bytes_with_nul ( ) . contains ( & SLASH_ASCII ) {
37
117
return Err ( einval ( ) ) ;
38
118
}
39
119
self . do_lookup ( parent, name)
40
120
}
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
+ }
41
197
}
0 commit comments