mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 03:58:12 +00:00
Kernel: Protect Inode flock list with spinlock instead of mutex
This commit is contained in:
parent
a81aebfd6e
commit
e7dc9f71b8
2 changed files with 45 additions and 48 deletions
|
@ -289,27 +289,26 @@ ErrorOr<void> Inode::can_apply_flock(OpenFileDescription const& description, flo
|
||||||
{
|
{
|
||||||
VERIFY(new_lock.l_whence == SEEK_SET);
|
VERIFY(new_lock.l_whence == SEEK_SET);
|
||||||
|
|
||||||
MutexLocker locker(m_inode_lock, Mutex::Mode::Shared);
|
return m_flocks.with([&](auto& flocks) -> ErrorOr<void> {
|
||||||
|
if (new_lock.l_type == F_UNLCK) {
|
||||||
if (new_lock.l_type == F_UNLCK) {
|
for (auto const& lock : flocks) {
|
||||||
for (auto const& lock : m_flocks) {
|
if (&description == lock.owner && lock.start == new_lock.l_start && lock.len == new_lock.l_len)
|
||||||
if (&description == lock.owner && lock.start == new_lock.l_start && lock.len == new_lock.l_len)
|
return {};
|
||||||
return {};
|
}
|
||||||
|
return EINVAL;
|
||||||
}
|
}
|
||||||
return EINVAL;
|
for (auto const& lock : flocks) {
|
||||||
}
|
if (!range_overlap(lock.start, lock.len, new_lock.l_start, new_lock.l_len))
|
||||||
|
continue;
|
||||||
|
|
||||||
for (auto const& lock : m_flocks) {
|
if (new_lock.l_type == F_RDLCK && lock.type == F_WRLCK)
|
||||||
if (!range_overlap(lock.start, lock.len, new_lock.l_start, new_lock.l_len))
|
return EAGAIN;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (new_lock.l_type == F_RDLCK && lock.type == F_WRLCK)
|
if (new_lock.l_type == F_WRLCK)
|
||||||
return EAGAIN;
|
return EAGAIN;
|
||||||
|
}
|
||||||
if (new_lock.l_type == F_WRLCK)
|
return {};
|
||||||
return EAGAIN;
|
});
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> Inode::apply_flock(Process const& process, OpenFileDescription const& description, Userspace<flock const*> input_lock)
|
ErrorOr<void> Inode::apply_flock(Process const& process, OpenFileDescription const& description, Userspace<flock const*> input_lock)
|
||||||
|
@ -317,22 +316,22 @@ ErrorOr<void> Inode::apply_flock(Process const& process, OpenFileDescription con
|
||||||
auto new_lock = TRY(copy_typed_from_user(input_lock));
|
auto new_lock = TRY(copy_typed_from_user(input_lock));
|
||||||
TRY(normalize_flock(description, new_lock));
|
TRY(normalize_flock(description, new_lock));
|
||||||
|
|
||||||
MutexLocker locker(m_inode_lock);
|
return m_flocks.with([&](auto& flocks) -> ErrorOr<void> {
|
||||||
|
TRY(can_apply_flock(description, new_lock));
|
||||||
|
|
||||||
TRY(can_apply_flock(description, new_lock));
|
if (new_lock.l_type == F_UNLCK) {
|
||||||
|
for (size_t i = 0; i < flocks.size(); ++i) {
|
||||||
if (new_lock.l_type == F_UNLCK) {
|
if (&description == flocks[i].owner && flocks[i].start == new_lock.l_start && flocks[i].len == new_lock.l_len) {
|
||||||
for (size_t i = 0; i < m_flocks.size(); ++i) {
|
flocks.remove(i);
|
||||||
if (&description == m_flocks[i].owner && m_flocks[i].start == new_lock.l_start && m_flocks[i].len == new_lock.l_len) {
|
return {};
|
||||||
m_flocks.remove(i);
|
}
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
return EINVAL;
|
||||||
}
|
}
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
TRY(m_flocks.try_append(Flock { new_lock.l_start, new_lock.l_len, &description, process.pid().value(), new_lock.l_type }));
|
TRY(flocks.try_append(Flock { new_lock.l_start, new_lock.l_len, &description, process.pid().value(), new_lock.l_type }));
|
||||||
return {};
|
return {};
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<void> Inode::get_flock(OpenFileDescription const& description, Userspace<flock*> reference_lock) const
|
ErrorOr<void> Inode::get_flock(OpenFileDescription const& description, Userspace<flock*> reference_lock) const
|
||||||
|
@ -341,31 +340,29 @@ ErrorOr<void> Inode::get_flock(OpenFileDescription const& description, Userspace
|
||||||
TRY(copy_from_user(&lookup, reference_lock));
|
TRY(copy_from_user(&lookup, reference_lock));
|
||||||
TRY(normalize_flock(description, lookup));
|
TRY(normalize_flock(description, lookup));
|
||||||
|
|
||||||
MutexLocker locker(m_inode_lock, Mutex::Mode::Shared);
|
return m_flocks.with([&](auto& flocks) {
|
||||||
|
for (auto const& lock : flocks) {
|
||||||
|
if (!range_overlap(lock.start, lock.len, lookup.l_start, lookup.l_len))
|
||||||
|
continue;
|
||||||
|
|
||||||
for (auto const& lock : m_flocks) {
|
if ((lookup.l_type == F_RDLCK && lock.type == F_WRLCK) || lookup.l_type == F_WRLCK) {
|
||||||
if (!range_overlap(lock.start, lock.len, lookup.l_start, lookup.l_len))
|
lookup = { lock.type, SEEK_SET, lock.start, lock.len, lock.pid };
|
||||||
continue;
|
return copy_to_user(reference_lock, &lookup);
|
||||||
|
}
|
||||||
if ((lookup.l_type == F_RDLCK && lock.type == F_WRLCK) || lookup.l_type == F_WRLCK) {
|
|
||||||
lookup = { lock.type, SEEK_SET, lock.start, lock.len, lock.pid };
|
|
||||||
return copy_to_user(reference_lock, &lookup);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
lookup.l_type = F_UNLCK;
|
lookup.l_type = F_UNLCK;
|
||||||
return copy_to_user(reference_lock, &lookup);
|
return copy_to_user(reference_lock, &lookup);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inode::remove_flocks_for_description(OpenFileDescription const& description)
|
void Inode::remove_flocks_for_description(OpenFileDescription const& description)
|
||||||
{
|
{
|
||||||
MutexLocker locker(m_inode_lock);
|
m_flocks.with([&](auto& flocks) {
|
||||||
|
flocks.remove_all_matching([&](auto& entry) { return entry.owner == &description; });
|
||||||
for (size_t i = 0; i < m_flocks.size(); ++i) {
|
});
|
||||||
if (&description == m_flocks[i].owner)
|
|
||||||
m_flocks.remove(i--);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Inode::has_watchers() const
|
bool Inode::has_watchers() const
|
||||||
{
|
{
|
||||||
return !m_watchers.with([&](auto& watchers) { return watchers.is_empty(); });
|
return !m_watchers.with([&](auto& watchers) { return watchers.is_empty(); });
|
||||||
|
|
|
@ -131,7 +131,7 @@ private:
|
||||||
short type;
|
short type;
|
||||||
};
|
};
|
||||||
|
|
||||||
Vector<Flock> m_flocks;
|
SpinlockProtected<Vector<Flock>> m_flocks;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using AllInstancesList = IntrusiveList<&Inode::m_inode_list_node>;
|
using AllInstancesList = IntrusiveList<&Inode::m_inode_list_node>;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue