vfs: handle alloc failed in block_file_system

Fixes #2154
This commit is contained in:
Alexander Boettcher 2016-10-27 19:44:33 +02:00 committed by Christian Helmuth
parent d3d4381128
commit a090c9047d
1 changed files with 32 additions and 5 deletions

View File

@ -49,25 +49,47 @@ class Vfs::Block_file_system : public Single_file_system
bool _readable; bool _readable;
bool _writeable; bool _writeable;
Genode::Signal_receiver _signal_receiver;
Genode::Signal_context _signal_context;
Genode::Signal_context_capability _source_submit_cap;
file_size _block_io(file_size nr, void *buf, file_size sz, file_size _block_io(file_size nr, void *buf, file_size sz,
bool write, bool bulk = false) bool write, bool bulk = false)
{ {
Lock::Guard guard(_lock);
Block::Packet_descriptor::Opcode op; Block::Packet_descriptor::Opcode op;
op = write ? Block::Packet_descriptor::WRITE : Block::Packet_descriptor::READ; op = write ? Block::Packet_descriptor::WRITE : Block::Packet_descriptor::READ;
file_size packet_size = bulk ? sz : _block_size; file_size packet_size = bulk ? sz : _block_size;
file_size packet_count = bulk ? (sz / _block_size) : 1; file_size packet_count = bulk ? (sz / _block_size) : 1;
Block::Packet_descriptor packet;
/* sanity check */ /* sanity check */
if (packet_count > _block_buffer_count) { if (packet_count > _block_buffer_count) {
packet_size = _block_buffer_count * _block_size; packet_size = _block_buffer_count * _block_size;
packet_count = _block_buffer_count; packet_count = _block_buffer_count;
} }
Block::Packet_descriptor p(_tx_source->alloc_packet(packet_size), op, while (true) {
nr, packet_count); try {
Lock::Guard guard(_lock);
packet = _tx_source->alloc_packet(packet_size);
break;
} catch (Block::Session::Tx::Source::Packet_alloc_failed) {
if (!_tx_source->ready_to_submit())
_signal_receiver.wait_for_signal();
else {
if (packet_count > 1) {
packet_size /= 2;
packet_count /= 2;
}
}
}
}
Lock::Guard guard(_lock);
Block::Packet_descriptor p(packet, op, nr, packet_count);
if (write) if (write)
Genode::memcpy(_tx_source->packet_content(p), buf, packet_size); Genode::memcpy(_tx_source->packet_content(p), buf, packet_size);
@ -102,7 +124,8 @@ class Vfs::Block_file_system : public Single_file_system
_block(env, &_tx_block_alloc, 128*1024, _label.string()), _block(env, &_tx_block_alloc, 128*1024, _label.string()),
_tx_source(_block.tx()), _tx_source(_block.tx()),
_readable(false), _readable(false),
_writeable(false) _writeable(false),
_source_submit_cap(_signal_receiver.manage(&_signal_context))
{ {
try { config.attribute("block_buffer_count").value(&_block_buffer_count); } try { config.attribute("block_buffer_count").value(&_block_buffer_count); }
catch (...) { } catch (...) { }
@ -113,10 +136,14 @@ class Vfs::Block_file_system : public Single_file_system
_writeable = _block_ops.supported(Block::Packet_descriptor::WRITE); _writeable = _block_ops.supported(Block::Packet_descriptor::WRITE);
_block_buffer = new (_alloc) char[_block_buffer_count * _block_size]; _block_buffer = new (_alloc) char[_block_buffer_count * _block_size];
_block.tx_channel()->sigh_ready_to_submit(_source_submit_cap);
} }
~Block_file_system() ~Block_file_system()
{ {
_signal_receiver.dissolve(&_signal_context);
destroy(_alloc, _block_buffer); destroy(_alloc, _block_buffer);
} }