mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-22 06:57:51 +00:00
parent
abe76e0d93
commit
9cdc24bd32
@ -41,6 +41,18 @@
|
|||||||
#include "libc_errno.h"
|
#include "libc_errno.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
|
static Genode::Lock &vfs_lock()
|
||||||
|
{
|
||||||
|
static Genode::Lock _vfs_lock;
|
||||||
|
return _vfs_lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define VFS_THREAD_SAFE(code) ({ \
|
||||||
|
Genode::Lock::Guard g(vfs_lock()); \
|
||||||
|
code; \
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
static Vfs::Vfs_handle *vfs_handle(Libc::File_descriptor *fd)
|
static Vfs::Vfs_handle *vfs_handle(Libc::File_descriptor *fd)
|
||||||
{
|
{
|
||||||
@ -137,10 +149,11 @@ namespace Libc {
|
|||||||
{
|
{
|
||||||
Vfs::Vfs_handle *handle;
|
Vfs::Vfs_handle *handle;
|
||||||
Check(Vfs::Vfs_handle *handle) : handle(handle) { }
|
Check(Vfs::Vfs_handle *handle) : handle(handle) { }
|
||||||
bool suspend() override { return !handle->fs().notify_read_ready(handle); }
|
bool suspend() override {
|
||||||
|
return !VFS_THREAD_SAFE(handle->fs().notify_read_ready(handle)); }
|
||||||
} check(handle);
|
} check(handle);
|
||||||
|
|
||||||
while (!handle->fs().notify_read_ready(handle))
|
while (!VFS_THREAD_SAFE(handle->fs().notify_read_ready(handle)))
|
||||||
Libc::suspend(check);
|
Libc::suspend(check);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,7 +164,7 @@ namespace Libc {
|
|||||||
|
|
||||||
notify_read_ready(handle);
|
notify_read_ready(handle);
|
||||||
|
|
||||||
return handle->fs().read_ready(handle);
|
return VFS_THREAD_SAFE(handle->fs().read_ready(handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -221,7 +234,7 @@ Libc::File_descriptor *Libc::Vfs_plugin::open(char const *path, int flags,
|
|||||||
|
|
||||||
while (handle == 0) {
|
while (handle == 0) {
|
||||||
|
|
||||||
switch (_root_dir.open(path, flags, &handle, _alloc)) {
|
switch (VFS_THREAD_SAFE(_root_dir.open(path, flags, &handle, _alloc))) {
|
||||||
|
|
||||||
case Result::OPEN_OK:
|
case Result::OPEN_OK:
|
||||||
break;
|
break;
|
||||||
@ -238,7 +251,7 @@ Libc::File_descriptor *Libc::Vfs_plugin::open(char const *path, int flags,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* O_CREAT is set, so try to create the file */
|
/* O_CREAT is set, so try to create the file */
|
||||||
switch (_root_dir.open(path, flags | O_EXCL, &handle, _alloc)) {
|
switch (VFS_THREAD_SAFE(_root_dir.open(path, flags | O_EXCL, &handle, _alloc))) {
|
||||||
|
|
||||||
case Result::OPEN_OK:
|
case Result::OPEN_OK:
|
||||||
break;
|
break;
|
||||||
@ -299,7 +312,7 @@ int Libc::Vfs_plugin::close(Libc::File_descriptor *fd)
|
|||||||
{
|
{
|
||||||
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
Vfs::Vfs_handle *handle = vfs_handle(fd);
|
||||||
_vfs_sync(handle);
|
_vfs_sync(handle);
|
||||||
handle->close();
|
VFS_THREAD_SAFE(handle->close());
|
||||||
Libc::file_descriptor_allocator()->free(fd);
|
Libc::file_descriptor_allocator()->free(fd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -339,9 +352,9 @@ int Libc::Vfs_plugin::mkdir(const char *path, mode_t mode)
|
|||||||
|
|
||||||
typedef Vfs::Directory_service::Opendir_result Opendir_result;
|
typedef Vfs::Directory_service::Opendir_result Opendir_result;
|
||||||
|
|
||||||
switch (_root_dir.opendir(path, true, &dir_handle, _alloc)) {
|
switch (VFS_THREAD_SAFE(_root_dir.opendir(path, true, &dir_handle, _alloc))) {
|
||||||
case Opendir_result::OPENDIR_OK:
|
case Opendir_result::OPENDIR_OK:
|
||||||
dir_handle->close();
|
VFS_THREAD_SAFE(dir_handle->close());
|
||||||
break;
|
break;
|
||||||
case Opendir_result::OPENDIR_ERR_LOOKUP_FAILED:
|
case Opendir_result::OPENDIR_ERR_LOOKUP_FAILED:
|
||||||
return Errno(ENOENT);
|
return Errno(ENOENT);
|
||||||
@ -372,7 +385,7 @@ int Libc::Vfs_plugin::stat(char const *path, struct stat *buf)
|
|||||||
|
|
||||||
Vfs::Directory_service::Stat stat;
|
Vfs::Directory_service::Stat stat;
|
||||||
|
|
||||||
switch (_root_dir.stat(path, stat)) {
|
switch (VFS_THREAD_SAFE(_root_dir.stat(path, stat))) {
|
||||||
case Result::STAT_ERR_NO_ENTRY: errno = ENOENT; return -1;
|
case Result::STAT_ERR_NO_ENTRY: errno = ENOENT; return -1;
|
||||||
case Result::STAT_ERR_NO_PERM: errno = EACCES; return -1;
|
case Result::STAT_ERR_NO_PERM: errno = EACCES; return -1;
|
||||||
case Result::STAT_OK: break;
|
case Result::STAT_OK: break;
|
||||||
@ -396,7 +409,7 @@ ssize_t Libc::Vfs_plugin::write(Libc::File_descriptor *fd, const void *buf,
|
|||||||
if (fd->flags & O_NONBLOCK) {
|
if (fd->flags & O_NONBLOCK) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
out_result = handle->fs().write(handle, (char const *)buf, count, out_count);
|
out_result = VFS_THREAD_SAFE(handle->fs().write(handle, (char const *)buf, count, out_count));
|
||||||
} catch (Vfs::File_io_service::Insufficient_buffer) { }
|
} catch (Vfs::File_io_service::Insufficient_buffer) { }
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@ -421,8 +434,8 @@ ssize_t Libc::Vfs_plugin::write(Libc::File_descriptor *fd, const void *buf,
|
|||||||
bool suspend() override
|
bool suspend() override
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
out_result = handle->fs().write(handle, (char const *)buf,
|
out_result = VFS_THREAD_SAFE(handle->fs().write(handle, (char const *)buf,
|
||||||
count, out_count);
|
count, out_count));
|
||||||
retry = false;
|
retry = false;
|
||||||
} catch (Vfs::File_io_service::Insufficient_buffer) {
|
} catch (Vfs::File_io_service::Insufficient_buffer) {
|
||||||
retry = true;
|
retry = true;
|
||||||
@ -446,7 +459,7 @@ ssize_t Libc::Vfs_plugin::write(Libc::File_descriptor *fd, const void *buf,
|
|||||||
case Result::WRITE_OK: break;
|
case Result::WRITE_OK: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle->advance_seek(out_count);
|
VFS_THREAD_SAFE(handle->advance_seek(out_count));
|
||||||
|
|
||||||
return out_count;
|
return out_count;
|
||||||
}
|
}
|
||||||
@ -480,7 +493,7 @@ ssize_t Libc::Vfs_plugin::read(Libc::File_descriptor *fd, void *buf,
|
|||||||
|
|
||||||
bool suspend() override
|
bool suspend() override
|
||||||
{
|
{
|
||||||
retry = !handle->fs().queue_read(handle, count);
|
retry = !VFS_THREAD_SAFE(handle->fs().queue_read(handle, count));
|
||||||
return retry;
|
return retry;
|
||||||
}
|
}
|
||||||
} check ( handle, count);
|
} check ( handle, count);
|
||||||
@ -512,8 +525,8 @@ ssize_t Libc::Vfs_plugin::read(Libc::File_descriptor *fd, void *buf,
|
|||||||
|
|
||||||
bool suspend() override
|
bool suspend() override
|
||||||
{
|
{
|
||||||
out_result = handle->fs().complete_read(handle, (char *)buf,
|
out_result = VFS_THREAD_SAFE(handle->fs().complete_read(handle, (char *)buf,
|
||||||
count, out_count);
|
count, out_count));
|
||||||
/* suspend me if read is still queued */
|
/* suspend me if read is still queued */
|
||||||
|
|
||||||
retry = (out_result == Result::READ_QUEUED);
|
retry = (out_result == Result::READ_QUEUED);
|
||||||
@ -538,7 +551,7 @@ ssize_t Libc::Vfs_plugin::read(Libc::File_descriptor *fd, void *buf,
|
|||||||
case Result::READ_QUEUED: /* handled above, so never reached */ break;
|
case Result::READ_QUEUED: /* handled above, so never reached */ break;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle->advance_seek(out_count);
|
VFS_THREAD_SAFE(handle->advance_seek(out_count));
|
||||||
|
|
||||||
return out_count;
|
return out_count;
|
||||||
}
|
}
|
||||||
@ -602,10 +615,10 @@ ssize_t Libc::Vfs_plugin::getdirentries(Libc::File_descriptor *fd, char *buf,
|
|||||||
|
|
||||||
bool suspend() override
|
bool suspend() override
|
||||||
{
|
{
|
||||||
out_result = handle->fs().complete_read(handle,
|
out_result = VFS_THREAD_SAFE(handle->fs().complete_read(handle,
|
||||||
(char*)&dirent_out,
|
(char*)&dirent_out,
|
||||||
sizeof(Dirent),
|
sizeof(Dirent),
|
||||||
out_count);
|
out_count));
|
||||||
|
|
||||||
/* suspend me if read is still queued */
|
/* suspend me if read is still queued */
|
||||||
|
|
||||||
@ -652,7 +665,7 @@ ssize_t Libc::Vfs_plugin::getdirentries(Libc::File_descriptor *fd, char *buf,
|
|||||||
/*
|
/*
|
||||||
* Keep track of VFS seek pointer and user-supplied basep.
|
* Keep track of VFS seek pointer and user-supplied basep.
|
||||||
*/
|
*/
|
||||||
handle->advance_seek(sizeof(Vfs::Directory_service::Dirent));
|
VFS_THREAD_SAFE(handle->advance_seek(sizeof(Vfs::Directory_service::Dirent)));
|
||||||
|
|
||||||
*basep += sizeof(struct dirent);
|
*basep += sizeof(struct dirent);
|
||||||
|
|
||||||
@ -834,7 +847,7 @@ int Libc::Vfs_plugin::ftruncate(Libc::File_descriptor *fd, ::off_t length)
|
|||||||
|
|
||||||
typedef Vfs::File_io_service::Ftruncate_result Result;
|
typedef Vfs::File_io_service::Ftruncate_result Result;
|
||||||
|
|
||||||
switch (handle->fs().ftruncate(handle, length)) {
|
switch (VFS_THREAD_SAFE(handle->fs().ftruncate(handle, length))) {
|
||||||
case Result::FTRUNCATE_ERR_NO_PERM: errno = EPERM; return -1;
|
case Result::FTRUNCATE_ERR_NO_PERM: errno = EPERM; return -1;
|
||||||
case Result::FTRUNCATE_ERR_INTERRUPT: errno = EINTR; return -1;
|
case Result::FTRUNCATE_ERR_INTERRUPT: errno = EINTR; return -1;
|
||||||
case Result::FTRUNCATE_ERR_NO_SPACE: errno = ENOSPC; return -1;
|
case Result::FTRUNCATE_ERR_NO_SPACE: errno = ENOSPC; return -1;
|
||||||
@ -898,7 +911,7 @@ int Libc::Vfs_plugin::symlink(const char *oldpath, const char *newpath)
|
|||||||
Vfs::Vfs_handle *handle { 0 };
|
Vfs::Vfs_handle *handle { 0 };
|
||||||
|
|
||||||
Openlink_result openlink_result =
|
Openlink_result openlink_result =
|
||||||
_root_dir.openlink(newpath, true, &handle, _alloc);
|
VFS_THREAD_SAFE(_root_dir.openlink(newpath, true, &handle, _alloc));
|
||||||
|
|
||||||
switch (openlink_result) {
|
switch (openlink_result) {
|
||||||
case Openlink_result::OPENLINK_OK:
|
case Openlink_result::OPENLINK_OK:
|
||||||
@ -939,8 +952,8 @@ int Libc::Vfs_plugin::symlink(const char *oldpath, const char *newpath)
|
|||||||
bool suspend() override
|
bool suspend() override
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
handle->fs().write(handle, (char const *)buf,
|
VFS_THREAD_SAFE(handle->fs().write(handle, (char const *)buf,
|
||||||
count, out_count);
|
count, out_count));
|
||||||
retry = false;
|
retry = false;
|
||||||
} catch (Vfs::File_io_service::Insufficient_buffer) {
|
} catch (Vfs::File_io_service::Insufficient_buffer) {
|
||||||
retry = true;
|
retry = true;
|
||||||
@ -955,7 +968,7 @@ int Libc::Vfs_plugin::symlink(const char *oldpath, const char *newpath)
|
|||||||
} while (check.retry);
|
} while (check.retry);
|
||||||
|
|
||||||
_vfs_sync(handle);
|
_vfs_sync(handle);
|
||||||
handle->close();
|
VFS_THREAD_SAFE(handle->close());
|
||||||
|
|
||||||
if (out_count != count)
|
if (out_count != count)
|
||||||
return Errno(ENAMETOOLONG);
|
return Errno(ENAMETOOLONG);
|
||||||
@ -1038,7 +1051,7 @@ ssize_t Libc::Vfs_plugin::readlink(const char *path, char *buf, ::size_t buf_siz
|
|||||||
|
|
||||||
bool suspend() override
|
bool suspend() override
|
||||||
{
|
{
|
||||||
out_result = symlink_handle->fs().complete_read(symlink_handle, buf, buf_size, out_len);
|
out_result = VFS_THREAD_SAFE(symlink_handle->fs().complete_read(symlink_handle, buf, buf_size, out_len));
|
||||||
|
|
||||||
/* suspend me if read is still queued */
|
/* suspend me if read is still queued */
|
||||||
|
|
||||||
@ -1064,7 +1077,7 @@ ssize_t Libc::Vfs_plugin::readlink(const char *path, char *buf, ::size_t buf_siz
|
|||||||
case Result::READ_QUEUED: /* handled above, so never reached */ break;
|
case Result::READ_QUEUED: /* handled above, so never reached */ break;
|
||||||
};
|
};
|
||||||
|
|
||||||
symlink_handle->close();
|
VFS_THREAD_SAFE(symlink_handle->close());
|
||||||
|
|
||||||
return out_len;
|
return out_len;
|
||||||
}
|
}
|
||||||
@ -1080,7 +1093,7 @@ int Libc::Vfs_plugin::unlink(char const *path)
|
|||||||
{
|
{
|
||||||
typedef Vfs::Directory_service::Unlink_result Result;
|
typedef Vfs::Directory_service::Unlink_result Result;
|
||||||
|
|
||||||
switch (_root_dir.unlink(path)) {
|
switch (VFS_THREAD_SAFE(_root_dir.unlink(path))) {
|
||||||
case Result::UNLINK_ERR_NO_ENTRY: errno = ENOENT; return -1;
|
case Result::UNLINK_ERR_NO_ENTRY: errno = ENOENT; return -1;
|
||||||
case Result::UNLINK_ERR_NO_PERM: errno = EPERM; return -1;
|
case Result::UNLINK_ERR_NO_PERM: errno = EPERM; return -1;
|
||||||
case Result::UNLINK_ERR_NOT_EMPTY: errno = ENOTEMPTY; return -1;
|
case Result::UNLINK_ERR_NOT_EMPTY: errno = ENOTEMPTY; return -1;
|
||||||
@ -1112,7 +1125,7 @@ int Libc::Vfs_plugin::rename(char const *from_path, char const *to_path)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_root_dir.rename(from_path, to_path)) {
|
switch (VFS_THREAD_SAFE(_root_dir.rename(from_path, to_path))) {
|
||||||
case Result::RENAME_ERR_NO_ENTRY: errno = ENOENT; return -1;
|
case Result::RENAME_ERR_NO_ENTRY: errno = ENOENT; return -1;
|
||||||
case Result::RENAME_ERR_CROSS_FS: errno = EXDEV; return -1;
|
case Result::RENAME_ERR_CROSS_FS: errno = EXDEV; return -1;
|
||||||
case Result::RENAME_ERR_NO_PERM: errno = EPERM; return -1;
|
case Result::RENAME_ERR_NO_PERM: errno = EPERM; return -1;
|
||||||
@ -1214,7 +1227,7 @@ int Libc::Vfs_plugin::select(int nfds,
|
|||||||
if (!handle) continue;
|
if (!handle) continue;
|
||||||
|
|
||||||
if (FD_ISSET(fd, &in_readfds)) {
|
if (FD_ISSET(fd, &in_readfds)) {
|
||||||
if (handle->fs().read_ready(handle)) {
|
if (VFS_THREAD_SAFE(handle->fs().read_ready(handle))) {
|
||||||
FD_SET(fd, readfds);
|
FD_SET(fd, readfds);
|
||||||
++nready;
|
++nready;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user