File_system: replace per-handle signals with notification packets

Replace registration and signaling of per-handle signal capabilities
with CONTENT_CHANGED notification packets.

Fix #2397
This commit is contained in:
Emery Hemingway 2017-04-20 12:02:43 -05:00 committed by Christian Helmuth
parent 29b3fff5eb
commit 24a9537a27
13 changed files with 382 additions and 194 deletions

View File

@ -61,12 +61,6 @@ class File_system::Session_component : public Session_rpc_object
{ {
void * const content = tx_sink()->packet_content(packet); void * const content = tx_sink()->packet_content(packet);
size_t const length = packet.length(); size_t const length = packet.length();
seek_off_t const offset = packet.position();
if (!content || (packet.length() > packet.size())) {
packet.succeeded(false);
return;
}
/* resulting length */ /* resulting length */
size_t res_length = 0; size_t res_length = 0;
@ -74,13 +68,22 @@ class File_system::Session_component : public Session_rpc_object
switch (packet.operation()) { switch (packet.operation()) {
case Packet_descriptor::READ: case Packet_descriptor::READ:
res_length = node.read((char *)content, length, offset); if (content && (packet.length() <= packet.size()))
res_length = node.read((char *)content, length, packet.position());
break; break;
case Packet_descriptor::WRITE: case Packet_descriptor::WRITE:
res_length = node.write((char const *)content, length, offset); if (content && (packet.length() <= packet.size()))
res_length = node.write((char const *)content, length, packet.position());
break; break;
case Packet_descriptor::CONTENT_CHANGED:
_handle_registry.register_notify(*tx_sink(), packet.handle());
/* notify_listeners may bounce the packet back*/
node.notify_listeners();
/* otherwise defer acknowledgement of this packet */
return;
case Packet_descriptor::READ_READY: case Packet_descriptor::READ_READY:
/* not supported */ /* not supported */
break; break;
@ -88,6 +91,7 @@ class File_system::Session_component : public Session_rpc_object
packet.length(res_length); packet.length(res_length);
packet.succeeded(res_length > 0); packet.succeeded(res_length > 0);
tx_sink()->acknowledge_packet(packet);
} }
void _process_packet() void _process_packet()
@ -103,12 +107,6 @@ class File_system::Session_component : public Session_rpc_object
_process_packet_op(packet, *node); _process_packet_op(packet, *node);
} }
catch (Invalid_handle) { Genode::error("Invalid_handle"); } catch (Invalid_handle) { Genode::error("Invalid_handle"); }
/*
* The 'acknowledge_packet' function cannot block because we
* checked for 'ready_to_ack' in '_process_packets'.
*/
tx_sink()->acknowledge_packet(packet);
} }
/** /**
@ -353,11 +351,6 @@ class File_system::Session_component : public Session_rpc_object
throw Permission_denied(); throw Permission_denied();
} }
void sigh(Node_handle node_handle, Signal_context_capability sigh) override
{
_handle_registry.sigh(node_handle, sigh);
}
void sync(Node_handle) override { rump_sys_sync(); } void sync(Node_handle) override { rump_sys_sync(); }
}; };
@ -367,6 +360,8 @@ class File_system::Root : public Root_component<Session_component>
Genode::Env &_env; Genode::Env &_env;
Genode::Attached_rom_dataspace _config { _env, "config" };
protected: protected:
Session_component *_create_session(const char *args) Session_component *_create_session(const char *args)
@ -408,7 +403,7 @@ class File_system::Root : public Root_component<Session_component>
char tmp[MAX_PATH_LEN]; char tmp[MAX_PATH_LEN];
try { try {
Session_policy policy(label); Session_policy policy(label, _config.xml());
/* determine policy root offset */ /* determine policy root offset */
try { try {

View File

@ -63,12 +63,6 @@ class File_system::Session_component : public Session_rpc_object
{ {
void * const content = tx_sink()->packet_content(packet); void * const content = tx_sink()->packet_content(packet);
size_t const length = packet.length(); size_t const length = packet.length();
seek_off_t const offset = packet.position();
if (!content || (packet.length() > packet.size())) {
packet.succeeded(false);
return;
}
/* resulting length */ /* resulting length */
size_t res_length = 0; size_t res_length = 0;
@ -76,17 +70,22 @@ class File_system::Session_component : public Session_rpc_object
switch (packet.operation()) { switch (packet.operation()) {
case Packet_descriptor::READ: case Packet_descriptor::READ:
res_length = node.read((char *)content, length, offset); if (content && (packet.length() <= packet.size()))
res_length = node.read((char *)content, length, packet.position());
break; break;
case Packet_descriptor::WRITE: case Packet_descriptor::WRITE:
/* session is read-only */ if (content && (packet.length() <= packet.size()))
if (!_writeable) res_length = node.write((char const *)content, length, packet.position());
break;
res_length = node.write((char const *)content, length, offset);
break; break;
case Packet_descriptor::CONTENT_CHANGED:
_handle_registry.register_notify(*tx_sink(), packet.handle());
/* notify_listeners may bounce the packet back*/
node.notify_listeners();
/* otherwise defer acknowledgement of this packet */
return;
case Packet_descriptor::READ_READY: case Packet_descriptor::READ_READY:
/* not supported */ /* not supported */
break; break;
@ -94,6 +93,7 @@ class File_system::Session_component : public Session_rpc_object
packet.length(res_length); packet.length(res_length);
packet.succeeded(res_length > 0); packet.succeeded(res_length > 0);
tx_sink()->acknowledge_packet(packet);
} }
void _process_packet() void _process_packet()
@ -110,12 +110,6 @@ class File_system::Session_component : public Session_rpc_object
_process_packet_op(packet, *node); _process_packet_op(packet, *node);
} }
catch (Invalid_handle) { Genode::error("Invalid_handle"); } catch (Invalid_handle) { Genode::error("Invalid_handle"); }
/*
* The 'acknowledge_packet' function cannot block because we
* checked for 'ready_to_ack' in '_process_packets'.
*/
tx_sink()->acknowledge_packet(packet);
} }
/** /**
@ -397,11 +391,6 @@ class File_system::Session_component : public Session_rpc_object
} }
} }
void sigh(Node_handle node_handle, Signal_context_capability sigh)
{
_handle_registry.sigh(node_handle, sigh);
}
void sync(Node_handle) override void sync(Node_handle) override
{ {
Fuse::sync_fs(); Fuse::sync_fs();

View File

@ -8,36 +8,41 @@
#define _FILE_SYSTEM__LISTENER_H_ #define _FILE_SYSTEM__LISTENER_H_
/* Genode includes */ /* Genode includes */
#include <file_system_session/file_system_session.h> #include <file_system_session/rpc_object.h>
#include <util/list.h> #include <util/list.h>
#include <base/lock.h> #include <base/lock.h>
#include <base/signal.h> #include <base/signal.h>
namespace File_system { namespace File_system {
typedef File_system::Session_rpc_object::Tx::Sink Sink;
class Listener : public Genode::List<Listener>::Element class Listener : public Genode::List<Listener>::Element
{ {
private: private:
Genode::Lock _lock; Genode::Lock _lock;
Genode::Signal_context_capability _sigh; Sink *_sink = nullptr;
bool _marked_as_updated; Node_handle _handle;
bool _marked_as_updated;
public: public:
Listener() : _marked_as_updated(false) { } Listener() : _marked_as_updated(false) { }
Listener(Genode::Signal_context_capability sigh) Listener(Sink &sink, Node_handle handle)
: _sigh(sigh), _marked_as_updated(false) { } : _sink(&sink), _handle(handle), _marked_as_updated(false) { }
void notify() void notify()
{ {
Genode::Lock::Guard guard(_lock); Genode::Lock::Guard guard(_lock);
if (_marked_as_updated && _sigh.valid()) if (_marked_as_updated && _sink && _sink->ready_to_ack()) {
Genode::Signal_transmitter(_sigh).submit(); _sink->acknowledge_packet(Packet_descriptor(
_handle, Packet_descriptor::CONTENT_CHANGED));
_marked_as_updated = false; _marked_as_updated = false;
}
} }
void mark_as_updated() void mark_as_updated()
@ -47,7 +52,7 @@ namespace File_system {
_marked_as_updated = true; _marked_as_updated = true;
} }
bool valid() const { return _sigh.valid(); } bool valid() const { return _sink != nullptr; }
}; };
} }

