pxar: fuse: avoid possible hash collision in lookup by additional checking against filename

The hash of the filename in the goodbye table items allows to quickly compare to
a hashed filename.
Unfortunately, a matching hash is no garantee for matching filenames as hash
collisions are possible.
This patch fixes such possible collisions by further checking the filenames once
a matching hash has been found.
This introduces no significant extra cost (except for the filename comparison)
for cases with matching hashes, as the lookup call has to seek and read the file
attributes (including the filename) anyway.
In cases with hash collision, the next matching item is read and treaded
analogously (what means we need at least one extra seek).
As collisions should be not that frequent, this should be an acceptable penalty.

Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
This commit is contained in:
Christian Ebner
2019-09-11 17:25:03 +02:00
committed by Dietmar Maurer
parent ba5e67475a
commit 0e20b336e1
2 changed files with 67 additions and 26 deletions

View File

@ -289,7 +289,7 @@ impl<R: Read + Seek, F: Fn(&Path) -> Result<(), Error>> Decoder<R, F> {
/// directories `PXAR_GOODBYE_TAIL_MARKER`. This is not mandatory and it can
/// also directly point to its `PXAR_FILENAME` or `PXAR_ENTRY`, thereby
/// avoiding an additional seek.
pub fn attributes(&mut self, offset: u64) -> Result<(PxarEntry, PxarAttributes, u64), Error> {
pub fn attributes(&mut self, offset: u64) -> Result<(OsString, PxarEntry, PxarAttributes, u64), Error> {
self.seek(SeekFrom::Start(offset))?;
let mut marker: u64 = self.inner.read_item()?;
@ -301,11 +301,14 @@ impl<R: Read + Seek, F: Fn(&Path) -> Result<(), Error>> Decoder<R, F> {
marker = self.inner.read_item()?;
}
if marker == PXAR_FILENAME {
let filename = if marker == PXAR_FILENAME {
let size: u64 = self.inner.read_item()?;
let _filename = self.inner.read_filename(size)?;
let filename = self.inner.read_filename(size)?;
marker = self.inner.read_item()?;
}
filename
} else {
OsString::new()
};
if marker == PXAR_FORMAT_HARDLINK {
let size: u64 = self.inner.read_item()?;
@ -324,12 +327,12 @@ impl<R: Read + Seek, F: Fn(&Path) -> Result<(), Error>> Decoder<R, F> {
_ => 0,
};
Ok((entry, xattr, file_size))
Ok((filename, entry, xattr, file_size))
}
/// Opens the file by validating the given `offset` and returning its attrs,
/// xattrs and size.
pub fn open(&mut self, offset: u64) -> Result<(PxarEntry, PxarAttributes, u64), Error> {
pub fn open(&mut self, offset: u64) -> Result<(OsString, PxarEntry, PxarAttributes, u64), Error> {
self.attributes(offset)
}