pxar::fuse: Get rid of broken cacheing

Remove the current caching of attrs and goodbye tables as it is broken anyway.
This will be replaced with a LRU cache.

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
This commit is contained in:
Christian Ebner 2020-01-10 17:37:32 +01:00 committed by Dietmar Maurer
parent 6d20a29d73
commit caa201d895
1 changed files with 14 additions and 36 deletions

View File

@ -32,7 +32,6 @@ const FUSE_ROOT_ID: u64 = 1;
const GOODBYE_ITEM_SIZE: u64 = std::mem::size_of::<PxarGoodbyeItem>() as u64; const GOODBYE_ITEM_SIZE: u64 = std::mem::size_of::<PxarGoodbyeItem>() as u64;
type Inode = u64;
type Offset = u64; type Offset = u64;
/// FFI types for easier readability /// FFI types for easier readability
type Request = *mut c_void; type Request = *mut c_void;
@ -77,8 +76,6 @@ struct FuseArgs {
/// offset within the archive for the i-node given by the caller. /// offset within the archive for the i-node given by the caller.
struct Context { struct Context {
decoder: Decoder, decoder: Decoder,
goodbye_cache: HashMap<Inode, Vec<(PxarGoodbyeItem, Offset, Offset)>>,
attr_cache: Option<(Inode, PxarAttributes)>,
ino_offset: Offset, ino_offset: Offset,
/// HashMap holding the mapping from the child offsets to their parent /// HashMap holding the mapping from the child offsets to their parent
/// offsets. /// offsets.
@ -109,8 +106,9 @@ impl Context {
filename: &CStr, filename: &CStr,
hash: u64, hash: u64,
) -> Result<(u64, PxarEntry, PxarAttributes, u64), i32> { ) -> Result<(u64, PxarEntry, PxarAttributes, u64), i32> {
let gbt = self.goodbye_cache.get(&self.ino_offset) let gbt = self.decoder
.ok_or_else(|| libc::EIO)?; .goodbye_table(None, self.ino_offset + GOODBYE_ITEM_SIZE)
.map_err(|_| libc::EIO)?;
let mut start_idx = 0; let mut start_idx = 0;
let mut skip_multiple = 0; let mut skip_multiple = 0;
loop { loop {
@ -228,23 +226,12 @@ impl Session {
/// default signal handlers. /// default signal handlers.
/// Options have to be provided as comma separated OsStr, e.g. /// Options have to be provided as comma separated OsStr, e.g.
/// ("ro,default_permissions"). /// ("ro,default_permissions").
pub fn new( pub fn new(decoder: Decoder, options: &OsStr, verbose: bool) -> Result<Self, Error> {
mut decoder: Decoder,
options: &OsStr,
verbose: bool,
) -> Result<Self, Error> {
let args = Self::setup_args(options, verbose)?; let args = Self::setup_args(options, verbose)?;
let oprs = Self::setup_callbacks(); let oprs = Self::setup_callbacks();
let root_ino_offset = decoder.root_end_offset() - GOODBYE_ITEM_SIZE;
let root_goodbye_table = decoder.goodbye_table(None, root_ino_offset + GOODBYE_ITEM_SIZE)?;
let mut goodbye_cache = HashMap::new();
goodbye_cache.insert(root_ino_offset, root_goodbye_table);
let ctx = Context { let ctx = Context {
decoder, decoder,
goodbye_cache,
attr_cache: None,
ino_offset: 0, ino_offset: 0,
child_parent: HashMap::new(), child_parent: HashMap::new(),
}; };
@ -414,11 +401,10 @@ impl Session {
let filename = unsafe { CStr::from_ptr(name) }; let filename = unsafe { CStr::from_ptr(name) };
let hash = super::format_definition::compute_goodbye_hash(filename.to_bytes()); let hash = super::format_definition::compute_goodbye_hash(filename.to_bytes());
Self::run_in_context(req, parent, |mut ctx| { Self::run_in_context(req, parent, |ctx| {
// find_ goodbye_entry() will also update the goodbye cache // find_ goodbye_entry() will also update the goodbye cache
let (child_offset, entry, attr, payload_size) = let (child_offset, entry, _attr, payload_size) =
ctx.find_goodbye_entry(&filename, hash)?; ctx.find_goodbye_entry(&filename, hash)?;
ctx.attr_cache = Some((child_offset, attr));
let child_inode = calculate_inode(child_offset, ctx.decoder.root_end_offset()); let child_inode = calculate_inode(child_offset, ctx.decoder.root_end_offset());
let e = EntryParam { let e = EntryParam {
@ -440,11 +426,10 @@ impl Session {
extern "C" fn getattr(req: Request, inode: u64, _fileinfo: MutPtr) { extern "C" fn getattr(req: Request, inode: u64, _fileinfo: MutPtr) {
Self::run_in_context(req, inode, |ctx| { Self::run_in_context(req, inode, |ctx| {
let (_, entry, attr, payload_size) = ctx let (_, entry, _, payload_size) = ctx
.decoder .decoder
.attributes(ctx.ino_offset) .attributes(ctx.ino_offset)
.map_err(|_| libc::EIO)?; .map_err(|_| libc::EIO)?;
ctx.attr_cache = Some((ctx.ino_offset, attr));
let attr = stat(inode, &entry, payload_size)?; let attr = stat(inode, &entry, payload_size)?;
let _res = unsafe { let _res = unsafe {
// Since fs is read-only, the timeout can be max. // Since fs is read-only, the timeout can be max.
@ -500,12 +485,7 @@ impl Session {
/// This simply checks if the inode references a valid directory, no internal /// This simply checks if the inode references a valid directory, no internal
/// state identifies the directory as opened. /// state identifies the directory as opened.
extern "C" fn opendir(req: Request, inode: u64, fileinfo: MutPtr) { extern "C" fn opendir(req: Request, inode: u64, fileinfo: MutPtr) {
Self::run_in_context(req, inode, |ctx| { Self::run_in_context(req, inode, |_ctx| {
let gbt = ctx.decoder
.goodbye_table(None, ctx.ino_offset + GOODBYE_ITEM_SIZE)
.map_err(|_| libc::EIO)?;
ctx.goodbye_cache.insert(ctx.ino_offset, gbt);
let _ret = unsafe { fuse_reply_open(req, fileinfo as MutPtr) }; let _ret = unsafe { fuse_reply_open(req, fileinfo as MutPtr) };
Ok(()) Ok(())
@ -518,19 +498,18 @@ impl Session {
/// `size`, as requested by the caller. /// `size`, as requested by the caller.
/// `offset` identifies the start index of entries to return. This is used on /// `offset` identifies the start index of entries to return. This is used on
/// repeated calls, occurring if not all entries fitted into the buffer. /// repeated calls, occurring if not all entries fitted into the buffer.
/// The goodbye table of the directory is cached in order to speedup repeated
/// calls occurring when not all entries fitted in the reply buffer.
extern "C" fn readdir(req: Request, inode: u64, size: size_t, offset: c_int, _fileinfo: MutPtr) { extern "C" fn readdir(req: Request, inode: u64, size: size_t, offset: c_int, _fileinfo: MutPtr) {
let offset = offset as usize; let offset = offset as usize;
Self::run_in_context(req, inode, |ctx| { Self::run_in_context(req, inode, |ctx| {
let gb_table = ctx.goodbye_cache.get(&ctx.ino_offset) let gbt = ctx.decoder
.ok_or_else(|| libc::EIO)?; .goodbye_table(None, ctx.ino_offset + GOODBYE_ITEM_SIZE)
let n_entries = gb_table.len(); .map_err(|_| libc::EIO)?;
let n_entries = gbt.len();
let mut buf = ReplyBuf::new(req, size, offset); let mut buf = ReplyBuf::new(req, size, offset);
if offset < n_entries { if offset < n_entries {
for e in gb_table[offset..gb_table.len()].iter() { for e in gbt[offset..gbt.len()].iter() {
let (filename, entry, _, payload_size) = let (filename, entry, _, payload_size) =
ctx.decoder.attributes(e.1).map_err(|_| libc::EIO)?; ctx.decoder.attributes(e.1).map_err(|_| libc::EIO)?;
let name = CString::new(filename.as_bytes()).map_err(|_| libc::EIO)?; let name = CString::new(filename.as_bytes()).map_err(|_| libc::EIO)?;
@ -585,8 +564,7 @@ impl Session {
} }
extern "C" fn releasedir(req: Request, inode: u64, _fileinfo: MutPtr) { extern "C" fn releasedir(req: Request, inode: u64, _fileinfo: MutPtr) {
Self::run_in_context(req, inode, |ctx| { Self::run_in_context(req, inode, |_ctx| {
let _gbt = ctx.goodbye_cache.remove(&ctx.ino_offset);
Ok(()) Ok(())
}); });
} }