diff --git a/repos/os/src/server/part_blk/component.h b/repos/os/src/server/part_blk/component.h index 7fa69067d9..f4457ef080 100644 --- a/repos/os/src/server/part_blk/component.h +++ b/repos/os/src/server/part_blk/component.h @@ -87,8 +87,10 @@ class Block::Session_component : public Block::Session_rpc_object, try { _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); + if (!_req_queue_full) { + _req_queue_full = true; + Session_component::wait_queue().insert(this); + } } } @@ -139,6 +141,15 @@ class Block::Session_component : public Block::Session_rpc_object, _tx.sigh_packet_avail(_sink_submit); } + ~Session_component() + { + _driver.remove_dispatcher(*this); + + if (_req_queue_full) + wait_queue().remove(this); + } + + Ram_dataspace_capability const rq_ds() const { return _rq_ds; } Partition *partition() { return _partition; } void dispatch(Packet_descriptor &request, Packet_descriptor &reply) @@ -165,7 +176,7 @@ class Block::Session_component : public Block::Session_rpc_object, static void wake_up() { - for (Session_component *c = wait_queue().first(); c; c = c->next()) + for (; Session_component *c = wait_queue().first();) { wait_queue().remove(c); c->_req_queue_full = false; @@ -204,10 +215,17 @@ class Block::Root : protected: + void _destroy_session(Session_component *session) override + { + Ram_dataspace_capability rq_ds = session->rq_ds(); + Genode::Root_component::_destroy_session(session); + _env.ram().free(rq_ds); + } + /** * Always returns the singleton block-session component */ - Session_component *_create_session(const char *args) + Session_component *_create_session(const char *args) override { long num = -1; diff --git a/repos/os/src/server/part_blk/driver.h b/repos/os/src/server/part_blk/driver.h index d02d948416..8eafc767fc 100644 --- a/repos/os/src/server/part_blk/driver.h +++ b/repos/os/src/server/part_blk/driver.h @@ -70,6 +70,9 @@ class Block::Driver if (ret) _dispatcher.dispatch(_cli, reply); return ret; } + + bool same_dispatcher(Block_dispatcher &same) { + return &same == &_dispatcher; } }; private: @@ -152,6 +155,22 @@ class Block::Driver _session.tx()->submit_packet(p); } + + void remove_dispatcher(Block_dispatcher &dispatcher) + { + for (Request *r = _r_list.first(); r;) { + if (!r->same_dispatcher(dispatcher)) { + r = r->next(); + continue; + } + + Request *remove = r; + r = r->next(); + + _r_list.remove(remove); + Genode::destroy(&_r_slab, remove); + } + } }; #endif /* _PART_BLK__DRIVER_H_ */