part_blk: transition to the new base API

Ref #1987
Ref #2051
This commit is contained in:
Stefan Kalkowski 2016-08-03 10:35:32 +02:00 committed by Christian Helmuth
parent d4879f04a6
commit ef7c51548d
6 changed files with 192 additions and 197 deletions

View File

@ -14,8 +14,9 @@
#ifndef _PART_BLK__COMPONENT_H_
#define _PART_BLK__COMPONENT_H_
#include <os/session_policy.h>
#include <base/exception.h>
#include <base/component.h>
#include <os/session_policy.h>
#include <root/component.h>
#include <block_session/rpc_object.h>
@ -39,12 +40,13 @@ class Block::Session_component : public Block::Session_rpc_object,
Ram_dataspace_capability _rq_ds;
addr_t _rq_phys;
Partition *_partition;
Signal_dispatcher<Session_component> _sink_ack;
Signal_dispatcher<Session_component> _sink_submit;
Signal_handler<Session_component> _sink_ack;
Signal_handler<Session_component> _sink_submit;
bool _req_queue_full;
bool _ack_queue_full;
Packet_descriptor _p_to_handle;
unsigned _p_in_fly;
Block::Driver &_driver;
/**
* Acknowledge a packet already handled
@ -52,7 +54,7 @@ class Block::Session_component : public Block::Session_rpc_object,
inline void _ack_packet(Packet_descriptor &packet)
{
if (!tx_sink()->ready_to_ack())
PERR("Not ready to ack!");
error("Not ready to ack!");
tx_sink()->acknowledge_packet(packet);
_p_in_fly--;
@ -83,7 +85,7 @@ class Block::Session_component : public Block::Session_rpc_object,
size_t cnt = _p_to_handle.block_count();
void* addr = tx_sink()->packet_content(_p_to_handle);
try {
Driver::driver().io(write, off, cnt, addr, *this, _p_to_handle);
_driver.io(write, off, cnt, addr, *this, _p_to_handle);
} catch (Block::Session::Tx::Source::Packet_alloc_failed) {
_req_queue_full = true;
Session_component::wait_queue().insert(this);
@ -93,7 +95,7 @@ class Block::Session_component : public Block::Session_rpc_object,
/**
* Triggered when a packet was placed into the empty submit queue
*/
void _packet_avail(unsigned)
void _packet_avail()
{
_ack_queue_full = _p_in_fly >= tx_sink()->ack_slots_free();
@ -111,7 +113,7 @@ class Block::Session_component : public Block::Session_rpc_object,
/**
* Triggered when an ack got removed from the full ack queue
*/
void _ready_to_ack(unsigned) { _packet_avail(0); }
void _ready_to_ack() { _packet_avail(); }
public:
@ -120,17 +122,18 @@ class Block::Session_component : public Block::Session_rpc_object,
*/
Session_component(Ram_dataspace_capability rq_ds,
Partition *partition,
Rpc_entrypoint &ep,
Signal_receiver &receiver)
: Session_rpc_object(rq_ds, ep),
Genode::Entrypoint &ep,
Block::Driver &driver)
: Session_rpc_object(rq_ds, ep.rpc_ep()),
_rq_ds(rq_ds),
_rq_phys(Dataspace_client(_rq_ds).phys_addr()),
_partition(partition),
_sink_ack(receiver, *this, &Session_component::_ready_to_ack),
_sink_submit(receiver, *this, &Session_component::_packet_avail),
_sink_ack(ep, *this, &Session_component::_ready_to_ack),
_sink_submit(ep, *this, &Session_component::_packet_avail),
_req_queue_full(false),
_ack_queue_full(false),
_p_in_fly(0)
_p_in_fly(0),
_driver(driver)
{
_tx.sigh_ready_to_ack(_sink_ack);
_tx.sigh_packet_avail(_sink_submit);
@ -142,16 +145,16 @@ class Block::Session_component : public Block::Session_rpc_object,
{
if (request.operation() == Block::Packet_descriptor::READ) {
void *src =
Driver::driver().session().tx()->packet_content(reply);
_driver.session().tx()->packet_content(reply);
Genode::size_t sz =
request.block_count() * Driver::driver().blk_size();
request.block_count() * _driver.blk_size();
Genode::memcpy(tx_sink()->packet_content(request), src, sz);
}
request.succeeded(reply.succeeded());
_ack_packet(request);
if (_ack_queue_full)
_packet_avail(0);
_packet_avail();
}
static List<Session_component>& wait_queue()
@ -167,7 +170,7 @@ class Block::Session_component : public Block::Session_rpc_object,
wait_queue().remove(c);
c->_req_queue_full = false;
c->_handle_packet(c->_p_to_handle);
c->_packet_avail(0);
c->_packet_avail();
}
}
@ -179,11 +182,11 @@ class Block::Session_component : public Block::Session_rpc_object,
Operations *ops)
{
*blk_count = _partition->sectors;
*blk_size = Driver::driver().blk_size();
*ops = Driver::driver().ops();
*blk_size = _driver.blk_size();
*ops = _driver.ops();
}
void sync() { Driver::driver().session().sync(); }
void sync() { _driver.session().sync(); }
};
@ -195,8 +198,8 @@ class Block::Root :
{
private:
Rpc_entrypoint &_ep;
Signal_receiver &_receiver;
Genode::Env &_env;
Block::Driver &_driver;
Block::Partition_table &_table;
protected:
@ -217,15 +220,17 @@ class Block::Root :
policy.attribute("partition").value(&num);
} catch (Xml_node::Nonexistent_attribute) {
PERR("policy does not define partition number for for '%s'", label_str);
error("policy does not define partition number for for '",
label_str, "'");
throw Root::Unavailable();
} catch (Session_policy::No_policy_defined) {
PERR("rejecting session request, no matching policy for '%s'", label_str);
error("rejecting session request, no matching policy for '",
label_str, "'");
throw Root::Unavailable();
}
if (!_table.partition(num)) {
PERR("Partition %ld unavailable for '%s'", num, label_str);
error("Partition ", num, " unavailable for '", label_str, "'");
throw Root::Unavailable();
}
@ -250,32 +255,27 @@ class Block::Root :
* to handle a possible overflow of the sum of both sizes.
*/
if (tx_buf_size > ram_quota - session_size) {
PERR("insufficient 'ram_quota', got %zd, need %zd",
ram_quota, tx_buf_size + session_size);
error("insufficient 'ram_quota', got ", ram_quota, ", need ",
tx_buf_size + session_size);
throw Root::Quota_exceeded();
}
Ram_dataspace_capability ds_cap;
ds_cap = Genode::env()->ram_session()->alloc(tx_buf_size);
ds_cap = _env.ram().alloc(tx_buf_size);
Session_component *session = new (md_alloc())
Session_component(ds_cap,
_table.partition(num),
_ep, _receiver);
Session_component(ds_cap, _table.partition(num),
_env.ep(), _driver);
PLOG("session opened at partition %ld for '%s'", num, label_str);
log("session opened at partition ", num, " for '", label_str, "'");
return session;
}
public:
Root(Rpc_entrypoint *session_ep, Allocator *md_alloc,
Signal_receiver &receiver, Block::Partition_table& table)
:
Root_component(session_ep, md_alloc),
_ep(*session_ep),
_receiver(receiver),
_table(table)
{ }
Root(Genode::Env &env, Genode::Heap &heap,
Block::Driver &driver, Block::Partition_table &table)
: Root_component(env.ep(), heap), _env(env),
_driver(driver), _table(table) { }
};
#endif /* _PART_BLK__COMPONENT_H_ */