View File

@ -182,7 +182,7 @@ namespace File_system {
/** /**
* Register signal handler to be notified of node changes * Register signal handler to be notified of node changes
*/ */
void sigh(Node_handle handle, Genode::Signal_context_capability sigh) void register_notify(Sink &sink, Node_handle handle)
{ {
Genode::Lock::Guard guard(_lock); Genode::Lock::Guard guard(_lock);
@ -193,9 +193,6 @@ namespace File_system {
if (!node) if (!node)
throw Invalid_handle(); throw Invalid_handle();
node->lock();
Node_lock_guard node_lock_guard(node);
Listener &listener = _listeners[handle.value]; Listener &listener = _listeners[handle.value];
/* /*
@ -208,7 +205,7 @@ namespace File_system {
/* /*
* Register new handler * Register new handler
*/ */
listener = Listener(sigh); listener = Listener(sink, handle);
node->add_listener(&listener); node->add_listener(&listener);
} }
}; };

View File

@ -112,11 +112,6 @@ class File_system::Session_client : public Genode::Rpc_client<Session>
call<Rpc_move>(from_dir, from_name, to_dir, to_name); call<Rpc_move>(from_dir, from_name, to_dir, to_name);
} }
void sigh(Node_handle node, Genode::Signal_context_capability sigh) override
{
call<Rpc_sigh>(node, sigh);
}
void sync(Node_handle node) override void sync(Node_handle node) override
{ {
call<Rpc_sync>(node); call<Rpc_sync>(node);

View File

@ -119,7 +119,7 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor
{ {
public: public:
enum Opcode { READ, WRITE, READ_READY }; enum Opcode { READ, WRITE, CONTENT_CHANGED, READ_READY };
private: private:
@ -158,6 +158,19 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor
_position(position), _length(length), _success(false) _position(position), _length(length), _success(false)
{ } { }
/**
* Constructor
*
* This constructor provided for sending server-side
* notification packets.
*/
Packet_descriptor(Node_handle handle, Opcode op)
:
Genode::Packet_descriptor(0, 0),
_handle(handle), _op(op),
_position(0), _length(0), _success(true)
{ }
Node_handle handle() const { return _handle; } Node_handle handle() const { return _handle; }
Opcode operation() const { return _op; } Opcode operation() const { return _op; }
seek_off_t position() const { return _position; } seek_off_t position() const { return _position; }
@ -351,11 +364,6 @@ struct File_system::Session : public Genode::Session
virtual void move(Dir_handle, Name const &from, virtual void move(Dir_handle, Name const &from,
Dir_handle, Name const &to) = 0; Dir_handle, Name const &to) = 0;
/**
* Register handler that should be notified on node changes
*/
virtual void sigh(Node_handle, Genode::Signal_context_capability sigh) = 0;
/** /**
* Synchronize file system * Synchronize file system
* *
@ -406,14 +414,11 @@ struct File_system::Session : public Genode::Session
GENODE_TYPE_LIST(Invalid_handle, Invalid_name, GENODE_TYPE_LIST(Invalid_handle, Invalid_name,
Lookup_failed, Permission_denied), Lookup_failed, Permission_denied),
Dir_handle, Name const &, Dir_handle, Name const &); Dir_handle, Name const &, Dir_handle, Name const &);
GENODE_RPC_THROW(Rpc_sigh, void, sigh,
GENODE_TYPE_LIST(Invalid_handle),
Node_handle, Genode::Signal_context_capability);
GENODE_RPC(Rpc_sync, void, sync, Node_handle); GENODE_RPC(Rpc_sync, void, sync, Node_handle);
GENODE_RPC_INTERFACE(Rpc_tx_cap, Rpc_file, Rpc_symlink, Rpc_dir, Rpc_node, GENODE_RPC_INTERFACE(Rpc_tx_cap, Rpc_file, Rpc_symlink, Rpc_dir, Rpc_node,
Rpc_close, Rpc_status, Rpc_control, Rpc_unlink, Rpc_close, Rpc_status, Rpc_control, Rpc_unlink,
Rpc_truncate, Rpc_move, Rpc_sigh, Rpc_sync); Rpc_truncate, Rpc_move, Rpc_sync);
}; };
#endif /* _INCLUDE__FILE_SYSTEM_SESSION__FILE_SYSTEM_SESSION_H_ */ #endif /* _INCLUDE__FILE_SYSTEM_SESSION__FILE_SYSTEM_SESSION_H_ */

View File

@ -0,0 +1,121 @@
if {[have_spec arm]} {
assert_spec arm_v7
}
#
# Build
#
set build_components {
core init
app/rom_logger
app/rom_to_file
drivers/timer
server/dynamic_rom
server/fs_rom
server/ram_fs
}
build $build_components
create_boot_directory
#
# Generate config
#
append config {
<config>
<parent-provides>
<service name="CPU"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="IRQ"/>
<service name="LOG"/>
<service name="PD"/>
<service name="RAM"/>
<service name="RM"/>
<service name="ROM"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="ram_fs">
<resource name="RAM" quantum="10M"/>
<provides><service name="File_system"/></provides>
<config>
<policy label_prefix="rom_to_file" root="/" writeable="yes"/>
<policy label_prefix="fs_rom" root="/" writeable="no"/>
</config>
</start>
<start name="dynamic_rom">
<resource name="RAM" quantum="4M"/>
<provides><service name="ROM"/></provides>
<config verbose="yes">
<rom name="dynamic_rom">
<inline description="iteration 1">
<config iteration="1" />
</inline>
<sleep milliseconds="2000" />
<inline description="iteration 2">
<config iteration="2" />
</inline>
<sleep milliseconds="2000" />
<inline description="iteration 3">
<config iteration="3" />
</inline>
<sleep milliseconds="2000" />
<inline description="iteration 4">
<config iteration="4" />
</inline>
<sleep milliseconds="2000" />
</rom>
</config>
</start>
<start name="rom_to_file">
<resource name="RAM" quantum="2M"/>
<config rom="dynamic_rom"/>
<route>
<service name="ROM" label="dynamic_rom"> <child name="dynamic_rom"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="fs_rom">
<resource name="RAM" quantum="2M"/>
<provides><service name="ROM"/></provides>
</start>
<start name="rom_logger">
<resource name="RAM" quantum="1M"/>
<config rom="dynamic_rom"/>
<route>
<service name="ROM" label="dynamic_rom"> <child name="fs_rom"/> </service>
<any-service> <parent/> </any-service>
</route>
</start>
</config>}
install_config $config
#
# Boot modules
#
# generic modules
set boot_modules {
core ld.lib.so init
dynamic_rom
fs_rom
ram_fs
rom_logger
rom_to_file
test-libc_vfs
timer
}
build_boot_image $boot_modules
append qemu_args " -m 256 -nographic"
run_genode_until {.*child "test-libc_vfs" exited with exit value 0.*} 60

View File

@ -263,6 +263,9 @@ class Vfs::Fs_file_system : public File_system
handle.queued_write_packet = packet; handle.queued_write_packet = packet;
handle.queued_write_state = Handle_state::Queued_state::ACK; handle.queued_write_state = Handle_state::Queued_state::ACK;
break; break;
case Packet_descriptor::CONTENT_CHANGED:
break;
} }
_post_signal_hook.arm(handle.context); _post_signal_hook.arm(handle.context);

View File

@ -16,6 +16,7 @@
#include <file_system_session/connection.h> #include <file_system_session/connection.h>
#include <file_system/util.h> #include <file_system/util.h>
#include <os/path.h> #include <os/path.h>
#include <base/attached_ram_dataspace.h>
#include <root/component.h> #include <root/component.h>
#include <base/component.h> #include <base/component.h>
#include <base/session_label.h> #include <base/session_label.h>
@ -23,17 +24,29 @@
#include <base/heap.h> #include <base/heap.h>
#include <base/log.h> #include <base/log.h>
using namespace Genode;
/***************** /*****************
** ROM service ** ** ROM service **
*****************/ *****************/
namespace Fs_rom {
using namespace Genode;
struct Packet_handler;
class Rom_session_component;
class Rom_root;
typedef Genode::List<Rom_session_component> Sessions;
typedef File_system::Session_client::Tx::Source Tx_source;
}
/** /**
* A 'Rom_session_component' exports a single file of the file system * A 'Rom_session_component' exports a single file of the file system
*/ */
class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session> class Fs_rom::Rom_session_component :
public Genode::Rpc_object<Genode::Rom_session>, public Sessions::Element
{ {
private: private:
@ -59,6 +72,11 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
*/ */
File_system::file_size_t _file_size = 0; File_system::file_size_t _file_size = 0;
/**
* Read offset of the file
*/
File_system::seek_off_t _file_seek = 0;
/** /**
* Handle of currently watched compound directory * Handle of currently watched compound directory
* *
@ -70,36 +88,13 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
/** /**
* Dataspace exposed as ROM module to the client * Dataspace exposed as ROM module to the client
*/ */
Genode::Ram_dataspace_capability _file_ds; Genode::Attached_ram_dataspace _file_ds;
/** /**
* Signal destination for ROM file changes * Signal destination for ROM file changes
*/ */
Genode::Signal_context_capability _sigh; Genode::Signal_context_capability _sigh;
/**
* Signal-handling function called by the main thread the compound
* directory changed.
*/
void _dir_changed()
{
Genode::log("detected directory change");
if (_sigh.valid())
Genode::Signal_transmitter(_sigh).submit();
}
/**
* Handler that is called each time when the requested file is not
* yet available and the compound directory changes
*
* The change of the compound directory bears the chance that the
* requested file re-appears. So we inform the client about a ROM
* module change and thereby give it a chance to call 'dataspace()' in
* response.
*/
Genode::Signal_handler<Rom_session_component> _dir_change_handler
{ _env.ep(), *this, &Rom_session_component::_dir_changed };
/** /**
* Open compound directory of specified file * Open compound directory of specified file
* *
@ -162,12 +157,15 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
catch (Invalid_handle) { Genode::error(_file_path, ": Invalid_handle"); } catch (Invalid_handle) { Genode::error(_file_path, ": Invalid_handle"); }
catch (Invalid_name) { Genode::error(_file_path, ": invalid_name"); } catch (Invalid_name) { Genode::error(_file_path, ": invalid_name"); }
catch (Lookup_failed) { Genode::error(_file_path, ": lookup_failed"); } catch (Lookup_failed) { Genode::error(_file_path, ": lookup_failed"); }
catch (...) { Genode::error(_file_path, ": unhandled error"); };
return file_handle; return file_handle;
} }
void _register_for_compound_dir_changes() void _register_for_compound_dir_changes()
{ {
using namespace File_system;
/* forget about the previously watched compound directory */ /* forget about the previously watched compound directory */
if (_compound_dir_handle.valid()) if (_compound_dir_handle.valid())
_fs.close(_compound_dir_handle); _fs.close(_compound_dir_handle);
@ -176,7 +174,9 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
/* register for changes in compound directory */ /* register for changes in compound directory */
if (_compound_dir_handle.valid()) if (_compound_dir_handle.valid())
_fs.sigh(_compound_dir_handle, _dir_change_handler); _fs.tx()->submit_packet(File_system::Packet_descriptor(
_compound_dir_handle,
File_system::Packet_descriptor::CONTENT_CHANGED));
else else
Genode::warning("could not track compound dir, giving up"); Genode::warning("could not track compound dir, giving up");
} }
@ -200,12 +200,11 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
File_system::file_size_t const new_file_size = File_system::file_size_t const new_file_size =
_fs.status(file_handle).size; _fs.status(file_handle).size;
if (_file_ds.valid() && (new_file_size > _file_size)) { if (_file_ds.size() && (new_file_size > _file_size)) {
_env.ram().free(_file_ds);
/* mark as invalid */ /* mark as invalid */
_file_ds = Ram_dataspace_capability(); _file_ds.realloc(&_env.ram(), 0);
_file_size = 0; _file_size = 0;
_file_seek = 0;
} }
} }
_fs.close(file_handle); _fs.close(file_handle);
@ -225,8 +224,9 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
_fs.close(_compound_dir_handle); _fs.close(_compound_dir_handle);
/* register for file changes */ /* register for file changes */
if (_sigh.valid() && _file_handle.valid()) if (_file_handle.valid())
_fs.sigh(_file_handle, _sigh); _fs.tx()->submit_packet(File_system::Packet_descriptor(
_file_handle, File_system::Packet_descriptor::CONTENT_CHANGED));
size_t const file_size = _file_handle.valid() size_t const file_size = _file_handle.valid()
? _fs.status(_file_handle).size : 0; ? _fs.status(_file_handle).size : 0;
@ -234,30 +234,37 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
/* allocate new RAM dataspace according to file size */ /* allocate new RAM dataspace according to file size */
if (file_size > 0) { if (file_size > 0) {
try { try {
if (!_file_ds.valid()) { _file_seek = 0;
_file_ds = _env.ram().alloc(file_size); _file_ds.realloc(&_env.ram(), file_size);
_file_size = file_size; _file_size = file_size;
}
} catch (...) { } catch (...) {
Genode::error("couldn't allocate memory for file, empty result"); Genode::error("couldn't allocate memory for file, empty result");;
_file_ds = Ram_dataspace_capability();
return; return;
} }
} } else {
if (!_file_ds.valid()) {
_register_for_compound_dir_changes(); _register_for_compound_dir_changes();
return; return;
} }
/* map dataspace locally */
void * const dst_addr = _env.rm().attach(_file_ds);
/* read content from file */ /* read content from file */
read(_fs, _file_handle, dst_addr, file_size); Tx_source &source = *_fs.tx();
while (_file_seek < _file_size) {
/* if we cannot submit then process acknowledgements */
if (source.ready_to_submit()) {
size_t chunk_size = min(_file_size - _file_seek,
source.bulk_buffer_size() / 2);
File_system::Packet_descriptor
packet(source.alloc_packet(chunk_size),
_file_handle,
File_system::Packet_descriptor::READ,
chunk_size,
_file_seek);
source.submit_packet(packet);
}
/* unmap dataspace */ /* process ack at the global signal handler */
_env.rm().detach(dst_addr); _env.ep().wait_and_dispatch_one_io_signal();
}
} }
public: public:
@ -275,8 +282,10 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
Rom_session_component(Genode::Env &env, Rom_session_component(Genode::Env &env,
File_system::Session &fs, const char *file_path) File_system::Session &fs, const char *file_path)
: :
_env(env), _fs(fs), _file_path(file_path), _env(env), _fs(fs),
_file_handle(_open_file(_fs, _file_path)) _file_path(file_path),
_file_handle(_open_file(_fs, _file_path)),
_file_ds(env.ram(), env.rm(), 0) /* realloc later */
{ {
if (!_file_handle.valid()) if (!_file_handle.valid())
_register_for_compound_dir_changes(); _register_for_compound_dir_changes();
@ -293,9 +302,6 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
if (_compound_dir_handle.valid()) if (_compound_dir_handle.valid())
_fs.close(_compound_dir_handle); _fs.close(_compound_dir_handle);
/* close file */
_env.ram().free(_file_ds);
} }
/** /**
@ -304,20 +310,88 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
Genode::Rom_dataspace_capability dataspace() Genode::Rom_dataspace_capability dataspace()
{ {
_update_dataspace(); _update_dataspace();
Genode::Dataspace_capability ds = _file_ds; Genode::Dataspace_capability ds = _file_ds.cap();
return Genode::static_cap_cast<Genode::Rom_dataspace>(ds); return Genode::static_cap_cast<Genode::Rom_dataspace>(ds);
} }
void sigh(Genode::Signal_context_capability sigh) void sigh(Genode::Signal_context_capability sigh) {
_sigh = sigh; }
/**
* If packet corresponds to this session then process and return true.
*
* Called from the signal handler.
*/
bool process_packet(File_system::Packet_descriptor const packet)
{ {
_sigh = sigh; switch (packet.operation()) {
if (_file_handle.valid())
_fs.sigh(_file_handle, _sigh); case File_system::Packet_descriptor::CONTENT_CHANGED:
if (_file_handle == packet.handle() ||
_compound_dir_handle == packet.handle())
{
if (_sigh.valid())
Genode::Signal_transmitter(_sigh).submit();
return true;
}
return false;
case File_system::Packet_descriptor::READ: {
if (_file_handle != packet.handle())
return false;
if (packet.position() > _file_seek || _file_seek >= _file_size) {
error("bad packet seek position");
_file_ds.realloc(&_env.ram(), 0);
return true;
}
size_t const n = min(packet.length(), _file_size - _file_seek);
memcpy(_file_ds.local_addr<char>()+_file_seek,
_fs.tx()->packet_content(packet), n);
_file_seek += n;
return true;
}
default:
Genode::error("discarding strange packet acknowledgement");
return true;
}
return false;
} }
}; };
struct Fs_rom::Packet_handler : Genode::Io_signal_handler<Packet_handler>
{
Tx_source &source;
class Rom_root : public Genode::Root_component<Rom_session_component> /* list of open sessions */
Sessions sessions;
void handle_packets()
{
while (source.ack_avail()) {
File_system::Packet_descriptor pack = source.get_acked_packet();
for (Rom_session_component *session = sessions.first();
session; session = session->next())
{
if (session->process_packet(pack))
break;
}
source.release_packet(pack);
}
}
Packet_handler(Genode::Entrypoint &ep, Tx_source &source)
:
Genode::Io_signal_handler<Packet_handler>(
ep, *this, &Packet_handler::handle_packets),
source(source)
{ }
};
class Fs_rom::Rom_root : public Genode::Root_component<Fs_rom::Rom_session_component>
{ {
private: private:
@ -328,7 +402,9 @@ class Rom_root : public Genode::Root_component<Rom_session_component>
/* open file-system session */ /* open file-system session */
File_system::Connection _fs { _env, _fs_tx_block_alloc }; File_system::Connection _fs { _env, _fs_tx_block_alloc };
Rom_session_component *_create_session(const char *args) Packet_handler _packet_handler { _env.ep(), *_fs.tx() };
Rom_session_component *_create_session(const char *args) override
{ {
Genode::Session_label const label = label_from_args(args); Genode::Session_label const label = label_from_args(args);
Genode::Session_label const module_name = label.last_element(); Genode::Session_label const module_name = label.last_element();
@ -336,8 +412,17 @@ class Rom_root : public Genode::Root_component<Rom_session_component>
Genode::log("request for ", label); Genode::log("request for ", label);
/* create new session for the requested file */ /* create new session for the requested file */
return new (md_alloc()) Rom_session_component *session = new (md_alloc())
Rom_session_component(_env, _fs, module_name.string()); Rom_session_component(_env, _fs, module_name.string());
_packet_handler.sessions.insert(session);
return session;
}
void _destroy_session(Rom_session_component *session) override
{
_packet_handler.sessions.remove(session);
Genode::destroy(md_alloc(), session);
} }
public: public:
@ -354,6 +439,9 @@ class Rom_root : public Genode::Root_component<Rom_session_component>
Genode::Root_component<Rom_session_component>(env.ep(), md_alloc), Genode::Root_component<Rom_session_component>(env.ep(), md_alloc),
_env(env) _env(env)
{ {
/* Process CONTENT_CHANGED acknowledgement packets at the entrypoint */
_fs.sigh_ack_avail(_packet_handler);
env.parent().announce(env.ep().manage(*this)); env.parent().announce(env.ep().manage(*this));
} }
}; };
@ -361,6 +449,6 @@ class Rom_root : public Genode::Root_component<Rom_session_component>
void Component::construct(Genode::Env &env) void Component::construct(Genode::Env &env)
{ {
static Sliced_heap sliced_heap(env.ram(), env.rm()); static Genode::Sliced_heap sliced_heap(env.ram(), env.rm());
static Rom_root inst(env, sliced_heap); static Fs_rom::Rom_root inst(env, sliced_heap);
} }

