mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 18:56:29 +00:00
parent
1eb37fbe22
commit
47c616ab94
2
repos/os/recipes/src/fs_report/content.mk
Normal file
2
repos/os/recipes/src/fs_report/content.mk
Normal file
@ -0,0 +1,2 @@
|
||||
SRC_DIR = include/report_rom src/server/fs_report
|
||||
include $(GENODE_DIR)/repos/base/recipes/src/content.inc
|
1
repos/os/recipes/src/fs_report/hash
Normal file
1
repos/os/recipes/src/fs_report/hash
Normal file
@ -0,0 +1 @@
|
||||
2017-06-09 3abb3c9c0dabc2d8281f46e5f667fb72d6906d48
|
8
repos/os/recipes/src/fs_report/used_apis
Normal file
8
repos/os/recipes/src/fs_report/used_apis
Normal file
@ -0,0 +1,8 @@
|
||||
base
|
||||
block_session
|
||||
file_system_session
|
||||
os
|
||||
report_session
|
||||
rtc_session
|
||||
terminal_session
|
||||
vfs
|
103
repos/os/run/fs_report.run
Normal file
103
repos/os/run/fs_report.run
Normal file
@ -0,0 +1,103 @@
|
||||
#
|
||||
# Build
|
||||
#
|
||||
set build_components {
|
||||
core init
|
||||
drivers/timer
|
||||
server/fs_report
|
||||
server/vfs
|
||||
}
|
||||
|
||||
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="RM"/>
|
||||
<service name="ROM"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<default caps="1024"/>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides ><service name="Timer"/> </provides>
|
||||
</start>
|
||||
<start name="log_fs">
|
||||
<binary name="vfs"/>
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides> <service name="File_system"/> </provides>
|
||||
<config>
|
||||
<vfs> <dir name="init"> <log name="state.report"/> <ram/> </dir> </vfs>
|
||||
<policy label_prefix="fs_report" writeable="yes"/>
|
||||
</config>
|
||||
</start>
|
||||
<start name="fs_report">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides> <service name="Report"/> </provides>
|
||||
<config>
|
||||
<vfs> <fs/> </vfs>
|
||||
</config>
|
||||
</start>
|
||||
<start name="init">
|
||||
<resource name="RAM" quantum="8M"/>
|
||||
<provides><service name="ROM"/></provides>
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="PD"/>
|
||||
<service name="RAM"/>
|
||||
<service name="RM"/>
|
||||
<service name="ROM"/>
|
||||
<service name="Report"/>
|
||||
<service name="Timer"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> </any-service>
|
||||
</default-route>
|
||||
<report init_caps="yes" child_caps="yes" init_ram="yes" ids="yes" requested="yes" provided="yes" session_args="yes" child_ram="yes"/>
|
||||
|
||||
<start name="init" caps="512">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides><service name="ROM"/></provides>
|
||||
<config>
|
||||
<report init_caps="yes" child_caps="yes" init_ram="yes" ids="yes" requested="yes" provided="yes" session_args="yes" child_ram="yes"/>
|
||||
</config>
|
||||
</start>
|
||||
|
||||
</config>
|
||||
</start>
|
||||
</config>}
|
||||
|
||||
install_config $config
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
|
||||
# generic modules
|
||||
set boot_modules {
|
||||
core ld.lib.so init
|
||||
fs_report
|
||||
timer
|
||||
vfs
|
||||
}
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
append qemu_args " -nographic"
|
||||
|
||||
run_genode_until {.*</state>.*} 20
|
259
repos/os/src/server/fs_report/main.cc
Normal file
259
repos/os/src/server/fs_report/main.cc
Normal file
@ -0,0 +1,259 @@
|
||||
/*
|
||||
* \brief Report server that writes reports to file-systems
|
||||
* \author Emery Hemingway
|
||||
* \date 2017-05-19
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 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.
|
||||
*/
|
||||
|
||||
#include <vfs/dir_file_system.h>
|
||||
#include <vfs/file_system_factory.h>
|
||||
#include <os/path.h>
|
||||
#include <report_session/report_session.h>
|
||||
#include <root/component.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <base/session_label.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/component.h>
|
||||
#include <util/arg_string.h>
|
||||
|
||||
namespace Fs_report {
|
||||
using namespace Genode;
|
||||
using namespace Report;
|
||||
using namespace Vfs;
|
||||
|
||||
class Session_component;
|
||||
class Root;
|
||||
struct Main;
|
||||
|
||||
typedef Genode::Path<Session_label::capacity()> Path;
|
||||
|
||||
static bool create_parent_dir(Vfs::Directory_service &vfs, Path const &child)
|
||||
{
|
||||
typedef Vfs::Directory_service::Mkdir_result Mkdir_result;
|
||||
|
||||
Path parent = child;
|
||||
parent.strip_last_element();
|
||||
|
||||
Mkdir_result res = vfs.mkdir(parent.base(), 0);
|
||||
if (res == Mkdir_result::MKDIR_ERR_NO_ENTRY) {
|
||||
if (!create_parent_dir(vfs, parent))
|
||||
return false;
|
||||
res = vfs.mkdir(parent.base(), 0);
|
||||
}
|
||||
|
||||
switch (res) {
|
||||
case Mkdir_result::MKDIR_OK:
|
||||
case Mkdir_result::MKDIR_ERR_EXISTS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Fs_report::Session_component : public Genode::Rpc_object<Report::Session>
|
||||
{
|
||||
private:
|
||||
|
||||
Path _leaf_path;
|
||||
|
||||
Attached_ram_dataspace _ds;
|
||||
|
||||
Vfs_handle *_handle;
|
||||
file_size _file_size = 0;
|
||||
bool _success = true;
|
||||
|
||||
public:
|
||||
|
||||
Session_component(Genode::Env &env,
|
||||
Genode::Allocator &alloc,
|
||||
Vfs::File_system &vfs,
|
||||
Genode::Session_label const &label,
|
||||
size_t buffer_size)
|
||||
: _ds(env.ram(), env.rm(), buffer_size)
|
||||
{
|
||||
typedef Vfs::Directory_service::Open_result Open_result;
|
||||
|
||||
Path path = path_from_label<Path>(label.string());
|
||||
path.append(".report");
|
||||
|
||||
create_parent_dir(vfs, path);
|
||||
|
||||
Open_result res = vfs.open(
|
||||
path.base(),
|
||||
Directory_service::OPEN_MODE_WRONLY |
|
||||
Directory_service::OPEN_MODE_CREATE,
|
||||
&_handle, alloc);
|
||||
|
||||
if (res == Open_result::OPEN_ERR_EXISTS) {
|
||||
res = vfs.open(
|
||||
path.base(),
|
||||
Directory_service::OPEN_MODE_WRONLY,
|
||||
&_handle, alloc);
|
||||
if (res == Open_result::OPEN_OK)
|
||||
_handle->fs().ftruncate(_handle, 0);
|
||||
}
|
||||
|
||||
if (res != Open_result::OPEN_OK) {
|
||||
error("failed to open '", path, "'");
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
/* get the leaf path from the leaf file-system */
|
||||
if (char const *leaf_path = _handle->ds().leaf_path(path.base()))
|
||||
_leaf_path.import(leaf_path);
|
||||
}
|
||||
|
||||
~Session_component()
|
||||
{
|
||||
if (_handle)
|
||||
_handle->ds().close(_handle);
|
||||
}
|
||||
|
||||
Dataspace_capability dataspace() override { return _ds.cap(); }
|
||||
|
||||
void submit(size_t const length) override
|
||||
{
|
||||
/* TODO: close and reopen on error */
|
||||
|
||||
typedef Vfs::File_io_service::Write_result Write_result;
|
||||
|
||||
if (_file_size != length)
|
||||
_handle->fs().ftruncate(_handle, length);
|
||||
|
||||
size_t offset = 0;
|
||||
while (offset < length) {
|
||||
file_size n = 0;
|
||||
|
||||
_handle->seek(offset);
|
||||
Write_result res = _handle->fs().write(
|
||||
_handle, _ds.local_addr<char const>(),
|
||||
length - offset, n);
|
||||
|
||||
if (res != Write_result::WRITE_OK) {
|
||||
/* do not spam the log */
|
||||
if (_success)
|
||||
error("failed to write report to '", _leaf_path, "'");
|
||||
_file_size = 0;
|
||||
_success = false;
|
||||
return;
|
||||
}
|
||||
|
||||
offset += n;
|
||||
}
|
||||
|
||||
_file_size = length;
|
||||
_success = true;
|
||||
|
||||
/* flush to notify watchers */
|
||||
_handle->ds().sync(_leaf_path.base());
|
||||
}
|
||||
|
||||
void response_sigh(Genode::Signal_context_capability) override { }
|
||||
|
||||
size_t obtain_response() override { return 0; }
|
||||
};
|
||||
|
||||
|
||||
class Fs_report::Root : public Genode::Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;
|
||||
Genode::Heap _heap { &_env.ram(), &_env.rm() };
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
struct Io_dummy : Io_response_handler {
|
||||
void handle_io_response(Vfs::Vfs_handle::Context*) override { }
|
||||
} _io_response_handler { };
|
||||
|
||||
Vfs::Global_file_system_factory _global_file_system_factory { _heap };
|
||||
|
||||
Vfs::Dir_file_system _vfs {
|
||||
_env, _heap, vfs_config(),
|
||||
_io_response_handler,
|
||||
_global_file_system_factory };
|
||||
|
||||
Genode::Signal_handler<Root> _config_dispatcher {
|
||||
_env.ep(), *this, &Root::_config_update };
|
||||
|
||||
void _config_update()
|
||||
{
|
||||
_config_rom.update();
|
||||
_vfs.apply_config(vfs_config());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args) override
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
/* read label from session arguments */
|
||||
Session_label const label = label_from_args(args);
|
||||
|
||||
/* read RAM donation from session arguments */
|
||||
size_t const ram_quota =
|
||||
Arg_string::find_arg(args, "ram_quota").aligned_size();
|
||||
/* read report buffer size from session arguments */
|
||||
size_t const buffer_size =
|
||||
Arg_string::find_arg(args, "buffer_size").aligned_size();
|
||||
|
||||
size_t session_size =
|
||||
max((size_t)4096, sizeof(Session_component)) +
|
||||
buffer_size;
|
||||
|
||||
if (session_size > ram_quota) {
|
||||
error("insufficient 'ram_quota' from '", label, "' "
|
||||
"got ", ram_quota, ", need ", session_size);
|
||||
throw Insufficient_ram_quota();
|
||||
}
|
||||
|
||||
return new (md_alloc())
|
||||
Session_component(_env, _heap, _vfs, label, buffer_size);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Root(Genode::Env &env, Genode::Allocator &md_alloc)
|
||||
:
|
||||
Genode::Root_component<Session_component>(env.ep(), md_alloc),
|
||||
_env(env)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
struct Fs_report::Main
|
||||
{
|
||||
Env &env;
|
||||
|
||||
Sliced_heap sliced_heap { env.ram(), env.rm() };
|
||||
|
||||
Root root { env, sliced_heap };
|
||||
|
||||
Main(Env &env) : env(env)
|
||||
{
|
||||
env.parent().announce(env.ep().manage(root));
|
||||
}
|
||||
};
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Fs_report::Main main(env); }
|
3
repos/os/src/server/fs_report/target.mk
Normal file
3
repos/os/src/server/fs_report/target.mk
Normal file
@ -0,0 +1,3 @@
|
||||
TARGET = fs_report
|
||||
LIBS = base vfs
|
||||
SRC_CC = main.cc
|
Loading…
Reference in New Issue
Block a user