2013-12-05 15:45:14 +01:00
|
|
|
/**
|
2017-01-06 14:23:53 +01:00
|
|
|
* \brief Connect rump kernel to Genode's block interface
|
2013-12-05 15:45:14 +01:00
|
|
|
* \author Sebastian Sumpf
|
|
|
|
* \date 2013-12-16
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2017-02-20 13:23:52 +01:00
|
|
|
* Copyright (C) 2013-2017 Genode Labs GmbH
|
2013-12-05 15:45:14 +01:00
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
2017-02-20 13:23:52 +01:00
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
2013-12-05 15:45:14 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "sched.h"
|
|
|
|
#include <base/allocator_avl.h>
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
#include <base/printf.h>
|
2013-12-05 15:45:14 +01:00
|
|
|
#include <block_session/connection.h>
|
2017-01-06 14:23:53 +01:00
|
|
|
#include <rump/env.h>
|
2013-12-05 15:45:14 +01:00
|
|
|
#include <rump_fs/fs.h>
|
|
|
|
|
|
|
|
|
|
|
|
static const bool verbose = false;
|
|
|
|
|
|
|
|
enum { GENODE_FD = 64 };
|
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
/**
|
|
|
|
* Block session connection
|
|
|
|
*/
|
|
|
|
class Backend
|
2013-12-05 15:45:14 +01:00
|
|
|
{
|
|
|
|
private:
|
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
Genode::Allocator_avl _alloc { &Rump::env().heap() };
|
|
|
|
Block::Connection _session { Rump::env().env(), &_alloc };
|
2013-12-05 15:45:14 +01:00
|
|
|
Genode::size_t _blk_size; /* block size of the device */
|
|
|
|
Block::sector_t _blk_cnt; /* number of blocks of device */
|
|
|
|
Block::Session::Operations _blk_ops;
|
2017-01-06 14:23:53 +01:00
|
|
|
Genode::Lock _session_lock;
|
2013-12-05 15:45:14 +01:00
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
public:
|
2013-12-05 15:45:14 +01:00
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
Backend()
|
2013-12-05 15:45:14 +01:00
|
|
|
{
|
2017-01-06 14:23:53 +01:00
|
|
|
_session.info(&_blk_cnt, &_blk_size, &_blk_ops);
|
2013-12-05 15:45:14 +01:00
|
|
|
}
|
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
uint64_t block_count() const { return (uint64_t)_blk_cnt; }
|
|
|
|
size_t block_size() const { return (size_t)_blk_size; }
|
2013-12-05 15:45:14 +01:00
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
bool writable()
|
2013-12-05 15:45:14 +01:00
|
|
|
{
|
2017-01-06 14:23:53 +01:00
|
|
|
return _blk_ops.supported(Block::Packet_descriptor::WRITE);
|
2013-12-05 15:45:14 +01:00
|
|
|
}
|
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
void sync()
|
2013-12-05 15:45:14 +01:00
|
|
|
{
|
2017-01-06 14:23:53 +01:00
|
|
|
Genode::Lock::Guard guard(_session_lock);
|
|
|
|
_session.sync();
|
2013-12-05 15:45:14 +01:00
|
|
|
}
|
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
bool submit(int op, int64_t offset, size_t length, void *data)
|
2013-12-05 15:45:14 +01:00
|
|
|
{
|
2017-01-06 14:23:53 +01:00
|
|
|
using namespace Block;
|
2013-12-05 15:45:14 +01:00
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
/* sync request */
|
|
|
|
if (op & RUMPUSER_BIO_SYNC) {
|
|
|
|
sync();
|
|
|
|
return true;
|
2013-12-05 15:45:14 +01:00
|
|
|
}
|
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
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;
|
2013-12-05 15:45:14 +01:00
|
|
|
}
|
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
/* wait and process result */
|
|
|
|
Packet_descriptor packet = _session.tx()->get_acked_packet();
|
2013-12-05 15:45:14 +01:00
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
/* in packet */
|
|
|
|
if (opcode == Packet_descriptor::READ)
|
|
|
|
Genode::memcpy(data, _session.tx()->packet_content(packet), length);
|
2013-12-05 15:45:14 +01:00
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
bool succeeded = packet.succeeded();
|
|
|
|
_session.tx()->release_packet(packet);
|
2013-12-05 15:45:14 +01:00
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
return succeeded;
|
2013-12-05 15:45:14 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
static Backend &backend()
|
2013-12-05 15:45:14 +01:00
|
|
|
{
|
2017-01-06 14:23:53 +01:00
|
|
|
static Backend _b;
|
2013-12-05 15:45:14 +01:00
|
|
|
return _b;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int rumpuser_getfileinfo(const char *name, uint64_t *size, int *type)
|
|
|
|
{
|
|
|
|
if (Genode::strcmp(GENODE_BLOCK_SESSION, name))
|
|
|
|
return ENXIO;
|
|
|
|
|
|
|
|
if (type)
|
|
|
|
*type = RUMPUSER_FT_BLK;
|
|
|
|
|
|
|
|
if (size)
|
2017-01-06 14:23:53 +01:00
|
|
|
*size = backend().block_count() * backend().block_size();
|
2013-12-05 15:45:14 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int rumpuser_open(const char *name, int mode, int *fdp)
|
|
|
|
{
|
|
|
|
if (!(mode & RUMPUSER_OPEN_BIO || Genode::strcmp(GENODE_BLOCK_SESSION, name)))
|
|
|
|
return ENXIO;
|
|
|
|
|
|
|
|
/* check for writable */
|
2017-01-06 14:23:53 +01:00
|
|
|
if ((mode & RUMPUSER_OPEN_ACCMODE) && !backend().writable())
|
2013-12-05 15:45:14 +01:00
|
|
|
return EROFS;
|
|
|
|
|
|
|
|
*fdp = GENODE_FD;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void rumpuser_bio(int fd, int op, void *data, size_t dlen, int64_t off,
|
|
|
|
rump_biodone_fn biodone, void *donearg)
|
|
|
|
{
|
|
|
|
int nlocks;
|
2015-02-19 11:40:41 +01:00
|
|
|
rumpkern_unsched(&nlocks, 0);
|
2013-12-05 15:45:14 +01:00
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
/* data request */
|
2015-02-19 11:40:41 +01:00
|
|
|
if (verbose)
|
base: avoid use of deprecated base/printf.h
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
2016-07-13 19:07:09 +02:00
|
|
|
Genode::log("fd: ", fd, " "
|
|
|
|
"op: ", op, " "
|
|
|
|
"len: ", dlen, " "
|
|
|
|
"off: ", Genode::Hex((unsigned long)off), " "
|
|
|
|
"bio ", donearg, " "
|
|
|
|
"sync: ", !!(op & RUMPUSER_BIO_SYNC));
|
2013-12-05 15:45:14 +01:00
|
|
|
|
2017-01-06 14:23:53 +01:00
|
|
|
bool succeeded = backend().submit(op, off, dlen, data);
|
2013-12-05 15:45:14 +01:00
|
|
|
|
|
|
|
rumpkern_sched(nlocks, 0);
|
2017-01-06 14:23:53 +01:00
|
|
|
|
|
|
|
if (biodone)
|
|
|
|
biodone(donearg, dlen, succeeded ? 0 : EIO);
|
2013-12-05 15:45:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void rump_io_backend_sync()
|
|
|
|
{
|
2017-01-06 14:23:53 +01:00
|
|
|
backend().sync();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void rump_io_backend_init()
|
|
|
|
{
|
|
|
|
/* create back end */
|
|
|
|
backend();
|
2013-12-05 15:45:14 +01:00
|
|
|
}
|
|
|
|
|
2014-04-22 16:02:00 +02:00
|
|
|
|
|
|
|
void rumpuser_dprintf(const char *fmt, ...)
|
|
|
|
{
|
|
|
|
va_list list;
|
|
|
|
va_start(list, fmt);
|
|
|
|
|
|
|
|
Genode::vprintf(fmt, list);
|
|
|
|
|
|
|
|
va_end(list);
|
|
|
|
}
|