mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-27 17:18:53 +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
|
||||||
test-spark_exception
|
test-spark_exception
|
||||||
test-spark_secondary_stack
|
test-spark_secondary_stack
|
||||||
test-block
|
|
||||||
test-clipboard
|
test-clipboard
|
||||||
test-depot_query_index
|
test-depot_query_index
|
||||||
test-ds_ownership
|
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