View File

@ -81,13 +81,13 @@ class Block::Driver
Block::Connection _session;
Block::sector_t _blk_cnt;
Genode::size_t _blk_size;
Genode::Signal_dispatcher<Driver> _source_ack;
Genode::Signal_dispatcher<Driver> _source_submit;
Genode::Signal_handler<Driver> _source_ack;
Genode::Signal_handler<Driver> _source_submit;
Block::Session::Operations _ops;
void _ready_to_submit(unsigned);
void _ready_to_submit();
void _ack_avail(unsigned)
void _ack_avail()
{
/* check for acknowledgements */
while (_session.tx()->ack_avail()) {
@ -102,17 +102,17 @@ class Block::Driver
_session.tx()->release_packet(p);
}
_ready_to_submit(0);
_ready_to_submit();
}
public:
Driver(Genode::Signal_receiver &receiver)
: _r_slab(Genode::env()->heap()),
_block_alloc(Genode::env()->heap()),
Driver(Genode::Entrypoint &ep, Genode::Heap &heap)
: _r_slab(&heap),
_block_alloc(&heap),
_session(&_block_alloc, 4 * 1024 * 1024),
_source_ack(receiver, *this, &Driver::_ack_avail),
_source_submit(receiver, *this, &Driver::_ready_to_submit)
_source_ack(ep, *this, &Driver::_ack_avail),
_source_submit(ep, *this, &Driver::_ready_to_submit)
{
_session.info(&_blk_cnt, &_blk_size, &_ops);
}

