Add fs_block server
A server that was written in 2015 but never got into any Genode repos.
This commit is contained in:
parent
666f63fe8b
commit
20082eda74
|
@ -1,33 +0,0 @@
|
|||
TARGET_NAME = fetch_nixos
|
||||
|
||||
PKG_DEPENDS += \
|
||||
@(SDK_USER)/src/init/@(SDK_VERSION) \
|
||||
@(SDK_USER)/src/libc/@(SDK_VERSION) \
|
||||
@(SDK_USER)/src/vfs/@(SDK_VERSION) \
|
||||
genodelabs/src/init/2019-02-27 \
|
||||
genodelabs/src/libpng/2019-02-25 \
|
||||
genodelabs/src/libssl/2019-02-25 \
|
||||
ehmry/src/libcrypto/2019-03-04 \
|
||||
genodelabs/src/menu_view/2019-02-26 \
|
||||
genodelabs/src/report_rom/2019-02-25 \
|
||||
ehmry/src/vfs_lwip/2019-03-04 \
|
||||
genodelabs/src/zlib/2019-02-25 \
|
||||
_/raw/fetch-nixos/ \
|
||||
_/src/fetch_and_copy \
|
||||
|
||||
include_rules
|
||||
|
||||
URL = https://releases.nixos.org/nixos/18.09/nixos-18.09.2436.395a543f360/nixos-minimal-18.09.2436.395a543f360-x86_64-linux.iso
|
||||
SHA256 = 056a16891c416297944617f274c79b45c3d9d16a4d584e67947923a2f3c7ad3b
|
||||
|
||||
: runtime.in |> ^ SED %o^ \
|
||||
sed \
|
||||
-e 's|@URL@|$(URL)|' \
|
||||
-e 's|@SHA256@|$(SHA256)|' \
|
||||
%f > %o |> %B
|
||||
|
||||
: nixos.vbox |> !collect_raw |>
|
||||
: machine.vdi |> !collect_raw |>
|
||||
: |> !raw |>
|
||||
|
||||
: runtime |> !collect_pkg_runtime |> {package}
|
Binary file not shown.
|
@ -1,60 +0,0 @@
|
|||
<?xml version="1.0"?>
|
||||
<VirtualBox xmlns="http://www.virtualbox.org/" version="1.14-freebsd">
|
||||
<Machine uuid="{37ab43a5-38d8-4491-93f5-5b0b077f5c32}" name="ubuntu_16_04_64" OSType="Ubuntu_64" snapshotFolder="Snapshots" lastStateChange="2018-01-23T18:40:00Z">
|
||||
<MediaRegistry>
|
||||
<HardDisks>
|
||||
<HardDisk uuid="{a90a16bf-f724-4321-99df-5498d6e4b796}" location="machine.vdi" format="VDI" type="Normal"/>
|
||||
</HardDisks>
|
||||
<DVDImages>
|
||||
<Image uuid="{81763434-9a51-49e8-9444-528a5a28c4bc}" location="installer.iso"/>
|
||||
</DVDImages>
|
||||
</MediaRegistry>
|
||||
<Hardware>
|
||||
<CPU count="2">
|
||||
<PAE enabled="true"/>
|
||||
<LongMode enabled="true"/>
|
||||
<HardwareVirtExLargePages enabled="false"/>
|
||||
</CPU>
|
||||
<Memory RAMSize="1536"/>
|
||||
<HID Pointing="USBTablet"/>
|
||||
<Display VRAMSize="20"/>
|
||||
<RemoteDisplay enabled="false"/>
|
||||
<BIOS>
|
||||
<IOAPIC enabled="true"/>
|
||||
</BIOS>
|
||||
<USB>
|
||||
<Controllers>
|
||||
<Controller name="OHCI" type="OHCI"/>
|
||||
</Controllers>
|
||||
</USB>
|
||||
<Network>
|
||||
<Adapter slot="0" enabled="true" MACAddress="0800271D7901" cable="true" type="82540EM">
|
||||
<BridgedInterface/>
|
||||
</Adapter>
|
||||
</Network>
|
||||
<UART>
|
||||
<Port slot="0" enabled="false" IOBase="0x3f8" IRQ="4" hostMode="Disconnected"/>
|
||||
<Port slot="1" enabled="false" IOBase="0x2f8" IRQ="3" hostMode="Disconnected"/>
|
||||
</UART>
|
||||
<LPT>
|
||||
<Port slot="0" enabled="false" IOBase="0x378" IRQ="7"/>
|
||||
<Port slot="1" enabled="false" IOBase="0x378" IRQ="7"/>
|
||||
</LPT>
|
||||
<AudioAdapter controller="HDA" driver="OSS" enabled="false"/>
|
||||
<RTC localOrUTC="UTC"/>
|
||||
<SharedFolders>
|
||||
<SharedFolder name="shared" hostPath="/shared" writable="true" autoMount="true"/>
|
||||
</SharedFolders>
|
||||
</Hardware>
|
||||
<StorageControllers>
|
||||
<StorageController name="SATA" type="AHCI" PortCount="4" useHostIOCache="true" Bootable="true" IDE0MasterEmulationPort="0" IDE0SlaveEmulationPort="1" IDE1MasterEmulationPort="2" IDE1SlaveEmulationPort="3">
|
||||
<AttachedDevice type="HardDisk" port="0" device="0">
|
||||
<Image uuid="{a90a16bf-f724-4321-99df-5498d6e4b796}"/>
|
||||
</AttachedDevice>
|
||||
<AttachedDevice passthrough="false" type="DVD" port="3" device="0">
|
||||
<Image uuid="{81763434-9a51-49e8-9444-528a5a28c4bc}"/>
|
||||
</AttachedDevice>
|
||||
</StorageController>
|
||||
</StorageControllers>
|
||||
</Machine>
|
||||
</VirtualBox>
|
|
@ -1,107 +0,0 @@
|
|||
<runtime ram="24M" caps="768" binary="init">
|
||||
|
||||
<requires>
|
||||
<file_system label="fonts"/>
|
||||
<file_system label="target"/>
|
||||
<nic/>
|
||||
<nitpicker/>
|
||||
</requires>
|
||||
|
||||
<content>
|
||||
<rom label="fetch_and_copy"/>
|
||||
<rom label="init"/>
|
||||
<rom label="libc.lib.so"/>
|
||||
<rom label="libcrypto.lib.so"/>
|
||||
<rom label="libm.lib.so"/>
|
||||
<rom label="libpng.lib.so"/>
|
||||
<rom label="libssl.lib.so"/>
|
||||
<rom label="machine.vdi"/>
|
||||
<rom label="menu_view"/>
|
||||
<rom label="menu_view_styles.tar"/>
|
||||
<rom label="nixos.vbox"/>
|
||||
<rom label="report_rom"/>
|
||||
<rom label="vfs.lib.so"/>
|
||||
<rom label="vfs_lwip.lib.so"/>
|
||||
<rom label="zlib.lib.so"/>
|
||||
</content>
|
||||
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="Timer"/>
|
||||
<service name="File_system"/>
|
||||
<service name="Nitpicker"/>
|
||||
<service name="Nic"/>
|
||||
</parent-provides>
|
||||
|
||||
<default-route>
|
||||
<any-service> <parent/> </any-service>
|
||||
</default-route>
|
||||
|
||||
<default caps="128"/>
|
||||
|
||||
<start name="report_rom">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides>
|
||||
<service name="Report"/>
|
||||
<service name="ROM"/>
|
||||
</provides>
|
||||
<config>
|
||||
<policy label="dialog" report="dialog"/>
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="menu_view" caps="256">
|
||||
<resource name="RAM" quantum="8M"/>
|
||||
<config>
|
||||
<libc stderr="/dev/log"/>
|
||||
<vfs>
|
||||
<tar name="menu_view_styles.tar" />
|
||||
<dir name="dev"> <log/> </dir>
|
||||
<dir name="fonts"> <fs label="fonts"/> </dir>
|
||||
</vfs>
|
||||
</config>
|
||||
<route>
|
||||
<service name="File_system" label="fonts">
|
||||
<parent label="fonts"/> </service>
|
||||
<service name="ROM" label="dialog">
|
||||
<child name="report_rom" label="dialog"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="fetch_and_copy" caps="256">
|
||||
<resource name="RAM" quantum="16M"/>
|
||||
<config>
|
||||
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket" rtc="/dev/rtc"/>
|
||||
<vfs>
|
||||
<dir name="dev">
|
||||
<inline name="rtc">2018-01-01 00:01</inline>
|
||||
<log/> <zero name="random"/>
|
||||
</dir>
|
||||
<dir name="socket"> <lwip dhcp="yes"/> </dir>
|
||||
<dir name="target"> <fs label="target"/> </dir>
|
||||
<rom name="nixos.vbox"/>
|
||||
<rom name="machine.vdi"/>
|
||||
</vfs>
|
||||
<fetch url="@URL@"
|
||||
path="/target/installer.iso"
|
||||
sha256="@SHA256@"/>
|
||||
<copy from="/nixos.vbox" to="/target/machine.vbox"/>
|
||||
<copy from="/machine.vdi" to="/target/machine.vdi"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="File_system" label="target">
|
||||
<parent label="target"/> </service>
|
||||
<service name="Report" label="dialog">
|
||||
<child name="report_rom" label="dialog"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
</config>
|
||||
|
||||
</runtime>
|
|
@ -0,0 +1,15 @@
|
|||
Fs_block serves an image from a file system server over a Block session.
|
||||
Only one session is served at a time. Configuration is straightforward;
|
||||
images are not writeable by default.
|
||||
|
||||
! <config>
|
||||
! <default-policy file="/image.raw" block_size="512" writeable="yes""/>
|
||||
! </config>
|
||||
|
||||
! <config>
|
||||
! <default-policy file="/disk" writeable="yes" device_size="64G"/>
|
||||
! </config>
|
||||
|
||||
! <config>
|
||||
! <default-policy file="/image.iso" block_size="2048"/>
|
||||
! </config>
|
|
@ -0,0 +1,13 @@
|
|||
TARGET_NAME = fs_block
|
||||
include_rules
|
||||
|
||||
PKGS = genode-os genode-prg
|
||||
|
||||
: foreach *.cc |> ^ CC %o^ \
|
||||
$(CC) -std=gnu++11 `pkg-config --cflags $(PKGS)` -c %f -o %o |> %B.o {objs}
|
||||
|
||||
: {objs} |> ^o LD %o^ \
|
||||
$(LD) `pkg-config --libs $(PKGS)` %f -o %o |> %d {binary}
|
||||
|
||||
: {binary} |> !collect_bin |>
|
||||
: |> !bin |>
|
|
@ -0,0 +1,421 @@
|
|||
/*
|
||||
* \brief Serve blocks from a file system session
|
||||
* \author Emery Hemingway
|
||||
* \date 2015-09-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
#include <file_system_session/connection.h>
|
||||
#include <file_system/util.h>
|
||||
#include <block_session/rpc_object.h>
|
||||
#include <block/driver.h>
|
||||
#include <os/path.h>
|
||||
#include <os/session_policy.h>
|
||||
#include <root/component.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/component.h>
|
||||
|
||||
|
||||
namespace Fs_block {
|
||||
|
||||
using namespace Genode;
|
||||
using namespace Block;
|
||||
|
||||
struct Block_buffer;
|
||||
class Session_component;
|
||||
class Root_component;
|
||||
|
||||
typedef Genode::Path<File_system::MAX_PATH_LEN> Path;
|
||||
typedef File_system::file_size_t file_size_t;
|
||||
}
|
||||
|
||||
|
||||
struct Fs_block::Block_buffer
|
||||
{
|
||||
Attached_ram_dataspace buffer_ds;
|
||||
|
||||
Block_buffer(Genode::Env &env, size_t buffer_size)
|
||||
: buffer_ds(env.pd(), env.rm(), buffer_size) { }
|
||||
};
|
||||
|
||||
|
||||
class Fs_block::Session_component final : private Block_buffer,
|
||||
public Block::Session_rpc_object
|
||||
{
|
||||
private:
|
||||
|
||||
enum { PENDING_QUEUE_COUNT = File_system::Session::TX_QUEUE_SIZE };
|
||||
Block::Packet_descriptor _pending[PENDING_QUEUE_COUNT];
|
||||
|
||||
Genode::Heap &_heap;
|
||||
Genode::Allocator_avl _fs_tx_alloc { &_heap };
|
||||
File_system::Connection _fs;
|
||||
Signal_handler<Session_component> _fs_handler;
|
||||
Signal_handler<Session_component> _blk_handler;
|
||||
File_system::File_handle _handle { ~0U };
|
||||
Genode::size_t const _blk_size;
|
||||
Block::sector_t _blk_count = 0;
|
||||
Block::Session::Operations _ops { };
|
||||
Genode::size_t _pending_count = 0; /* pending index */
|
||||
bool _pending_sync = false;
|
||||
|
||||
void _process_blk_pkt(Block::Packet_descriptor const blk_packet)
|
||||
{
|
||||
File_system::Session::Tx::Source &source = *_fs.tx();
|
||||
Block::Session::Tx::Sink &sink = *tx_sink();
|
||||
|
||||
File_system::seek_off_t start = blk_packet.block_number() * _blk_size;
|
||||
size_t const len = blk_packet.block_count() * _blk_size;
|
||||
|
||||
File_system::Packet_descriptor::Opcode op;
|
||||
switch (blk_packet.operation()) {
|
||||
case Block::Packet_descriptor::Opcode::READ:
|
||||
op = File_system::Packet_descriptor::Opcode::READ; break;
|
||||
case Block::Packet_descriptor::Opcode::WRITE:
|
||||
op = File_system::Packet_descriptor::Opcode::WRITE; break;
|
||||
default:
|
||||
throw ~0;
|
||||
}
|
||||
|
||||
File_system::Packet_descriptor fs_packet(
|
||||
source.alloc_packet(len), _handle, op,
|
||||
len, File_system::seek_off_t(start));
|
||||
|
||||
if (op == File_system::Packet_descriptor::WRITE)
|
||||
memcpy(source.packet_content(fs_packet),
|
||||
sink.packet_content(blk_packet),
|
||||
fs_packet.length());
|
||||
|
||||
source.submit_packet(fs_packet);
|
||||
}
|
||||
|
||||
void _process_blk()
|
||||
{
|
||||
File_system::Session::Tx::Source &source = *_fs.tx();
|
||||
Block::Session::Tx::Sink &sink = *tx_sink();
|
||||
while (sink.packet_avail()
|
||||
&& source.ready_to_submit()
|
||||
&& _pending_count < PENDING_QUEUE_COUNT)
|
||||
{
|
||||
Block::Packet_descriptor pkt = sink.get_packet();
|
||||
|
||||
if (pkt.size() == 0 || pkt.operation() > Block::Packet_descriptor::Opcode::WRITE)
|
||||
{
|
||||
warning("refusing invalid Block packet");
|
||||
sink.acknowledge_packet(pkt);
|
||||
} else {
|
||||
pkt.succeeded(false);
|
||||
for (int i = 0; i < PENDING_QUEUE_COUNT; ++i) {
|
||||
if (_pending[i].size() == 0) {
|
||||
_pending[i] = pkt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
++_pending_count;
|
||||
_process_blk_pkt(pkt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _process_fs_packet()
|
||||
{
|
||||
File_system::Session::Tx::Source &source = *_fs.tx();
|
||||
Block::Session::Tx::Sink &sink = *tx_sink();
|
||||
|
||||
File_system::Packet_descriptor fs_packet = source.get_acked_packet();
|
||||
|
||||
Block::Packet_descriptor::Opcode op;
|
||||
switch (fs_packet.operation()) {
|
||||
case File_system::Packet_descriptor::Opcode::READ:
|
||||
op = Block::Packet_descriptor::Opcode::READ; break;
|
||||
case File_system::Packet_descriptor::Opcode::WRITE:
|
||||
op = Block::Packet_descriptor::Opcode::WRITE; break;
|
||||
case File_system::Packet_descriptor::Opcode::SYNC:
|
||||
_pending_sync = false;
|
||||
default:
|
||||
source.release_packet(fs_packet);
|
||||
return;
|
||||
}
|
||||
|
||||
Block::sector_t const blk_num = fs_packet.position() / _blk_size;
|
||||
|
||||
if (_pending_count < 1)
|
||||
error("got a packet but nothing pending");
|
||||
|
||||
for (int i = 0; i < PENDING_QUEUE_COUNT; ++i) {
|
||||
/* process the first queue item with the same offset */
|
||||
if (_pending[i].operation() == op &&
|
||||
_pending[i].block_number() == blk_num)
|
||||
{
|
||||
size_t byte_count = min(
|
||||
_pending[i].size(), fs_packet.length());
|
||||
size_t blk_count = min(
|
||||
_pending[i].block_count(), byte_count / _blk_size);
|
||||
|
||||
/* create a new packet with the length from the FS */
|
||||
Block::Packet_descriptor ack_pkt(
|
||||
_pending[i], op, blk_num, blk_count);
|
||||
ack_pkt.succeeded(fs_packet.succeeded());
|
||||
|
||||
/* wipe the queue entry */
|
||||
_pending[i] = Block::Packet_descriptor();
|
||||
--_pending_count;
|
||||
|
||||
if (op == Block::Packet_descriptor::Opcode::READ) {
|
||||
/* zero any trailing content (last block of file) */
|
||||
if (byte_count < ack_pkt.size()) {
|
||||
memset(sink.packet_content(ack_pkt),
|
||||
0x00, ack_pkt.size());
|
||||
}
|
||||
|
||||
memcpy(sink.packet_content(ack_pkt),
|
||||
source.packet_content(fs_packet),
|
||||
byte_count);
|
||||
}
|
||||
|
||||
/* free packets */
|
||||
sink.acknowledge_packet(ack_pkt);
|
||||
source.release_packet(fs_packet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _process_fs()
|
||||
{
|
||||
Block::Session::Tx::Sink &sink = *tx_sink();
|
||||
File_system::Session::Tx::Source &source = *_fs.tx();
|
||||
while (source.ack_avail() && sink.ready_to_ack())
|
||||
_process_fs_packet();
|
||||
}
|
||||
|
||||
Path _file_root(char const *file_path)
|
||||
{
|
||||
Path r(file_path);
|
||||
r.strip_last_element();
|
||||
return r;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Session_component(Genode::Env &env,
|
||||
Genode::Heap &heap,
|
||||
size_t tx_buf_size,
|
||||
file_size_t device_size,
|
||||
size_t block_size,
|
||||
char const *file_path,
|
||||
bool writeable)
|
||||
:
|
||||
Block_buffer(env, tx_buf_size),
|
||||
Session_rpc_object(env.rm(), Block_buffer::buffer_ds.cap(),
|
||||
env.ep().rpc_ep()),
|
||||
_heap(heap),
|
||||
_fs(env, _fs_tx_alloc, "", _file_root(file_path).string(),
|
||||
writeable, tx_buf_size),
|
||||
_fs_handler( env.ep(), *this, &Session_component::_process_fs),
|
||||
_blk_handler(env.ep(), *this, &Session_component::_process_blk),
|
||||
_blk_size(block_size)
|
||||
{
|
||||
using namespace File_system;
|
||||
|
||||
/* the File_system session is rooted at the parent directory of the file */
|
||||
Path file_name(file_path);
|
||||
file_name.keep_only_last_element();
|
||||
char const *name = file_name.string()+1;
|
||||
|
||||
try {
|
||||
Dir_handle dir = _fs.dir("/", false);
|
||||
Handle_guard guard(_fs, dir);
|
||||
|
||||
if (writeable) {
|
||||
try {
|
||||
_ops.set_operation(Block::Packet_descriptor::READ);
|
||||
_ops.set_operation(Block::Packet_descriptor::WRITE);
|
||||
_handle = _fs.file(dir, name, READ_WRITE, false);
|
||||
} catch (Lookup_failed) {
|
||||
if (device_size == 0) throw;
|
||||
_handle = _fs.file(dir, name, READ_WRITE, true);
|
||||
} catch (Permission_denied) {
|
||||
try {
|
||||
_ops.set_operation(Block::Packet_descriptor::READ);
|
||||
_handle = _fs.file(dir, name, READ_ONLY, false);
|
||||
} catch (Permission_denied) {
|
||||
/* not likely, but still supported */
|
||||
_ops.set_operation(Block::Packet_descriptor::WRITE);
|
||||
_handle = _fs.file(dir, name, WRITE_ONLY, false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_ops.set_operation(Block::Packet_descriptor::READ);
|
||||
_handle = _fs.file(dir, name, READ_ONLY, false);
|
||||
}
|
||||
} catch (...) {
|
||||
error("failed to open ", file_path);
|
||||
throw;
|
||||
}
|
||||
|
||||
File_system::Status st = _fs.status(_handle);
|
||||
if (device_size != 0 && st.size != device_size) {
|
||||
if (!writeable) {
|
||||
Genode::error("cannot resize read-only file ", file_path);
|
||||
throw Service_denied();
|
||||
}
|
||||
try { _fs.truncate(_handle, device_size); }
|
||||
catch (...) {
|
||||
Genode::error("failed to resize ", file_path, " to ", Genode::Number_of_bytes(device_size));
|
||||
throw;
|
||||
}
|
||||
st = _fs.status(_handle);
|
||||
}
|
||||
|
||||
_blk_count = st.size / block_size;
|
||||
if (st.size % block_size) /* round up */
|
||||
++_blk_count;
|
||||
|
||||
/* register signal handlers */
|
||||
_fs.sigh_ack_avail(_fs_handler);
|
||||
_tx.sigh_packet_avail(_blk_handler);
|
||||
|
||||
for (int i = 0; i < PENDING_QUEUE_COUNT; ++i)
|
||||
_pending[i] = Block::Packet_descriptor();
|
||||
}
|
||||
|
||||
/*****************************
|
||||
** Block session interface **
|
||||
*****************************/
|
||||
|
||||
void info(sector_t *blk_count,
|
||||
Genode::size_t *blk_size,
|
||||
Operations *ops)
|
||||
{
|
||||
*blk_count = _blk_count;
|
||||
*blk_size = _blk_size;
|
||||
*ops = _ops;
|
||||
}
|
||||
|
||||
void sync() override
|
||||
{
|
||||
if (_fs.tx()->ready_to_submit()) {
|
||||
_fs.tx()->submit_packet(File_system::Packet_descriptor(
|
||||
File_system::Packet_descriptor(), _handle,
|
||||
File_system::Packet_descriptor::SYNC, 0, 0));
|
||||
_pending_sync = true;
|
||||
} else {
|
||||
error("cannot sync, File_system submit queue is full");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Fs_block::Root_component final :
|
||||
public Genode::Root_component<Fs_block::Session_component, Genode::Single_client>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;
|
||||
Genode::Heap &_heap;
|
||||
|
||||
Attached_rom_dataspace _config_rom { _env, "config" };
|
||||
|
||||
static
|
||||
file_size_t _device_size(Xml_node const &config)
|
||||
{
|
||||
Genode::Number_of_bytes zero { 0 };
|
||||
return config.attribute_value("device_size", zero);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(char const *args) override
|
||||
{
|
||||
Session_label const label = label_from_args(args);
|
||||
|
||||
long block_size = 512;
|
||||
bool writeable = false;
|
||||
|
||||
_config_rom.update();
|
||||
|
||||
String<File_system::MAX_PATH_LEN> path;
|
||||
Session_policy const policy(label, _config_rom.xml());
|
||||
policy.attribute("file").value(&path);
|
||||
|
||||
file_size_t device_size = _device_size(policy);
|
||||
block_size = policy.attribute_value("block_size", block_size);
|
||||
writeable = policy.attribute_value("writeable", false);
|
||||
|
||||
/*
|
||||
* Check that there is sufficient quota, but the client is not
|
||||
* required to pay for the entire cost of the session for two
|
||||
* reasons.
|
||||
*
|
||||
* First, we only serve a single client at a time so a denial of
|
||||
* service is not issue. If the quota is deficient the session
|
||||
* is denied and the parent is not consulted.
|
||||
*
|
||||
* Second, we maintain a packet buffer of equal size with the
|
||||
* backend that we do not expect the client to account for.
|
||||
* This simplifies the implementation because any packet
|
||||
* allocation at the client can be matched at the backend.
|
||||
*/
|
||||
|
||||
size_t ram_quota =
|
||||
Arg_string::find_arg(args, "ram_quota" ).aligned_size();
|
||||
size_t tx_buf_size =
|
||||
Arg_string::find_arg(args, "tx_buf_size").aligned_size();
|
||||
|
||||
if (!tx_buf_size) {
|
||||
error("invalid buffer size");
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
size_t avail = ram_quota + _env.pd().avail_ram().value;
|
||||
|
||||
size_t session_size = max((size_t)4096, sizeof(Session_component));
|
||||
|
||||
if ((avail < session_size) ||
|
||||
(tx_buf_size*2 > avail - session_size))
|
||||
{
|
||||
error("insufficient 'ram_quota', got %zd, need %zd",
|
||||
ram_quota, (tx_buf_size*2 + session_size) - avail);
|
||||
throw Service_denied();
|
||||
}
|
||||
|
||||
return new (_heap)
|
||||
Session_component(_env, _heap, tx_buf_size,\
|
||||
device_size, block_size,
|
||||
path.string(), writeable);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Root_component(Genode::Env &env, Genode::Heap &heap)
|
||||
:
|
||||
Genode::Root_component<Fs_block::Session_component, Genode::Single_client>(
|
||||
env.ep(), heap),
|
||||
_env(env), _heap(heap)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env)
|
||||
{
|
||||
static Genode::Heap heap(env.pd(), env.rm());
|
||||
static Fs_block::Root_component root(env, heap);
|
||||
|
||||
env.parent().announce(env.ep().manage(root));
|
||||
}
|
Loading…
Reference in New Issue