mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
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:
parent
29b3fff5eb
commit
24a9537a27
@ -61,12 +61,6 @@ class File_system::Session_component : public Session_rpc_object
|
||||
{
|
||||
void * const content = tx_sink()->packet_content(packet);
|
||||
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 */
|
||||
size_t res_length = 0;
|
||||
@ -74,13 +68,22 @@ class File_system::Session_component : public Session_rpc_object
|
||||
switch (packet.operation()) {
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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:
|
||||
/* not supported */
|
||||
break;
|
||||
@ -88,6 +91,7 @@ class File_system::Session_component : public Session_rpc_object
|
||||
|
||||
packet.length(res_length);
|
||||
packet.succeeded(res_length > 0);
|
||||
tx_sink()->acknowledge_packet(packet);
|
||||
}
|
||||
|
||||
void _process_packet()
|
||||
@ -103,12 +107,6 @@ class File_system::Session_component : public Session_rpc_object
|
||||
_process_packet_op(packet, *node);
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
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(); }
|
||||
};
|
||||
|
||||
@ -367,6 +360,8 @@ class File_system::Root : public Root_component<Session_component>
|
||||
|
||||
Genode::Env &_env;
|
||||
|
||||
Genode::Attached_rom_dataspace _config { _env, "config" };
|
||||
|
||||
protected:
|
||||
|
||||
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];
|
||||
try {
|
||||
Session_policy policy(label);
|
||||
Session_policy policy(label, _config.xml());
|
||||
|
||||
/* determine policy root offset */
|
||||
try {
|
||||
|
@ -63,12 +63,6 @@ class File_system::Session_component : public Session_rpc_object
|
||||
{
|
||||
void * const content = tx_sink()->packet_content(packet);
|
||||
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 */
|
||||
size_t res_length = 0;
|
||||
@ -76,17 +70,22 @@ class File_system::Session_component : public Session_rpc_object
|
||||
switch (packet.operation()) {
|
||||
|
||||
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;
|
||||
|
||||
case Packet_descriptor::WRITE:
|
||||
/* session is read-only */
|
||||
if (!_writeable)
|
||||
break;
|
||||
|
||||
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;
|
||||
|
||||
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:
|
||||
/* not supported */
|
||||
break;
|
||||
@ -94,6 +93,7 @@ class File_system::Session_component : public Session_rpc_object
|
||||
|
||||
packet.length(res_length);
|
||||
packet.succeeded(res_length > 0);
|
||||
tx_sink()->acknowledge_packet(packet);
|
||||
}
|
||||
|
||||
void _process_packet()
|
||||
@ -110,12 +110,6 @@ class File_system::Session_component : public Session_rpc_object
|
||||
_process_packet_op(packet, *node);
|
||||
}
|
||||
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
|
||||
{
|
||||
Fuse::sync_fs();
|
||||
|
@ -8,36 +8,41 @@
|
||||
#define _FILE_SYSTEM__LISTENER_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <file_system_session/file_system_session.h>
|
||||
#include <file_system_session/rpc_object.h>
|
||||
#include <util/list.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/signal.h>
|
||||
|
||||
namespace File_system {
|
||||
|
||||
typedef File_system::Session_rpc_object::Tx::Sink Sink;
|
||||
|
||||
class Listener : public Genode::List<Listener>::Element
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
Genode::Lock _lock;
|
||||
Genode::Signal_context_capability _sigh;
|
||||
bool _marked_as_updated;
|
||||
Genode::Lock _lock;
|
||||
Sink *_sink = nullptr;
|
||||
Node_handle _handle;
|
||||
bool _marked_as_updated;
|
||||
|
||||
public:
|
||||
|
||||
Listener() : _marked_as_updated(false) { }
|
||||
|
||||
Listener(Genode::Signal_context_capability sigh)
|
||||
: _sigh(sigh), _marked_as_updated(false) { }
|
||||
Listener(Sink &sink, Node_handle handle)
|
||||
: _sink(&sink), _handle(handle), _marked_as_updated(false) { }
|
||||
|
||||
void notify()
|
||||
{
|
||||
Genode::Lock::Guard guard(_lock);
|
||||
|
||||
if (_marked_as_updated && _sigh.valid())
|
||||
Genode::Signal_transmitter(_sigh).submit();
|
||||
|
||||
_marked_as_updated = false;
|
||||
if (_marked_as_updated && _sink && _sink->ready_to_ack()) {
|
||||
_sink->acknowledge_packet(Packet_descriptor(
|
||||
_handle, Packet_descriptor::CONTENT_CHANGED));
|
||||
_marked_as_updated = false;
|
||||
}
|
||||
}
|
||||
|
||||
void mark_as_updated()
|
||||
@ -47,7 +52,7 @@ namespace File_system {
|
||||
_marked_as_updated = true;
|
||||
}
|
||||
|
||||
bool valid() const { return _sigh.valid(); }
|
||||
bool valid() const { return _sink != nullptr; }
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ namespace File_system {
|
||||
/**
|
||||
* 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);
|
||||
|
||||
@ -193,9 +193,6 @@ namespace File_system {
|
||||
if (!node)
|
||||
throw Invalid_handle();
|
||||
|
||||
node->lock();
|
||||
Node_lock_guard node_lock_guard(node);
|
||||
|
||||
Listener &listener = _listeners[handle.value];
|
||||
|
||||
/*
|
||||
@ -208,7 +205,7 @@ namespace File_system {
|
||||
/*
|
||||
* Register new handler
|
||||
*/
|
||||
listener = Listener(sigh);
|
||||
listener = Listener(sink, handle);
|
||||
node->add_listener(&listener);
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
void sigh(Node_handle node, Genode::Signal_context_capability sigh) override
|
||||
{
|
||||
call<Rpc_sigh>(node, sigh);
|
||||
}
|
||||
|
||||
void sync(Node_handle node) override
|
||||
{
|
||||
call<Rpc_sync>(node);
|
||||
|
@ -119,7 +119,7 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor
|
||||
{
|
||||
public:
|
||||
|
||||
enum Opcode { READ, WRITE, READ_READY };
|
||||
enum Opcode { READ, WRITE, CONTENT_CHANGED, READ_READY };
|
||||
|
||||
private:
|
||||
|
||||
@ -158,6 +158,19 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor
|
||||
_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; }
|
||||
Opcode operation() const { return _op; }
|
||||
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,
|
||||
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
|
||||
*
|
||||
@ -406,14 +414,11 @@ struct File_system::Session : public Genode::Session
|
||||
GENODE_TYPE_LIST(Invalid_handle, Invalid_name,
|
||||
Lookup_failed, Permission_denied),
|
||||
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_INTERFACE(Rpc_tx_cap, Rpc_file, Rpc_symlink, Rpc_dir, Rpc_node,
|
||||
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_ */
|
||||
|
121
repos/os/run/fs_rom_update.run
Normal file
121
repos/os/run/fs_rom_update.run
Normal 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
|
@ -263,6 +263,9 @@ class Vfs::Fs_file_system : public File_system
|
||||
handle.queued_write_packet = packet;
|
||||
handle.queued_write_state = Handle_state::Queued_state::ACK;
|
||||
break;
|
||||
|
||||
case Packet_descriptor::CONTENT_CHANGED:
|
||||
break;
|
||||
}
|
||||
|
||||
_post_signal_hook.arm(handle.context);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <file_system_session/connection.h>
|
||||
#include <file_system/util.h>
|
||||
#include <os/path.h>
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <root/component.h>
|
||||
#include <base/component.h>
|
||||
#include <base/session_label.h>
|
||||
@ -23,17 +24,29 @@
|
||||
#include <base/heap.h>
|
||||
#include <base/log.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
/*****************
|
||||
** 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
|
||||
*/
|
||||
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:
|
||||
|
||||
@ -59,6 +72,11 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
|
||||
*/
|
||||
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
|
||||
*
|
||||
@ -70,36 +88,13 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
*
|
||||
@ -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_name) { Genode::error(_file_path, ": invalid_name"); }
|
||||
catch (Lookup_failed) { Genode::error(_file_path, ": lookup_failed"); }
|
||||
catch (...) { Genode::error(_file_path, ": unhandled error"); };
|
||||
|
||||
return file_handle;
|
||||
}
|
||||
|
||||
void _register_for_compound_dir_changes()
|
||||
{
|
||||
using namespace File_system;
|
||||
|
||||
/* forget about the previously watched compound directory */
|
||||
if (_compound_dir_handle.valid())
|
||||
_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 */
|
||||
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
|
||||
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 =
|
||||
_fs.status(file_handle).size;
|
||||
|
||||
if (_file_ds.valid() && (new_file_size > _file_size)) {
|
||||
_env.ram().free(_file_ds);
|
||||
|
||||
if (_file_ds.size() && (new_file_size > _file_size)) {
|
||||
/* mark as invalid */
|
||||
_file_ds = Ram_dataspace_capability();
|
||||
_file_ds.realloc(&_env.ram(), 0);
|
||||
_file_size = 0;
|
||||
_file_seek = 0;
|
||||
}
|
||||
}
|
||||
_fs.close(file_handle);
|
||||
@ -225,8 +224,9 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
|
||||
_fs.close(_compound_dir_handle);
|
||||
|
||||
/* register for file changes */
|
||||
if (_sigh.valid() && _file_handle.valid())
|
||||
_fs.sigh(_file_handle, _sigh);
|
||||
if (_file_handle.valid())
|
||||
_fs.tx()->submit_packet(File_system::Packet_descriptor(
|
||||
_file_handle, File_system::Packet_descriptor::CONTENT_CHANGED));
|
||||
|
||||
size_t const file_size = _file_handle.valid()
|
||||
? _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 */
|
||||
if (file_size > 0) {
|
||||
try {
|
||||
if (!_file_ds.valid()) {
|
||||
_file_ds = _env.ram().alloc(file_size);
|
||||
_file_size = file_size;
|
||||
}
|
||||
_file_seek = 0;
|
||||
_file_ds.realloc(&_env.ram(), file_size);
|
||||
_file_size = file_size;
|
||||
} catch (...) {
|
||||
Genode::error("couldn't allocate memory for file, empty result");
|
||||
_file_ds = Ram_dataspace_capability();
|
||||
Genode::error("couldn't allocate memory for file, empty result");;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!_file_ds.valid()) {
|
||||
} else {
|
||||
_register_for_compound_dir_changes();
|
||||
return;
|
||||
}
|
||||
|
||||
/* map dataspace locally */
|
||||
void * const dst_addr = _env.rm().attach(_file_ds);
|
||||
|
||||
/* 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 */
|
||||
_env.rm().detach(dst_addr);
|
||||
/* process ack at the global signal handler */
|
||||
_env.ep().wait_and_dispatch_one_io_signal();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
@ -275,8 +282,10 @@ class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
|
||||
Rom_session_component(Genode::Env &env,
|
||||
File_system::Session &fs, const char *file_path)
|
||||
:
|
||||
_env(env), _fs(fs), _file_path(file_path),
|
||||
_file_handle(_open_file(_fs, _file_path))
|
||||
_env(env), _fs(fs),
|
||||
_file_path(file_path),
|
||||
_file_handle(_open_file(_fs, _file_path)),
|
||||
_file_ds(env.ram(), env.rm(), 0) /* realloc later */
|
||||
{
|
||||
if (!_file_handle.valid())
|
||||
_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())
|
||||
_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()
|
||||
{
|
||||
_update_dataspace();
|
||||
Genode::Dataspace_capability ds = _file_ds;
|
||||
Genode::Dataspace_capability ds = _file_ds.cap();
|
||||
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;
|
||||
if (_file_handle.valid())
|
||||
_fs.sigh(_file_handle, _sigh);
|
||||
switch (packet.operation()) {
|
||||
|
||||
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:
|
||||
|
||||
@ -328,7 +402,9 @@ class Rom_root : public Genode::Root_component<Rom_session_component>
|
||||
/* open file-system session */
|
||||
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 module_name = label.last_element();
|
||||
@ -336,8 +412,17 @@ class Rom_root : public Genode::Root_component<Rom_session_component>
|
||||
Genode::log("request for ", label);
|
||||
|
||||
/* 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());
|
||||
|
||||
_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:
|
||||
@ -354,6 +439,9 @@ class Rom_root : public Genode::Root_component<Rom_session_component>
|
||||
Genode::Root_component<Rom_session_component>(env.ep(), md_alloc),
|
||||
_env(env)
|
||||
{
|
||||
/* Process CONTENT_CHANGED acknowledgement packets at the entrypoint */
|
||||
_fs.sigh_ack_avail(_packet_handler);
|
||||
|
||||
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)
|
||||
{
|
||||
static Sliced_heap sliced_heap(env.ram(), env.rm());
|
||||
static Rom_root inst(env, sliced_heap);
|
||||
static Genode::Sliced_heap sliced_heap(env.ram(), env.rm());
|
||||
static Fs_rom::Rom_root inst(env, sliced_heap);
|
||||
}
|
||||
|
@ -58,12 +58,6 @@ class File_system::Session_component : public Session_rpc_object
|
||||
{
|
||||
void * const content = tx_sink()->packet_content(packet);
|
||||
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 */
|
||||
size_t res_length = 0;
|
||||
@ -71,13 +65,22 @@ class File_system::Session_component : public Session_rpc_object
|
||||
switch (packet.operation()) {
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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:
|
||||
/* not supported */
|
||||
break;
|
||||
@ -85,6 +88,7 @@ class File_system::Session_component : public Session_rpc_object
|
||||
|
||||
packet.length(res_length);
|
||||
packet.succeeded(res_length > 0);
|
||||
tx_sink()->acknowledge_packet(packet);
|
||||
}
|
||||
|
||||
void _process_packet()
|
||||
@ -101,12 +105,6 @@ class File_system::Session_component : public Session_rpc_object
|
||||
_process_packet_op(packet, *node);
|
||||
}
|
||||
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");
|
||||
}
|
||||
|
||||
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
|
||||
* reminder because besides testing, there is currently no
|
||||
|
@ -63,12 +63,6 @@ class File_system::Session_component : public Session_rpc_object
|
||||
{
|
||||
void * const content = tx_sink()->packet_content(packet);
|
||||
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 */
|
||||
size_t res_length = 0;
|
||||
@ -76,13 +70,20 @@ class File_system::Session_component : public Session_rpc_object
|
||||
switch (packet.operation()) {
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
case Packet_descriptor::CONTENT_CHANGED:
|
||||
_handle_registry.register_notify(*tx_sink(), packet.handle());
|
||||
node.notify_listeners();
|
||||
return;
|
||||
|
||||
case Packet_descriptor::READ_READY:
|
||||
/* not supported */
|
||||
break;
|
||||
@ -90,6 +91,7 @@ class File_system::Session_component : public Session_rpc_object
|
||||
|
||||
packet.length(res_length);
|
||||
packet.succeeded(res_length > 0);
|
||||
tx_sink()->acknowledge_packet(packet);
|
||||
}
|
||||
|
||||
void _process_packet()
|
||||
@ -106,12 +108,6 @@ class File_system::Session_component : public Session_rpc_object
|
||||
_process_packet_op(packet, *node);
|
||||
}
|
||||
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()
|
||||
@ -414,9 +410,11 @@ class File_system::Session_component : public Session_rpc_object
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -647,12 +647,6 @@ class File_system::Session_component : public Session_rpc_object
|
||||
{
|
||||
void * const content = tx_sink()->packet_content(packet);
|
||||
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 */
|
||||
size_t res_length = 0;
|
||||
@ -660,13 +654,22 @@ class File_system::Session_component : public Session_rpc_object
|
||||
switch (packet.operation()) {
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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:
|
||||
/* not supported */
|
||||
break;
|
||||
@ -674,6 +677,7 @@ class File_system::Session_component : public Session_rpc_object
|
||||
|
||||
packet.length(res_length);
|
||||
packet.succeeded(res_length > 0);
|
||||
tx_sink()->acknowledge_packet(packet);
|
||||
}
|
||||
|
||||
void _process_packet()
|
||||
@ -689,12 +693,6 @@ class File_system::Session_component : public Session_rpc_object
|
||||
_process_packet_op(packet, *node);
|
||||
}
|
||||
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 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;
|
||||
|
||||
Genode::Attached_rom_dataspace _config { _env, "config" };
|
||||
|
||||
protected:
|
||||
|
||||
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);
|
||||
try {
|
||||
Session_policy policy(label);
|
||||
Session_policy policy(label, _config.xml());
|
||||
|
||||
/*
|
||||
* Override default settings with specific session settings by
|
||||
|
@ -192,6 +192,10 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object,
|
||||
catch (Dont_ack) { throw; }
|
||||
catch (...) { }
|
||||
break;
|
||||
|
||||
case Packet_descriptor::CONTENT_CHANGED:
|
||||
/* The VFS does not track file changes yet */
|
||||
throw Dont_ack();
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user