diff options
author | Tim Schumacher <timschumi@gmx.de> | 2022-05-13 12:20:57 +0200 |
---|---|---|
committer | Brian Gianforcaro <b.gianfo@gmail.com> | 2022-07-08 22:27:38 +0000 |
commit | dc6016cd18deaeaf6121605540d876169475d491 (patch) | |
tree | 0709f6dbc9d189fc107b4e47704dc6a3e389747e /Kernel | |
parent | 7d3f71a6485791f9fb87621c5a15571889f6c687 (diff) | |
download | serenity-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.cpp | 17 |
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 })); |