summaryrefslogtreecommitdiff
path: root/Kernel
diff options
context:
space:
mode:
authorTim Schumacher <timschumi@gmx.de>2022-05-13 12:20:57 +0200
committerBrian Gianforcaro <b.gianfo@gmail.com>2022-07-08 22:27:38 +0000
commitdc6016cd18deaeaf6121605540d876169475d491 (patch)
tree0709f6dbc9d189fc107b4e47704dc6a3e389747e /Kernel
parent7d3f71a6485791f9fb87621c5a15571889f6c687 (diff)
downloadserenity-dc6016cd18deaeaf6121605540d876169475d491.zip
Kernel: Don't fail on unlocking nonexistent file locks
I haven't found any POSIX specification on this, but the Linux kernel appears to handle it like that. This is required by QEMU, as it just bulk-unlocks all its file locking bytes without checking first if they are held.
Diffstat (limited to 'Kernel')
-rw-r--r--Kernel/FileSystem/Inode.cpp17
1 files changed, 7 insertions, 10 deletions
diff --git a/Kernel/FileSystem/Inode.cpp b/Kernel/FileSystem/Inode.cpp
index 04857e8a04..59066cf751 100644
--- a/Kernel/FileSystem/Inode.cpp
+++ b/Kernel/FileSystem/Inode.cpp
@@ -291,18 +291,14 @@ static inline ErrorOr<void> normalize_flock(OpenFileDescription const& descripti
return {};
}
-ErrorOr<void> Inode::can_apply_flock(OpenFileDescription const& description, flock const& new_lock) const
+ErrorOr<void> Inode::can_apply_flock(OpenFileDescription const&, flock const& new_lock) const
{
VERIFY(new_lock.l_whence == SEEK_SET);
+ if (new_lock.l_type == F_UNLCK)
+ return {};
+
return m_flocks.with([&](auto& flocks) -> ErrorOr<void> {
- if (new_lock.l_type == F_UNLCK) {
- for (auto const& lock : flocks) {
- if (&description == lock.owner && lock.start == new_lock.l_start && lock.len == new_lock.l_len)
- return {};
- }
- return EINVAL;
- }
for (auto const& lock : flocks) {
if (!range_overlap(lock.start, lock.len, new_lock.l_start, new_lock.l_len))
continue;
@@ -329,10 +325,11 @@ ErrorOr<void> Inode::apply_flock(Process const& process, OpenFileDescription con
for (size_t i = 0; i < flocks.size(); ++i) {
if (&description == flocks[i].owner && flocks[i].start == new_lock.l_start && flocks[i].len == new_lock.l_len) {
flocks.remove(i);
- return {};
}
}
- return EINVAL;
+
+ // Judging by the Linux implementation, unlocking a non-existent lock also works.
+ return {};
}
TRY(flocks.try_append(Flock { new_lock.l_start, new_lock.l_len, &description, process.pid().value(), new_lock.l_type }));