genode/repos/os/src/lib/vfs/fs_file_system.h

1098 lines
32 KiB
C
Raw Normal View History

/*
* \brief Adapter from Genode 'File_system' session to VFS
* \author Norman Feske
* \author Emery Hemingway
* \author Christian Helmuth
* \date 2011-02-17
*/
/*
* Copyright (C) 2012-2019 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _INCLUDE__VFS__FS_FILE_SYSTEM_H_
#define _INCLUDE__VFS__FS_FILE_SYSTEM_H_
/* Genode includes */
#include <base/allocator_avl.h>
#include <base/id_space.h>
#include <file_system_session/connection.h>
namespace Vfs { class Fs_file_system; }
class Vfs::Fs_file_system : public File_system
{
private:
/*
2020-02-20 15:47:08 +01:00
* Mutex used to serialize the interaction with the packet stream of the
* file-system session.
*
* XXX Once, we change the VFS file-system interface to use
* asynchronous read/write operations, we can possibly remove it.
*/
2020-02-20 15:47:08 +01:00
Mutex _mutex { };
Vfs::Env &_env;
Genode::Allocator_avl _fs_packet_alloc { &_env.alloc() };
typedef Genode::String<64> Label_string;
Label_string _label;
typedef Genode::String<::File_system::MAX_NAME_LEN> Root_string;
Root_string _root;
::File_system::Connection _fs;
typedef Genode::Id_space<::File_system::Node> Handle_space;
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Handle_space _handle_space { };
Handle_space _watch_handle_space { };
struct Handle_state
{
enum class Read_ready_state { IDLE, PENDING, READY };
Read_ready_state read_ready_state = Read_ready_state::IDLE;
enum class Queued_state { IDLE, QUEUED, ACK };
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
Queued_state queued_read_state = Queued_state::IDLE;
Queued_state queued_sync_state = Queued_state::IDLE;
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
::File_system::Packet_descriptor queued_read_packet { };
::File_system::Packet_descriptor queued_sync_packet { };
};
struct Fs_vfs_handle;
typedef Genode::Fifo<Fs_vfs_handle> Fs_vfs_handle_queue;
/**
* Convert 'File_system::Node_type' to 'Dirent_type'
*/
static Dirent_type _dirent_type(::File_system::Node_type type)
{
using ::File_system::Node_type;
switch (type) {
case Node_type::DIRECTORY: return Dirent_type::DIRECTORY;
case Node_type::CONTINUOUS_FILE: return Dirent_type::CONTINUOUS_FILE;
case Node_type::TRANSACTIONAL_FILE: return Dirent_type::TRANSACTIONAL_FILE;
case Node_type::SYMLINK: return Dirent_type::SYMLINK;
}
return Dirent_type::END;
}
/**
* Convert 'File_system::Node_type' to 'Vfs::Node_type'
*/
static Node_type _node_type(::File_system::Node_type type)
{
using Type = ::File_system::Node_type;
switch (type) {
case Type::DIRECTORY: return Node_type::DIRECTORY;
case Type::CONTINUOUS_FILE: return Node_type::CONTINUOUS_FILE;
case Type::TRANSACTIONAL_FILE: return Node_type::TRANSACTIONAL_FILE;
case Type::SYMLINK: return Node_type::SYMLINK;
}
Genode::error("invalid File_system::Node_type");
return Node_type::CONTINUOUS_FILE;
}
/**
* Convert 'File_system::Node_rwx' to 'Vfs::Node_rwx'
*/
static Node_rwx _node_rwx(::File_system::Node_rwx rwx)
{
return { .readable = rwx.readable,
.writeable = rwx.writeable,
.executable = rwx.executable };
}
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
struct Fs_vfs_handle : Vfs_handle,
private ::File_system::Node,
private Handle_space::Element,
private Fs_vfs_handle_queue::Element,
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
private Handle_state
{
friend Genode::Id_space<::File_system::Node>;
friend Fs_vfs_handle_queue;
using Fs_vfs_handle_queue::Element::enqueued;
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
using Handle_state::queued_read_state;
using Handle_state::queued_read_packet;
using Handle_state::queued_sync_packet;
using Handle_state::queued_sync_state;
using Handle_state::read_ready_state;
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
::File_system::Connection &_fs;
bool _queue_read(file_size count, file_size const seek_offset)
{
if (queued_read_state != Handle_state::Queued_state::IDLE)
return false;
::File_system::Session::Tx::Source &source = *_fs.tx();
/* if not ready to submit suggest retry */
if (!source.ready_to_submit())
return false;
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
file_size const max_packet_size = source.bulk_buffer_size() / 2;
file_size const clipped_count = min(max_packet_size, count);
::File_system::Packet_descriptor p;
try {
p = source.alloc_packet(clipped_count);
} catch (::File_system::Session::Tx::Source::Packet_alloc_failed) {
return false;
}
::File_system::Packet_descriptor const
packet(p, file_handle(),
::File_system::Packet_descriptor::READ,
clipped_count, seek_offset);
read_ready_state = Handle_state::Read_ready_state::IDLE;
queued_read_state = Handle_state::Queued_state::QUEUED;
/* pass packet to server side */
source.submit_packet(packet);
return true;
}
Read_result _complete_read(void *dst, file_size count,
file_size &out_count)
{
if (queued_read_state != Handle_state::Queued_state::ACK)
return READ_QUEUED;
::File_system::Session::Tx::Source &source = *_fs.tx();
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
/* obtain result packet descriptor with updated status info */
::File_system::Packet_descriptor const
packet = queued_read_packet;
Read_result result = packet.succeeded() ? READ_OK : READ_ERR_IO;
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
if (result == READ_OK) {
file_size const read_num_bytes = min(packet.length(), count);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
memcpy(dst, source.packet_content(packet), read_num_bytes);
out_count = read_num_bytes;
}
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
queued_read_state = Handle_state::Queued_state::IDLE;
queued_read_packet = ::File_system::Packet_descriptor();
source.release_packet(packet);
return result;
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
}
Fs_vfs_handle(File_system &fs, Allocator &alloc,
int status_flags, Handle_space &space,
::File_system::Node_handle node_handle,
::File_system::Connection &fs_connection)
:
Vfs_handle(fs, fs, alloc, status_flags),
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
Handle_space::Element(*this, space, node_handle),
_fs(fs_connection)
{ }
::File_system::File_handle file_handle() const
{ return ::File_system::File_handle { id().value }; }
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
virtual bool queue_read(file_size /* count */)
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
{
Genode::error("Fs_vfs_handle::queue_read() called");
return true;
}
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
virtual Read_result complete_read(char *,
file_size /* in count */,
file_size & /* out count */)
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
{
Genode::error("Fs_vfs_handle::complete_read() called");
return READ_ERR_INVALID;
}
bool queue_sync()
{
if (queued_sync_state != Handle_state::Queued_state::IDLE)
return true;
::File_system::Session::Tx::Source &source = *_fs.tx();
/* if not ready to submit suggest retry */
if (!source.ready_to_submit()) return false;
::File_system::Packet_descriptor p;
try {
p = source.alloc_packet(0);
} catch (::File_system::Session::Tx::Source::Packet_alloc_failed) {
return false;
}
::File_system::Packet_descriptor const
packet(p, file_handle(),
::File_system::Packet_descriptor::SYNC, 0);
queued_sync_state = Handle_state::Queued_state::QUEUED;
/* pass packet to server side */
source.submit_packet(packet);
return true;
}
Sync_result complete_sync()
{
if (queued_sync_state != Handle_state::Queued_state::ACK)
return SYNC_QUEUED;
/* obtain result packet descriptor */
::File_system::Packet_descriptor const
packet = queued_sync_packet;
::File_system::Session::Tx::Source &source = *_fs.tx();
Sync_result result = packet.succeeded()
? SYNC_OK : SYNC_ERR_INVALID;
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
queued_sync_state = Handle_state::Queued_state::IDLE;
queued_sync_packet = ::File_system::Packet_descriptor();
source.release_packet(packet);
return result;
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
}
bool update_modification_timestamp(Vfs::Timestamp time)
{
::File_system::Session::Tx::Source &source = *_fs.tx();
using ::File_system::Packet_descriptor;
if (!source.ready_to_submit()) {
return false;
}
try {
Packet_descriptor p(source.alloc_packet(0),
file_handle(),
Packet_descriptor::WRITE_TIMESTAMP,
::File_system::Timestamp { .value = time.value });
/* pass packet to server side */
source.submit_packet(p);
} catch (::File_system::Session::Tx::Source::Packet_alloc_failed) {
return false;
}
return true;
}
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
};
struct Fs_vfs_file_handle : Fs_vfs_handle
{
using Fs_vfs_handle::Fs_vfs_handle;
bool queue_read(file_size count) override
{
return _queue_read(count, seek());
}
Read_result complete_read(char *dst, file_size count,
file_size &out_count) override
{
return _complete_read(dst, count, out_count);
}
};
struct Fs_vfs_dir_handle : Fs_vfs_handle
{
enum { DIRENT_SIZE = sizeof(::File_system::Directory_entry) };
using Fs_vfs_handle::Fs_vfs_handle;
bool queue_read(file_size count) override
{
if (count < sizeof(Dirent))
return true;
return _queue_read(DIRENT_SIZE,
(seek() / sizeof(Dirent) * DIRENT_SIZE));
}
Read_result complete_read(char *dst, file_size count,
file_size &out_count) override
{
if (count < sizeof(Dirent))
return READ_ERR_INVALID;
using ::File_system::Directory_entry;
Directory_entry entry { };
file_size entry_out_count = 0;
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
Read_result const read_result =
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
_complete_read(&entry, DIRENT_SIZE, entry_out_count);
if (read_result != READ_OK)
return read_result;
entry.sanitize();
Dirent &dirent = *(Dirent*)dst;
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
if (entry_out_count < DIRENT_SIZE) {
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
/* no entry found for the given index, or error */
dirent = Dirent {
.fileno = 0,
.type = Dirent_type::END,
.rwx = { },
.name = { }
};
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
out_count = sizeof(Dirent);
return READ_OK;
}
dirent = Dirent {
.fileno = entry.inode,
.type = _dirent_type(entry.type),
.rwx = _node_rwx(entry.rwx),
.name = { entry.name.buf }
};
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
out_count = sizeof(Dirent);
return READ_OK;
}
};
struct Fs_vfs_symlink_handle : Fs_vfs_handle
{
using Fs_vfs_handle::Fs_vfs_handle;
bool queue_read(file_size count) override
{
return _queue_read(count, seek());
}
Read_result complete_read(char *dst, file_size count,
file_size &out_count) override
{
return _complete_read(dst, count, out_count);
}
};
/**
* Helper for managing the lifetime of temporary open node handles
*/
struct Fs_handle_guard : Fs_vfs_handle
{
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
::File_system::Session &_fs_session;
Fs_handle_guard(File_system &fs,
::File_system::Session &fs_session,
::File_system::Node_handle fs_handle,
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
Handle_space &space,
::File_system::Connection &fs_connection)
:
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
Fs_vfs_handle(fs, *(Allocator*)nullptr, 0, space, fs_handle,
fs_connection),
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
_fs_session(fs_session)
{ }
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
~Fs_handle_guard()
{
_fs_session.close(file_handle());
}
};
struct Fs_vfs_watch_handle final : Vfs_watch_handle,
private ::File_system::Node,
private Handle_space::Element
{
friend Genode::Id_space<::File_system::Node>;
::File_system::Watch_handle const fs_handle;
Fs_vfs_watch_handle(Vfs::File_system &fs,
Allocator &alloc,
Handle_space &space,
::File_system::Watch_handle handle)
:
Vfs_watch_handle(fs, alloc),
Handle_space::Element(*this, space, handle),
fs_handle(handle)
{ }
};
Fs_vfs_handle_queue _congested_handles { };
file_size _read(Fs_vfs_handle &handle, void *buf,
file_size const count, file_size const seek_offset)
{
::File_system::Session::Tx::Source &source = *_fs.tx();
using ::File_system::Packet_descriptor;
file_size const max_packet_size = source.bulk_buffer_size() / 2;
file_size const clipped_count = min(max_packet_size, count);
/* XXX check if alloc_packet() and submit_packet() will succeed! */
Packet_descriptor const packet_in(source.alloc_packet(clipped_count),
handle.file_handle(),
Packet_descriptor::READ,
clipped_count,
seek_offset);
/* wait until packet was acknowledged */
handle.queued_read_state = Handle_state::Queued_state::QUEUED;
/* pass packet to server side */
source.submit_packet(packet_in);
while (handle.queued_read_state != Handle_state::Queued_state::ACK)
_env.env().ep().wait_and_dispatch_one_io_signal();
/* obtain result packet descriptor with updated status info */
Packet_descriptor const packet_out = handle.queued_read_packet;
handle.queued_read_state = Handle_state::Queued_state::IDLE;
handle.queued_read_packet = Packet_descriptor();
if (!packet_out.succeeded()) {
/* could be EOF or a real error */
try {
::File_system::Status status = _fs.status(handle.file_handle());
if (seek_offset < status.size)
Genode::warning("unexpected failure on file-system read");
}
catch (::File_system::Invalid_handle) { }
catch (::File_system::Unavailable) { }
}
file_size const read_num_bytes = min(packet_out.length(), count);
memcpy(buf, source.packet_content(packet_out), read_num_bytes);
source.release_packet(packet_out);
return read_num_bytes;
}
file_size _write(Fs_vfs_handle &handle,
const char *buf, file_size count, file_size seek_offset)
{
/*
* TODO
* a sustained write loop will congest the packet buffer,
* perhaps acks should be processed before submission?
*
* _handle_ack();
*/
::File_system::Session::Tx::Source &source = *_fs.tx();
using ::File_system::Packet_descriptor;
file_size const max_packet_size = source.bulk_buffer_size() / 2;
count = min(max_packet_size, count);
if (!source.ready_to_submit()) {
if (!handle.enqueued())
_congested_handles.enqueue(handle);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
throw Insufficient_buffer();
}
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
try {
Packet_descriptor packet_in(source.alloc_packet(count),
handle.file_handle(),
Packet_descriptor::WRITE,
count,
seek_offset);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
memcpy(source.packet_content(packet_in), buf, count);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
/* pass packet to server side */
source.submit_packet(packet_in);
} catch (::File_system::Session::Tx::Source::Packet_alloc_failed) {
if (!handle.enqueued())
_congested_handles.enqueue(handle);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
throw Insufficient_buffer();
} catch (...) {
Genode::error("unhandled exception");
return 0;
}
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
return count;
}
void _ready_to_submit()
{
_congested_handles.dequeue_all([] (Fs_vfs_handle &handle) {
handle.io_progress_response(); });
}
void _handle_ack()
{
::File_system::Session::Tx::Source &source = *_fs.tx();
using ::File_system::Packet_descriptor;
while (source.ack_avail()) {
Packet_descriptor const packet = source.get_acked_packet();
Handle_space::Id const id(packet.handle());
auto handle_read = [&] (Fs_vfs_handle &handle) {
if (!packet.succeeded())
Genode::error("packet operation=", (int)packet.operation(), " failed");
switch (packet.operation()) {
case Packet_descriptor::READ_READY:
handle.read_ready_state = Handle_state::Read_ready_state::READY;
handle.read_ready_response();
break;
case Packet_descriptor::READ:
handle.queued_read_packet = packet;
handle.queued_read_state = Handle_state::Queued_state::ACK;
handle.io_progress_response();
break;
case Packet_descriptor::WRITE:
/*
* Notify anyone who might have failed on
* 'alloc_packet()'
*/
handle.io_progress_response();
break;
case Packet_descriptor::SYNC:
handle.queued_sync_packet = packet;
handle.queued_sync_state = Handle_state::Queued_state::ACK;
handle.io_progress_response();
break;
case Packet_descriptor::CONTENT_CHANGED:
/* previously handled */
break;
case Packet_descriptor::WRITE_TIMESTAMP:
/* previously handled */
break;
}
};
try {
if (packet.operation() == Packet_descriptor::CONTENT_CHANGED) {
_watch_handle_space.apply<Fs_vfs_watch_handle>(id, [&] (Fs_vfs_watch_handle &handle) {
handle.watch_response(); });
} else {
_handle_space.apply<Fs_vfs_handle>(id, handle_read);
}
}
catch (Handle_space::Unknown_id) {
Genode::warning("ack for unknown File_system handle ", id); }
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
if (packet.operation() == Packet_descriptor::WRITE) {
2020-02-20 15:47:08 +01:00
Mutex::Guard guard(_mutex);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
source.release_packet(packet);
}
if (packet.operation() == Packet_descriptor::WRITE_TIMESTAMP) {
2020-02-20 15:47:08 +01:00
Mutex::Guard guard(_mutex);
source.release_packet(packet);
}
}
}
void _handle_ack_signal()
{
_handle_ack();
/* packet buffer space available */
_ready_to_submit();
}
Genode::Io_signal_handler<Fs_file_system> _ack_handler {
_env.env().ep(), *this, &Fs_file_system::_handle_ack_signal };
Genode::Io_signal_handler<Fs_file_system> _ready_handler {
_env.env().ep(), *this, &Fs_file_system::_ready_to_submit };
static
Genode::size_t buffer_size(Genode::Xml_node const &config)
{
Genode::Number_of_bytes fs_default { ::File_system::DEFAULT_TX_BUF_SIZE };
return config.attribute_value("buffer_size", fs_default);
}
public:
Fs_file_system(Vfs::Env &env, Genode::Xml_node config)
:
_env(env),
_label(config.attribute_value("label", Label_string())),
_root( config.attribute_value("root", Root_string())),
_fs(_env.env(), _fs_packet_alloc,
_label.string(), _root.string(),
config.attribute_value("writeable", true),
buffer_size(config))
{
_fs.sigh_ack_avail(_ack_handler);
_fs.sigh_ready_to_submit(_ready_handler);
}
/*********************************
** Directory-service interface **
*********************************/
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
Dataspace_capability dataspace(char const *) override
{
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
/* cannot be implemented without blocking */
return Dataspace_capability();
}
Follow practices suggested by "Effective C++" The patch adjust the code of the base, base-<kernel>, and os repository. To adapt existing components to fix violations of the best practices suggested by "Effective C++" as reported by the -Weffc++ compiler argument. The changes follow the patterns outlined below: * A class with virtual functions can no longer publicly inherit base classed without a vtable. The inherited object may either be moved to a member variable, or inherited privately. The latter would be used for classes that inherit 'List::Element' or 'Avl_node'. In order to enable the 'List' and 'Avl_tree' to access the meta data, the 'List' must become a friend. * Instead of adding a virtual destructor to abstract base classes, we inherit the new 'Interface' class, which contains a virtual destructor. This way, single-line abstract base classes can stay as compact as they are now. The 'Interface' utility resides in base/include/util/interface.h. * With the new warnings enabled, all member variables must be explicitly initialized. Basic types may be initialized with '='. All other types are initialized with braces '{ ... }' or as class initializers. If basic types and non-basic types appear in a row, it is nice to only use the brace syntax (also for basic types) and align the braces. * If a class contains pointers as members, it must now also provide a copy constructor and assignment operator. In the most cases, one would make them private, effectively disallowing the objects to be copied. Unfortunately, this warning cannot be fixed be inheriting our existing 'Noncopyable' class (the compiler fails to detect that the inheriting class cannot be copied and still gives the error). For now, we have to manually add declarations for both the copy constructor and assignment operator as private class members. Those declarations should be prepended with a comment like this: /* * Noncopyable */ Thread(Thread const &); Thread &operator = (Thread const &); In the future, we should revisit these places and try to replace the pointers with references. In the presence of at least one reference member, the compiler would no longer implicitly generate a copy constructor. So we could remove the manual declaration. Issue #465
2017-12-21 15:42:15 +01:00
void release(char const *, Dataspace_capability) override { }
Stat_result stat(char const *path, Stat &out) override
{
::File_system::Status status;
try {
::File_system::Node_handle node = _fs.node(path);
Fs_handle_guard node_guard(*this, _fs, node, _handle_space, _fs);
status = _fs.status(node);
}
catch (Genode::Out_of_ram) {
Genode::error("out-of-ram during stat");
return STAT_ERR_NO_PERM;
}
catch (Genode::Out_of_caps) {
Genode::error("out-of-caps during stat");
return STAT_ERR_NO_PERM;
}
catch (...) { return STAT_ERR_NO_ENTRY; }
out = Stat();
out.size = status.size;
out.type = _node_type(status.type);
out.rwx = _node_rwx(status.rwx);
out.inode = status.inode;
out.device = (Genode::addr_t)this;
out.modification_time.value = status.modification_time.value;
return STAT_OK;
}
Unlink_result unlink(char const *path) override
{
Absolute_path dir_path(path);
dir_path.strip_last_element();
Absolute_path file_name(path);
file_name.keep_only_last_element();
try {
::File_system::Dir_handle dir = _fs.dir(dir_path.base(), false);
Fs_handle_guard dir_guard(*this, _fs, dir, _handle_space, _fs);
_fs.unlink(dir, file_name.base() + 1);
}
catch (::File_system::Invalid_handle) { return UNLINK_ERR_NO_ENTRY; }
catch (::File_system::Invalid_name) { return UNLINK_ERR_NO_ENTRY; }
catch (::File_system::Lookup_failed) { return UNLINK_ERR_NO_ENTRY; }
catch (::File_system::Not_empty) { return UNLINK_ERR_NOT_EMPTY; }
catch (::File_system::Permission_denied) { return UNLINK_ERR_NO_PERM; }
catch (::File_system::Unavailable) { return UNLINK_ERR_NO_ENTRY; }
return UNLINK_OK;
}
Rename_result rename(char const *from_path, char const *to_path) override
{
if ((strcmp(from_path, to_path) == 0) && leaf_path(from_path))
return RENAME_OK;
Absolute_path from_dir_path(from_path);
from_dir_path.strip_last_element();
Absolute_path from_file_name(from_path);
from_file_name.keep_only_last_element();
Absolute_path to_dir_path(to_path);
to_dir_path.strip_last_element();
Absolute_path to_file_name(to_path);
to_file_name.keep_only_last_element();
try {
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
::File_system::Dir_handle from_dir =
_fs.dir(from_dir_path.base(), false);
Fs_handle_guard from_dir_guard(*this, _fs, from_dir,
_handle_space, _fs);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
::File_system::Dir_handle to_dir = _fs.dir(to_dir_path.base(),
false);
Fs_handle_guard to_dir_guard(
*this, _fs, to_dir, _handle_space, _fs);
_fs.move(from_dir, from_file_name.base() + 1,
to_dir, to_file_name.base() + 1);
}
catch (::File_system::Lookup_failed) { return RENAME_ERR_NO_ENTRY; }
catch (...) { return RENAME_ERR_NO_PERM; }
return RENAME_OK;
}
file_size num_dirent(char const *path) override
{
if (strcmp(path, "") == 0)
path = "/";
try {
::File_system::Node_handle node = _fs.node(path);
Fs_handle_guard node_guard(*this, _fs, node,
_handle_space, _fs);
::File_system::Status status = _fs.status(node);
return status.size / sizeof(::File_system::Directory_entry);
}
catch (...) { }
return 0;
}
bool directory(char const *path) override
{
try {
::File_system::Node_handle node = _fs.node(path);
Fs_handle_guard node_guard(*this, _fs, node, _handle_space, _fs);
::File_system::Status status = _fs.status(node);
return status.directory();
}
catch (...) { }
return false;
}
char const *leaf_path(char const *path) override
{
/* check if node at path exists within file system */
try {
::File_system::Node_handle node = _fs.node(path);
_fs.close(node);
}
catch (...) { return 0; }
return path;
}
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
Open_result open(char const *path, unsigned vfs_mode, Vfs_handle **out_handle,
Genode::Allocator& alloc) override
{
2020-02-20 15:47:08 +01:00
Mutex::Guard guard(_mutex);
Absolute_path dir_path(path);
dir_path.strip_last_element();
Absolute_path file_name(path);
file_name.keep_only_last_element();
::File_system::Mode mode;
switch (vfs_mode & OPEN_MODE_ACCMODE) {
default: mode = ::File_system::STAT_ONLY; break;
case OPEN_MODE_RDONLY: mode = ::File_system::READ_ONLY; break;
case OPEN_MODE_WRONLY: mode = ::File_system::WRITE_ONLY; break;
case OPEN_MODE_RDWR: mode = ::File_system::READ_WRITE; break;
}
bool const create = vfs_mode & OPEN_MODE_CREATE;
try {
::File_system::Dir_handle dir = _fs.dir(dir_path.base(), false);
Fs_handle_guard dir_guard(*this, _fs, dir, _handle_space, _fs);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
::File_system::File_handle file = _fs.file(dir,
file_name.base() + 1,
mode, create);
*out_handle = new (alloc)
Fs_vfs_file_handle(*this, alloc, vfs_mode, _handle_space, file, _fs);
}
catch (::File_system::Lookup_failed) { return OPEN_ERR_UNACCESSIBLE; }
catch (::File_system::Permission_denied) { return OPEN_ERR_NO_PERM; }
catch (::File_system::Invalid_handle) { return OPEN_ERR_UNACCESSIBLE; }
catch (::File_system::Node_already_exists) { return OPEN_ERR_EXISTS; }
catch (::File_system::Invalid_name) { return OPEN_ERR_NAME_TOO_LONG; }
catch (::File_system::Name_too_long) { return OPEN_ERR_NAME_TOO_LONG; }
catch (::File_system::No_space) { return OPEN_ERR_NO_SPACE; }
catch (::File_system::Unavailable) { return OPEN_ERR_UNACCESSIBLE; }
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
return OPEN_OK;
}
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
Opendir_result opendir(char const *path, bool create,
Vfs_handle **out_handle, Allocator &alloc) override
{
2020-02-20 15:47:08 +01:00
Mutex::Guard guard(_mutex);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
Absolute_path dir_path(path);
try {
::File_system::Dir_handle dir = _fs.dir(dir_path.base(), create);
*out_handle = new (alloc)
Fs_vfs_dir_handle(*this, alloc, ::File_system::READ_ONLY,
_handle_space, dir, _fs);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
}
catch (::File_system::Lookup_failed) { return OPENDIR_ERR_LOOKUP_FAILED; }
catch (::File_system::Name_too_long) { return OPENDIR_ERR_NAME_TOO_LONG; }
catch (::File_system::Node_already_exists) { return OPENDIR_ERR_NODE_ALREADY_EXISTS; }
catch (::File_system::No_space) { return OPENDIR_ERR_NO_SPACE; }
catch (::File_system::Permission_denied) { return OPENDIR_ERR_PERMISSION_DENIED; }
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
return OPENDIR_OK;
}
Openlink_result openlink(char const *path, bool create,
Vfs_handle **out_handle, Allocator &alloc) override
{
2020-02-20 15:47:08 +01:00
Mutex::Guard guard(_mutex);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
/*
* Canonicalize path (i.e., path must start with '/')
*/
Absolute_path abs_path(path);
abs_path.strip_last_element();
Absolute_path symlink_name(path);
symlink_name.keep_only_last_element();
try {
::File_system::Dir_handle dir_handle = _fs.dir(abs_path.base(),
false);
Fs_handle_guard from_dir_guard(*this, _fs, dir_handle,
_handle_space, _fs);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
::File_system::Symlink_handle symlink_handle =
_fs.symlink(dir_handle, symlink_name.base() + 1, create);
*out_handle = new (alloc)
Fs_vfs_symlink_handle(*this, alloc,
::File_system::READ_ONLY,
_handle_space, symlink_handle, _fs);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
return OPENLINK_OK;
}
catch (::File_system::Invalid_handle) { return OPENLINK_ERR_LOOKUP_FAILED; }
catch (::File_system::Invalid_name) { return OPENLINK_ERR_LOOKUP_FAILED; }
catch (::File_system::Lookup_failed) { return OPENLINK_ERR_LOOKUP_FAILED; }
catch (::File_system::Node_already_exists) { return OPENLINK_ERR_NODE_ALREADY_EXISTS; }
catch (::File_system::No_space) { return OPENLINK_ERR_NO_SPACE; }
catch (::File_system::Permission_denied) { return OPENLINK_ERR_PERMISSION_DENIED; }
catch (::File_system::Unavailable) { return OPENLINK_ERR_LOOKUP_FAILED; }
catch (Genode::Out_of_ram) { return OPENLINK_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENLINK_ERR_OUT_OF_CAPS; }
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
}
void close(Vfs_handle *vfs_handle) override
{
2020-02-20 15:47:08 +01:00
Mutex::Guard guard(_mutex);
Fs_vfs_handle *fs_handle = static_cast<Fs_vfs_handle *>(vfs_handle);
if (fs_handle->enqueued())
_congested_handles.remove(*fs_handle);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
_fs.close(fs_handle->file_handle());
destroy(fs_handle->alloc(), fs_handle);
}
Watch_result watch(char const *path,
Vfs_watch_handle **handle,
Allocator &alloc) override
{
using namespace ::File_system;
Watch_result res = WATCH_ERR_UNACCESSIBLE;
::File_system::Watch_handle fs_handle { -1U };
try { fs_handle = _fs.watch(path); }
catch (Unavailable) { return WATCH_ERR_UNACCESSIBLE; }
catch (Lookup_failed) { return WATCH_ERR_UNACCESSIBLE; }
catch (Permission_denied) { return WATCH_ERR_STATIC; }
catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; }
catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; }
try {
*handle = new (alloc)
Fs_vfs_watch_handle(
*this, alloc, _watch_handle_space, fs_handle);
return WATCH_OK;
}
catch (Out_of_ram) { res = WATCH_ERR_OUT_OF_RAM; }
catch (Out_of_caps) { res = WATCH_ERR_OUT_OF_CAPS; }
_fs.close(fs_handle);
return res;
}
void close(Vfs_watch_handle *vfs_handle) override
{
Fs_vfs_watch_handle *handle =
static_cast<Fs_vfs_watch_handle *>(vfs_handle);
_fs.close(handle->fs_handle);
destroy(handle->alloc(), handle);
};
/***************************
** File_system interface **
***************************/
2017-02-07 19:03:23 +01:00
static char const *name() { return "fs"; }
char const *type() override { return "fs"; }
/********************************
** File I/O service interface **
********************************/
Write_result write(Vfs_handle *vfs_handle, char const *buf,
file_size buf_size, file_size &out_count) override
{
2020-02-20 15:47:08 +01:00
Mutex::Guard guard(_mutex);
Fs_vfs_handle &handle = static_cast<Fs_vfs_handle &>(*vfs_handle);
out_count = _write(handle, buf, buf_size, handle.seek());
return WRITE_OK;
}
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
bool queue_read(Vfs_handle *vfs_handle, file_size count) override
{
2020-02-20 15:47:08 +01:00
Mutex::Guard guard(_mutex);
Fs_vfs_handle *handle = static_cast<Fs_vfs_handle *>(vfs_handle);
bool result = handle->queue_read(count);
if (!result && !handle->enqueued())
_congested_handles.enqueue(*handle);
return result;
}
Read_result complete_read(Vfs_handle *vfs_handle, char *dst, file_size count,
file_size &out_count) override
{
2020-02-20 15:47:08 +01:00
Mutex::Guard guard(_mutex);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
out_count = 0;
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
Fs_vfs_handle *handle = static_cast<Fs_vfs_handle *>(vfs_handle);
Read_result result = handle->complete_read(dst, count, out_count);
if (result == READ_QUEUED && !handle->enqueued())
_congested_handles.enqueue(*handle);
return result;
}
bool read_ready(Vfs_handle *vfs_handle) override
{
Fs_vfs_handle *handle = static_cast<Fs_vfs_handle *>(vfs_handle);
return handle->read_ready_state == Handle_state::Read_ready_state::READY;
}
bool notify_read_ready(Vfs_handle *vfs_handle) override
{
Fs_vfs_handle *handle = static_cast<Fs_vfs_handle *>(vfs_handle);
if (handle->read_ready_state != Handle_state::Read_ready_state::IDLE)
return true;
::File_system::Session::Tx::Source &source = *_fs.tx();
/* if not ready to submit suggest retry */
if (!source.ready_to_submit()) return false;
using ::File_system::Packet_descriptor;
Packet_descriptor packet(Packet_descriptor(),
handle->file_handle(),
Packet_descriptor::READ_READY,
0, 0);
handle->read_ready_state = Handle_state::Read_ready_state::PENDING;
source.submit_packet(packet);
/*
* When the packet is acknowledged the application is notified via
* Response_handler::handle_response().
*/
return true;
}
Ftruncate_result ftruncate(Vfs_handle *vfs_handle, file_size len) override
{
Fs_vfs_handle const *handle = static_cast<Fs_vfs_handle *>(vfs_handle);
try {
_fs.truncate(handle->file_handle(), len);
}
catch (::File_system::Invalid_handle) { return FTRUNCATE_ERR_NO_PERM; }
catch (::File_system::Permission_denied) { return FTRUNCATE_ERR_NO_PERM; }
catch (::File_system::No_space) { return FTRUNCATE_ERR_NO_SPACE; }
catch (::File_system::Unavailable) { return FTRUNCATE_ERR_NO_PERM; }
return FTRUNCATE_OK;
}
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
bool queue_sync(Vfs_handle *vfs_handle) override
{
2020-02-20 15:47:08 +01:00
Mutex::Guard guard(_mutex);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
Fs_vfs_handle *handle = static_cast<Fs_vfs_handle *>(vfs_handle);
return handle->queue_sync();
}
Sync_result complete_sync(Vfs_handle *vfs_handle) override
{
2020-02-20 15:47:08 +01:00
Mutex::Guard guard(_mutex);
VFS: nonblocking interface The VFS library can be used in single-threaded or multi-threaded environments and depending on that, signals are handled by the same thread which uses the VFS library or possibly by a different thread. If a VFS plugin needs to block to wait for a signal, there is currently no way which works reliably in both environments. For this reason, this commit makes the interface of the VFS library nonblocking, similar to the File_system session interface. The most important changes are: - Directories are created and opened with the 'opendir()' function and the directory entries are read with the recently introduced 'queue_read()' and 'complete_read()' functions. - Symbolic links are created and opened with the 'openlink()' function and the link target is read with the 'queue_read()' and 'complete_read()' functions and written with the 'write()' function. - The 'write()' function does not wait for signals anymore. This can have the effect that data written by a VFS library user has not been processed by a file system server yet when the library user asks for the size of the file or closes it (both done with RPC functions at the file system server). For this reason, a user of the VFS library should request synchronization before calling 'stat()' or 'close()'. To make sure that a file system server has processed all write request packets which a client submitted before the synchronization request, synchronization is now requested at the file system server with a synchronization packet instead of an RPC function. Because of this change, the synchronization interface of the VFS library is now split into 'queue_sync()' and 'complete_sync()' functions. Fixes #2399
2017-08-15 20:51:53 +02:00
Fs_vfs_handle *handle = static_cast<Fs_vfs_handle *>(vfs_handle);
return handle->complete_sync();
}
bool update_modification_timestamp(Vfs_handle *vfs_handle, Vfs::Timestamp time) override
{
2020-02-20 15:47:08 +01:00
Mutex::Guard guard(_mutex);
Fs_vfs_handle *handle = static_cast<Fs_vfs_handle *>(vfs_handle);
return handle->update_modification_timestamp(time);
}
};
#endif /* _INCLUDE__VFS__FS_FILE_SYSTEM_H_ */