View File

@ -58,12 +58,6 @@ class File_system::Session_component : public Session_rpc_object
{ {
void * const content = tx_sink()->packet_content(packet); void * const content = tx_sink()->packet_content(packet);
size_t const length = packet.length(); size_t const length = packet.length();
seek_off_t const offset = packet.position();
if (!content || (packet.length() > packet.size())) {
packet.succeeded(false);
return;
}
/* resulting length */ /* resulting length */
size_t res_length = 0; size_t res_length = 0;
@ -71,13 +65,22 @@ class File_system::Session_component : public Session_rpc_object
switch (packet.operation()) { switch (packet.operation()) {
case Packet_descriptor::READ: case Packet_descriptor::READ:
res_length = node.read((char *)content, length, offset); if (content && (packet.length() <= packet.size()))
res_length = node.read((char *)content, length, packet.position());
break; break;
case Packet_descriptor::WRITE: case Packet_descriptor::WRITE:
res_length = node.write((char const *)content, length, offset); if (content && (packet.length() <= packet.size()))
res_length = node.write((char const *)content, length, packet.position());
break; break;
case Packet_descriptor::CONTENT_CHANGED:
_handle_registry.register_notify(*tx_sink(), packet.handle());
/* notify_listeners may bounce the packet back*/
node.notify_listeners();
/* otherwise defer acknowledgement of this packet */
return;
case Packet_descriptor::READ_READY: case Packet_descriptor::READ_READY:
/* not supported */ /* not supported */
break; break;
@ -85,6 +88,7 @@ class File_system::Session_component : public Session_rpc_object
packet.length(res_length); packet.length(res_length);
packet.succeeded(res_length > 0); packet.succeeded(res_length > 0);
tx_sink()->acknowledge_packet(packet);
} }
void _process_packet() void _process_packet()
@ -101,12 +105,6 @@ class File_system::Session_component : public Session_rpc_object
_process_packet_op(packet, *node); _process_packet_op(packet, *node);
} }
catch (Invalid_handle) { Genode::error("Invalid_handle"); } catch (Invalid_handle) { Genode::error("Invalid_handle"); }
/*
* The 'acknowledge_packet' function cannot block because we
* checked for 'ready_to_ack' in '_process_packets'.
*/
tx_sink()->acknowledge_packet(packet);
} }
/** /**
@ -304,11 +302,6 @@ class File_system::Session_component : public Session_rpc_object
Genode::error(__func__, " not implemented"); Genode::error(__func__, " not implemented");
} }
void sigh(Node_handle node_handle, Signal_context_capability sigh)
{
_handle_registry.sigh(node_handle, sigh);
}
/** /**
* We could call sync(2) here but for now we forward just the * We could call sync(2) here but for now we forward just the
* reminder because besides testing, there is currently no * reminder because besides testing, there is currently no

View File

@ -63,12 +63,6 @@ class File_system::Session_component : public Session_rpc_object
{ {
void * const content = tx_sink()->packet_content(packet); void * const content = tx_sink()->packet_content(packet);
size_t const length = packet.length(); size_t const length = packet.length();
seek_off_t const offset = packet.position();
if (!content || (packet.length() > packet.size())) {
packet.succeeded(false);
return;
}
/* resulting length */ /* resulting length */
size_t res_length = 0; size_t res_length = 0;
@ -76,13 +70,20 @@ class File_system::Session_component : public Session_rpc_object
switch (packet.operation()) { switch (packet.operation()) {
case Packet_descriptor::READ: case Packet_descriptor::READ:
res_length = node.read((char *)content, length, offset); if (content && (packet.length() <= packet.size()))
res_length = node.read((char *)content, length, packet.position());
break; break;
case Packet_descriptor::WRITE: case Packet_descriptor::WRITE:
res_length = node.write((char const *)content, length, offset); if (content && (packet.length() <= packet.size()))
res_length = node.write((char const *)content, length, packet.position());
break; break;
case Packet_descriptor::CONTENT_CHANGED:
_handle_registry.register_notify(*tx_sink(), packet.handle());
node.notify_listeners();
return;
case Packet_descriptor::READ_READY: case Packet_descriptor::READ_READY:
/* not supported */ /* not supported */
break; break;
@ -90,6 +91,7 @@ class File_system::Session_component : public Session_rpc_object
packet.length(res_length); packet.length(res_length);
packet.succeeded(res_length > 0); packet.succeeded(res_length > 0);
tx_sink()->acknowledge_packet(packet);
} }
void _process_packet() void _process_packet()
@ -106,12 +108,6 @@ class File_system::Session_component : public Session_rpc_object
_process_packet_op(packet, *node); _process_packet_op(packet, *node);
} }
catch (Invalid_handle) { Genode::error("Invalid_handle"); } catch (Invalid_handle) { Genode::error("Invalid_handle"); }
/*
* The 'acknowledge_packet' function cannot block because we
* checked for 'ready_to_ack' in '_process_packets'.
*/
tx_sink()->acknowledge_packet(packet);
} }
void _process_packets() void _process_packets()
@ -414,9 +410,11 @@ class File_system::Session_component : public Session_rpc_object
node->notify_listeners(); node->notify_listeners();
} }
void sigh(Node_handle node_handle, Signal_context_capability sigh) void sync(Node_handle handle) override
{ {
_handle_registry.sigh(node_handle, sigh); Node *node = _handle_registry.lookup_and_lock(handle);
Node_lock_guard guard(node);
node->notify_listeners();
} }
}; };

