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;