mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-27 01:11:06 +00:00
os: remove outdated test/block components
The functionality of the test-block-client, test-block-server, and test-block-bench components is now covered by the block_tester application and the vfs_block server. Issue #4405
This commit is contained in:
parent
378e2d9e74
commit
26d9bac78f
@ -649,7 +649,6 @@ set default_test_pkgs {
|
||||
test-spark
|
||||
test-spark_exception
|
||||
test-spark_secondary_stack
|
||||
test-block
|
||||
test-clipboard
|
||||
test-depot_query_index
|
||||
test-ds_ownership
|
||||
|
@ -1 +0,0 @@
|
||||
Block session tests
|
@ -1,2 +0,0 @@
|
||||
_/src/init
|
||||
_/src/test-block
|
@ -1 +0,0 @@
|
||||
2022-01-18 577ca2da21d29b23a8fd4f5ba9c7512371cc7fdb
|
@ -1,41 +0,0 @@
|
||||
<runtime ram="32M" caps="1000" binary="init">
|
||||
|
||||
<requires> <timer/> </requires>
|
||||
|
||||
<events>
|
||||
<timeout meaning="failed" sec="20" />
|
||||
<log meaning="succeeded">--- all tests finished ---</log>
|
||||
<log meaning="failed">test-block-client] Error: </log>
|
||||
</events>
|
||||
|
||||
<content>
|
||||
<rom label="ld.lib.so"/>
|
||||
<rom label="test-block-server"/>
|
||||
<rom label="test-block-client"/>
|
||||
</content>
|
||||
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="TRACE"/>
|
||||
<service name="Timer"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="test-block-server" caps="200">
|
||||
<resource name="RAM" quantum="10M" />
|
||||
<provides><service name="Block" /></provides>
|
||||
</start>
|
||||
<start name="test-block-client" caps="200">
|
||||
<resource name="RAM" quantum="50M" />
|
||||
</start>
|
||||
</config>
|
||||
</runtime>
|
@ -1,9 +0,0 @@
|
||||
SRC_DIR = src/test/block
|
||||
include $(GENODE_DIR)/repos/base/recipes/src/content.inc
|
||||
|
||||
MIRROR_FROM_REP_DIR := include/os
|
||||
|
||||
content: $(MIRROR_FROM_REP_DIR)
|
||||
|
||||
$(MIRROR_FROM_REP_DIR):
|
||||
$(mirror_from_rep_dir)
|
@ -1 +0,0 @@
|
||||
2022-01-18 ca54d93526f633ba06da899f089ffebef3ec168a
|
@ -1,4 +0,0 @@
|
||||
base
|
||||
os
|
||||
block_session
|
||||
timer_session
|
@ -1,92 +0,0 @@
|
||||
assert_spec x86
|
||||
|
||||
set mke2fs [installed_command mke2fs]
|
||||
set dd [installed_command dd]
|
||||
|
||||
#
|
||||
# Build
|
||||
#
|
||||
set build_components {
|
||||
core init timer
|
||||
drivers/ahci
|
||||
drivers/platform
|
||||
test/block/bench
|
||||
}
|
||||
|
||||
source ${genode_dir}/repos/base/run/platform_drv.inc
|
||||
append_platform_drv_build_components
|
||||
|
||||
build $build_components
|
||||
#
|
||||
# Build EXT2-file-system image
|
||||
#
|
||||
catch { exec $dd if=/dev/zero of=bin/ext2.raw bs=1M count=16 }
|
||||
catch { exec $mke2fs -F bin/ext2.raw }
|
||||
|
||||
create_boot_directory
|
||||
|
||||
#
|
||||
# Generate config
|
||||
#
|
||||
set config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<default caps="100"/>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
}
|
||||
|
||||
append_platform_drv_config
|
||||
|
||||
append config {
|
||||
<start name="ahci_drv">
|
||||
<resource name="RAM" quantum="10M" />
|
||||
<provides><service name="Block" /></provides>
|
||||
<config>
|
||||
<report ports="yes"/>
|
||||
<policy label_prefix="test-ahci" device="0" writeable="yes" />
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="test-ahci">
|
||||
<binary name="test-block-bench" />
|
||||
<resource name="RAM" quantum="5M" />
|
||||
<route>
|
||||
<service name="Block"><child name="ahci_drv"/></service>
|
||||
<any-service> <parent/> <any-child /> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
</config> }
|
||||
|
||||
install_config $config
|
||||
|
||||
#
|
||||
# Boot modules
|
||||
#
|
||||
set boot_modules { core init timer ahci_drv test-block-bench ld.lib.so }
|
||||
|
||||
append_platform_drv_boot_modules
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
append qemu_args " -nographic "
|
||||
append qemu_args " -drive id=disk,file=bin/ext2.raw,format=raw,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -boot d"
|
||||
append qemu_args " -drive id=cd,file=[run_dir]/../ahci_bench.iso,if=none,media=cdrom -device ide-cd,drive=cd,bus=ahci.1"
|
||||
|
||||
run_genode_until "Done.*\n" 100
|
||||
|
||||
exec rm -f bin/ext2.raw
|
@ -1,150 +0,0 @@
|
||||
/*
|
||||
* \brief Benchmark for block connection
|
||||
* \author Sebastian Sumpf
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2015-03-24
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-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 <base/allocator_avl.h>
|
||||
#include <base/component.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/log.h>
|
||||
#include <block_session/connection.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
enum {
|
||||
TEST_WRITE = false,
|
||||
TEST_SIZE = 1024 * 1024 * 1024,
|
||||
REQUEST_SIZE = 8 * 512,
|
||||
TX_BUFFER = Block::Session::TX_QUEUE_SIZE * REQUEST_SIZE
|
||||
};
|
||||
|
||||
|
||||
class Throughput
|
||||
{
|
||||
private:
|
||||
|
||||
typedef Genode::size_t size_t;
|
||||
|
||||
Env & _env;
|
||||
Heap _heap { _env.ram(), _env.rm() };
|
||||
Allocator_avl _alloc { &_heap };
|
||||
Block::Connection<> _session { _env, &_alloc, TX_BUFFER };
|
||||
Timer::Connection _timer { _env };
|
||||
|
||||
Signal_handler<Throughput> _disp_ack { _env.ep(), *this,
|
||||
&Throughput::_ack };
|
||||
Signal_handler<Throughput> _disp_submit { _env.ep(), *this,
|
||||
&Throughput::_submit };
|
||||
bool _read_done = false;
|
||||
bool _write_done = false;
|
||||
|
||||
uint64_t _start = 0;
|
||||
uint64_t _stop = 0;
|
||||
size_t _bytes = 0;
|
||||
Block::sector_t _current = 0;
|
||||
|
||||
Block::Session::Info const _info { _session.info() };
|
||||
size_t const _blk_size { _info.block_size };
|
||||
Block::sector_t const _blk_count { _info.block_count };
|
||||
|
||||
void _submit()
|
||||
{
|
||||
static size_t count = REQUEST_SIZE / _blk_size;
|
||||
|
||||
if (_read_done && (_write_done || !TEST_WRITE))
|
||||
return;
|
||||
|
||||
try {
|
||||
while (_session.tx()->ready_to_submit()) {
|
||||
Block::Packet_descriptor p(
|
||||
_session.alloc_packet(REQUEST_SIZE),
|
||||
!_read_done ? Block::Packet_descriptor::READ : Block::Packet_descriptor::WRITE,
|
||||
_current, count);
|
||||
|
||||
_session.tx()->submit_packet(p);
|
||||
|
||||
/* increment for next read */
|
||||
_current += count;
|
||||
if (_current + count >= _blk_count)
|
||||
_current = 0;
|
||||
}
|
||||
} catch (...) { }
|
||||
}
|
||||
|
||||
void _ack()
|
||||
{
|
||||
while (_session.tx()->ack_avail()) {
|
||||
|
||||
Block::Packet_descriptor p = _session.tx()->get_acked_packet();
|
||||
if (!p.succeeded())
|
||||
error("packet error: block: ", p.block_number(), " "
|
||||
"count: ", p.block_count());
|
||||
|
||||
if (!_read_done || (_read_done && p.operation() == Block::Packet_descriptor::WRITE))
|
||||
_bytes += p.size();
|
||||
|
||||
_session.tx()->release_packet(p);
|
||||
}
|
||||
|
||||
if (_bytes >= TEST_SIZE) {
|
||||
_finish();
|
||||
return;
|
||||
}
|
||||
|
||||
_submit();
|
||||
}
|
||||
|
||||
void _finish()
|
||||
{
|
||||
if (_read_done && (_write_done || !TEST_WRITE))
|
||||
return;
|
||||
|
||||
_stop = _timer.elapsed_ms();
|
||||
log(!_read_done ? "Read" : "Wrote", " ", _bytes / 1024, " KiB in ",
|
||||
_stop - _start, " ms (",
|
||||
((double)_bytes / (1024 * 1024)) / ((double)(_stop - _start) / 1000),
|
||||
" MiB/s)");
|
||||
|
||||
/* start write */
|
||||
if (!_read_done ) {
|
||||
_read_done = true;
|
||||
_start = _timer.elapsed_ms();
|
||||
_bytes = 0;
|
||||
_current = 0;
|
||||
if (TEST_WRITE)
|
||||
_submit();
|
||||
else
|
||||
log("Done");
|
||||
} else if (!_write_done && TEST_WRITE) {
|
||||
_write_done = true;
|
||||
log("Done");
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Throughput(Env & env)
|
||||
: _env(env)
|
||||
{
|
||||
_session.tx_channel()->sigh_ack_avail(_disp_ack);
|
||||
_session.tx_channel()->sigh_ready_to_submit(_disp_submit);
|
||||
|
||||
warning("block count ", _blk_count, " size ", _blk_size);
|
||||
log("read/write ", TEST_SIZE / 1024, " KiB ...");
|
||||
_start = _timer.elapsed_ms();
|
||||
_submit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Env &env) { static Throughput test(env); }
|
@ -1,3 +0,0 @@
|
||||
TARGET = test-block-bench
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
@ -1,441 +0,0 @@
|
||||
/*
|
||||
* \brief Block session tests - client side.
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2013-12-10
|
||||
*/
|
||||
|
||||
#include <base/allocator_avl.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/component.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/log.h>
|
||||
#include <block_session/connection.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <os/ring_buffer.h>
|
||||
|
||||
static Genode::size_t blk_sz; /* block size of the device */
|
||||
static Block::sector_t test_cnt; /* number test blocks */
|
||||
static Block::sector_t blk_cnt; /* number of blocks of device */
|
||||
static bool writeable;
|
||||
|
||||
|
||||
/**
|
||||
* Virtual base class of all test scenarios, provides basic signal handling
|
||||
*/
|
||||
class Test : Genode::Interface
|
||||
{
|
||||
public:
|
||||
|
||||
struct Exception : private Genode::Exception, Genode::Interface
|
||||
{
|
||||
virtual void print_error() = 0;
|
||||
};
|
||||
|
||||
class Block_exception : public Exception
|
||||
{
|
||||
protected:
|
||||
|
||||
Block::sector_t _nr;
|
||||
Genode::size_t _cnt;
|
||||
bool _write;
|
||||
|
||||
public:
|
||||
|
||||
Block_exception(Block::sector_t nr, Genode::size_t cnt,
|
||||
bool write)
|
||||
: _nr(nr), _cnt(cnt), _write(write) {}
|
||||
|
||||
void print_error() override
|
||||
{
|
||||
Genode::error("couldn't ", _write ? "write" : "read", " "
|
||||
"block ", _nr, " - ", _nr+_cnt);
|
||||
}
|
||||
};
|
||||
|
||||
struct Submit_queue_full : Exception {
|
||||
void print_error() override {
|
||||
Genode::error("submit queue is full!"); } };
|
||||
|
||||
struct Timeout : Exception {
|
||||
void print_error() override {
|
||||
Genode::error("test timed out!"); } };
|
||||
|
||||
virtual void perform() = 0;
|
||||
virtual void ack_avail() = 0;
|
||||
|
||||
protected:
|
||||
|
||||
Genode::Entrypoint &_ep;
|
||||
Genode::Allocator_avl _alloc;
|
||||
Block::Connection<> _session;
|
||||
|
||||
Genode::Io_signal_handler<Test> _disp_ack;
|
||||
Genode::Io_signal_handler<Test> _disp_submit;
|
||||
Genode::Io_signal_handler<Test> _disp_timeout;
|
||||
|
||||
Timer::Connection _timer;
|
||||
bool _handle = false;
|
||||
|
||||
Genode::size_t _shared_buffer_size(Genode::size_t bulk)
|
||||
{
|
||||
return bulk +
|
||||
sizeof(Block::Session::Tx_policy::Ack_queue) +
|
||||
sizeof(Block::Session::Tx_policy::Submit_queue) +
|
||||
(1 << Block::Packet_descriptor::PACKET_ALIGNMENT) - 1;
|
||||
}
|
||||
|
||||
void _ack_avail() { ack_avail(); }
|
||||
void _ready_to_submit() { _handle = false; }
|
||||
void _timeout() { throw Timeout(); }
|
||||
|
||||
Test(Genode::Env &env,
|
||||
Genode::Heap &heap,
|
||||
Genode::size_t bulk_buffer_size,
|
||||
Genode::uint64_t timeout_ms)
|
||||
: _ep(env.ep()),
|
||||
_alloc(&heap),
|
||||
_session(env, &_alloc, _shared_buffer_size(bulk_buffer_size)),
|
||||
_disp_ack(env.ep(), *this, &Test::_ack_avail),
|
||||
_disp_submit(env.ep(), *this, &Test::_ready_to_submit),
|
||||
_disp_timeout(env.ep(), *this, &Test::_timeout),
|
||||
_timer(env)
|
||||
{
|
||||
_session.tx_channel()->sigh_ack_avail(_disp_ack);
|
||||
_session.tx_channel()->sigh_ready_to_submit(_disp_submit);
|
||||
|
||||
if (timeout_ms) {
|
||||
_timer.sigh(_disp_timeout);
|
||||
_timer.trigger_once(1000*timeout_ms);
|
||||
}
|
||||
}
|
||||
|
||||
void _handle_signal()
|
||||
{
|
||||
_handle = true;
|
||||
while (_handle) _ep.wait_and_dispatch_one_io_signal();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <unsigned BULK_BLK_NR, unsigned NR_PER_REQ>
|
||||
struct Read_test : Test
|
||||
{
|
||||
bool done;
|
||||
|
||||
Read_test(Genode::Env &env, Genode::Heap &heap, Genode::uint64_t timeo_ms)
|
||||
: Test(env, heap, BULK_BLK_NR*blk_sz, timeo_ms), done(false) { }
|
||||
|
||||
void perform() override
|
||||
{
|
||||
Genode::log("reading block 0 - ", test_cnt - 1, ", ", NR_PER_REQ,
|
||||
" per request");
|
||||
|
||||
for (Block::sector_t nr = 0, cnt = NR_PER_REQ; nr < test_cnt;
|
||||
nr += cnt) {
|
||||
|
||||
while (!_session.tx()->ready_to_submit())
|
||||
_handle_signal();
|
||||
|
||||
cnt = Genode::min<Block::sector_t>(NR_PER_REQ, test_cnt-nr);
|
||||
|
||||
try {
|
||||
Block::Packet_descriptor p(
|
||||
_session.alloc_packet(cnt*blk_sz),
|
||||
Block::Packet_descriptor::READ, nr, cnt);
|
||||
_session.tx()->submit_packet(p);
|
||||
} catch(Block::Session::Tx::Source::Packet_alloc_failed) {
|
||||
cnt = 0; /* retry the current block number */
|
||||
_handle_signal();
|
||||
}
|
||||
}
|
||||
|
||||
while (!done)
|
||||
_handle_signal();
|
||||
}
|
||||
|
||||
void ack_avail() override
|
||||
{
|
||||
_handle = false;
|
||||
|
||||
while (_session.tx()->ack_avail()) {
|
||||
Block::Packet_descriptor p = _session.tx()->get_acked_packet();
|
||||
|
||||
if (!p.succeeded())
|
||||
throw Block_exception(p.block_number(), p.block_count(),
|
||||
false);
|
||||
|
||||
if ((p.block_number() + p.block_count()) == test_cnt)
|
||||
done = true;
|
||||
|
||||
_session.tx()->release_packet(p);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <unsigned BULK_BLK_NR, unsigned NR_PER_REQ, unsigned BATCH>
|
||||
struct Write_test : Test
|
||||
{
|
||||
struct Invalid_dimensions : Exception {
|
||||
void print_error() override {
|
||||
Genode::error("invalid bulk buffer, or batch size!"); } };
|
||||
|
||||
struct Integrity_exception : Block_exception
|
||||
{
|
||||
Integrity_exception(Block::sector_t nr, Genode::size_t cnt)
|
||||
: Block_exception(nr, cnt, false) {}
|
||||
|
||||
void print_error() override
|
||||
{
|
||||
Genode::error("integrity check failed: block ", _nr, " - ",
|
||||
_nr+_cnt);
|
||||
}
|
||||
};
|
||||
|
||||
typedef Genode::Ring_buffer<Block::Packet_descriptor, BATCH+1,
|
||||
Genode::Ring_buffer_unsynchronized> Req_buffer;
|
||||
|
||||
Req_buffer read_packets { };
|
||||
Req_buffer write_packets { };
|
||||
|
||||
Write_test(Genode::Env &env, Genode::Heap &heap, Genode::uint64_t timeo_ms)
|
||||
: Test(env, heap, BULK_BLK_NR*blk_sz, timeo_ms)
|
||||
{
|
||||
if (BULK_BLK_NR < BATCH*NR_PER_REQ ||
|
||||
BATCH > Block::Session::TX_QUEUE_SIZE ||
|
||||
BULK_BLK_NR % BATCH != 0)
|
||||
throw Invalid_dimensions();
|
||||
}
|
||||
|
||||
bool compare(Block::Packet_descriptor &r, Block::Packet_descriptor &w)
|
||||
{
|
||||
signed char *dst = (signed char*)_session.tx()->packet_content(w),
|
||||
*src = (signed char*)_session.tx()->packet_content(r);
|
||||
for (Genode::size_t i = 0; i < blk_sz; i++)
|
||||
if (dst[i] != src[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void compare()
|
||||
{
|
||||
while (!read_packets.empty()) {
|
||||
Block::Packet_descriptor r = read_packets.get();
|
||||
while (true) {
|
||||
Block::Packet_descriptor w = write_packets.get();
|
||||
if (r.block_number() == w.block_number()) {
|
||||
if (!compare(r,w))
|
||||
throw Integrity_exception(r.block_number(),
|
||||
r.block_count());
|
||||
|
||||
_session.tx()->release_packet(w);
|
||||
break;
|
||||
}
|
||||
write_packets.add(w);
|
||||
}
|
||||
_session.tx()->release_packet(r);
|
||||
}
|
||||
}
|
||||
|
||||
void write(signed char val)
|
||||
{
|
||||
while (!read_packets.empty()) {
|
||||
Block::Packet_descriptor r = read_packets.get();
|
||||
Block::Packet_descriptor w(_session.alloc_packet(r.block_count()*blk_sz),
|
||||
Block::Packet_descriptor::WRITE,
|
||||
r.block_number(), r.block_count());
|
||||
signed char *dst = (signed char*)_session.tx()->packet_content(w),
|
||||
*src = (signed char*)_session.tx()->packet_content(r);
|
||||
for (Genode::size_t i = 0; i < blk_sz; i++)
|
||||
dst[i] = src[i] + val;
|
||||
_session.tx()->submit_packet(w);
|
||||
_session.tx()->release_packet(r);
|
||||
}
|
||||
while (write_packets.avail_capacity())
|
||||
_handle_signal();
|
||||
}
|
||||
|
||||
void read(Block::sector_t start, Block::sector_t end)
|
||||
{
|
||||
using namespace Block;
|
||||
|
||||
for (sector_t nr = start, cnt = Genode::min(NR_PER_REQ, end - start); nr < end;
|
||||
nr += cnt,
|
||||
cnt = Genode::min<sector_t>(NR_PER_REQ, end-nr)) {
|
||||
Block::Packet_descriptor p(_session.alloc_packet(cnt*blk_sz),
|
||||
Block::Packet_descriptor::READ, nr, cnt);
|
||||
_session.tx()->submit_packet(p);
|
||||
}
|
||||
while (read_packets.avail_capacity())
|
||||
_handle_signal();
|
||||
}
|
||||
|
||||
void batch(Block::sector_t start, Block::sector_t end, signed char val)
|
||||
{
|
||||
read(start, end);
|
||||
write(val);
|
||||
read(start, end);
|
||||
compare();
|
||||
}
|
||||
|
||||
void perform() override
|
||||
{
|
||||
if (!writeable)
|
||||
return;
|
||||
|
||||
Genode::log("read/write/compare block 0 - ", test_cnt - 1,
|
||||
", ", NR_PER_REQ, " per request");
|
||||
|
||||
for (Block::sector_t nr = 0, cnt = BATCH*NR_PER_REQ; nr < test_cnt;
|
||||
nr += cnt,
|
||||
cnt = Genode::min<Block::sector_t>(BATCH*NR_PER_REQ, test_cnt-nr)) {
|
||||
batch(nr, nr + cnt, 1);
|
||||
batch(nr, nr + cnt, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void ack_avail() override
|
||||
{
|
||||
_handle = false;
|
||||
|
||||
while (_session.tx()->ack_avail()) {
|
||||
Block::Packet_descriptor p = _session.tx()->get_acked_packet();
|
||||
bool write = p.operation() == Block::Packet_descriptor::WRITE;
|
||||
if (!p.succeeded())
|
||||
throw Block_exception(p.block_number(), p.block_count(), write);
|
||||
if (write)
|
||||
write_packets.add(p);
|
||||
else
|
||||
read_packets.add(p);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Violation_test : Test
|
||||
{
|
||||
struct Write_on_read_only : Exception {
|
||||
void print_error() override {
|
||||
Genode::error("write on read-only device succeeded!"); } };
|
||||
|
||||
struct Range_check_failed : Block_exception
|
||||
{
|
||||
Range_check_failed(Block::sector_t nr, Genode::size_t cnt)
|
||||
: Block_exception(nr, cnt, false) {}
|
||||
|
||||
void print_error() override
|
||||
{
|
||||
Genode::error("range check failed: access to block ", _nr,
|
||||
" - ", _nr+_cnt, " succeeded");
|
||||
}
|
||||
};
|
||||
|
||||
int p_in_fly;
|
||||
|
||||
Violation_test(Genode::Env &env, Genode::Heap &heap, Genode::uint64_t timeo)
|
||||
: Test(env, heap, 20*blk_sz, timeo), p_in_fly(0) {}
|
||||
|
||||
void req(Block::sector_t nr, Genode::size_t cnt, bool write)
|
||||
{
|
||||
Block::Packet_descriptor p(_session.alloc_packet(blk_sz),
|
||||
write ? Block::Packet_descriptor::WRITE
|
||||
: Block::Packet_descriptor::READ,
|
||||
nr, cnt);
|
||||
_session.tx()->submit_packet(p);
|
||||
p_in_fly++;
|
||||
}
|
||||
|
||||
void perform() override
|
||||
{
|
||||
if (!writeable)
|
||||
req(0, 1, true);
|
||||
|
||||
req(blk_cnt, 1, false);
|
||||
req(blk_cnt-1, 2, false);
|
||||
|
||||
while (p_in_fly > 0)
|
||||
_handle_signal();
|
||||
}
|
||||
|
||||
void ack_avail() override
|
||||
{
|
||||
_handle = false;
|
||||
|
||||
while (_session.tx()->ack_avail()) {
|
||||
Block::Packet_descriptor p = _session.tx()->get_acked_packet();
|
||||
if (p.succeeded()) {
|
||||
if (p.operation() == Block::Packet_descriptor::WRITE)
|
||||
throw Write_on_read_only();
|
||||
throw Range_check_failed(p.block_number(), p.block_count());
|
||||
}
|
||||
_session.tx()->release_packet(p);
|
||||
p_in_fly--;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename TEST>
|
||||
void perform(Genode::Env &env, Genode::Heap &heap, unsigned timeo_ms = 0)
|
||||
{
|
||||
TEST * test = new (&heap) TEST(env, heap, timeo_ms);
|
||||
test->perform();
|
||||
destroy(&heap, test);
|
||||
}
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
try {
|
||||
|
||||
static Heap heap(env.ram(), env.rm());
|
||||
|
||||
/**
|
||||
* First we ask for the block size of the driver to dimension
|
||||
* the queue size for our tests. Moreover, we implicitely test,
|
||||
* whether closing and opening again works for the driver
|
||||
*/
|
||||
{
|
||||
Allocator_avl alloc(&heap);
|
||||
Block::Connection<> blk(env, &alloc);
|
||||
|
||||
Block::Session::Info const info { blk.info() };
|
||||
|
||||
blk_sz = info.block_size;
|
||||
blk_cnt = info.block_count;
|
||||
writeable = info.writeable;
|
||||
}
|
||||
|
||||
try {
|
||||
Genode::Number_of_bytes test_size;;
|
||||
Genode::Attached_rom_dataspace config { env, "config" };
|
||||
config.xml().attribute("test_size").value(test_size);
|
||||
test_cnt = Genode::min(test_size / blk_sz, blk_cnt);
|
||||
} catch (...) { test_cnt = blk_cnt; }
|
||||
|
||||
/* must be multiple of 16 */
|
||||
test_cnt &= ~0xfLLU;
|
||||
|
||||
log("block device with block size ", blk_sz, " sector count ",
|
||||
blk_cnt, " (testing ", test_cnt, " sectors)");
|
||||
|
||||
perform<Read_test<Block::Session::TX_QUEUE_SIZE-10,
|
||||
Block::Session::TX_QUEUE_SIZE-10> >(env, heap);
|
||||
perform<Read_test<Block::Session::TX_QUEUE_SIZE*5, 1> >(env, heap);
|
||||
perform<Read_test<Block::Session::TX_QUEUE_SIZE, 1> >(env, heap);
|
||||
perform<Write_test<Block::Session::TX_QUEUE_SIZE, 8, 16> >(env, heap);
|
||||
perform<Violation_test>(env, heap, 1000);
|
||||
|
||||
log("--- all tests finished ---");
|
||||
}
|
||||
catch (Genode::Service_denied) {
|
||||
error("opening block session was denied!");
|
||||
}
|
||||
catch (Test::Exception &e) {
|
||||
error("test failed!");
|
||||
e.print_error();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
TARGET = test-block-client
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
||||
|
||||
CC_CXX_WARN_STRICT_CONVERSION =
|
@ -1,155 +0,0 @@
|
||||
/*
|
||||
* \brief Test block session interface - server side
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2013-12-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-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 <base/attached_rom_dataspace.h>
|
||||
#include <block/component.h>
|
||||
#include <block/driver.h>
|
||||
#include <os/ring_buffer.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
|
||||
class Driver : public Block::Driver
|
||||
{
|
||||
private:
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Driver(Driver const &);
|
||||
Driver &operator = (Driver const &);
|
||||
|
||||
enum { MAX_REQUESTS = 5 };
|
||||
|
||||
typedef Genode::Ring_buffer<Block::Packet_descriptor, MAX_REQUESTS,
|
||||
Genode::Ring_buffer_unsynchronized> Req_buffer;
|
||||
|
||||
Genode::size_t _number;
|
||||
Genode::size_t _size;
|
||||
Req_buffer _packets { };
|
||||
Genode::Ram_dataspace_capability _blk_ds;
|
||||
unsigned char *_blk_buf;
|
||||
|
||||
public:
|
||||
|
||||
Driver(Genode::Env &env, Genode::size_t number, Genode::size_t size)
|
||||
: Block::Driver(env.ram()),
|
||||
_number(number), _size(size),
|
||||
_blk_ds(env.ram().alloc(number*size)),
|
||||
_blk_buf(env.rm().attach(_blk_ds)) {}
|
||||
|
||||
void handler()
|
||||
{
|
||||
while (!_packets.empty()) {
|
||||
Block::Packet_descriptor p = _packets.get();
|
||||
ack_packet(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************
|
||||
** Block::Driver interface **
|
||||
*******************************/
|
||||
|
||||
void session_invalidated() override {
|
||||
while (!_packets.empty()) _packets.get(); }
|
||||
|
||||
Block::Session::Info info() const override
|
||||
{
|
||||
return { .block_size = _size,
|
||||
.block_count = _number,
|
||||
.align_log2 = Genode::log2(_size),
|
||||
.writeable = true };
|
||||
}
|
||||
|
||||
void read(Block::sector_t block_number,
|
||||
Genode::size_t block_count,
|
||||
char *buffer,
|
||||
Block::Packet_descriptor &packet) override
|
||||
{
|
||||
if (!_packets.avail_capacity())
|
||||
throw Block::Driver::Request_congestion();
|
||||
|
||||
Genode::memcpy((void*)buffer, &_blk_buf[block_number*_size],
|
||||
block_count * _size);
|
||||
_packets.add(packet);
|
||||
}
|
||||
|
||||
void write(Block::sector_t block_number,
|
||||
Genode::size_t block_count,
|
||||
const char *buffer,
|
||||
Block::Packet_descriptor &packet) override
|
||||
{
|
||||
if (!_packets.avail_capacity())
|
||||
throw Block::Driver::Request_congestion();
|
||||
Genode::memcpy(&_blk_buf[block_number*_size],
|
||||
(void*)buffer, block_count * _size);
|
||||
_packets.add(packet);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Main
|
||||
{
|
||||
Genode::Env &env;
|
||||
Genode::Heap heap { env.ram(), env.rm() };
|
||||
|
||||
class Factory : public Block::Driver_factory
|
||||
{
|
||||
private:
|
||||
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
Factory(Factory const &);
|
||||
Factory &operator = (Factory const &);
|
||||
|
||||
public:
|
||||
|
||||
::Driver *driver = nullptr;
|
||||
|
||||
Factory(Genode::Env &env, Genode::Heap &heap)
|
||||
{
|
||||
Genode::size_t blk_nr = 1024;
|
||||
Genode::size_t blk_sz = 512;
|
||||
|
||||
try {
|
||||
Genode::Attached_rom_dataspace config { env, "config" };
|
||||
config.xml().attribute("sectors").value(blk_nr);
|
||||
config.xml().attribute("block_size").value(blk_sz);
|
||||
}
|
||||
catch (...) { }
|
||||
|
||||
driver = new (&heap) Driver(env, blk_nr, blk_sz);
|
||||
}
|
||||
|
||||
Block::Driver *create() override { return driver; }
|
||||
|
||||
void destroy(Block::Driver *) override { }
|
||||
|
||||
} factory { env, heap };
|
||||
|
||||
Block::Root root { env.ep(), heap, env.rm(), factory, true };
|
||||
Timer::Connection timer { env };
|
||||
Genode::Signal_handler<Driver> dispatcher { env.ep(), *factory.driver,
|
||||
&Driver::handler };
|
||||
|
||||
Main(Genode::Env &env) : env(env)
|
||||
{
|
||||
timer.sigh(dispatcher);
|
||||
timer.trigger_periodic(10000);
|
||||
env.parent().announce(env.ep().manage(root));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Main server(env); }
|
@ -1,5 +0,0 @@
|
||||
TARGET = test-block-server
|
||||
SRC_CC = main.cc
|
||||
LIBS = base
|
||||
|
||||
CC_CXX_WARN_STRICT_CONVERSION =
|
Loading…
Reference in New Issue
Block a user