View File

@ -647,12 +647,6 @@ class File_system::Session_component : public Session_rpc_object
{ {
void * const content = tx_sink()->packet_content(packet); void * const content = tx_sink()->packet_content(packet);
size_t const length = packet.length(); size_t const length = packet.length();
seek_off_t const offset = packet.position();
if (!content || (packet.length() > packet.size())) {
packet.succeeded(false);
return;
}
/* resulting length */ /* resulting length */
size_t res_length = 0; size_t res_length = 0;
@ -660,13 +654,22 @@ class File_system::Session_component : public Session_rpc_object
switch (packet.operation()) { switch (packet.operation()) {
case Packet_descriptor::READ: case Packet_descriptor::READ:
res_length = node.read((char *)content, length, offset); if (content && (packet.length() <= packet.size()))
res_length = node.read((char *)content, length, packet.position());
break; break;
case Packet_descriptor::WRITE: case Packet_descriptor::WRITE:
res_length = node.write((char const *)content, length, offset); if (content && (packet.length() <= packet.size()))
res_length = node.write((char const *)content, length, packet.position());
break; break;
case Packet_descriptor::CONTENT_CHANGED:
_handle_registry.register_notify(*tx_sink(), packet.handle());
/* notify_listeners may bounce the packet back*/
node.notify_listeners();
/* otherwise defer acknowledgement of this packet */
return;
case Packet_descriptor::READ_READY: case Packet_descriptor::READ_READY:
/* not supported */ /* not supported */
break; break;
@ -674,6 +677,7 @@ class File_system::Session_component : public Session_rpc_object
packet.length(res_length); packet.length(res_length);
packet.succeeded(res_length > 0); packet.succeeded(res_length > 0);
tx_sink()->acknowledge_packet(packet);
} }
void _process_packet() void _process_packet()
@ -689,12 +693,6 @@ class File_system::Session_component : public Session_rpc_object
_process_packet_op(packet, *node); _process_packet_op(packet, *node);
} }
catch (Invalid_handle) { Genode::error("Invalid_handle"); } catch (Invalid_handle) { Genode::error("Invalid_handle"); }
/*
* The 'acknowledge_packet' function cannot block because we
* checked for 'ready_to_ack' in '_process_packets'.
*/
tx_sink()->acknowledge_packet(packet);
} }
/** /**
@ -904,9 +902,6 @@ class File_system::Session_component : public Session_rpc_object
} }
void move(Dir_handle, Name const &, Dir_handle, Name const &) { } void move(Dir_handle, Name const &, Dir_handle, Name const &) { }
void sigh(Node_handle node_handle, Signal_context_capability sigh) {
_handle_registry.sigh(node_handle, sigh); }
}; };
@ -921,6 +916,8 @@ class File_system::Root : public Root_component<Session_component>
Directory &_root_dir; Directory &_root_dir;
Genode::Attached_rom_dataspace _config { _env, "config" };
protected: protected:
Session_component *_create_session(const char *args) Session_component *_create_session(const char *args)
@ -946,7 +943,7 @@ class File_system::Root : public Root_component<Session_component>
Session_label const label = label_from_args(args); Session_label const label = label_from_args(args);
try { try {
Session_policy policy(label); Session_policy policy(label, _config.xml());
/* /*
* Override default settings with specific session settings by * Override default settings with specific session settings by

View File

@ -192,6 +192,10 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object,
catch (Dont_ack) { throw; } catch (Dont_ack) { throw; }
catch (...) { } catch (...) { }
break; break;
case Packet_descriptor::CONTENT_CHANGED:
/* The VFS does not track file changes yet */
throw Dont_ack();
} }
packet.length(res_length); packet.length(res_length);
@ -570,8 +574,6 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object,
}); });
} }
void sigh(Node_handle handle, Signal_context_capability sigh) override { }
/** /**
* Sync the VFS and send any pending signals on the node. * Sync the VFS and send any pending signals on the node.
*/ */