rump_fs: Transition to new API

The rump libraries and the rump_fs component are now conform to the new base
API. Also the I/O back end should be running stable now.

issue #2224
This commit is contained in:
Sebastian Sumpf
2017-01-06 14:23:53 +01:00
committed by Norman Feske
parent a7f40b24ca
commit 6fa6d72c0b
15 changed files with 312 additions and 369 deletions

View File

@ -1,21 +0,0 @@
/*
* \brief Rump initialization
* \author Norman Feske
* \date 2016-11-02
*/
/*
* Copyright (C) 2016 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 _INCLUDE__RUMP__BOOTSTRAP_H_
#define _INCLUDE__RUMP__BOOTSTRAP_H_
#include <base/env.h>
#include <base/allocator.h>
void rump_bootstrap_init(Genode::Env &env, Genode::Allocator &heap);
#endif /* _INCLUDE__RUMP__BOOTSTRAP_H_ */

View File

@ -0,0 +1,47 @@
/*
* \brief Helper class to make the Genode Env globally available
* \author Sebastian Sumpf
* \date 2016-06-21
*/
/*
* Copyright (C) 2016 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 _INCLUDE__RUMP__ENV_H_
#define _INCLUDE__RUMP__ENV_H_
#include <base/attached_rom_dataspace.h>
#include <base/env.h>
#include <base/heap.h>
#include <util/reconstructible.h>
namespace Rump {
class Env;
Env &env();
void construct_env(Genode::Env &env);
}
class Rump::Env
{
private:
Genode::Env &_env;
Genode::Heap _heap { _env.ram(), _env.rm() };
Genode::Attached_rom_dataspace _config { _env, "config" };
public:
Env(Genode::Env &env) : _env(env) { }
Genode::Env &env() { return _env; }
Genode::Heap &heap() { return _heap; }
Genode::Attached_rom_dataspace &config_rom() { return _config; }
};
#endif /* _INCLUDE__RUMP__ENV_H_ */

View File

@ -24,6 +24,8 @@
#define GENODE_DEVICE "/genode" #define GENODE_DEVICE "/genode"
void rump_io_backend_init();
/** /**
* Sync I/O back-end with underlying Genode subsystems * Sync I/O back-end with underlying Genode subsystems
*/ */

View File

