Skip to content

Commit 7fb0ad7

Browse files
authored
Introduce FileHandle (#1063)
### What does this PR do? This commit introduces a FileHandle concept, allowing us to rig the filesystem up so that we can keep track of bytes lost when files are unlinked and then the last fp is closed. Unfortunately as of this commit the property tests are still failing but it's a start.
1 parent eb78eac commit 7fb0ad7

File tree

3 files changed

+447
-162
lines changed

3 files changed

+447
-162
lines changed

lading/proptest-regressions/generator/file_gen/model.txt

+3
Large diffs are not rendered by default.

lading/src/bin/logrotate_fs.rs

+63-9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use tracing_subscriber::{fmt::format::FmtSpan, util::SubscriberInitExt};
1212
use nix::libc::{self, ENOENT};
1313
use serde::Deserialize;
1414
use std::{
15+
collections::HashMap,
1516
ffi::OsStr,
1617
num::NonZeroU32,
1718
path::PathBuf,
@@ -83,6 +84,8 @@ const TTL: Duration = Duration::from_secs(1); // Attribute cache timeout
8384
#[derive(Debug)]
8485
struct LogrotateFS {
8586
state: Arc<Mutex<model::State>>,
87+
open_files: Arc<Mutex<HashMap<u64, model::FileHandle>>>,
88+
8689
start_time: std::time::Instant,
8790
start_time_system: std::time::SystemTime,
8891
}
@@ -189,7 +192,7 @@ impl Filesystem for LogrotateFS {
189192
&mut self,
190193
_req: &Request,
191194
ino: u64,
192-
_fh: u64,
195+
fh: u64,
193196
offset: i64,
194197
size: u32,
195198
_flags: i32,
@@ -199,13 +202,51 @@ impl Filesystem for LogrotateFS {
199202
let tick = self.get_current_tick();
200203
let mut state = self.state.lock().expect("lock poisoned");
201204

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();
209250
} else {
210251
reply.error(ENOENT);
211252
}
@@ -276,7 +317,19 @@ impl Filesystem for LogrotateFS {
276317

277318
#[tracing::instrument(skip(self, _req, reply))]
278319
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+
}
280333
}
281334
}
282335

@@ -321,6 +374,7 @@ fn main() -> Result<(), Error> {
321374
// Initialize the FUSE filesystem
322375
let fs = LogrotateFS {
323376
state: Arc::new(Mutex::new(state)),
377+
open_files: Arc::new(Mutex::new(HashMap::new())),
324378
start_time: std::time::Instant::now(),
325379
start_time_system: std::time::SystemTime::now(),
326380
};

0 commit comments

Comments
 (0)