refactor(tvix/store/fs): reduce write lock, return children

Very similar to the previous CL

Change-Id: I0df07ddca742b7b9485d48771c8d295dc3aa7136
Reviewed-on: https://cl.tvl.fyi/c/depot/+/9979
Tested-by: BuildkiteCI
Reviewed-by: Connor Brewster <cbrewster@hey.com>
This commit is contained in:
Florian Klink 2023-11-07 11:30:50 +02:00 committed by flokli
parent 2405399580
commit 9e6d89983a

View file

@ -441,65 +441,74 @@ impl FileSystem for TvixStoreFs {
} }
// lookup the inode data. // lookup the inode data.
let mut inode_tracker = self.inode_tracker.write(); let dir_inode_data = {
let dir_inode_data = inode_tracker.get(inode).unwrap(); let inode_tracker = self.inode_tracker.read();
let dir_inode_data = match *dir_inode_data { inode_tracker.get(inode).unwrap()
InodeData::Regular(..) | InodeData::Symlink(..) => { };
warn!("Not a directory");
return Err(io::Error::from_raw_os_error(libc::ENOTDIR)); let children = match *dir_inode_data {
InodeData::Directory(DirectoryInodeData::Populated(ref _digest, ref children)) => {
children.to_vec()
} }
InodeData::Directory(DirectoryInodeData::Sparse(ref directory_digest, _)) => { InodeData::Directory(DirectoryInodeData::Sparse(ref directory_digest, _)) => {
let directory_digest = directory_digest.to_owned(); match self
let directory_service = self.directory_service.clone(); .tokio_handle
let task = self.tokio_handle.spawn(async move { .block_on(self.tokio_handle.spawn({
fetch_directory_inode_data(directory_service, &directory_digest).await let directory_digest = directory_digest.to_owned();
}); let directory_service = self.directory_service.clone();
match self.tokio_handle.block_on(task).unwrap() { async move {
Ok(new_data) => { fetch_directory_inode_data(directory_service, &directory_digest).await
}
}))
.unwrap()
{
Ok(
ref new_data @ InodeData::Directory(DirectoryInodeData::Populated(
ref _digest,
ref children,
)),
) => {
// update data in [self.inode_tracker] with populated variant. // update data in [self.inode_tracker] with populated variant.
// FUTUREWORK: change put to return the data after {
// inserting, so we don't need to lookup a second let mut inode_tracker = self.inode_tracker.write();
// time? inode_tracker.put(new_data.clone());
let ino = inode_tracker.put(new_data.clone()); }
inode_tracker.get(ino).unwrap() children.to_vec()
} }
// we know fetch_directory_inode_data only returns InodeData::Directory(DirectoryInodeData::Populated(..))
Ok(_) => panic!("unexpected type"),
Err(_e) => { Err(_e) => {
return Err(io::Error::from_raw_os_error(libc::EIO)); return Err(io::Error::from_raw_os_error(libc::EIO));
} }
} }
} }
InodeData::Directory(DirectoryInodeData::Populated(..)) => dir_inode_data, InodeData::Regular(..) | InodeData::Symlink(..) => {
return Err(io::Error::from_raw_os_error(libc::ENOTDIR));
}
}; };
// now parent_data can only be InodeData::Directory(DirectoryInodeData::Populated(..)) for (i, (ino, child_node)) in children.iter().skip(offset as usize).enumerate() {
if let InodeData::Directory(DirectoryInodeData::Populated(ref _digest, ref children)) = // the second parameter will become the "offset" parameter on the next call.
*dir_inode_data let written = add_entry(fuse_backend_rs::api::filesystem::DirEntry {
{ ino: *ino,
for (i, (ino, child_node)) in children.iter().skip(offset as usize).enumerate() { offset: offset + i as u64 + 1,
// the second parameter will become the "offset" parameter on the next call. type_: match child_node {
let written = add_entry(fuse_backend_rs::api::filesystem::DirEntry { #[allow(clippy::unnecessary_cast)]
ino: *ino, // libc::S_IFDIR is u32 on Linux and u16 on MacOS
offset: offset + i as u64 + 1, Node::Directory(_) => libc::S_IFDIR as u32,
type_: match child_node { #[allow(clippy::unnecessary_cast)]
#[allow(clippy::unnecessary_cast)] // libc::S_IFDIR is u32 on Linux and u16 on MacOS
// libc::S_IFDIR is u32 on Linux and u16 on MacOS Node::File(_) => libc::S_IFREG as u32,
Node::Directory(_) => libc::S_IFDIR as u32, #[allow(clippy::unnecessary_cast)]
#[allow(clippy::unnecessary_cast)] // libc::S_IFDIR is u32 on Linux and u16 on MacOS
// libc::S_IFDIR is u32 on Linux and u16 on MacOS Node::Symlink(_) => libc::S_IFLNK as u32,
Node::File(_) => libc::S_IFREG as u32, },
#[allow(clippy::unnecessary_cast)] name: child_node.get_name(),
// libc::S_IFDIR is u32 on Linux and u16 on MacOS })?;
Node::Symlink(_) => libc::S_IFLNK as u32, // If the buffer is full, add_entry will return `Ok(0)`.
}, if written == 0 {
name: child_node.get_name(), break;
})?;
// If the buffer is full, add_entry will return `Ok(0)`.
if written == 0 {
break;
}
} }
} else {
panic!("unexpected type")
} }
Ok(()) Ok(())