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:
Norman Feske 2022-02-04 13:45:58 +01:00
parent 378e2d9e74
commit 26d9bac78f
15 changed files with 0 additions and 911 deletions

View File

@ -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

View File

@ -1 +0,0 @@
Block session tests

View File

@ -1,2 +0,0 @@
_/src/init
_/src/test-block

View File

@ -1 +0,0 @@
2022-01-18 577ca2da21d29b23a8fd4f5ba9c7512371cc7fdb

View File

@ -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>

View File

@ -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)

View File

@ -1 +0,0 @@
2022-01-18 ca54d93526f633ba06da899f089ffebef3ec168a

View File

@ -1,4 +0,0 @@
base
os
block_session
timer_session

View File

@ -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

View File

@ -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); }

View File

@ -1,3 +0,0 @@
TARGET = test-block-bench
SRC_CC = main.cc
LIBS = base

View File

@ -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();
}
}

View File

@ -1,5 +0,0 @@
TARGET = test-block-client
SRC_CC = main.cc
LIBS = base
CC_CXX_WARN_STRICT_CONVERSION =

View File

@ -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); }

View File

@ -1,5 +0,0 @@
TARGET = test-block-server
SRC_CC = main.cc
LIBS = base
CC_CXX_WARN_STRICT_CONVERSION =