@ -18,7 +18,7 @@
#include <dataspace/client.h> #include <dataspace/client.h>
#include <rm_session/connection.h> #include <rm_session/connection.h>
#include <region_map/client.h> #include <region_map/client.h>
#include <rump/env.h>
namespace Allocator { namespace Allocator {
template <unsigned VM_SIZE, typename POLICY> class Backend_alloc; template <unsigned VM_SIZE, typename POLICY> class Backend_alloc;
@ -85,7 +85,7 @@ namespace Allocator {
Policy_guard<POLICY> guard; Policy_guard<POLICY> guard;
try { try {
_ds_cap[_index] = Genode::env()->ram_session()->alloc(BLOCK_SIZE, _cached); _ds_cap[_index] = Rump::env().env().ram().alloc(BLOCK_SIZE, _cached);
/* attach at index * BLOCK_SIZE */ /* attach at index * BLOCK_SIZE */
Region_map_client::attach_at(_ds_cap[_index], _index * BLOCK_SIZE, BLOCK_SIZE, 0); Region_map_client::attach_at(_ds_cap[_index], _index * BLOCK_SIZE, BLOCK_SIZE, 0);
/* lookup phys. address */ /* lookup phys. address */
@ -114,10 +114,10 @@ namespace Allocator {
: :
Region_map_client(Rm_connection::create(VM_SIZE)), Region_map_client(Rm_connection::create(VM_SIZE)),
_cached(cached), _cached(cached),
_range(Genode::env()->heap()) _range(&Rump::env().heap())
{ {
/* reserver attach us, anywere */ /* reserver attach us, anywere */
_base = Genode::env()->rm_session()->attach(dataspace()); _base = Rump::env().env().rm().attach(dataspace());
} }
/** /**

View File

@ -22,6 +22,8 @@ extern "C" {
#include <base/thread.h> #include <base/thread.h>
#include <base/log.h> #include <base/log.h>
#include <rump/env.h>
#include <util/avl_tree.h>
/************* /*************
@ -35,12 +37,17 @@ namespace Timer {
}; };
class Hard_context class Hard_context : public Genode::Avl_node<Hard_context>
{ {
private: private:
int _cookie; int _cookie;
lwp *_lwp = 0; lwp *_lwp = nullptr;
public:
Genode::Thread *_myself = nullptr;
public: public:
@ -50,12 +57,65 @@ class Hard_context
void set_lwp(lwp *l) { _lwp = l; } void set_lwp(lwp *l) { _lwp = l; }
lwp *get_lwp() { return _lwp; } lwp *get_lwp() { return _lwp; }
static Timer::Connection *timer(); static Timer::Connection &timer();
bool higher(Hard_context *h) { return _myself > h->_myself; }
Hard_context *find(Genode::Thread const *t)
{
if (_myself == t)
return this;
Hard_context *h = child(_myself > t);
if (!h)
return nullptr;
return h->find(t);
}
void thread(Genode::Thread *t) { _myself = t; }
};
class Hard_context_registry : public Genode::Avl_tree<Hard_context>
{
private:
Genode::Lock lock;
public:
Hard_context *find(Genode::Thread const *t)
{
Genode::Lock::Guard g(lock);
if (!first())
return nullptr;
return first()->find(t);
}
void insert(Hard_context *h)
{
Genode::Lock::Guard g(lock);
Avl_tree::insert(h);
}
void remove(Hard_context *h)
{
Genode::Lock::Guard g(lock);
Avl_tree::remove(h);
}
static Hard_context_registry &r()
{
static Hard_context_registry _r;
return _r;
}
}; };
class Hard_context_thread : public Hard_context, class Hard_context_thread : public Hard_context,
public Genode::Thread_deprecated<sizeof(Genode::addr_t) * 2048> public Genode::Thread
{ {
private: private:
@ -66,14 +126,17 @@ class Hard_context_thread : public Hard_context,
void entry() void entry()
{ {
Hard_context::thread(Genode::Thread::myself());
Hard_context_registry::r().insert(this);
_func(_arg); _func(_arg);
Hard_context_registry::r().remove(this);
Genode::log(__func__, " returned from func"); Genode::log(__func__, " returned from func");
} }
public: public:
Hard_context_thread(char const *name, func f, void *arg, int cookie, bool run = true) Hard_context_thread(char const *name, func f, void *arg, int cookie, bool run = true)
: Hard_context(cookie), Thread_deprecated(name), : Hard_context(cookie), Thread(Rump::env().env(), name, sizeof(long) * 2048),
_func(f), _arg(arg) { if (run) start(); } _func(f), _arg(arg) { if (run) start(); }
}; };

View File

@ -15,7 +15,7 @@ VERBOSE_LEVEL ?= 0
# #
# Sources # Sources
# #
SRC_CC = dummies.cc hypercall.cc bootstrap.cc io.cc sync.cc misc.cc SRC_CC = dummies.cc hypercall.cc bootstrap.cc io.cc sync.cc misc.cc env.cc
# #
# TARGET to trigger rump build # TARGET to trigger rump build

View File

@ -85,7 +85,7 @@ install_config $config
set boot_modules { set boot_modules {
core ld.lib.so init timer test-libc_vfs ram_blk core ld.lib.so init timer test-libc_vfs ram_blk
rump.lib.so rump_fs.lib.so rump_fs rump.lib.so rump_fs.lib.so rump_fs
ext2.raw libc.lib.so ext2.raw libc.lib.so libm.lib.so
} }
build_boot_image $boot_modules build_boot_image $boot_modules

View File

@ -17,11 +17,13 @@ extern "C" {
#include <elf.h> #include <elf.h>
} }
#include <rump/bootstrap.h> #include <rump/env.h>
#include <base/log.h> #include <base/log.h>
#include <base/shared_object.h> #include <base/shared_object.h>
#include <util/string.h> #include <util/string.h>
extern "C" void wait_for_continue(); extern "C" void wait_for_continue();
#ifdef _LP64 #ifdef _LP64
@ -36,46 +38,20 @@ static bool const verbose = false;
static Genode::Shared_object *obj_main; static Genode::Shared_object *obj_main;
static Genode::Env *env_ptr;
static Genode::Allocator *heap_ptr;
void rump_bootstrap_init(Genode::Env &env, Genode::Allocator &alloc)
{
/* ignore subsequent calls */
if (env_ptr)
return;
env_ptr = &env;
heap_ptr = &alloc;
}
/**
* Exception type
*/
class Missing_call_of_rump_bootstrap_init { };
static Genode::Env &env() static Genode::Env &env()
{ {
if (!env_ptr) return Rump::env().env();
throw Missing_call_of_rump_bootstrap_init();
return *env_ptr;
} }
static Genode::Allocator &heap() static Genode::Allocator &heap()
{ {
if (!heap_ptr) return Rump::env().heap();
throw Missing_call_of_rump_bootstrap_init();
return *heap_ptr;
} }
struct Sym_tab struct Sym_tab
{ {
Genode::Shared_object::Link_map const *map; Genode::Shared_object::Link_map const *map;
@ -119,7 +95,7 @@ struct Sym_tab
~Sym_tab() ~Sym_tab()
{ {
if (sym_tab) if (sym_tab)
destroy(Genode::env()->heap(), sym_tab); destroy(heap(), sym_tab);
} }
@ -186,7 +162,7 @@ struct Sym_tab
void alloc_memory() void alloc_memory()
{ {
sym_tab = (Elf_Sym *)Genode::env()->heap()->alloc(sizeof(Elf_Sym) * sym_cnt); sym_tab = (Elf_Sym *)heap().alloc(sizeof(Elf_Sym) * sym_cnt);
} }
void read_symbols() void read_symbols()

View File

@ -0,0 +1,31 @@
/**
* \brief Rump::Env initialization
* \author Sebastian Sumpf
* \date 2016-06-23
*/
/*
* Copyright (C) 2016 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 <rump/env.h>
/*
* Genode nviroment instance
*/
static Genode::Constructible<Rump::Env> _env;
Rump::Env &Rump::env()
{
return *_env;
}
void Rump::construct_env(Genode::Env &env)
{
_env.construct(env);
}

View File

@ -14,10 +14,10 @@
#include "sched.h" #include "sched.h"
#include <base/env.h>
#include <base/log.h> #include <base/log.h>
#include <base/sleep.h> #include <base/sleep.h>
#include <os/timed_semaphore.h> #include <os/timed_semaphore.h>
#include <rump/env.h>
#include <util/allocator_fap.h> #include <util/allocator_fap.h>
#include <util/random.h> #include <util/random.h>
#include <util/string.h> #include <util/string.h>
@ -31,53 +31,32 @@ static bool verbose = false;
struct rumpuser_hyperup _rump_upcalls; struct rumpuser_hyperup _rump_upcalls;
/********************
** Initialization **
********************/
int rumpuser_init(int version, const struct rumpuser_hyperup *hyp)
{
Genode::log("RUMP ver: ", version);
if (version != SUPPORTED_RUMP_VERSION) {
Genode::error("unsupported rump-kernel version (", version, ") - "
"supported is ", (int)SUPPORTED_RUMP_VERSION);
return -1;
}
_rump_upcalls = *hyp;
/*
* Start 'Timeout_thread' so it does not get constructed concurrently (which
* causes one thread to spin in cxa_guard_aqcuire), making emulation *really*
* slow
*/
Genode::Timeout_thread::alarm_timer();
return 0;
}
/************* /*************
** Threads ** ** Threads **
*************/ *************/
static Hard_context * main_thread() static Hard_context *main_context()
{ {
static Hard_context inst(0); static Hard_context inst(0);
return &inst; return &inst;
} }
static Hard_context *myself() static Hard_context *myself()
{ {
Hard_context *h = dynamic_cast<Hard_context *>(Genode::Thread::myself()); Hard_context *h = Hard_context_registry::r().find(Genode::Thread::myself());
return h ? h : main_thread();
if (!h)
Genode::error("Hard context is nullptr (", Genode::Thread::myself(), ")");
return h;
} }
Timer::Connection *Hard_context::timer() Timer::Connection &Hard_context::timer()
{ {
static Timer::Connection _timer; static Timer::Connection _timer { Rump::env().env() };
return &_timer; return _timer;
} }
@ -112,7 +91,7 @@ int rumpuser_thread_create(func f, void *arg, const char *name,
if (mustjoin) if (mustjoin)
*cookie = (void *)++count; *cookie = (void *)++count;
new (Genode::env()->heap()) Hard_context_thread(name, f, arg, mustjoin ? count : 0); new (Rump::env().heap()) Hard_context_thread(name, f, arg, mustjoin ? count : 0);
return 0; return 0;
} }
@ -128,6 +107,37 @@ int errno;
void rumpuser_seterrno(int e) { errno = e; } void rumpuser_seterrno(int e) { errno = e; }
/********************
** Initialization **
********************/
int rumpuser_init(int version, const struct rumpuser_hyperup *hyp)
{
Genode::log("RUMP ver: ", version);
if (version != SUPPORTED_RUMP_VERSION) {
Genode::error("unsupported rump-kernel version (", version, ") - "
"supported is ", (int)SUPPORTED_RUMP_VERSION);
return -1;
}
_rump_upcalls = *hyp;
/* register context for main EP */
main_context()->thread(Genode::Thread::myself());
Hard_context_registry::r().insert(main_context());
/*
* Start 'Timeout_thread' so it does not get constructed concurrently (which
* causes one thread to spin in cxa_guard_aqcuire), making emulation *really*
* slow
*/
Genode::Timeout_thread::alarm_timer();
return 0;
}
/************************* /*************************
** Parameter retrieval ** ** Parameter retrieval **
*************************/ *************************/
@ -152,7 +162,7 @@ int rumpuser_getparam(const char *name, void *buf, size_t buflen)
if (!Genode::strcmp(name, "RUMP_MEMLIMIT")) { if (!Genode::strcmp(name, "RUMP_MEMLIMIT")) {
/* leave 2 MB for the Genode */ /* leave 2 MB for the Genode */
size_t rump_ram = Genode::env()->ram_session()->avail(); size_t rump_ram = Rump::env().env().ram().avail();
if (rump_ram <= RESERVE_MEM) { if (rump_ram <= RESERVE_MEM) {
Genode::error("insufficient quota left: ", Genode::error("insufficient quota left: ",
@ -178,20 +188,22 @@ int rumpuser_getparam(const char *name, void *buf, size_t buflen)
void rumpuser_putchar(int ch) void rumpuser_putchar(int ch)
{ {
static unsigned char buf[256]; enum { BUF_SIZE = 256 };
static unsigned char buf[BUF_SIZE];
static int count = 0; static int count = 0;
if (count < BUF_SIZE - 1 && ch != '\n')
buf[count++] = (unsigned char)ch; buf[count++] = (unsigned char)ch;
if (ch == '\n') { if (ch == '\n' || count == BUF_SIZE - 1) {
buf[count] = 0; buf[count] = 0;
int nlocks; int nlocks;
if (myself() != main_thread()) if (myself() != main_context())
rumpkern_unsched(&nlocks, 0); rumpkern_unsched(&nlocks, 0);
Genode::log("rump: ", Genode::Cstring((char const *)buf)); Genode::log("rump: ", Genode::Cstring((char const *)buf));
if (myself() != main_thread()) if (myself() != main_context())
rumpkern_sched(nlocks, 0); rumpkern_sched(nlocks, 0);
count = 0; count = 0;
@ -209,14 +221,14 @@ struct Allocator_policy
{ {
int nlocks; int nlocks;
if (myself() != main_thread()) if (myself() != main_context())
rumpkern_unsched(&nlocks, 0); rumpkern_unsched(&nlocks, 0);
return nlocks; return nlocks;
} }
static void unblock(int nlocks) static void unblock(int nlocks)
{ {
if (myself() != main_thread()) if (myself() != main_context())
rumpkern_sched(nlocks, 0); rumpkern_sched(nlocks, 0);
} }
}; };
@ -230,12 +242,14 @@ static Genode::Lock & alloc_lock()
return inst; return inst;
} }
static Rump_alloc* allocator() static Rump_alloc* allocator()
{ {
static Rump_alloc _fap(true); static Rump_alloc _fap(true);
return &_fap; return &_fap;
} }
int rumpuser_malloc(size_t len, int alignment, void **memp) int rumpuser_malloc(size_t len, int alignment, void **memp)
{ {
Genode::Lock::Guard guard(alloc_lock()); Genode::Lock::Guard guard(alloc_lock());
@ -269,7 +283,7 @@ void rumpuser_free(void *mem, size_t len)
int rumpuser_clock_gettime(int enum_rumpclock, int64_t *sec, long *nsec) int rumpuser_clock_gettime(int enum_rumpclock, int64_t *sec, long *nsec)
{ {
Hard_context *h = myself(); Hard_context *h = myself();
unsigned long t = h->timer()->elapsed_ms(); unsigned long t = h->timer().elapsed_ms();
*sec = (int64_t)t / 1000; *sec = (int64_t)t / 1000;
*nsec = (t % 1000) * 1000; *nsec = (t % 1000) * 1000;
return 0; return 0;
@ -281,7 +295,7 @@ int rumpuser_clock_sleep(int enum_rumpclock, int64_t sec, long nsec)
int nlocks; int nlocks;
unsigned int msec = 0; unsigned int msec = 0;
Timer::Connection *timer = myself()->timer(); Timer::Connection &timer = myself()->timer();
rumpkern_unsched(&nlocks, 0); rumpkern_unsched(&nlocks, 0);
switch (enum_rumpclock) { switch (enum_rumpclock) {
@ -289,12 +303,12 @@ int rumpuser_clock_sleep(int enum_rumpclock, int64_t sec, long nsec)
msec = sec * 1000 + nsec / (1000*1000UL); msec = sec * 1000 + nsec / (1000*1000UL);
break; break;
case RUMPUSER_CLOCK_ABSMONO: case RUMPUSER_CLOCK_ABSMONO:
msec = timer->elapsed_ms(); msec = timer.elapsed_ms();
msec = ((sec * 1000) + (nsec / (1000 * 1000))) - msec; msec = ((sec * 1000) + (nsec / (1000 * 1000))) - msec;
break; break;
} }
timer->msleep(msec); timer.msleep(msec);
rumpkern_sched(nlocks, 0); rumpkern_sched(nlocks, 0);
return 0; return 0;
} }

View File

@ -1,5 +1,5 @@
/** /**
* \brief Connect rump kernel Genode's block interface * \brief Connect rump kernel to Genode's block interface
* \author Sebastian Sumpf * \author Sebastian Sumpf
* \date 2013-12-16 * \date 2013-12-16
*/ */
@ -13,218 +13,35 @@
#include "sched.h" #include "sched.h"
#include <base/allocator_avl.h> #include <base/allocator_avl.h>
#include <base/thread.h>
#include <base/printf.h> #include <base/printf.h>
#include <block_session/connection.h> #include <block_session/connection.h>
#include <rump/env.h>
#include <rump_fs/fs.h> #include <rump_fs/fs.h>
#include <util/list.h>
#include <util/string.h>
static const bool verbose = false; static const bool verbose = false;
enum { GENODE_FD = 64 }; enum { GENODE_FD = 64 };
struct Packet : Genode::List<Packet>::Element /**
* Block session connection
*/
class Backend
{ {
Block::sector_t blk;
Genode::size_t cnt;
Block::Packet_descriptor::Opcode opcode;
void *data;
long offset;
rump_biodone_fn biodone;
void *donearg;
bool valid;
bool pending;
bool sync;
};
class Backend : public Hard_context_thread
{
private: private:
enum { COUNT = Block::Session::TX_QUEUE_SIZE }; Genode::Allocator_avl _alloc { &Rump::env().heap() };
Block::Connection _session { Rump::env().env(), &_alloc };
Genode::Allocator_avl _alloc;
Block::Connection _session;
Genode::size_t _blk_size; /* block size of the device */ Genode::size_t _blk_size; /* block size of the device */
Block::sector_t _blk_cnt; /* number of blocks of device */ Block::sector_t _blk_cnt; /* number of blocks of device */
Block::Session::Operations _blk_ops; Block::Session::Operations _blk_ops;
Packet _p[COUNT]; Genode::Lock _session_lock;
Genode::Semaphore _alloc_sem;
Genode::Semaphore _packet_sem;
int _index_thread = 0;
int _index_client = 0;
Genode::Lock _alloc_lock;
bool _handle;
Genode::Signal_receiver _receiver;
Genode::Signal_dispatcher<Backend> _disp_ack;
Genode::Signal_dispatcher<Backend> _disp_submit;
Genode::List<Packet> *_pending()
{
static Genode::List<Packet> _p;
return &_p;
}
bool _have_pending()
{
return !!_pending()->first();
}
Packet *_find(Block::Packet_descriptor &packet)
{
Packet *p = _pending()->first();
while (p) {
if (p->offset == packet.offset())
return p;
p = p->next();
}
Genode::error("pending packet not found");
return 0;
}
Packet *_dequeue()
{
int idx;
for (int i = 0; i < COUNT; i++) {
idx = (_index_thread + i) % COUNT;
if (_p[idx].valid && !_p[idx].pending) {
_index_thread = idx;
_p[idx].pending = true;
return &_p[idx];
}
}
Genode::warning("dequeue returned 0");
return 0;
}
void _free(Packet *p)
{
p->valid = false;
p->pending = false;
_alloc_sem.up();
}
void _ready_to_submit(unsigned) { _handle = false; }
void _ack_avail(unsigned)
{
_handle = false;
while (_session.tx()->ack_avail()) {
Block::Packet_descriptor packet = _session.tx()->get_acked_packet();
Packet *p = _find(packet);
if (p->opcode == Block::Packet_descriptor::READ)
Genode::memcpy(p->data, _session.tx()->packet_content(packet),
packet.block_count() * _blk_size);
/* sync session if requested */
if (p->sync)
_session.sync();
int dummy;
if (verbose)
Genode::log("BIO done p: ", p, " bio ", p->donearg);
rumpkern_sched(0, 0);
if (p->biodone)
p->biodone(p->donearg, p->cnt * _blk_size,
packet.succeeded() ? 0 : EIO);
rumpkern_unsched(&dummy, 0);
_session.tx()->release_packet(packet);
_pending()->remove(p);
_free(p);
}
}
void _handle_signal()
{
_handle = true;
while (_handle) {
Genode::Signal s = _receiver.wait_for_signal();
static_cast<Genode::Signal_dispatcher_base *>
(s.context())->dispatch(s.num());
}
}
protected:
void entry()
{
_rump_upcalls.hyp_schedule();
_rump_upcalls.hyp_lwproc_newlwp(0);
_rump_upcalls.hyp_unschedule();
while (true) {
while (_packet_sem.cnt() <= 0 && _have_pending())
_handle_signal();
_packet_sem.down();
while (!_session.tx()->ready_to_submit())
_handle_signal();
Packet *p = _dequeue();
/* zero or sync request */
if (!p->cnt) {
if (p->sync)
_session.sync();
_free(p);
continue;
}
for (bool done = false; !done;)
try {
Block::Packet_descriptor packet(
_session.dma_alloc_packet(p->cnt * _blk_size),
p->opcode, p->blk, p->cnt);
/* got packet copy data */
if (p->opcode == Block::Packet_descriptor::WRITE)
Genode::memcpy(_session.tx()->packet_content(packet),
p->data, p->cnt * _blk_size);
_session.tx()->submit_packet(packet);
/* mark as pending */
p->offset = packet.offset();
_pending()->insert(p);
done = true;
} catch(Block::Session::Tx::Source::Packet_alloc_failed) {
_handle_signal();
}
}
}
public: public:
Backend() Backend()
: Hard_context_thread("block_io", 0, 0, 0, false),
_alloc(Genode::env()->heap()),
_session(&_alloc),
_alloc_sem(COUNT),
_disp_ack(_receiver, *this, &Backend::_ack_avail),
_disp_submit(_receiver, *this, &Backend::_ready_to_submit)
{ {
_session.tx_channel()->sigh_ack_avail(_disp_ack);
_session.tx_channel()->sigh_ready_to_submit(_disp_submit);
_session.info(&_blk_cnt, &_blk_size, &_blk_ops); _session.info(&_blk_cnt, &_blk_size, &_blk_ops);
Genode::log("Backend blk_size ", _blk_size);
Genode::memset(_p, 0, sizeof(_p));
start();
} }
uint64_t block_count() const { return (uint64_t)_blk_cnt; } uint64_t block_count() const { return (uint64_t)_blk_cnt; }
@ -235,44 +52,61 @@ class Backend : public Hard_context_thread
return _blk_ops.supported(Block::Packet_descriptor::WRITE); return _blk_ops.supported(Block::Packet_descriptor::WRITE);
} }
Packet *alloc() void sync()
{ {
int idx; Genode::Lock::Guard guard(_session_lock);
_alloc_sem.down(); _session.sync();
Genode::Lock::Guard guard(_alloc_lock);
for (int i = 0; i < COUNT; i++) {
idx = (_index_client + i) % COUNT;
if (!_p[idx].valid) {
_p[idx].valid = true;
_p[idx].pending = false;
_index_client = idx;
return &_p[idx];
}
}
Genode::warning("alloc returned 0");
return 0;
} }
void submit() { _packet_sem.up(); } bool submit(int op, int64_t offset, size_t length, void *data)
{
using namespace Block;
/* sync request */
if (op & RUMPUSER_BIO_SYNC) {
sync();
return true;
}
Genode::Lock::Guard guard(_session_lock);
Packet_descriptor::Opcode opcode;
opcode = op & RUMPUSER_BIO_WRITE ? Packet_descriptor::WRITE :
Packet_descriptor::READ;
/* allocate packet */
try {
Packet_descriptor packet( _session.dma_alloc_packet(length),
opcode, offset / _blk_size,
length / _blk_size);
/* out packet -> copy data */
if (opcode == Packet_descriptor::WRITE)
Genode::memcpy(_session.tx()->packet_content(packet), data, length);
_session.tx()->submit_packet(packet);
} catch(Block::Session::Tx::Source::Packet_alloc_failed) {
Genode::error("I/O back end: Packet allocation failed!");
return false;
}
/* wait and process result */
Packet_descriptor packet = _session.tx()->get_acked_packet();
/* in packet */
if (opcode == Packet_descriptor::READ)
Genode::memcpy(data, _session.tx()->packet_content(packet), length);
bool succeeded = packet.succeeded();
_session.tx()->release_packet(packet);
return succeeded;
}
}; };
static Backend *backend() static Backend &backend()
{ {
static Backend *_b = 0; static Backend _b;
if (_b)
return _b;
int nlocks;
rumpkern_unsched(&nlocks, 0);
try {
_b = new(Genode::env()->heap())Backend();
} catch (Genode::Parent::Service_denied) {
Genode::error("opening block session denied!");
}
rumpkern_sched(nlocks, 0);
return _b; return _b;
} }
@ -286,7 +120,7 @@ int rumpuser_getfileinfo(const char *name, uint64_t *size, int *type)
*type = RUMPUSER_FT_BLK; *type = RUMPUSER_FT_BLK;
if (size) if (size)
*size = backend()->block_count() * backend()->block_size(); *size = backend().block_count() * backend().block_size();
return 0; return 0;
} }
@ -298,7 +132,7 @@ int rumpuser_open(const char *name, int mode, int *fdp)
return ENXIO; return ENXIO;
/* check for writable */ /* check for writable */
if ((mode & RUMPUSER_OPEN_ACCMODE) && !backend()->writable()) if ((mode & RUMPUSER_OPEN_ACCMODE) && !backend().writable())
return EROFS; return EROFS;
*fdp = GENODE_FD; *fdp = GENODE_FD;
@ -310,40 +144,36 @@ void rumpuser_bio(int fd, int op, void *data, size_t dlen, int64_t off,
rump_biodone_fn biodone, void *donearg) rump_biodone_fn biodone, void *donearg)
{ {
int nlocks; int nlocks;
rumpkern_unsched(&nlocks, 0); rumpkern_unsched(&nlocks, 0);
Packet *p = backend()->alloc();
/* data request */
if (verbose) if (verbose)
Genode::log("fd: ", fd, " " Genode::log("fd: ", fd, " "
"op: ", op, " " "op: ", op, " "
"len: ", dlen, " " "len: ", dlen, " "
"off: ", Genode::Hex((unsigned long)off), " " "off: ", Genode::Hex((unsigned long)off), " "
"p: ", p, " "
"bio ", donearg, " " "bio ", donearg, " "
"sync: ", !!(op & RUMPUSER_BIO_SYNC)); "sync: ", !!(op & RUMPUSER_BIO_SYNC));
p->opcode= op & RUMPUSER_BIO_WRITE ? Block::Packet_descriptor::WRITE : bool succeeded = backend().submit(op, off, dlen, data);
Block::Packet_descriptor::READ;
p->cnt = dlen / backend()->block_size();
p->blk = off / backend()->block_size();
p->data = data;
p->biodone = biodone;
p->donearg = donearg;
p->sync = !!(op & RUMPUSER_BIO_SYNC);
backend()->submit();
rumpkern_sched(nlocks, 0); rumpkern_sched(nlocks, 0);
if (biodone)
biodone(donearg, dlen, succeeded ? 0 : EIO);
} }
void rump_io_backend_sync() void rump_io_backend_sync()
{ {
/* send empty packet with sync request */ backend().sync();
Packet *p = backend()->alloc(); }
p->cnt = 0;
p->sync = true;
backend()->submit(); void rump_io_backend_init()
{
/* create back end */
backend();
} }

View File

@ -18,6 +18,8 @@ extern "C" {
#include <base/lock.h> #include <base/lock.h>
#include <util/fifo.h> #include <util/fifo.h>
#include <os/timed_semaphore.h> #include <os/timed_semaphore.h>
#include <rump/env.h>
#include "sched.h" #include "sched.h"
@ -106,7 +108,7 @@ struct rumpuser_mtx
void rumpuser_mutex_init(struct rumpuser_mtx **mtxp, int flags) void rumpuser_mutex_init(struct rumpuser_mtx **mtxp, int flags)
{ {
*mtxp = new(Genode::env()->heap()) rumpuser_mtx(flags); *mtxp = new(Rump::env().heap()) rumpuser_mtx(flags);
} }
@ -153,7 +155,7 @@ void rumpuser_mutex_exit(struct rumpuser_mtx *mtx)
void rumpuser_mutex_destroy(struct rumpuser_mtx *mtx) void rumpuser_mutex_destroy(struct rumpuser_mtx *mtx)
{ {
destroy(Genode::env()->heap(), mtx); destroy(Rump::env().heap(), mtx);
} }
@ -274,13 +276,13 @@ struct rumpuser_cv {
void rumpuser_cv_init(struct rumpuser_cv **cv) void rumpuser_cv_init(struct rumpuser_cv **cv)
{ {
*cv = new(Genode::env()->heap()) rumpuser_cv(); *cv = new(Rump::env().heap()) rumpuser_cv();
} }
void rumpuser_cv_destroy(struct rumpuser_cv *cv) void rumpuser_cv_destroy(struct rumpuser_cv *cv)
{ {
destroy(Genode::env()->heap(), cv); destroy(Rump::env().heap(), cv);
} }
@ -464,7 +466,7 @@ struct rumpuser_rw
void rumpuser_rw_init(struct rumpuser_rw **rw) void rumpuser_rw_init(struct rumpuser_rw **rw)
{ {
*rw = new(Genode::env()->heap()) rumpuser_rw(); *rw = new(Rump::env().heap()) rumpuser_rw();
} }
@ -531,6 +533,6 @@ void rumpuser_rw_held(int enum_rumprwlock, struct rumpuser_rw *rw, int *rv)
void rumpuser_rw_destroy(struct rumpuser_rw *rw) void rumpuser_rw_destroy(struct rumpuser_rw *rw)
{ {
destroy(Genode::env()->heap(), rw); destroy(Rump::env().heap(), rw);
} }

View File

@ -13,7 +13,7 @@
#include "file_system.h" #include "file_system.h"
#include <rump/bootstrap.h> #include <rump/env.h>
#include <rump_fs/fs.h> #include <rump_fs/fs.h>
#include <util/string.h> #include <util/string.h>
#include <util/hard_context.h> #include <util/hard_context.h>
@ -76,9 +76,9 @@ static bool check_read_only(Fs_type const &fs_type)
} }
void File_system::init(Genode::Env &env, Genode::Allocator &alloc, Genode::Xml_node config) void File_system::init()
{ {
Fs_type const fs_type = config.attribute_value("fs", Fs_type()); Fs_type const fs_type = Rump::env().config_rom().xml().attribute_value("fs", Fs_type());
if (!_check_type(fs_type)) { if (!_check_type(fs_type)) {
Genode::error("Invalid or no file system given (use \'<config fs=\"<fs type>\"/>)"); Genode::error("Invalid or no file system given (use \'<config fs=\"<fs type>\"/>)");
@ -87,12 +87,8 @@ void File_system::init(Genode::Env &env, Genode::Allocator &alloc, Genode::Xml_n
} }
Genode::log("Using ", fs_type, " as file system"); Genode::log("Using ", fs_type, " as file system");
/* make Genode env and heap known to the rump kernel */
rump_bootstrap_init(env, alloc);
/* start rump kernel */ /* start rump kernel */
rump_init(); rump_init();
/* register block device */ /* register block device */
rump_pub_etfs_register(GENODE_DEVICE, GENODE_BLOCK_SESSION, RUMP_ETFS_BLK); rump_pub_etfs_register(GENODE_DEVICE, GENODE_BLOCK_SESSION, RUMP_ETFS_BLK);

View File

@ -31,7 +31,7 @@ extern "C" {
} }
namespace File_system { namespace File_system {
void init(Genode::Env &, Genode::Allocator &heap, Genode::Xml_node config); void init();
bool supports_symlinks(); bool supports_symlinks();
} }

View File

@ -24,6 +24,7 @@
#include "undef.h" #include "undef.h"
#include <rump/env.h>
#include <rump_fs/fs.h> #include <rump_fs/fs.h>
#include <sys/resource.h> #include <sys/resource.h>
#include "file_system.h" #include "file_system.h"
@ -173,7 +174,7 @@ class File_system::Session_component : public Session_rpc_object
~Session_component() ~Session_component()
{ {
Dataspace_capability ds = tx_sink()->dataspace(); Dataspace_capability ds = tx_sink()->dataspace();
env()->ram_session()->free(static_cap_cast<Ram_dataspace>(ds)); Rump::env().env().ram().free(static_cap_cast<Ram_dataspace>(ds));
destroy(&_md_alloc, &_root); destroy(&_md_alloc, &_root);
} }
@ -491,11 +492,13 @@ struct File_system::Main
Root fs_root { env, sliced_heap }; Root fs_root { env, sliced_heap };
Attached_rom_dataspace config { env, "config" };
Main(Genode::Env &env) : env(env) Main(Genode::Env &env) : env(env)
{ {
File_system::init(env, heap, config.xml()); Rump::construct_env(env);
rump_io_backend_init();
File_system::init();
/* set all bits but the stickies */ /* set all bits but the stickies */
rump_sys_umask(S_ISUID|S_ISGID|S_ISVTX); rump_sys_umask(S_ISUID|S_ISGID|S_ISVTX);