View File

@ -15,7 +15,7 @@
#define _PART_BLK__GPT_H_
#include <base/env.h>
#include <base/printf.h>
#include <base/log.h>
#include <block_session/client.h>
#include "driver.h"
@ -24,7 +24,6 @@
namespace {
static bool const verbose = false;
#define PLOGV(...) do { if (verbose) PLOG(__VA_ARGS__); } while (0)
/* simple bitwise CRC32 checking */
static inline Genode::uint32_t crc32(void const * const buf, Genode::size_t size)
@ -110,23 +109,27 @@ class Gpt : public Block::Partition_table
void dump_hdr(bool check_primary)
{
PLOGV("GPT %s header:", check_primary ? "primary" : "backup");
PLOGV(" rev: %u", _revision);
PLOGV(" size: %u", _hdr_size);
PLOGV(" crc: %x", _hdr_crc);
PLOGV(" reserved: %u", _reserved);
PLOGV(" hdr lba: %llu", _hdr_lba);
PLOGV(" bak lba: %llu", _backup_hdr_lba);
PLOGV(" part start lba: %llu", _part_lba_start);
PLOGV(" part end lba: %llu", _part_lba_end);
PLOGV(" guid: %s", _guid.to_string());
PLOGV(" gpe lba: %llu", _gpe_lba);
PLOGV(" entries: %u", _entries);
PLOGV(" entry size: %u", _entry_size);
PLOGV(" gpe crc: %x", _gpe_crc);
if (!verbose) return;
using namespace Genode;
log("GPT ", check_primary ? "primary" : "backup", " header:");
log(" rev: ", (unsigned) _revision);
log(" size: ", (unsigned) _hdr_size);
log(" crc: ", Hex(_hdr_crc, Hex::OMIT_PREFIX));
log(" reserved: ", (unsigned) _reserved);
log(" hdr lba: ", (unsigned long long) _hdr_lba);
log(" bak lba: ", (unsigned long long) _backup_hdr_lba);
log(" part start lba: ", (unsigned long long) _part_lba_start);
log(" part end lba: ", (unsigned long long) _part_lba_end);
log(" guid: ", _guid.to_string());
log(" gpe lba: ", (unsigned long long) _gpe_lba);
log(" entries: ", (unsigned) _entries);
log(" entry size: ", (unsigned) _entry_size);
log(" gpe crc: ", Hex(_gpe_crc, Hex::OMIT_PREFIX));
}
bool valid(bool check_primary = true)
bool valid(Block::Driver &driver, bool check_primary = true)
{
dump_hdr(check_primary);
@ -138,7 +141,7 @@ class Gpt : public Block::Partition_table
Genode::uint32_t crc = _hdr_crc;
_hdr_crc = 0;
if (crc32(this, _hdr_size) != crc) {
PERR("Wrong GPT header checksum");
Genode::error("Wrong GPT header checksum");
return false;
}
@ -149,15 +152,15 @@ class Gpt : public Block::Partition_table
/* check GPT entry array */
Genode::size_t length = _entries * _entry_size;
Sector gpe(_gpe_lba, length / Block::Driver::driver().blk_size());
Sector gpe(driver, _gpe_lba, length / driver.blk_size());
if (crc32(gpe.addr<void *>(), length) != _gpe_crc)
return false;
if (check_primary) {
/* check backup gpt header */
Sector backup_hdr(_backup_hdr_lba, 1);
if (!backup_hdr.addr<Gpt_hdr*>()->valid(false)) {
PWRN("Backup GPT header is corrupted");
Sector backup_hdr(driver, _backup_hdr_lba, 1);
if (!backup_hdr.addr<Gpt_hdr*>()->valid(driver, false)) {
Genode::warning("Backup GPT header is corrupted");
}
}
@ -226,11 +229,11 @@ class Gpt : public Block::Partition_table
*/
void _parse_gpt(Gpt_hdr *gpt)
{
if (!(gpt->valid()))
if (!(gpt->valid(driver)))
throw Genode::Exception();
Sector entry_array(gpt->_gpe_lba,
gpt->_entries * gpt->_entry_size / Block::Driver::driver().blk_size());
Sector entry_array(driver, gpt->_gpe_lba,
gpt->_entries * gpt->_entry_size / driver.blk_size());
Gpt_entry *entries = entry_array.addr<Gpt_entry *>();
for (int i = 0; i < MAX_PARTITIONS; i++) {
@ -242,43 +245,31 @@ class Gpt : public Block::Partition_table
Genode::uint64_t start = e->_lba_start;
Genode::uint64_t length = e->_lba_end - e->_lba_start + 1; /* [...) */
_part_list[i] = new (Genode::env()->heap()) Block::Partition(start, length);
_part_list[i] = new (&heap) Block::Partition(start, length);
PINF("Partition %d: LBA %llu (%llu blocks) type: '%s' name: '%s'",
i + 1, start, length, e->_type.to_string(), e->name());
Genode::log("Partition ", i + 1, ": LBA ", start, " (", length,
" blocks) type: '", e->_type.to_string(),
"' name: '", e->name(), "'");
}
}
Gpt()
{
Sector s(Gpt_hdr::HEADER_LBA, 1);
_parse_gpt(s.addr<Gpt_hdr *>());
/*
* we read all partition information,
* now it's safe to turn in asynchronous mode
*/
Block::Driver::driver().work_asynchronously();
}
public:
using Partition_table::Partition_table;
Block::Partition *partition(int num) {
return (num <= MAX_PARTITIONS && num > 0) ? _part_list[num-1] : 0; }
bool avail()
bool parse()
{
Sector s(driver, Gpt_hdr::HEADER_LBA, 1);
_parse_gpt(s.addr<Gpt_hdr *>());
for (unsigned num = 0; num < MAX_PARTITIONS; num++)
if (_part_list[num])
return true;
return false;
}
static Gpt& table()
{
static Gpt table;
return table;
}
};
#endif /* _PART_BLK__GUID_PARTITION_TABLE_H_ */

View File

@ -7,84 +7,92 @@
*/
/*
* Copyright (C) 2011-2014 Genode Labs GmbH
* Copyright (C) 2011-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 <os/attached_rom_dataspace.h>
#include <block_session/rpc_object.h>
#include <cap_session/connection.h>
#include <os/config.h>
#include "component.h"
#include "driver.h"
#include "gpt.h"
#include "mbr.h"
static Genode::Signal_receiver receiver;
Block::Driver& Block::Driver::driver()
{
static Block::Driver driver(receiver);
return driver;
}
void Block::Driver::_ready_to_submit(unsigned) {
void Block::Driver::_ready_to_submit() {
Block::Session_component::wake_up(); }
static bool _use_gpt()
class Main
{
return Genode::config()->xml_node().attribute_value("use_gpt", false);
private:
Block::Partition_table & _table();
Genode::Env & _env;
Genode::Heap _heap { _env.ram(), _env.rm() };
Block::Driver _driver { _env.ep(), _heap };
Mbr_partition_table _mbr { _heap, _driver };
Gpt _gpt { _heap, _driver };
Block::Root _root { _env, _heap, _driver, _table() };
public:
class No_partion_table : Genode::Exception {};
Main(Genode::Env &env) : _env(env)
{
/*
* we read all partition information,
* now it's safe to turn in asynchronous mode
*/
_driver.work_asynchronously();
/* announce at parent */
env.parent().announce(env.ep().manage(_root));
}
};
int main()
Block::Partition_table & Main::_table()
{
using namespace Genode;
bool valid_mbr = false;
bool valid_gpt = false;
bool use_gpt = _use_gpt();
bool use_gpt = false;
try {
Genode::Attached_rom_dataspace config(_env, "config");
use_gpt = config.xml().attribute_value("use_gpt", false);
} catch(...) {}
if (use_gpt)
try { valid_gpt = Gpt::table().avail(); } catch (...) { }
try { valid_gpt = _gpt.parse(); } catch (...) { }
/* fall back to MBR */
if (!valid_gpt) {
try { valid_mbr = Mbr_partition_table::table().avail(); }
try { valid_mbr = _mbr.parse(); }
catch (Mbr_partition_table::Protective_mbr_found) {
if (!use_gpt)
PERR("Aborting: found protective MBR but GPT usage was not requested.");
return 1;
Genode::error("Aborting: found protective MBR but ",
"GPT usage was not requested.");
throw;
}
}
Block::Partition_table *partition_table = 0;
if (valid_gpt)
partition_table = &Gpt::table();
if (valid_mbr)
partition_table = &Mbr_partition_table::table();
if (valid_gpt) return _gpt;
if (valid_mbr) return _mbr;
if (!partition_table) {
PERR("Aborting: no partition table found.");
return 1;
Genode::error("Aborting: no partition table found.");
throw No_partion_table();
}
enum { STACK_SIZE = 2048 * sizeof(Genode::size_t) };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "part_ep");
static Block::Root block_root(&ep, env()->heap(), receiver,
*partition_table);
env()->parent()->announce(ep.manage(&block_root));
Genode::size_t Component::stack_size() {
return 2048*sizeof(Genode::addr_t); }
while (true) {
Signal s = receiver.wait_for_signal();
static_cast<Signal_dispatcher_base *>(s.context())->dispatch(s.num());
}
return 0;
}
void Component::construct(Genode::Env &env) {
static Main main(env); }

View File

@ -17,10 +17,9 @@
#define _PART_BLK__MBR_H_
#include <base/env.h>
#include <base/printf.h>
#include <base/log.h>
#include <block_session/client.h>
#include "driver.h"
#include "partition_table.h"
@ -83,7 +82,7 @@ struct Mbr_partition_table : public Block::Partition_table
/* first logical partition number */
int nr = 5;
do {
Sector s(lba, 1);
Sector s(driver, lba, 1);
Mbr *ebr = s.addr<Mbr *>();
if (!(ebr->valid()))
@ -93,11 +92,12 @@ struct Mbr_partition_table : public Block::Partition_table
* partition is relative to the lba of the current EBR */
Partition_record *logical = &(ebr->_records[0]);
if (logical->valid() && nr < MAX_PARTITIONS) {
_part_list[nr++] = new (Genode::env()->heap())
_part_list[nr++] = new (&heap)
Block::Partition(logical->_lba + lba, logical->_sectors);
PINF("Partition %d: LBA %u (%u blocks) type %x", nr - 1,
logical->_lba + lba, logical->_sectors, logical->_type);
Genode::log("Partition ", nr - 1, ": LBA ", logical->_lba + lba,
" (", (unsigned int)logical->_sectors, " blocks) type ",
Genode::Hex(logical->_type, Genode::Hex::OMIT_PREFIX));
}
/*
@ -114,8 +114,8 @@ struct Mbr_partition_table : public Block::Partition_table
{
/* no partition table, use whole disc as partition 0 */
if (!(mbr->valid()))
_part_list[0] = new(Genode::env()->heap())
Block::Partition(0, Block::Driver::driver().blk_cnt() - 1);
_part_list[0] = new (&heap)
Block::Partition(0, driver.blk_cnt() - 1);
for (int i = 0; i < 4; i++) {
Partition_record *r = &(mbr->_records[i]);
@ -123,8 +123,10 @@ struct Mbr_partition_table : public Block::Partition_table
if (!r->valid())
continue;
PINF("Partition %d: LBA %u (%u blocks) type: %x",
i + 1, r->_lba, r->_sectors, r->_type);
Genode::log("Partition ", i + 1, ": LBA ",
(unsigned int) r->_lba, " (",
(unsigned int) r->_sectors, " blocks) type: ",
Genode::Hex(r->_type, Genode::Hex::OMIT_PREFIX));
if (r->protective())
throw Protective_mbr_found();
@ -134,41 +136,27 @@ struct Mbr_partition_table : public Block::Partition_table
continue;
}
_part_list[i + 1] = new(Genode::env()->heap())
_part_list[i + 1] = new (&heap)
Block::Partition(r->_lba, r->_sectors);
}
}
Mbr_partition_table()
{
Sector s(0, 1);
_parse_mbr(s.addr<Mbr *>());
/*
* we read all partition information,
* now it's safe to turn in asynchronous mode
*/
Block::Driver::driver().work_asynchronously();
}
public:
using Partition_table::Partition_table;
Block::Partition *partition(int num) {
return (num < MAX_PARTITIONS) ? _part_list[num] : 0; }
bool avail()
bool parse()
{
Sector s(driver, 0, 1);
_parse_mbr(s.addr<Mbr *>());
for (unsigned num = 0; num < MAX_PARTITIONS; num++)
if (_part_list[num])
return true;
return false;
}
static Mbr_partition_table& table()
{
static Mbr_partition_table table;
return table;
}
};
#endif /* _PART_BLK__MBR_H_ */

