mirror of
https://github.com/RGBCube/serenity
synced 2025-05-16 19:55:06 +00:00
Kernel: Synchronize removals from TmpFS inode map
Previously we were uncaching inodes from TmpFSInode::one_ref_left(). This was not safe, since one_ref_left() was effectively being called on a raw pointer after decrementing the local ref count and observing it become 1. There was a race here where someone else could trigger the destructor by unreffing to 0 before one_ref_left() got called, causing us to call one_ref_left() on a deleted inode. We fix this by using the new remove_from_secondary_lists() mechanism in ListedRefCounted and synchronizing all access to the TmpFS inode map with the main Inode::all_instances() lock. There's probably a nicer way to solve this.
This commit is contained in:
parent
3550f12543
commit
08e927f084
3 changed files with 18 additions and 17 deletions
|
@ -37,19 +37,21 @@ Inode& TmpFS::root_inode()
|
|||
|
||||
void TmpFS::register_inode(TmpFSInode& inode)
|
||||
{
|
||||
MutexLocker locker(m_lock);
|
||||
VERIFY(inode.identifier().fsid() == fsid());
|
||||
|
||||
auto index = inode.identifier().index();
|
||||
m_inodes.set(index, inode);
|
||||
Inode::all_instances().with([&](auto&) {
|
||||
auto index = inode.identifier().index();
|
||||
m_inodes.set(index, &inode);
|
||||
});
|
||||
}
|
||||
|
||||
void TmpFS::unregister_inode(InodeIdentifier identifier)
|
||||
{
|
||||
MutexLocker locker(m_lock);
|
||||
VERIFY(identifier.fsid() == fsid());
|
||||
|
||||
m_inodes.remove(identifier.index());
|
||||
Inode::all_instances().with([&](auto&) {
|
||||
m_inodes.remove(identifier.index());
|
||||
});
|
||||
}
|
||||
|
||||
unsigned TmpFS::next_inode_index()
|
||||
|
@ -61,13 +63,13 @@ unsigned TmpFS::next_inode_index()
|
|||
|
||||
ErrorOr<NonnullRefPtr<Inode>> TmpFS::get_inode(InodeIdentifier identifier) const
|
||||
{
|
||||
MutexLocker locker(m_lock, Mutex::Mode::Shared);
|
||||
VERIFY(identifier.fsid() == fsid());
|
||||
|
||||
auto it = m_inodes.find(identifier.index());
|
||||
if (it == m_inodes.end())
|
||||
return ENOENT;
|
||||
return it->value;
|
||||
return Inode::all_instances().with([&](auto&) -> ErrorOr<NonnullRefPtr<Inode>> {
|
||||
VERIFY(identifier.fsid() == fsid());
|
||||
auto it = m_inodes.find(identifier.index());
|
||||
if (it == m_inodes.end())
|
||||
return ENOENT;
|
||||
return *it->value;
|
||||
});
|
||||
}
|
||||
|
||||
TmpFSInode::TmpFSInode(TmpFS& fs, const InodeMetadata& metadata, InodeIdentifier parent)
|
||||
|
@ -363,9 +365,8 @@ ErrorOr<void> TmpFSInode::set_mtime(time_t t)
|
|||
return {};
|
||||
}
|
||||
|
||||
void TmpFSInode::one_ref_left()
|
||||
void TmpFSInode::remove_from_secondary_lists()
|
||||
{
|
||||
// Destroy ourselves.
|
||||
fs().unregister_inode(identifier());
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue