@@ -12,6 +12,7 @@ use tracing_subscriber::{fmt::format::FmtSpan, util::SubscriberInitExt};
12
12
use nix:: libc:: { self , ENOENT } ;
13
13
use serde:: Deserialize ;
14
14
use std:: {
15
+ collections:: HashMap ,
15
16
ffi:: OsStr ,
16
17
num:: NonZeroU32 ,
17
18
path:: PathBuf ,
@@ -83,6 +84,8 @@ const TTL: Duration = Duration::from_secs(1); // Attribute cache timeout
83
84
#[ derive( Debug ) ]
84
85
struct LogrotateFS {
85
86
state : Arc < Mutex < model:: State > > ,
87
+ open_files : Arc < Mutex < HashMap < u64 , model:: FileHandle > > > ,
88
+
86
89
start_time : std:: time:: Instant ,
87
90
start_time_system : std:: time:: SystemTime ,
88
91
}
@@ -189,7 +192,7 @@ impl Filesystem for LogrotateFS {
189
192
& mut self ,
190
193
_req : & Request ,
191
194
ino : u64 ,
192
- _fh : u64 ,
195
+ fh : u64 ,
193
196
offset : i64 ,
194
197
size : u32 ,
195
198
_flags : i32 ,
@@ -199,13 +202,51 @@ impl Filesystem for LogrotateFS {
199
202
let tick = self . get_current_tick ( ) ;
200
203
let mut state = self . state . lock ( ) . expect ( "lock poisoned" ) ;
201
204
202
- // NOTE this call to State::read is almost surely allocating. It'd be
203
- // pretty slick if we could get the buffer directly from the OS to pass
204
- // down for writing but we can't. I suppose we could send up the raw
205
- // blocks and then chain them together as needed but absent a compelling
206
- // reason to do that the simplicity of this API is nice.
207
- if let Some ( data) = state. read ( ino as usize , offset as usize , size as usize , tick) {
208
- reply. data ( & data) ;
205
+ // Get the FileHandle from fh
206
+ let file_handle = {
207
+ let open_files = self . open_files . lock ( ) . expect ( "lock poisoned" ) ;
208
+ open_files. get ( & fh) . cloned ( )
209
+ } ;
210
+
211
+ if let Some ( file_handle) = file_handle {
212
+ assert ! (
213
+ file_handle. inode( ) as u64 == ino,
214
+ "file handle inode and passed ino do not match"
215
+ ) ;
216
+ if let Some ( data) = state. read ( file_handle, offset as usize , size as usize , tick) {
217
+ reply. data ( & data) ;
218
+ } else {
219
+ reply. error ( ENOENT ) ;
220
+ }
221
+ } else {
222
+ reply. error ( ENOENT ) ;
223
+ }
224
+ }
225
+
226
+ #[ tracing:: instrument( skip( self , _req, reply) ) ]
227
+ fn release (
228
+ & mut self ,
229
+ _req : & Request ,
230
+ _ino : u64 ,
231
+ fh : u64 ,
232
+ _flags : i32 ,
233
+ _lock_owner : Option < u64 > ,
234
+ _flush : bool ,
235
+ reply : fuser:: ReplyEmpty ,
236
+ ) {
237
+ let tick = self . get_current_tick ( ) ;
238
+ let mut state = self . state . lock ( ) . expect ( "lock poisoned" ) ;
239
+
240
+ // Remove the FileHandle from the mapping
241
+ let file_handle = {
242
+ let mut open_files = self . open_files . lock ( ) . expect ( "lock poisoned" ) ;
243
+ open_files. remove ( & fh)
244
+ } ;
245
+
246
+ if let Some ( file_handle) = file_handle {
247
+ // Close the file in the state
248
+ state. close_file ( tick, file_handle) ;
249
+ reply. ok ( ) ;
209
250
} else {
210
251
reply. error ( ENOENT ) ;
211
252
}
@@ -276,7 +317,19 @@ impl Filesystem for LogrotateFS {
276
317
277
318
#[ tracing:: instrument( skip( self , _req, reply) ) ]
278
319
fn open ( & mut self , _req : & Request , ino : u64 , flags : i32 , reply : fuser:: ReplyOpen ) {
279
- reply. opened ( ino, flags as u32 ) ;
320
+ let tick = self . get_current_tick ( ) ;
321
+ let mut state = self . state . lock ( ) . expect ( "lock poisoned" ) ;
322
+
323
+ if let Some ( file_handle) = state. open_file ( tick, ino as usize ) {
324
+ let fh = file_handle. id ( ) ;
325
+ {
326
+ let mut open_files = self . open_files . lock ( ) . expect ( "lock poisoned" ) ;
327
+ open_files. insert ( fh, file_handle) ;
328
+ }
329
+ reply. opened ( fh, flags as u32 ) ;
330
+ } else {
331
+ reply. error ( ENOENT ) ;
332
+ }
280
333
}
281
334
}
282
335
@@ -321,6 +374,7 @@ fn main() -> Result<(), Error> {
321
374
// Initialize the FUSE filesystem
322
375
let fs = LogrotateFS {
323
376
state : Arc :: new ( Mutex :: new ( state) ) ,
377
+ open_files : Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ,
324
378
start_time : std:: time:: Instant :: now ( ) ,
325
379
start_time_system : std:: time:: SystemTime :: now ( ) ,
326
380
} ;
0 commit comments