diff --git a/os/src/server/part_blk/back_end.cc b/os/src/server/part_blk/back_end.cc index 6be767283c..be71c7a40f 100644 --- a/os/src/server/part_blk/back_end.cc +++ b/os/src/server/part_blk/back_end.cc @@ -11,18 +11,24 @@ * under the terms of the GNU General Public License version 2. */ #include +#include #include #include "part_blk.h" using namespace Genode; +/** + * Used to block until a packet has been freed + */ +static Semaphore _alloc_sem(0); + namespace Partition { size_t _blk_cnt; size_t _blk_size; Allocator_avl _block_alloc(env()->heap()); - Block::Connection _blk(&_block_alloc); + Block::Connection _blk(&_block_alloc, 4 * MAX_PACKET_SIZE); Partition *_part_list[MAX_PARTITIONS]; /* contains pointers to valid partittions or 0 */ @@ -84,15 +90,8 @@ namespace Partition { Lock::Guard guard(_lock); Block::Packet_descriptor::Opcode op = write ? Block::Packet_descriptor::WRITE : Block::Packet_descriptor::READ; - - try { - _p = Block::Packet_descriptor( _blk.dma_alloc_packet(_blk_size * count), + _p = Block::Packet_descriptor(_blk.dma_alloc_packet(_blk_size * count), op, blk_nr, count); - } catch (Block::Session::Tx::Source::Packet_alloc_failed) { - PERR("Packet overrun!"); - _p = _blk.tx()->get_acked_packet(); - throw Io_error(); - } } void submit_request() @@ -101,6 +100,10 @@ namespace Partition { _blk.tx()->submit_packet(_p); _p = _blk.tx()->get_acked_packet(); + /* unblock clients that possibly wait for packet stream allocations */ + if (_alloc_sem.cnt() < 0) + _alloc_sem.up(); + if (!_p.succeeded()) { PERR("Could not access block %zu", _p.block_number()); throw Io_error(); @@ -198,16 +201,25 @@ namespace Partition { unsigned long curr_count = min(count, max_packets()); bytes = curr_count * _blk_size; + bool alloc = false; + while (!alloc) { + try { + Sector sec(lba, curr_count, write); + + if (!write) { + sec.submit_request(); + memcpy(buf, sec.addr(), bytes); + } + else { + memcpy(sec.addr(), buf, bytes); + sec.submit_request(); + } - Sector sec(lba, curr_count, write); - - if (!write) { - sec.submit_request(); - memcpy(buf, sec.addr(), bytes); - } - else { - memcpy(sec.addr(), buf, bytes); - sec.submit_request(); + alloc = true; + } catch (Block::Session::Tx::Source::Packet_alloc_failed) { + /* block */ + _alloc_sem.down(); + } } lba += curr_count;