mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-21 00:23:16 +00:00
block_session: SYNC and TRIM as async operations
This patch removes the blocking Block::Session::sync RPC function and adds the asynchronous operations SYNC and TRIM to the block session's packet-stream interface. Even though the patch adjusts all block components to the interface change, the components keep the former blocking handling of sync internally for now because of the design of the 'Block::Driver' interface. This old interface is not worth changing. We should instead migrate the block servers step by step to the new 'Block::Request_stream' API. Fixes #3274
This commit is contained in:
committed by
Christian Helmuth
parent
e058adc4fe
commit
593e971121
@ -89,27 +89,55 @@ class Block::Session_component : public Block::Session_rpc_object,
|
||||
return;
|
||||
}
|
||||
|
||||
bool write = _p_to_handle.operation() == Packet_descriptor::WRITE;
|
||||
sector_t off = _p_to_handle.block_number() + _partition->lba;
|
||||
size_t cnt = _p_to_handle.block_count();
|
||||
sector_t const off = _p_to_handle.block_number() + _partition->lba;
|
||||
size_t const cnt = _p_to_handle.block_count();
|
||||
|
||||
if (write && !_writeable) {
|
||||
_ack_packet(_p_to_handle);
|
||||
return;
|
||||
}
|
||||
auto perform_io = [&] ()
|
||||
{
|
||||
bool const write =
|
||||
(_p_to_handle.operation() == Packet_descriptor::WRITE);
|
||||
|
||||
try {
|
||||
_driver.io(write, off, cnt,
|
||||
tx_sink()->packet_content(_p_to_handle),
|
||||
*this, _p_to_handle);
|
||||
} catch (Block::Session::Tx::Source::Packet_alloc_failed) {
|
||||
if (!_req_queue_full) {
|
||||
_req_queue_full = true;
|
||||
Session_component::wait_queue().insert(this);
|
||||
try {
|
||||
_driver.io(write, off, cnt,
|
||||
tx_sink()->packet_content(_p_to_handle),
|
||||
*this, _p_to_handle);
|
||||
} catch (Block::Session::Tx::Source::Packet_alloc_failed) {
|
||||
if (!_req_queue_full) {
|
||||
_req_queue_full = true;
|
||||
Session_component::wait_queue().insert(this);
|
||||
}
|
||||
} catch (Genode::Packet_descriptor::Invalid_packet) {
|
||||
Genode::error("dropping invalid Block packet");
|
||||
_p_to_handle = Packet_descriptor();
|
||||
}
|
||||
} catch (Genode::Packet_descriptor::Invalid_packet) {
|
||||
Genode::error("dropping invalid Block packet");
|
||||
_p_to_handle = Packet_descriptor();
|
||||
};
|
||||
|
||||
switch (_p_to_handle.operation()) {
|
||||
|
||||
case Packet_descriptor::READ:
|
||||
perform_io();
|
||||
break;
|
||||
|
||||
case Packet_descriptor::WRITE:
|
||||
|
||||
if (!_writeable) {
|
||||
_ack_packet(_p_to_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
perform_io();
|
||||
break;
|
||||
|
||||
case Packet_descriptor::SYNC:
|
||||
_driver.sync_all(*this, _p_to_handle);
|
||||
break;
|
||||
|
||||
case Packet_descriptor::TRIM:
|
||||
case Packet_descriptor::END:
|
||||
|
||||
_p_to_handle.succeeded(true);
|
||||
_ack_packet(_p_to_handle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -223,8 +251,6 @@ class Block::Session_component : public Block::Session_rpc_object,
|
||||
.align_log2 = Genode::log2(_driver.blk_size()),
|
||||
.writeable = _writeable && _driver.writeable() };
|
||||
}
|
||||
|
||||
void sync() override { _driver.session().sync(); }
|
||||
};
|
||||
|
||||
|
||||
|
@ -37,9 +37,7 @@ struct Block::Block_dispatcher : Genode::Interface
|
||||
bool operator== (const Block::Packet_descriptor& p1,
|
||||
const Block::Packet_descriptor& p2)
|
||||
{
|
||||
return p1.operation() == p2.operation() &&
|
||||
p1.block_number() == p2.block_number() &&
|
||||
p1.block_count() == p2.block_count();
|
||||
return p1.tag().value == p2.tag().value;
|
||||
}
|
||||
|
||||
|
||||
@ -58,13 +56,13 @@ class Block::Driver
|
||||
public:
|
||||
|
||||
Request(Block_dispatcher &d,
|
||||
Packet_descriptor &cli,
|
||||
Packet_descriptor &srv)
|
||||
Packet_descriptor const &cli,
|
||||
Packet_descriptor const &srv)
|
||||
: _dispatcher(d), _cli(cli), _srv(srv) {}
|
||||
|
||||
bool handle(Packet_descriptor& reply)
|
||||
{
|
||||
bool ret = reply == _srv;
|
||||
bool ret = (reply == _srv);
|
||||
if (ret) _dispatcher.dispatch(_cli, reply);
|
||||
return ret;
|
||||
}
|
||||
@ -84,6 +82,7 @@ class Block::Driver
|
||||
Block::Session::Info const _info { _session.info() };
|
||||
Genode::Signal_handler<Driver> _source_ack;
|
||||
Genode::Signal_handler<Driver> _source_submit;
|
||||
unsigned long _tag_cnt { 0 };
|
||||
|
||||
void _ready_to_submit();
|
||||
|
||||
@ -105,6 +104,17 @@ class Block::Driver
|
||||
_ready_to_submit();
|
||||
}
|
||||
|
||||
Block::Session::Tag _alloc_tag()
|
||||
{
|
||||
/*
|
||||
* The wrapping of '_tag_cnt' is no problem because the number
|
||||
* of consecutive outstanding requests is much lower than the
|
||||
* value range of tags.
|
||||
*/
|
||||
_tag_cnt++;
|
||||
return Block::Session::Tag { _tag_cnt };
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Driver(Genode::Env &env, Genode::Heap &heap)
|
||||
@ -140,7 +150,7 @@ class Block::Driver
|
||||
: Block::Packet_descriptor::READ;
|
||||
Genode::size_t const size = _info.block_size * cnt;
|
||||
Packet_descriptor p(_session.alloc_packet(size),
|
||||
op, nr, cnt);
|
||||
op, nr, cnt, _alloc_tag());
|
||||
Request *r = new (&_r_slab) Request(dispatcher, cli, p);
|
||||
_r_list.insert(r);
|
||||
|
||||
@ -151,6 +161,19 @@ class Block::Driver
|
||||
_session.tx()->submit_packet(p);
|
||||
}
|
||||
|
||||
void sync_all(Block_dispatcher &dispatcher, Packet_descriptor &cli)
|
||||
{
|
||||
if (!_session.tx()->ready_to_submit())
|
||||
throw Block::Session::Tx::Source::Packet_alloc_failed();
|
||||
|
||||
Packet_descriptor const p =
|
||||
Block::Session::sync_all_packet_descriptor(_info, _alloc_tag());
|
||||
|
||||
_r_list.insert(new (&_r_slab) Request(dispatcher, cli, p));
|
||||
|
||||
_session.tx()->submit_packet(p);
|
||||
}
|
||||
|
||||
void remove_dispatcher(Block_dispatcher &dispatcher)
|
||||
{
|
||||
for (Request *r = _r_list.first(); r;) {
|
||||
|
Reference in New Issue
Block a user