View File

@ -16,7 +16,7 @@
#define _PART_BLK__PARTITION_TABLE_H_
#include <base/env.h>
#include <base/printf.h>
#include <base/log.h>
#include <block_session/client.h>
#include "driver.h"
@ -48,18 +48,20 @@ struct Block::Partition_table
public:
Sector(unsigned long blk_nr,
Sector(Driver &driver,
unsigned long blk_nr,
unsigned long count,
bool write = false)
: _session(Driver::driver().session()),
_p(_session.dma_alloc_packet(Driver::driver().blk_size() * count),
: _session(driver.session()),
_p(_session.dma_alloc_packet(driver.blk_size() * count),
write ? Packet_descriptor::WRITE : Packet_descriptor::READ,
blk_nr, count)
{
_session.tx()->submit_packet(_p);
_p = _session.tx()->get_acked_packet();
if (!_p.succeeded())
PERR("Could not access block %llu", _p.block_number());
Genode::error("Could not access block ",
(unsigned long long)_p.block_number());
}
~Sector() { _session.tx()->release_packet(_p); }
@ -68,9 +70,15 @@ struct Block::Partition_table
return reinterpret_cast<T>(_session.tx()->packet_content(_p)); }
};
Genode::Heap & heap;
Driver & driver;
Partition_table(Genode::Heap & h, Driver & d)
: heap(h), driver(d) {}
virtual Partition *partition(int num) = 0;
virtual bool avail() = 0;
virtual bool parse() = 0;
};
#endif /* _PART_BLK__PARTITION_TABLE_H_ */