iso9660: use new component APIs

Issue #1987.
This commit is contained in:
Josef Söntgen
2017-01-06 14:53:09 +01:00
committed by Norman Feske
parent b87a82784c
commit a9a8bb0d8f
4 changed files with 538 additions and 782 deletions

View File

@ -1,256 +0,0 @@
/*
* \brief Backing store for on-demand-paged managed dataspaces
* \author Norman Feske
* \date 2010-10-31
*/
/*
* Copyright (C) 2010-2013 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.
*/
#ifndef _BACKING_STORE_H_
#define _BACKING_STORE_H_
#include <base/env.h>
/**
* Fifo-based physical backing-store allocator
*
* \param UMD user-specific metadata attached to each backing-store block,
* for example the corresponding offset within a managed
* dataspace
*/
template <typename UMD>
class Backing_store
{
public:
/**
* Interface to be implemented by the user of the backing store
*/
struct User
{
virtual void detach_block(UMD umd)
{
Genode::warning(__func__, " this should never be called");
}
};
/**
* Pseudo user for marking a block as used during the
* time between the allocation and the assignment to the
* actual user
*/
User _not_yet_assigned;
/**
* Meta data of a backing-store block
*/
class Block
{
private:
friend class Backing_store;
/**
* User of the block, 0 if block is unused
*/
User *_user;
/**
* User-specific meta data. It is not used by the
* 'Backing_store', just handed back to the user with the
* 'detach_block' function.
*/
UMD _user_meta_data;
/**
* Default constructor used for array allocation
*/
Block() : _user(0) { }
/**
* Used by 'Backing_store::assign'
*/
void assign_user(User *user, UMD user_meta_data) {
_user = user, _user_meta_data = user_meta_data; }
/**
* Used by 'Backing_store::alloc'
*/
void assign_pseudo_user(User *user) { _user = user; }
/**
* Return true if block is in use
*/
bool occupied() const { return _user != 0; }
/**
* Return user of the block
*/
const User *user() const { return _user; }
/**
* Evict block, preparing to for reuse
*/
void evict()
{
if (_user)
_user->detach_block(_user_meta_data);
_user = 0;
}
};
private:
/**
* Lock for synchronizing the block allocator
*/
Genode::Lock _alloc_lock;
const Genode::size_t _block_size;
/**
* Number of physical blocks
*/
const Genode::size_t _num_blocks;
/**
* RAM dataspace holding the physical backing store
*/
const Genode::Dataspace_capability _ds;
/**
* Local address of physical backing store
*/
const void *_ds_addr;
/**
* Array of block meta data
*/
Block *_blocks;
/**
* Block index for next allocation (used for fifo)
*/
unsigned long _curr_block_idx;
/**
* Return meta data of next-to-be-allocated block
*/
Block *_curr_block() const { return &_blocks[_curr_block_idx]; }
/**
* Advance fifo allocation index
*/
void _advance_curr_block()
{
_curr_block_idx++;
if (_curr_block_idx == _num_blocks)
_curr_block_idx = 0;
}
/**
* Calculate number of blocks that fit into specified amount of RAM,
* taking the costs for meta data into account
*/
Genode::size_t _calc_num_blocks(Genode::size_t ram_size) const
{
return ram_size / (sizeof(Block) + _block_size);
}
public:
/**
* Constructor
*
* \param ram_size number of bytes of physical RAM to be used as
* backing store for both the meta data and the
* payload
*/
Backing_store(Genode::size_t ram_size, Genode::size_t block_size)
:
_block_size(block_size),
_num_blocks(_calc_num_blocks(ram_size)),
_ds(Genode::env()->ram_session()->alloc(_block_size*_num_blocks)),
_ds_addr(Genode::env()->rm_session()->attach(_ds)),
_blocks(new (Genode::env()->heap()) Block[_num_blocks]),
_curr_block_idx(0)
{ }
Block *alloc()
{
Genode::Lock::Guard guard(_alloc_lock);
/* skip blocks that are currently in the process of being assigned */
while (_curr_block()->user() == &_not_yet_assigned) {
_advance_curr_block();
}
/* evict block if needed */
if (_curr_block()->occupied())
_curr_block()->evict();
/* reserve allocated block (prevent eviction prior assignment) */
Block *block = _curr_block();
block->assign_pseudo_user(&_not_yet_assigned);
_advance_curr_block();
return block;
}
/**
* Return dataspace containing the backing store payload
*/
Genode::Dataspace_capability dataspace() const { return _ds; }
/**
* Return block size used by the backing store
*/
Genode::size_t block_size() const { return _block_size; }
/**
* Return block index of specified block
*/
Genode::off_t index(const Block *b) const { return b - _blocks; }
/**
* Return offset of block within physical backing store
*/
Genode::off_t offset(const Block *b) const {
return index(b)*_block_size; }
/**
* Return local address of physical backing-store block
*/
void *local_addr(const Block *b) const {
return (void *)((Genode::addr_t)_ds_addr + offset(b)); }
/**
* Assign final user of a block
*
* After calling this function, the block will be subjected to
* eviction, if needed.
*/
void assign(Block *block, User *user, UMD user_meta_data)
{
Genode::Lock::Guard guard(_alloc_lock);
block->assign_user(user, user_meta_data);
}
/**
* Evict all blocks currently in use by the specified user
*/
void flush(const User *user)
{
Genode::Lock::Guard guard(_alloc_lock);
for (unsigned i = 0; i < _num_blocks; i++)
if (_blocks[i].user() == user)
_blocks[i].evict();
}
};
#endif /* _BACKING_STORE_H_ */

