Fs_rom: send signals on file removal

Clients may wish to act on missing files. In any case the fs_rom
needs to reopen a watch handle when a file is deleted, and this
sort of change to the internal state machine is propelled by
client RPC requests.

Fix #2839
This commit is contained in:
Ehmry - 2018-05-27 10:09:00 +02:00 committed by Christian Helmuth
parent 87be50c542
commit 1af6bd1454
6 changed files with 57 additions and 27 deletions

View File

@ -39,6 +39,7 @@
</content>
<policy label_prefix="fs_report -> " root="/" writeable="yes"/>
<policy label_prefix="fs_rom -> " root="/test-fs_report"/>
<policy label_prefix="test-fs_report -> " root="/test-fs_report" writeable="yes"/>
</config>
</start>
<!--
@ -57,7 +58,7 @@
</start>
<start name="test-fs_report">
<resource name="RAM" quantum="4M"/>
<config/>
<config> <vfs> <fs/> </vfs> </config>
<route>
<service name="ROM" label="devices"> <child name="fs_rom"/> </service>
<service name="ROM" label="focus"> <child name="fs_rom"/> </service>

View File

@ -2,3 +2,4 @@ base
os
report_session
timer_session
vfs

View File

@ -45,6 +45,7 @@ append config {
</content>
<policy label_prefix="fs_report -> " root="/" writeable="yes"/>
<policy label_prefix="fs_rom -> " root="/test-fs_report"/>
<policy label_prefix="test-fs_report -> " root="/test-fs_report" writeable="yes"/>
</config>
</start>
<!--
@ -63,7 +64,7 @@ append config {
</start>
<start name="test-fs_report">
<resource name="RAM" quantum="4M"/>
<config/>
<config> <vfs> <fs/> </vfs> </config>
<route>
<service name="ROM" label="devices"> <child name="fs_rom"/> </service>
<service name="ROM" label="focus"> <child name="fs_rom"/> </service>

View File

@ -100,7 +100,7 @@ class Fs_rom::Rom_session_component : public Rpc_object<Rom_session>
*/
struct Version { unsigned value; };
Version _curr_version { 0 };
Version _handed_out_version { ~0U };
Version _handed_out_version { 0 };
/**
* Track if the session file or a directory is being watched
@ -257,26 +257,18 @@ class Fs_rom::Rom_session_component : public Rpc_object<Rom_session>
catch (Permission_denied) { error(_file_path, ": permission denied"); }
catch (...) { error(_file_path, ": unhandled error"); };
if (_file_size > 0) {
memset(_file_ds.local_addr<char>(), 0x00, min(_file_size, _file_ds.size()));
_file_size = 0;
}
return false;
}
void _notify_client_about_new_version()
{
using namespace File_system;
if (_sigh.valid() && _curr_version.value != _handed_out_version.value) {
/* notify if the file is not empty */
try {
Node_handle file = _fs.node(_file_path.base());
Handle_guard g(_fs, file);
_file_size = _fs.status(file).size;
}
catch (...) { _file_size = 0; }
if (_file_size > 0)
Signal_transmitter(_sigh).submit();
}
if (_sigh.valid() && _curr_version.value != _handed_out_version.value)
Signal_transmitter(_sigh).submit();
}
public:
@ -364,11 +356,9 @@ class Fs_rom::Rom_session_component : public Rpc_object<Rom_session>
_open_watch_handle();
}
if (_watching_file) {
/* notify the client of the change */
_curr_version = Version { _curr_version.value + 1 };
_notify_client_about_new_version();
}
/* notify the client of the change */
_curr_version = Version { _curr_version.value + 1 };
_notify_client_about_new_version();
return;
case File_system::Packet_descriptor::READ: {
@ -466,7 +456,6 @@ class Fs_rom::Rom_root : public Root_component<Fs_rom::Rom_session_component>
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));

View File

@ -11,6 +11,8 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#include <vfs/simple_env.h>
#include <base/heap.h>
#include <base/log.h>
#include <base/component.h>
#include <base/attached_rom_dataspace.h>
@ -28,8 +30,24 @@ struct Test::Main
{
Env &_env;
Genode::Heap _heap { _env.pd(), _env.rm() };
Timer::Connection _timer { _env };
Genode::Attached_rom_dataspace _config_rom { _env, "config" };
Genode::Xml_node vfs_config()
{
try { return _config_rom.xml().sub_node("vfs"); }
catch (...) {
Genode::error("VFS not configured");
_env.parent().exit(~0);
throw;
}
}
Vfs::Simple_env _vfs_env { _env, _heap, vfs_config() };
Constructible<Reporter> _devices_reporter { };
Constructible<Reporter> _focus_reporter { };
@ -50,6 +68,9 @@ struct Test::Main
Signal_handler<Main> _focus_rom_update_handler {
_env.ep(), *this, &Main::_handle_focus_rom_update };
Signal_handler<Main> _focus_removal_handler {
_env.ep(), *this, &Main::_handle_focus_removal };
Constructible<Timer::One_shot_timeout<Main> > _one_shot_timeout { };
void _handle_init()
@ -84,7 +105,7 @@ struct Test::Main
_devices_rom->update();
if (_devices_rom->xml().attribute_value("version", Version()) != "version 2") {
error("unexpected content of \"devices\" ROM after update");
error("(6) unexpected content of \"devices\" ROM after update");
throw Exception();
}
@ -111,12 +132,29 @@ struct Test::Main
_focus_rom->update();
if (_focus_rom->xml().attribute_value("version", Version()) != "focus version 1") {
error("unexpected content of \"focus\" ROM");
error("(9) unexpected content of \"focus\" ROM");
throw Exception();
}
log("(9) received expected focus ROM content");
_focus_rom->sigh(_focus_removal_handler);
log("(10) remove focus file");
_vfs_env.root_dir().unlink("focus");
}
void _handle_focus_removal()
{
_focus_rom->update();
if (!_focus_rom->xml().has_type("empty")) {
error("(11) unexpected content of \"focus\" ROM");
throw Exception();
}
log("(11) received empty focus ROM");
/* test completed successfully */
_env.parent().exit(0);
}

View File

@ -1,4 +1,4 @@
TARGET = test-fs_report
SRC_CC = main.cc
LIBS = base
LIBS = base vfs