Kernel/LibC: Implement flock
This commit is contained in:
parent
0cbc39698c
commit
93e5d09a63
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <BAN/Array.h>
|
#include <BAN/Array.h>
|
||||||
|
#include <BAN/HashSet.h>
|
||||||
#include <kernel/FS/Inode.h>
|
#include <kernel/FS/Inode.h>
|
||||||
#include <kernel/FS/VirtualFileSystem.h>
|
#include <kernel/FS/VirtualFileSystem.h>
|
||||||
|
|
||||||
|
@ -43,6 +44,8 @@ namespace Kernel
|
||||||
void close_all();
|
void close_all();
|
||||||
void close_cloexec();
|
void close_cloexec();
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> flock(int fd, int op);
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> read(int fd, BAN::ByteSpan);
|
BAN::ErrorOr<size_t> read(int fd, BAN::ByteSpan);
|
||||||
BAN::ErrorOr<size_t> write(int fd, BAN::ConstByteSpan);
|
BAN::ErrorOr<size_t> write(int fd, BAN::ConstByteSpan);
|
||||||
|
|
||||||
|
@ -69,6 +72,15 @@ namespace Kernel
|
||||||
off_t offset { 0 };
|
off_t offset { 0 };
|
||||||
int status_flags;
|
int status_flags;
|
||||||
|
|
||||||
|
struct flock_t
|
||||||
|
{
|
||||||
|
bool locked;
|
||||||
|
bool shared;
|
||||||
|
ThreadBlocker thread_blocker;
|
||||||
|
BAN::HashSet<pid_t> lockers;
|
||||||
|
};
|
||||||
|
flock_t flock;
|
||||||
|
|
||||||
friend class BAN::RefPtr<OpenFileDescription>;
|
friend class BAN::RefPtr<OpenFileDescription>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -112,6 +112,8 @@ namespace Kernel
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_symlinkat(const char* path1, int fd, const char* path2);
|
BAN::ErrorOr<long> sys_symlinkat(const char* path1, int fd, const char* path2);
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> sys_flock(int fd, int op);
|
||||||
|
|
||||||
BAN::ErrorOr<long> sys_pread(int fd, void* buffer, size_t count, off_t offset);
|
BAN::ErrorOr<long> sys_pread(int fd, void* buffer, size_t count, off_t offset);
|
||||||
BAN::ErrorOr<long> sys_pwrite(int fd, const void* buffer, size_t count, off_t offset);
|
BAN::ErrorOr<long> sys_pwrite(int fd, const void* buffer, size_t count, off_t offset);
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <kernel/OpenFileDescriptorSet.h>
|
#include <kernel/OpenFileDescriptorSet.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <sys/file.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
|
@ -310,6 +311,17 @@ namespace Kernel
|
||||||
TRY(validate_fd(fd));
|
TRY(validate_fd(fd));
|
||||||
|
|
||||||
auto& open_file = m_open_files[fd];
|
auto& open_file = m_open_files[fd];
|
||||||
|
|
||||||
|
if (auto& flock = open_file.description->flock; Thread::current().has_process() && flock.lockers.contains(Process::current().pid()))
|
||||||
|
{
|
||||||
|
flock.lockers.remove(Process::current().pid());
|
||||||
|
if (flock.lockers.empty())
|
||||||
|
{
|
||||||
|
flock.locked = false;
|
||||||
|
flock.thread_blocker.unblock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
open_file.inode()->on_close(open_file.status_flags());
|
open_file.inode()->on_close(open_file.status_flags());
|
||||||
open_file.description.clear();
|
open_file.description.clear();
|
||||||
open_file.descriptor_flags = 0;
|
open_file.descriptor_flags = 0;
|
||||||
|
@ -336,6 +348,63 @@ namespace Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<void> OpenFileDescriptorSet::flock(int fd, int op)
|
||||||
|
{
|
||||||
|
const auto pid = Process::current().pid();
|
||||||
|
|
||||||
|
LockGuard _(m_mutex);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
TRY(validate_fd(fd));
|
||||||
|
|
||||||
|
auto& flock = m_open_files[fd].description->flock;
|
||||||
|
switch (op & ~LOCK_NB)
|
||||||
|
{
|
||||||
|
case LOCK_UN:
|
||||||
|
flock.lockers.remove(pid);
|
||||||
|
if (flock.lockers.empty())
|
||||||
|
{
|
||||||
|
flock.locked = false;
|
||||||
|
flock.thread_blocker.unblock();
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
case LOCK_SH:
|
||||||
|
if (!flock.locked)
|
||||||
|
{
|
||||||
|
TRY(flock.lockers.insert(pid));
|
||||||
|
flock.locked = true;
|
||||||
|
flock.shared = true;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (flock.shared)
|
||||||
|
{
|
||||||
|
TRY(flock.lockers.insert(pid));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LOCK_EX:
|
||||||
|
if (!flock.locked)
|
||||||
|
{
|
||||||
|
TRY(flock.lockers.insert(pid));
|
||||||
|
flock.locked = true;
|
||||||
|
flock.shared = false;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
if (flock.lockers.contains(pid))
|
||||||
|
return {};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return BAN::Error::from_errno(EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op & LOCK_NB)
|
||||||
|
return BAN::Error::from_errno(EWOULDBLOCK);
|
||||||
|
|
||||||
|
TRY(Thread::current().block_or_eintr_indefinite(flock.thread_blocker, &m_mutex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<size_t> OpenFileDescriptorSet::read(int fd, BAN::ByteSpan buffer)
|
BAN::ErrorOr<size_t> OpenFileDescriptorSet::read(int fd, BAN::ByteSpan buffer)
|
||||||
{
|
{
|
||||||
BAN::RefPtr<Inode> inode;
|
BAN::RefPtr<Inode> inode;
|
||||||
|
|
|
@ -1208,6 +1208,16 @@ namespace Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::ErrorOr<long> Process::sys_flock(int fd, int op)
|
||||||
|
{
|
||||||
|
auto maybe_error = m_open_file_descriptors.flock(fd, op);
|
||||||
|
if (maybe_error.is_error() && maybe_error.error().get_error_code() == ENOMEM)
|
||||||
|
return BAN::Error::from_errno(ENOLCK);
|
||||||
|
if (maybe_error.is_error())
|
||||||
|
return maybe_error.error();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
BAN::ErrorOr<long> Process::sys_pread(int fd, void* buffer, size_t count, off_t offset)
|
BAN::ErrorOr<long> Process::sys_pread(int fd, void* buffer, size_t count, off_t offset)
|
||||||
{
|
{
|
||||||
auto inode = TRY(m_open_file_descriptors.inode_of(fd));
|
auto inode = TRY(m_open_file_descriptors.inode_of(fd));
|
||||||
|
|
|
@ -33,6 +33,7 @@ set(LIBC_SOURCES
|
||||||
strings.cpp
|
strings.cpp
|
||||||
sys/banan-os.cpp
|
sys/banan-os.cpp
|
||||||
sys/epoll.cpp
|
sys/epoll.cpp
|
||||||
|
sys/file.cpp
|
||||||
sys/ioctl.cpp
|
sys/ioctl.cpp
|
||||||
sys/mman.cpp
|
sys/mman.cpp
|
||||||
sys/resource.cpp
|
sys/resource.cpp
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef _SYS_FILE_H
|
||||||
|
#define _SYS_FILE_H 1
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
#define LOCK_UN 0
|
||||||
|
#define LOCK_EX 1
|
||||||
|
#define LOCK_SH 2
|
||||||
|
#define LOCK_NB 4
|
||||||
|
|
||||||
|
int flock(int fd, int op);
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif
|
|
@ -107,6 +107,7 @@ __BEGIN_DECLS
|
||||||
O(SYS_EPOLL_CREATE1, epoll_create1) \
|
O(SYS_EPOLL_CREATE1, epoll_create1) \
|
||||||
O(SYS_EPOLL_CTL, epoll_ctl) \
|
O(SYS_EPOLL_CTL, epoll_ctl) \
|
||||||
O(SYS_EPOLL_PWAIT2, epoll_pwait2) \
|
O(SYS_EPOLL_PWAIT2, epoll_pwait2) \
|
||||||
|
O(SYS_FLOCK, flock) \
|
||||||
|
|
||||||
enum Syscall
|
enum Syscall
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int flock(int fd, int op)
|
||||||
|
{
|
||||||
|
return syscall(SYS_FLOCK, fd, op);
|
||||||
|
}
|
Loading…
Reference in New Issue