View File

@ -5,7 +5,7 @@
*/ */
/* /*
* Copyright (C) 2010-2013 Genode Labs GmbH * Copyright (C) 2010-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -16,7 +16,6 @@
#include <base/exception.h> #include <base/exception.h>
#include <base/log.h> #include <base/log.h>
#include <base/stdint.h> #include <base/stdint.h>
#include <block_session/connection.h>
#include <util/misc_math.h> #include <util/misc_math.h>
#include <util/token.h> #include <util/token.h>
@ -25,42 +24,49 @@
using namespace Genode; using namespace Genode;
namespace Iso { namespace Iso {
class Sector;
class Rock_ridge;
class Iso_base;
}
/*
/*
* Sector reads one or more packets from the block interface * Sector reads one or more packets from the block interface
*/ */
class Sector { class Iso::Sector {
public: public:
enum { enum {
MAX_SECTORS = 32, /* max. number sectors that can be read in one MAX_SECTORS = 32, /* max. number sectors that can be read in one
transaction */ transaction */
BLOCK_SIZE = 2048,
}; };
static Block::Connection *_blk;
static Block::Session::Tx::Source *_source;
static size_t _blk_size;
static Lock _lock; static Lock _lock;
private: private:
Block::Session::Tx::Source &_source;
Block::Packet_descriptor _p; Block::Packet_descriptor _p;
public: public:
Sector(unsigned long blk_nr, unsigned long count) Sector(Block::Connection &block,
unsigned long blk_nr, unsigned long count)
: _source(*block.tx())
{ {
Lock::Guard lock_guard(_lock); // Lock::Guard lock_guard(_lock);
try { try {
_p = Block::Packet_descriptor( _p = Block::Packet_descriptor(
_blk->dma_alloc_packet(blk_size() * count), block.dma_alloc_packet(blk_size() * count),
Block::Packet_descriptor::READ, Block::Packet_descriptor::READ,
blk_nr * ((float)blk_size() / _blk_size), blk_nr * ((float)blk_size() / BLOCK_SIZE),
count * ((float)blk_size() / _blk_size)); count * ((float)blk_size() / BLOCK_SIZE));
_source->submit_packet(_p);
_p = _source->get_acked_packet(); _source.submit_packet(_p);
_p = _source.get_acked_packet();
if (!_p.succeeded()) { if (!_p.succeeded()) {
Genode::error("Could not read block ", blk_nr); Genode::error("Could not read block ", blk_nr);
@ -69,33 +75,40 @@ namespace Iso {
} catch (Block::Session::Tx::Source::Packet_alloc_failed) { } catch (Block::Session::Tx::Source::Packet_alloc_failed) {
Genode::error("packet overrun!"); Genode::error("packet overrun!");
_p = _source->get_acked_packet(); _p = _source.get_acked_packet();
throw Io_error(); throw Io_error();
} }
} }
~Sector() { ~Sector() {
Lock::Guard lock_guard(_lock); // Lock::Guard lock_guard(_lock);
_source->release_packet(_p); _source.release_packet(_p);
} }
/** /**
* Return address of packet content * Return address of packet content
*/ */
template <typename T> template <typename T>
T addr() { return reinterpret_cast<T>(_source->packet_content(_p)); } T addr() { return reinterpret_cast<T>(_source.packet_content(_p)); }
static size_t blk_size() { return 2048; } static size_t blk_size() { return BLOCK_SIZE; }
static unsigned long to_blk(unsigned long bytes) { static unsigned long to_blk(unsigned long bytes) {
return ((bytes + blk_size() - 1) & ~(blk_size() - 1)) / blk_size(); } return ((bytes + blk_size() - 1) & ~(blk_size() - 1)) / blk_size(); }
}; };
/**
/*
* Static members of Sector
*/
Lock Iso::Sector::_lock;
/**
* Rock ridge extension (see IEEE P1282) * Rock ridge extension (see IEEE P1282)
*/ */
class Rock_ridge class Iso::Rock_ridge
{ {
public: public:
enum { enum {
@ -129,18 +142,18 @@ namespace Iso {
} }
Rock_ridge *next() { return (Rock_ridge *)((uint8_t *)this + _length); } Rock_ridge *next() { return (Rock_ridge *)((uint8_t *)this + _length); }
}; };
/********************* /*********************
** ISO9660 classes ** ** ISO9660 classes **
*********************/ *********************/
/** /**
* Access memory using offsets * Access memory using offsets
*/ */
class Iso_base class Iso::Iso_base
{ {
protected: protected:
template <typename T> template <typename T>
@ -148,14 +161,14 @@ namespace Iso {
template <typename T> template <typename T>
T ptr(int offset) { return (T)(this + offset); } T ptr(int offset) { return (T)(this + offset); }
}; };
/** /**
* Class representing a directory descriptions (see ECMA 119) * Class representing a directory descriptions (see ECMA 119)
*/ */
class Directory_record : public Iso_base class Directory_record : public Iso::Iso_base
{ {
enum { enum {
TABLE_LENGTH = 33, /* fixed length of directory record */ TABLE_LENGTH = 33, /* fixed length of directory record */
@ -188,7 +201,7 @@ namespace Iso {
buf[0] = 0; buf[0] = 0;
/* try Rock Ridge name */ /* try Rock Ridge name */
Rock_ridge *rr = Rock_ridge::scan_name(system_use(), Iso::Rock_ridge *rr = Iso::Rock_ridge::scan_name(system_use(),
system_use_size()); system_use_size());
if (rr) { if (rr) {
@ -255,13 +268,13 @@ namespace Iso {
} }
/* find a directory record with file name matching 'level' */ /* find a directory record with file name matching 'level' */
Directory_record *locate(char *level) Directory_record *locate(char const *level)
{ {
Directory_record *dir = this; Directory_record *dir = this;
while (dir) { while (dir) {
char name[LEVEL_LENGTH]; char name[Iso::LEVEL_LENGTH];
dir->file_name(name); dir->file_name(name);
if (!strcmp(name, level)) if (!strcmp(name, level))
@ -275,14 +288,14 @@ namespace Iso {
/* describes this record a directory */ /* describes this record a directory */
bool directory() { return file_flags() & DIR_FLAG; } bool directory() { return file_flags() & DIR_FLAG; }
}; };
/** /**
* Volume descriptor (see ECMA 119) * Volume descriptor (see ECMA 119)
*/ */
class Volume_descriptor : public Iso_base class Volume_descriptor : public Iso::Iso_base
{ {
enum { enum {
/* volume types */ /* volume types */
PRIMARY = 0x01, /* type of primary volume descriptor */ PRIMARY = 0x01, /* type of primary volume descriptor */
@ -307,85 +320,65 @@ namespace Iso {
bool terminator() { return type() == TERMINATOR; } bool terminator() { return type() == TERMINATOR; }
/* copy the root record */ /* copy the root record */
Directory_record *copy_root_record() Directory_record *copy_root_record(Genode::Allocator &alloc)
{ {
Directory_record *buf; Directory_record *buf;
if (!(env()->heap()->alloc(ROOT_SIZE, &buf))) if (!(alloc.alloc(ROOT_SIZE, &buf)))
throw Root::Quota_exceeded(); throw Root::Quota_exceeded();
memcpy(buf, root_record(), ROOT_SIZE); memcpy(buf, root_record(), ROOT_SIZE);
return buf; return buf;
} }
}; };
/** /**
* Locate the root-directory record in the primary volume descriptor * Locate the root-directory record in the primary volume descriptor
*/ */
Directory_record *locate_root() static Directory_record *locate_root(Genode::Allocator &alloc,
{ Block::Connection &block)
{
/* volume descriptors in ISO9660 start at block 16 */ /* volume descriptors in ISO9660 start at block 16 */
for (unsigned long blk_nr = 16;; blk_nr++) { for (unsigned long blk_nr = 16;; blk_nr++) {
Sector sec(blk_nr, 1); Iso::Sector sec(block, blk_nr, 1);
Volume_descriptor *vol = sec.addr<Volume_descriptor *>(); Volume_descriptor *vol = sec.addr<Volume_descriptor *>();
if (vol->primary()) if (vol->primary())
return vol->copy_root_record(); return vol->copy_root_record(alloc);
if (vol->terminator()) if (vol->terminator())
return 0; return nullptr;
}
} }
}
/** /**
* Return root directory record * Return root directory record
*/ */
Directory_record *root_dir() static Directory_record *root_dir(Genode::Allocator &alloc,
{ Block::Connection &block)
static Directory_record *root = locate_root(); {
Directory_record *root = locate_root(alloc, block);
if (!root) if (!root) { throw Iso::Non_data_disc(); }
throw Non_data_disc();
return root; return root;
} }
unsigned long read_file(File_info *info, off_t file_offset, uint32_t length, void *buf_ptr) /*******************
{ ** Iso interface **
uint8_t *buf = (uint8_t *)buf_ptr; *******************/
if (info->size() <= (size_t)(length + file_offset))
length = info->size() - file_offset - 1;
unsigned long total_blk_count = ((length + (Sector::blk_size() - 1)) & static Directory_record *_root_dir;
~((Sector::blk_size()) - 1)) / Sector::blk_size();
unsigned long ret = total_blk_count;
unsigned long blk_count;
unsigned long blk_nr = info->blk_nr() + (file_offset / Sector::blk_size());
while ((blk_count = min<unsigned long>(Sector::MAX_SECTORS, total_blk_count))) {
Sector sec(blk_nr, blk_count);
total_blk_count -= blk_count;
blk_nr += blk_count;
unsigned long copy_length = blk_count * Sector::blk_size();
memcpy(buf, sec.addr<void *>(), copy_length);
length -= copy_length;
buf += copy_length;
/* zero out rest of page */
if (!total_blk_count && (blk_count % 2))
memset(buf, 0, Sector::blk_size());
}
return ret * Sector::blk_size();
}
Iso::File_info *Iso::file_info(Genode::Allocator &alloc, Block::Connection &block,
char const *path)
{
char level[PATH_LENGTH];
struct Scanner_policy_file struct Scanner_policy_file
{ {
@ -394,19 +387,15 @@ namespace Iso {
return c != '/' && c != 0; return c != '/' && c != 0;
} }
}; };
typedef ::Genode::Token<Scanner_policy_file> Token; typedef ::Genode::Token<Scanner_policy_file> Token;
/**
* ISO interface
*/
File_info *file_info(char *path)
{
char level[PATH_LENGTH];
Token t(path); Token t(path);
Directory_record *dir = root_dir();
if (!_root_dir) {
_root_dir = root_dir(alloc, block);
}
Directory_record *dir = _root_dir;
uint32_t blk_nr = 0, data_length = 0; uint32_t blk_nr = 0, data_length = 0;
/* determine block nr and file length on disk, parse directory records */ /* determine block nr and file length on disk, parse directory records */
@ -428,7 +417,7 @@ namespace Iso {
/* load extent of directory record and search for level */ /* load extent of directory record and search for level */
for (unsigned long i = 0; i < Sector::to_blk(dir->data_length()); i++) { for (unsigned long i = 0; i < Sector::to_blk(dir->data_length()); i++) {
Sector sec(current_blk_nr + i, 1); Sector sec(block, current_blk_nr + i, 1);
Directory_record *tmp = sec.addr<Directory_record *>()->locate(level); Directory_record *tmp = sec.addr<Directory_record *>()->locate(level);
if (!tmp && i == Sector::to_blk(dir->data_length()) - 1) { if (!tmp && i == Sector::to_blk(dir->data_length()) - 1) {
@ -459,32 +448,39 @@ namespace Iso {
throw File_not_found(); throw File_not_found();
} }
return new(env()->heap()) File_info(blk_nr, data_length); return new (alloc) File_info(blk_nr, data_length);
}
unsigned long Iso::read_file(Block::Connection &block, File_info *info,
off_t file_offset, uint32_t length, void *buf_ptr)
{
uint8_t *buf = (uint8_t *)buf_ptr;
if (info->size() <= (size_t)(length + file_offset))
length = info->size() - file_offset - 1;
unsigned long total_blk_count = ((length + (Sector::blk_size() - 1)) &
~((Sector::blk_size()) - 1)) / Sector::blk_size();
unsigned long ret = total_blk_count;
unsigned long blk_count;
unsigned long blk_nr = info->blk_nr() + (file_offset / Sector::blk_size());
while ((blk_count = min<unsigned long>(Sector::MAX_SECTORS, total_blk_count))) {
Sector sec(block, blk_nr, blk_count);
total_blk_count -= blk_count;
blk_nr += blk_count;
unsigned long copy_length = blk_count * Sector::blk_size();
memcpy(buf, sec.addr<void *>(), copy_length);
length -= copy_length;
buf += copy_length;
/* zero out rest of page */
if (!total_blk_count && (blk_count % 2))
memset(buf, 0, Sector::blk_size());
} }
return ret * Sector::blk_size();
/* }
* Static members of Sector
*/
Block::Connection *Sector::_blk;
Block::Session::Tx::Source *Sector::_source;
size_t Sector::_blk_size;
Lock Sector::_lock;
/**
* Initialize globals
*/
void __attribute__((constructor)) init()
{
static Allocator_avl block_alloc(env()->heap());
static Block::Connection _blk(&block_alloc);
Sector::_blk = &_blk;
Sector::_source = _blk.tx();
Block::sector_t blk_cnt = 0;
Block::Session::Operations ops;
_blk.info(&blk_cnt, &Sector::_blk_size, &ops);
}
} /* end of namespace Iso */

View File

@ -5,14 +5,15 @@
*/ */
/* /*
* Copyright (C) 2010-2013 Genode Labs GmbH * Copyright (C) 2010-2017 Genode Labs GmbH
* *
* This file is part of the Genode OS framework, which is distributed * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
*/ */
#include <rom_session/rom_session.h> /* Genode includes */
#include <base/stdint.h> #include <base/stdint.h>
#include <block_session/connection.h>
namespace Iso { namespace Iso {
@ -51,9 +52,15 @@ namespace Iso {
}; };
/*******************
** Iso interface **
*******************/
/** /**
* Retrieve file information * Retrieve file information
* *
* \param alloc allocator used for File_info object
* \param block Block session used to read sectors from ISO
* \param path absolute path of the file (slash separated) * \param path absolute path of the file (slash separated)
* *
* \throw File_not_found * \throw File_not_found
@ -62,11 +69,12 @@ namespace Iso {
* *
* \return Pointer to File_info class * \return Pointer to File_info class
*/ */
File_info *file_info(char *path); File_info *file_info(Genode::Allocator &alloc, Block::Connection &block, char const *path);
/** /**
* Read data from ISO * Read data from ISO
* *
* \param block Block session used to read sectors from ISO
* \param info File Info of file to read the data from * \param info File Info of file to read the data from
* \param file_offset Offset in file * \param file_offset Offset in file
* \param length Number of bytes to read * \param length Number of bytes to read
@ -76,6 +84,6 @@ namespace Iso {
* *
* \return Number of bytes read * \return Number of bytes read
*/ */
unsigned long read_file(File_info *info, Genode::off_t file_offset, unsigned long read_file(Block::Connection &block, File_info *info, Genode::off_t file_offset,
Genode::uint32_t length, void *buf); Genode::uint32_t length, void *buf);
} } /* namespace Iso */

View File

@ -12,22 +12,20 @@
*/ */
/* Genode includes */ /* Genode includes */
#include <base/component.h>
#include <base/heap.h>
#include <base/log.h> #include <base/log.h>
#include <base/sleep.h>
#include <base/rpc_server.h> #include <base/rpc_server.h>
#include <cap_session/connection.h>
#include <dataspace/client.h> #include <dataspace/client.h>
#include <rom_session/connection.h>
#include <root/component.h> #include <root/component.h>
#include <rm_session/connection.h>
#include <util/avl_string.h> #include <util/avl_string.h>
#include <util/misc_math.h>
#include <os/attached_ram_dataspace.h> #include <os/attached_ram_dataspace.h>
#include <base/session_label.h> #include <base/session_label.h>
#include <block_session/connection.h>
#include <rom_session/rom_session.h>
/* local includes */ /* local includes */
#include "iso9660.h" #include "iso9660.h"
#include "backing_store.h"
using namespace Genode; using namespace Genode;
@ -38,64 +36,62 @@ using namespace Genode;
namespace Iso { namespace Iso {
typedef Backing_store<Genode::off_t> Backing_store;
typedef Avl_string<PATH_LENGTH> File_base; typedef Avl_string<PATH_LENGTH> File_base;
typedef Avl_tree<Avl_string_base> File_cache;
/** class File;
class Rom_component;
typedef Genode::Root_component<Rom_component> Root_component;
class Root;
}
/**
* File abstraction * File abstraction
*/ */
class File : public File_base class Iso::File : public File_base
{ {
private: private:
Genode::Allocator &_alloc;
File_info *_info; File_info *_info;
Attached_ram_dataspace _ds; Attached_ram_dataspace _ds;
public: public:
File(char *path) : File_base(path), File(Genode::Env &env, Genode::Allocator &alloc,
_info(Iso::file_info(path)), Block::Connection &block, char const *path)
_ds(env()->ram_session(), align_addr(_info->page_sized(), 12)) :
File_base(path), _alloc(alloc),
_info(Iso::file_info(_alloc, block, path)),
_ds(env.ram(), env.rm(), align_addr(_info->page_sized(), 12))
{ {
Iso::read_file(_info, 0, _ds.size(), _ds.local_addr<void>()); Iso::read_file(block, _info, 0, _ds.size(), _ds.local_addr<void>());
} }
~File() ~File() { destroy(_alloc, _info); }
{
destroy(env()->heap(), _info);
}
Dataspace_capability dataspace() { return _ds.cap(); } Dataspace_capability dataspace() { return _ds.cap(); }
};
/************************** class Iso::Rom_component : public Genode::Rpc_object<Rom_session>
** File cache interface ** {
**************************/
/**
* File cache that holds files in order to re-use
* them in different sessions that request already cached files
*/
static Avl_tree<Avl_string_base> *cache()
{
static Avl_tree<Avl_string_base> _avl;
return &_avl;
}
static File *scan_cache(const char *path) {
return static_cast<File *>(cache()->first() ?
cache()->first()->find_by_name(path) :
0);
}
};
class Rom_component : public Genode::Rpc_object<Rom_session>
{
private: private:
File *_file; File *_file;
File *_lookup(File_cache &cache, char const *path)
{
return static_cast<File *>(cache.first() ?
cache.first()->find_by_name(path) :
0);
}
public: public:
Rom_dataspace_capability dataspace() { Rom_dataspace_capability dataspace() {
@ -103,27 +99,39 @@ namespace Iso {
void sigh(Signal_context_capability) { } void sigh(Signal_context_capability) { }
Rom_component(char *path) Rom_component(Genode::Env &env, Genode::Allocator &alloc,
File_cache &cache, Block::Connection &block,
char const *path)
{ {
if ((_file = File::scan_cache(path))) { if ((_file = _lookup(cache, path))) {
Genode::log("cache hit for file ", Genode::Cstring(path)); Genode::log("cache hit for file ", Genode::Cstring(path));
return; return;
} }
_file = new(env()->heap()) File(path); _file = new (alloc) File(env, alloc, block, path);
Genode::log("request for file ", Genode::Cstring(path)); Genode::log("request for file ", Genode::Cstring(path));
File::cache()->insert(_file); cache.insert(_file);
} }
}; };
typedef Root_component<Rom_component> Root_component; class Iso::Root : public Iso::Root_component
{
class Root : public Root_component
{
private: private:
Genode::Env &_env;
Genode::Allocator &_alloc;
Allocator_avl _block_alloc { &_alloc };
Block::Connection _block { _env, &_block_alloc };
/*
* Entries in the cache are never freed, even if the ROM session
* gets destroyed.
*/
File_cache _cache;
char _path[PATH_LENGTH]; char _path[PATH_LENGTH];
protected: protected:
@ -143,7 +151,7 @@ namespace Iso {
Genode::log("Request for file ", Cstring(_path), " len ", strlen(_path)); Genode::log("Request for file ", Cstring(_path), " len ", strlen(_path));
try { try {
return new (md_alloc()) Rom_component(_path); return new (_alloc) Rom_component(_env, _alloc, _cache, _block, _path);
} }
catch (Io_error) { throw Root::Unavailable(); } catch (Io_error) { throw Root::Unavailable(); }
catch (Non_data_disc) { throw Root::Unavailable(); } catch (Non_data_disc) { throw Root::Unavailable(); }
@ -152,26 +160,26 @@ namespace Iso {
public: public:
Root(Rpc_entrypoint *ep, Allocator *md_alloc) Root(Genode::Env &env, Allocator &alloc)
: :
Root_component(ep, md_alloc) Root_component(&env.ep().rpc_ep(), &alloc),
_env(env), _alloc(alloc)
{ } { }
}; };
}
int main() struct Main
{ {
/* initialize ROM service */ Genode::Env &_env;
enum { STACK_SIZE = sizeof(long)*4096 }; Genode::Heap _heap { _env.ram(), _env.rm() };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "iso9660_ep");
static Iso::Root root(&ep, env()->heap()); Iso::Root _root { _env, _heap };
env()->parent()->announce(ep.manage(&root));
sleep_forever(); Main(Genode::Env &env) : _env(env)
return 0; {
} _env.parent().announce(_env.ep().manage(_root));
}
};
void Component::construct(Genode::Env &env) { static Main main(env); }