diff --git a/repos/gems/run/tresor_tester.run b/repos/gems/run/tresor_tester.run index 71699c4d12..08c3978e1d 100644 --- a/repos/gems/run/tresor_tester.run +++ b/repos/gems/run/tresor_tester.run @@ -334,29 +334,32 @@ append config { - + - + - - + + + + + - + - - + + @@ -365,23 +368,24 @@ append config { - + - - + + + - + @@ -415,14 +419,14 @@ append config { - + - + @@ -446,7 +450,7 @@ append config { - + @@ -1068,11 +1072,11 @@ append config { - + - + - + diff --git a/repos/gems/src/app/tresor_tester/main.cc b/repos/gems/src/app/tresor_tester/main.cc index ddcd0744a4..5d4de78568 100644 --- a/repos/gems/src/app/tresor_tester/main.cc +++ b/repos/gems/src/app/tresor_tester/main.cc @@ -12,6 +12,7 @@ */ /* base includes */ +#include #include #include #include @@ -329,6 +330,7 @@ class Request_node bool const _sync; bool const _salt_avail; uint64_t const _salt; + Snapshot_id const _snap_id; Operation _read_op_attr(Xml_node const &node) { @@ -348,6 +350,9 @@ class Request_node if (node.attribute("op").has_value("create_snapshot")) { return Operation::CREATE_SNAPSHOT; } + if (node.attribute("op").has_value("discard_snapshot")) { + return Operation::DISCARD_SNAPSHOT; + } if (node.attribute("op").has_value("extend_ft")) { return Operation::EXTEND_FT; } @@ -377,7 +382,9 @@ class Request_node _salt_avail { has_attr_salt() ? node.has_attribute("salt") : false }, _salt { has_attr_salt() && _salt_avail ? - read_attribute(node, "salt") : 0 } + read_attribute(node, "salt") : 0 }, + _snap_id { has_attr_snap_id() ? + read_attribute(node, "id") : 0 } { } Operation op() const { return _op; } @@ -386,6 +393,7 @@ class Request_node bool sync() const { return _sync; } bool salt_avail() const { return _salt_avail; } uint64_t salt() const { return _salt; } + Snapshot_id snap_id() const { return _snap_id; } bool has_attr_vba() const { @@ -409,6 +417,12 @@ class Request_node _op == Operation::EXTEND_VBD; } + bool has_attr_snap_id() const + { + return _op == Operation::DISCARD_SNAPSHOT || + _op == Operation::CREATE_SNAPSHOT; + } + void print(Genode::Output &out) const { Genode::print(out, "op=", to_string(_op)); @@ -610,17 +624,76 @@ class Command : public Fifo::Element }; +class Snapshot_reference : public Genode::Avl_node +{ + private: + + Snapshot_id const _id; + Generation const _gen; + + public: + + Snapshot_reference(Snapshot_id id, Generation gen) : _id { id }, _gen { gen } { } + + Snapshot_id id() const { return _id; } + Generation gen() const { return _gen; } + + template + void find(Snapshot_id const id, + HANDLE_MATCH_FN && handle_match, + HANDLE_NO_MATCH_FN && handle_no_match) const + { + if (id != _id) { + Snapshot_reference *child_ptr { Avl_node::child(id > _id) }; + if (child_ptr) + child_ptr->find(id, handle_match, handle_no_match); + else + handle_no_match(); + } else + handle_match(*this); + } + + void print(Genode::Output &out) const + { + Genode::print(out, " id ", _id, " gen ", _gen); + } + + bool higher(Snapshot_reference *other_ptr) + { + return other_ptr->_id > _id; + } +}; + + +class Snapshot_reference_tree : public Avl_tree +{ + public: + + template + void find(Snapshot_id const snap_id, + HANDLE_MATCH_FN && handle_match, + HANDLE_NO_MATCH_FN && handle_no_match) const + { + if (first() != nullptr) + first()->find(snap_id, handle_match, handle_no_match); + else + handle_no_match(); + } +}; + + class Command_pool : public Module { private: - Allocator &_alloc; + Allocator &_alloc; Verbose_node const &_verbose_node; - Fifo _cmd_queue { }; - uint32_t _next_command_id { 0 }; - unsigned long _nr_of_uncompleted_cmds { 0 }; - unsigned long _nr_of_errors { 0 }; - Tresor::Block _blk_data { }; + Fifo _cmd_queue { }; + uint32_t _next_command_id { 0 }; + unsigned long _nr_of_uncompleted_cmds { 0 }; + unsigned long _nr_of_errors { 0 }; + Tresor::Block _blk_data { }; + Snapshot_reference_tree _snap_refs { }; void _read_cmd_node(Xml_node const &node, Command::Type cmd_type) @@ -772,6 +845,26 @@ class Command_pool : public Module { } } + template + void find_cmd(Module_request_id cmd_id, + HANDLE_MATCH_FN && handle_match_fn, + HANDLE_NO_MATCH_FN && handle_no_match_fn) + { + bool cmd_found { false }; + _cmd_queue.for_each([&] (Command &cmd) + { + if (cmd_found) + return; + + if (cmd.id() == cmd_id) { + handle_match_fn(cmd); + cmd_found = true; + } + }); + if (!cmd_found) + handle_no_match_fn(); + } + void generated_request_complete(Module_request &mod_req) override { switch (mod_req.dst_module_id()) { @@ -819,8 +912,17 @@ class Command_pool : public Module { Request const &rp_req { *static_cast(&mod_req)}; - mark_command_completed( - rp_req.src_request_id(), rp_req.success()); + Module_request_id const cmd_id { rp_req.src_request_id() }; + bool const success { rp_req.success() }; + if (success && rp_req.operation() == Tresor::Request::CREATE_SNAPSHOT) { + find_cmd(cmd_id, [&] (Command &cmd) + { + _snap_refs.insert(new (_alloc) + Snapshot_reference { cmd.request_node().snap_id(), rp_req.gen() }); + }, + [&] () { ASSERT_NEVER_REACHED; }); + } + mark_command_completed(cmd_id, success); break; } default: @@ -847,6 +949,17 @@ class Command_pool : public Module { }); } + Generation snap_id_to_gen(Snapshot_id id) + { + Generation gen { INVALID_GENERATION }; + _snap_refs.find(id, [&] (Snapshot_reference const &snap_ref) + { + gen = snap_ref.gen(); + }, + [&] () { ASSERT_NEVER_REACHED; }); + return gen; + } + Command peek_pending_command(Command::Type type) const { Reconstructible resulting_cmd { }; @@ -905,102 +1018,56 @@ class Command_pool : public Module { void mark_command_in_progress(Module_request_id cmd_id) { - bool exit_loop { false }; - _cmd_queue.for_each([&] (Command &cmd) + find_cmd(cmd_id, [&] (Command &cmd) { - if (exit_loop) { - return; - } - if (cmd.id() == cmd_id) { - if (cmd.state() != Command::PENDING) { - class Bad_state { }; - throw Bad_state { }; - } - cmd.state(Command::IN_PROGRESS); - exit_loop = true; - - if (_verbose_node.cmd_pool_cmd_in_progress()) { - log("cmd in progress: ", cmd); - } - } - }); + ASSERT(cmd.state() == Command::PENDING); + cmd.state(Command::IN_PROGRESS); + if (_verbose_node.cmd_pool_cmd_in_progress()) + log("cmd in progress: ", cmd); + }, + [&] () { ASSERT_NEVER_REACHED; }); } void mark_command_completed(Module_request_id cmd_id, bool success) { - bool exit_loop { false }; - _cmd_queue.for_each([&] (Command &cmd) + find_cmd(cmd_id, [&] (Command &cmd) { - if (exit_loop) { - return; + ASSERT(cmd.state() == Command::IN_PROGRESS); + cmd.state(Command::COMPLETED); + _nr_of_uncompleted_cmds--; + cmd.success(success); + if (!cmd.success()) { + error("cmd failed"); + _nr_of_errors++; } - if (cmd.id() == cmd_id) { - - if (cmd.state() != Command::IN_PROGRESS) { - - class Bad_state { }; - throw Bad_state { }; - } - cmd.state(Command::COMPLETED); - _nr_of_uncompleted_cmds--; - cmd.success(success); - if (!cmd.success()) { - error("cmd failed"); - _nr_of_errors++; - } - exit_loop = true; - - if (_verbose_node.cmd_pool_cmd_completed()) { - log("cmd completed: ", cmd); - } - } - }); + if (_verbose_node.cmd_pool_cmd_completed()) + log("cmd completed: ", cmd); + }, + [&] () { ASSERT_NEVER_REACHED; }); } void generate_blk_data(uint64_t tresor_req_tag, Virtual_block_address vba, - Tresor::Block &blk_data) const + Tresor::Block &blk_data) { - bool exit_loop { false }; - _cmd_queue.for_each([&] (Command &cmd) + find_cmd(tresor_req_tag, [&] (Command &cmd) { - if (exit_loop) { - return; - } - if (cmd.id() != tresor_req_tag) { - return; - } - if (cmd.type() != Command::REQUEST) { - class Bad_command_type { }; - throw Bad_command_type { }; - } + ASSERT(cmd.type() == Command::REQUEST); Request_node const &req_node { cmd.request_node() }; - if (req_node.salt_avail()) { - + if (req_node.salt_avail()) _generate_blk_data(blk_data, vba, req_node.salt()); - } - exit_loop = true; - }); + }, + [&] () { ASSERT_NEVER_REACHED; }); } void verify_blk_data(uint64_t tresor_req_tag, Virtual_block_address vba, Tresor::Block &blk_data) { - bool exit_loop { false }; - _cmd_queue.for_each([&] (Command &cmd) + find_cmd(tresor_req_tag, [&] (Command &cmd) { - if (exit_loop) { - return; - } - if (cmd.id() != tresor_req_tag) { - return; - } - if (cmd.type() != Command::REQUEST) { - class Bad_command_type { }; - throw Bad_command_type { }; - } + ASSERT(cmd.type() == Command::REQUEST); Request_node const &req_node { cmd.request_node() }; if (req_node.salt_avail()) { Tresor::Block gen_blk_data { }; @@ -1022,8 +1089,8 @@ class Command_pool : public Module { } } } - exit_loop = true; - }); + }, + [&] () { ASSERT_NEVER_REACHED; }); } void print_failed_cmds() const @@ -1153,26 +1220,6 @@ class Tresor_tester::Main */ void wakeup_vfs_user() override { _sigh.local_submit(); } - template - void _handle_completed_client_requests_of_module(MODULE &module, - bool &progress) - { - while (true) { - - Tresor::Request const tresor_req { - module.peek_completed_client_request() }; - - if (!tresor_req.valid()) { - break; - } - _cmd_pool.mark_command_completed(tresor_req.tag(), - tresor_req.success()); - - module.drop_completed_client_request(tresor_req); - progress = true; - } - } - bool ready_to_submit_request() override { return _client_data_request._type == Client_data_request::INVALID; @@ -1266,21 +1313,11 @@ class Tresor_tester::Main if (cmd.type() == Command::INVALID) { break; } - if (cmd.request_node().op() == Tresor::Request::Operation::CREATE_SNAPSHOT) { - warning("skip command because it is temporarily not supported"); - _cmd_pool.mark_command_in_progress(cmd.id()); - _cmd_pool.mark_command_completed(cmd.id(), true); - progress = true; - continue; - } - if (cmd.request_node().op() == Tresor::Request::Operation::DISCARD_SNAPSHOT) { - warning("skip command because it is temporarily not supported"); - _cmd_pool.mark_command_in_progress(cmd.id()); - _cmd_pool.mark_command_completed(cmd.id(), true); - progress = true; - continue; - } Request_node req_node { cmd.request_node() }; + Generation gen { INVALID_GENERATION }; + if (req_node.op() == Request::DISCARD_SNAPSHOT) + gen = _cmd_pool.snap_id_to_gen(req_node.snap_id()); + Tresor::Request tresor_req { cmd.request_node().op(), false, @@ -1288,9 +1325,7 @@ class Tresor_tester::Main 0, req_node.has_attr_count() ? req_node.count() : 0, 0, - cmd.id(), - 0, - COMMAND_POOL, cmd.id() }; + cmd.id(), gen, COMMAND_POOL, cmd.id() }; _request_pool->submit_request(tresor_req); if (VERBOSE_MODULE_COMMUNICATION) diff --git a/repos/gems/src/lib/tresor/include/tresor/request_pool.h b/repos/gems/src/lib/tresor/include/tresor/request_pool.h index 72b830d8f4..d0eb71ceaf 100644 --- a/repos/gems/src/lib/tresor/include/tresor/request_pool.h +++ b/repos/gems/src/lib/tresor/include/tresor/request_pool.h @@ -28,6 +28,8 @@ namespace Tresor { class Request : public Module_request { + friend class Request_pool; + public: enum Operation : uint32_t { @@ -54,7 +56,7 @@ namespace Tresor { Number_of_blocks _count; uint32_t _key_id; uint32_t _tag; - uint32_t _snap_id; + Generation _gen; public: @@ -65,7 +67,7 @@ namespace Tresor { Number_of_blocks count, uint32_t key_id, uint32_t tag, - uint32_t snap_id, + Generation gen, Module_id src_module_id, Module_request_id src_request_id) : @@ -77,7 +79,7 @@ namespace Tresor { _count { count }, _key_id { key_id }, _tag { tag }, - _snap_id { snap_id } + _gen { gen } { } Request() @@ -90,7 +92,7 @@ namespace Tresor { _count { 0 }, _key_id { 0 }, _tag { 0 }, - _snap_id { 0 } + _gen { 0 } { } bool valid() const @@ -122,12 +124,12 @@ namespace Tresor { Number_of_blocks count() const { return _count; } uint32_t key_id() const { return _key_id; } uint32_t tag() const { return _tag; } - uint32_t snap_id() const { return _snap_id; } + Generation gen() const { return _gen; } void offset(uint64_t arg) { _offset = arg; } void success(bool arg) { _success = arg; } void tag(uint32_t arg) { _tag = arg; } - void snap_id(uint32_t arg) { _snap_id = arg; } + void gen(Generation arg) { _gen = arg; } static char const *op_to_string(Operation op); @@ -152,9 +154,7 @@ namespace Tresor { break; } } - - } __attribute__((packed)); - + }; } class Tresor::Request_pool_channel @@ -212,6 +212,8 @@ class Tresor::Request_pool_channel TAG_POOL_SB_CTRL_DEINITIALIZE, TAG_POOL_SB_CTRL_INIT_REKEY, TAG_POOL_SB_CTRL_REKEY_VBA, + TAG_POOL_SB_CTRL_CREATE_SNAP, + TAG_POOL_SB_CTRL_DISCARD_SNAP }; using Pool_index = uint32_t; @@ -231,7 +233,6 @@ class Tresor::Request_pool_channel State _state { INVALID }; Generated_prim _prim { }; uint64_t _nr_of_blks { 0 }; - Generation _gen { }; Superblock::State _sb_state { Superblock::INVALID }; uint32_t _nr_of_requests_preponed { 0 }; bool _request_finished { false }; @@ -242,7 +243,6 @@ class Tresor::Request_pool_channel _state = { INVALID }; _prim = { }; _nr_of_blks = 0; - _gen = { }; _sb_state = { Superblock::INVALID }; } }; @@ -406,6 +406,16 @@ class Tresor::Request_pool : public Module void _execute_sync (Channel &, Index_queue &, Slots_index const, bool &); + void _execute_create_snap(Channel &channel, + Index_queue &indices, + Slots_index const idx, + bool &progress); + + void _execute_discard_snap(Channel &channel, + Index_queue &indices, + Slots_index const idx, + bool &progress); + void _execute_rekey(Channel &chan, Index_queue &indices, Slots_index idx, diff --git a/repos/gems/src/lib/tresor/include/tresor/superblock_control.h b/repos/gems/src/lib/tresor/include/tresor/superblock_control.h index cff7c1f67b..48cc1a73f8 100644 --- a/repos/gems/src/lib/tresor/include/tresor/superblock_control.h +++ b/repos/gems/src/lib/tresor/include/tresor/superblock_control.h @@ -53,6 +53,7 @@ class Tresor::Superblock_control_request : public Module_request Number_of_blocks _nr_of_blks { 0 }; bool _success { false }; bool _request_finished { false }; + addr_t _generation_ptr { 0 }; public: @@ -71,10 +72,15 @@ class Tresor::Superblock_control_request : public Module_request uint64_t client_req_offset, uint64_t client_req_tag, Number_of_blocks nr_of_blks, - uint64_t vba); + uint64_t vba, + Generation &gen); Superblock::State sb_state() { return _sb_state; } + Generation gen() const { return *(Generation const *)_generation_ptr; } + + void gen(Generation g) { *(Generation *)_generation_ptr = g; } + bool success() const { return _success; } bool request_finished() const { return _request_finished; } @@ -284,10 +290,17 @@ class Tresor::Superblock_control : public Module uint64_t chan_idx, bool &progress); + bool _secure_sb_finish(Channel &chan, + bool &progress); + void _init_sb_without_key_values(Superblock const &, Superblock &); void _execute_sync(Channel &, uint64_t const job_idx, Superblock &, - Superblock_index &, Generation &, bool &progress); + Superblock_index &, Generation &, bool &progress); + + void _execute_create_snap(Channel &, uint64_t, bool &progress); + + void _execute_discard_snap(Channel &, uint64_t, bool &progress); void _execute_tree_ext_step(Channel &chan, uint64_t chan_idx, @@ -310,7 +323,7 @@ class Tresor::Superblock_control : public Module Superblock const &, bool &progress); void _execute_write_vba(Channel &, uint64_t const job_idx, - Superblock &, Generation const &, bool &progress); + Superblock &, Generation const &, bool &progress); void _execute_initialize(Channel &, uint64_t const job_idx, Superblock &, Superblock_index &, diff --git a/repos/gems/src/lib/tresor/request_pool.cc b/repos/gems/src/lib/tresor/request_pool.cc index 0558415a8c..e70049423a 100644 --- a/repos/gems/src/lib/tresor/request_pool.cc +++ b/repos/gems/src/lib/tresor/request_pool.cc @@ -141,6 +141,84 @@ void Request_pool::_execute_write(Channel &channel, Index_queue &indices, } +void Request_pool::_execute_create_snap(Channel &channel, + Index_queue &indices, + Slots_index const idx, + bool &progress) +{ + switch (channel._state) { + case Channel::State::SUBMITTED: + + channel._prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_CREATE_SNAP, + .pl_idx = idx, + .blk_nr = 0, + .idx = 0 + }; + channel._state = Channel::State::CREATE_SNAP_AT_SB_CTRL_PENDING; + progress = true; + break; + + case Channel::State::CREATE_SNAP_AT_SB_CTRL_COMPLETE: + + if (channel._prim.succ) { + channel._request.success(true); + } else + channel._request.success(false); + + channel._state = Channel::State::COMPLETE; + indices.dequeue(idx); + progress = true; + break; + + default: + + break; + } +} + + +void Request_pool::_execute_discard_snap(Channel &channel, + Index_queue &indices, + Slots_index const idx, + bool &progress) +{ + switch (channel._state) { + case Channel::State::SUBMITTED: + + channel._prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_DISCARD_SNAP, + .pl_idx = idx, + .blk_nr = 0, + .idx = 0 + }; + channel._state = Channel::State::DISCARD_SNAP_AT_SB_CTRL_PENDING; + progress = true; + break; + + case Channel::State::DISCARD_SNAP_AT_SB_CTRL_COMPLETE: + + if (channel._prim.succ) { + channel._request.success(true); + } else + channel._request.success(false); + + channel._state = Channel::State::COMPLETE; + indices.dequeue(idx); + progress = true; + break; + + default: + + break; + } +} + + void Request_pool::_execute_sync(Channel &channel, Index_queue &indices, Slots_index const idx, bool &progress) { @@ -164,7 +242,6 @@ void Request_pool::_execute_sync(Channel &channel, Index_queue &indices, if (channel._prim.succ) { channel._request.success(true); - channel._request.offset(channel._gen); } else channel._request.success(false); @@ -597,8 +674,8 @@ void Request_pool::execute(bool &progress) case Tresor::Request::Operation::EXTEND_FT: _execute_extend_tree(channel, idx, Channel::FT_EXTENSION_STEP_PENDING, progress); break; case Tresor::Request::Operation::INITIALIZE: _execute_initialize(channel, _indices, idx, progress); break; case Tresor::Request::Operation::DEINITIALIZE: _execute_deinitialize(channel, _indices, idx, progress); break; - case Tresor::Request::Operation::CREATE_SNAPSHOT: throw Not_implemented { }; - case Tresor::Request::Operation::DISCARD_SNAPSHOT: throw Not_implemented { }; + case Tresor::Request::Operation::CREATE_SNAPSHOT: _execute_create_snap(channel, _indices, idx, progress); break; + case Tresor::Request::Operation::DISCARD_SNAPSHOT: _execute_discard_snap(channel, _indices, idx, progress); break; default: break; } } @@ -622,6 +699,8 @@ void Request_pool::submit_request(Module_request &mod_req) case Request::REKEY: case Request::EXTEND_VBD: case Request::EXTEND_FT: + case Request::CREATE_SNAPSHOT: + case Request::DISCARD_SNAPSHOT: mod_req.dst_request_id(idx); _channels[idx]._state = Channel::SUBMITTED; @@ -648,25 +727,27 @@ bool Request_pool::_peek_generated_request(uint8_t *buf_ptr, return false; Slots_index const idx { _indices.head() }; - Channel const &chan { _channels[idx] }; + Channel &chan { _channels[idx] }; Superblock_control_request::Type scr_type; switch (chan._state) { - case Channel::READ_VBA_AT_SB_CTRL_PENDING: scr_type = Superblock_control_request::READ_VBA; break; + case Channel::READ_VBA_AT_SB_CTRL_PENDING: scr_type = Superblock_control_request::READ_VBA; break; case Channel::WRITE_VBA_AT_SB_CTRL_PENDING: scr_type = Superblock_control_request::WRITE_VBA; break; - case Channel::SYNC_AT_SB_CTRL_PENDING: scr_type = Superblock_control_request::SYNC; break; - case Channel::INITIALIZE_SB_CTRL_PENDING: scr_type = Superblock_control_request::INITIALIZE; break; + case Channel::SYNC_AT_SB_CTRL_PENDING: scr_type = Superblock_control_request::SYNC; break; + case Channel::CREATE_SNAP_AT_SB_CTRL_PENDING: scr_type = Superblock_control_request::CREATE_SNAPSHOT; break; + case Channel::DISCARD_SNAP_AT_SB_CTRL_PENDING: scr_type = Superblock_control_request::DISCARD_SNAPSHOT; break; + case Channel::INITIALIZE_SB_CTRL_PENDING: scr_type = Superblock_control_request::INITIALIZE; break; case Channel::DEINITIALIZE_SB_CTRL_PENDING: scr_type = Superblock_control_request::DEINITIALIZE; break; - case Channel::REKEY_INIT_PENDING: scr_type = Superblock_control_request::INITIALIZE_REKEYING; break; - case Channel::REKEY_VBA_PENDING: scr_type = Superblock_control_request::REKEY_VBA; break; - case Channel::VBD_EXTENSION_STEP_PENDING: scr_type = Superblock_control_request::VBD_EXTENSION_STEP; break; - case Channel::FT_EXTENSION_STEP_PENDING: scr_type = Superblock_control_request::FT_EXTENSION_STEP; break; + case Channel::REKEY_INIT_PENDING: scr_type = Superblock_control_request::INITIALIZE_REKEYING; break; + case Channel::REKEY_VBA_PENDING: scr_type = Superblock_control_request::REKEY_VBA; break; + case Channel::VBD_EXTENSION_STEP_PENDING: scr_type = Superblock_control_request::VBD_EXTENSION_STEP; break; + case Channel::FT_EXTENSION_STEP_PENDING: scr_type = Superblock_control_request::FT_EXTENSION_STEP; break; default: return false; } Superblock_control_request::create( buf_ptr, buf_size, REQUEST_POOL, idx, scr_type, chan._request.offset(), chan._request.tag(), - chan._request.count(), chan._prim.blk_nr); + chan._request.count(), chan._prim.blk_nr, chan._request._gen); return true; } @@ -722,13 +803,9 @@ void Request_pool::generated_request_complete(Module_request &mod_req) break; case Channel::CREATE_SNAP_AT_SB_CTRL_IN_PROGRESS: chan._state = Channel::CREATE_SNAP_AT_SB_CTRL_COMPLETE; - class Exception_6 { }; - throw Exception_6 { }; break; case Channel::DISCARD_SNAP_AT_SB_CTRL_IN_PROGRESS: chan._state = Channel::DISCARD_SNAP_AT_SB_CTRL_COMPLETE; - class Exception_4 { }; - throw Exception_4 { }; break; case Channel::INITIALIZE_SB_CTRL_IN_PROGRESS: chan._sb_state = gen_req.sb_state(); diff --git a/repos/gems/src/lib/tresor/superblock_control.cc b/repos/gems/src/lib/tresor/superblock_control.cc index 801e23865b..0f3c1dc12b 100644 --- a/repos/gems/src/lib/tresor/superblock_control.cc +++ b/repos/gems/src/lib/tresor/superblock_control.cc @@ -38,7 +38,8 @@ void Superblock_control_request::create(void *buf_ptr, uint64_t client_req_offset, uint64_t client_req_tag, Number_of_blocks nr_of_blks, - uint64_t vba) + uint64_t vba, + Generation &gen) { Superblock_control_request req { src_module_id, src_request_id }; @@ -47,6 +48,7 @@ void Superblock_control_request::create(void *buf_ptr, req._client_req_tag = client_req_tag; req._nr_of_blks = nr_of_blks; req._vba = vba; + req._generation_ptr = (addr_t)&gen; if (sizeof(req) > buf_size) { class Bad_size_0 { }; @@ -463,10 +465,9 @@ void Superblock_control::_execute_tree_ext_step(Channel &chan, case Channel::SYNC_BLK_IO_COMPLETED: _secure_sb_sync_blk_io_compl(chan, chan_idx, progress); break; case Channel::SECURE_SB_COMPLETED: - if (_handle_failed_generated_req(chan, progress)) + if (!_secure_sb_finish(chan, progress)) break; - _sb.last_secured_generation = chan._generation; _mark_req_successful(chan, progress); break; @@ -573,11 +574,9 @@ void Superblock_control::_execute_rekey_vba(Channel &chan, case Channel::SYNC_BLK_IO_COMPLETED: _secure_sb_sync_blk_io_compl(chan, chan_idx, progress); break; case Channel::SECURE_SB_COMPLETED: - if (!chan._generated_prim.succ) { - _mark_req_failed(chan, progress, "secure superblock"); + if (!_secure_sb_finish(chan, progress)) break; - } - _sb.last_secured_generation = chan._generation; + _mark_req_successful(chan, progress); break; @@ -737,6 +736,17 @@ void Superblock_control::_secure_sb_write_sb_compl(Channel &chan, } +bool Superblock_control::_secure_sb_finish(Channel &chan, + bool &progress) +{ + if (_handle_failed_generated_req(chan, progress)) + return false; + + _sb.last_secured_generation = chan._generation; + return true; +} + + void Superblock_control::_execute_initialize_rekeying(Channel &chan, uint64_t const chan_idx, @@ -812,11 +822,9 @@ Superblock_control::_execute_initialize_rekeying(Channel &chan, case Channel::SYNC_BLK_IO_COMPLETED: _secure_sb_sync_blk_io_compl(chan, chan_idx, progress); break; case Channel::SECURE_SB_COMPLETED: - if (!chan._generated_prim.succ) { - _mark_req_failed(chan, progress, "secure superblock"); + if (!_secure_sb_finish(chan, progress)) break; - } - _sb.last_secured_generation = chan._generation; + _mark_req_successful(chan, progress); break; @@ -827,6 +835,69 @@ Superblock_control::_execute_initialize_rekeying(Channel &chan, } +void Superblock_control::_execute_discard_snap(Channel &chan, uint64_t chan_idx, bool &progress) +{ + Request &req { chan._request }; + switch (chan._state) { + case Channel::State::SUBMITTED: + { + for (Snapshot &snap : _sb.snapshots.items) + if (snap.valid && snap.gen == req.gen() && snap.keep) + snap.keep = false; + + _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); + _secure_sb_init(chan, chan_idx, progress); + break; + } + case Channel::ENCRYPT_CURRENT_KEY_COMPLETED: _secure_sb_encr_curr_key_compl(chan, chan_idx, progress); break; + case Channel::ENCRYPT_PREVIOUS_KEY_COMPLETED: _secure_sb_encr_prev_key_compl(chan, chan_idx, progress); break; + case Channel::SYNC_CACHE_COMPLETED: _secure_sb_sync_cache_compl(chan, chan_idx, progress); break; + case Channel::WRITE_SB_COMPLETED: _secure_sb_write_sb_compl(chan, chan_idx, progress); break; + case Channel::SYNC_BLK_IO_COMPLETED: _secure_sb_sync_blk_io_compl(chan, chan_idx, progress); break; + case Channel::SECURE_SB_COMPLETED: + + if (!_secure_sb_finish(chan, progress)) + break; + + req.gen(chan._generation); + _mark_req_successful(chan, progress); + break; + + default: break; + } +} + + +void Superblock_control::_execute_create_snap(Channel &chan, uint64_t chan_idx, bool &progress) +{ + Request &req { chan._request }; + switch (chan._state) { + case Channel::State::SUBMITTED: + + _sb.snapshots.items[_sb.curr_snap].keep = true; + _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); + _secure_sb_init(chan, chan_idx, progress); + break; + + case Channel::ENCRYPT_CURRENT_KEY_COMPLETED: _secure_sb_encr_curr_key_compl(chan, chan_idx, progress); break; + case Channel::ENCRYPT_PREVIOUS_KEY_COMPLETED: _secure_sb_encr_prev_key_compl(chan, chan_idx, progress); break; + case Channel::SYNC_CACHE_COMPLETED: _secure_sb_sync_cache_compl(chan, chan_idx, progress); break; + case Channel::WRITE_SB_COMPLETED: _secure_sb_write_sb_compl(chan, chan_idx, progress); break; + case Channel::SYNC_BLK_IO_COMPLETED: _secure_sb_sync_blk_io_compl(chan, chan_idx, progress); break; + case Channel::SECURE_SB_COMPLETED: + + if (!_secure_sb_finish(chan, progress)) + break; + + req.gen(chan._generation); + _mark_req_successful(chan, progress); + break; + + default: break; + } +} + + void Superblock_control::_execute_sync(Channel &channel, uint64_t const job_idx, Superblock &sb, @@ -972,11 +1043,9 @@ void Superblock_control::_execute_sync(Channel &channel, } case Channel::State::SECURE_SB_COMPLETED: - if (!channel._generated_prim.succ) { - class Secure_sb_completed_error { }; - throw Secure_sb_completed_error { }; - } - sb.last_secured_generation = channel._generation; + if (!_secure_sb_finish(channel, progress)) + break; + channel._request._success = true; channel._state = Channel::State::COMPLETED; progress = true; @@ -1374,12 +1443,8 @@ void Superblock_control::_execute_deinitialize(Channel &channel, } case Channel::State::SECURE_SB_COMPLETED: - if (!channel._generated_prim.succ) { - class Deinitialize_secure_sb_error { }; - throw Deinitialize_secure_sb_error { }; - } - - sb.last_secured_generation = channel._generation; + if (!_secure_sb_finish(channel, progress)) + break; channel._request._success = true; @@ -1831,16 +1896,8 @@ void Superblock_control::execute(bool &progress) case Request::REKEY_VBA: _execute_rekey_vba(channel, idx, progress); break; case Request::VBD_EXTENSION_STEP: _execute_tree_ext_step(channel, idx, Superblock::EXTENDING_VBD, VERBOSE_VBD_EXTENSION, Channel::TAG_SB_CTRL_VBD_VBD_EXT_STEP, Channel::VBD_EXT_STEP_IN_VBD_PENDING, "vbd", progress); break; case Request::FT_EXTENSION_STEP: _execute_tree_ext_step(channel, idx, Superblock::EXTENDING_FT, VERBOSE_FT_EXTENSION, Channel::TAG_SB_CTRL_FT_FT_EXT_STEP, Channel::FT_EXT_STEP_IN_FT_PENDING, "ft", progress); break; - case Request::CREATE_SNAPSHOT: - class Superblock_control_create_snapshot { }; - throw Superblock_control_create_snapshot { }; - - break; - case Request::DISCARD_SNAPSHOT: - class Superblock_control_discard_snapshot { }; - throw Superblock_control_discard_snapshot { }; - - break; + case Request::CREATE_SNAPSHOT: _execute_create_snap(channel, idx, progress); break; + case Request::DISCARD_SNAPSHOT: _execute_discard_snap(channel, idx, progress); break; case Request::INITIALIZE: _execute_initialize(channel, idx, _sb, _sb_idx, _curr_gen, progress); diff --git a/repos/gems/src/lib/vfs/tresor/vfs.cc b/repos/gems/src/lib/vfs/tresor/vfs.cc index dc2b0d00af..9195163e87 100644 --- a/repos/gems/src/lib/vfs/tresor/vfs.cc +++ b/repos/gems/src/lib/vfs/tresor/vfs.cc @@ -174,8 +174,8 @@ class Vfs_tresor::Wrapper { if (_helper_read_request.pending()) { if (_request_pool->ready_to_submit_request()) { - _helper_read_request.tresor_request.snap_id( - _frontend_request.tresor_request.snap_id()); + _helper_read_request.tresor_request.gen( + _frontend_request.tresor_request.gen()); _request_pool->submit_request(_helper_read_request.tresor_request); _helper_read_request.state = Helper_request::State::IN_PROGRESS; } @@ -183,8 +183,8 @@ class Vfs_tresor::Wrapper if (_helper_write_request.pending()) { if (_request_pool->ready_to_submit_request()) { - _helper_write_request.tresor_request.snap_id( - _frontend_request.tresor_request.snap_id()); + _helper_write_request.tresor_request.gen( + _frontend_request.tresor_request.gen()); _request_pool->submit_request(_helper_write_request.tresor_request); _helper_write_request.state = Helper_request::State::IN_PROGRESS; } @@ -577,7 +577,7 @@ class Vfs_tresor::Wrapper _helper_read_request.tresor_request.count(), _helper_read_request.tresor_request.key_id(), _helper_read_request.tresor_request.tag(), - _helper_read_request.tresor_request.snap_id(), + _helper_read_request.tresor_request.gen(), COMMAND_POOL, 0); _helper_write_request.state = Helper_request::State::PENDING; @@ -934,10 +934,10 @@ class Vfs_tresor::Wrapper _frontend_request.tresor_request = Tresor::Request { }; } - bool submit_frontend_request(Vfs_handle &handle, - Byte_range_ptr const &data, - Tresor::Request::Operation op, - uint32_t snap_id) + bool submit_frontend_request(Vfs_handle &handle, + Byte_range_ptr const &data, + Tresor::Request::Operation op, + Generation gen) { if (_frontend_request.state != Frontend_request::State::NONE) { return false; @@ -1020,15 +1020,9 @@ class Vfs_tresor::Wrapper _frontend_request.data = data.start; _frontend_request.offset = offset; _frontend_request.tresor_request = Tresor::Request( - op, - false, - offset / Tresor::BLOCK_SIZE, - (uint64_t)data.start, - (uint32_t)(count / Tresor::BLOCK_SIZE), - 0, - (Genode::uint32_t)tag, - snap_id, - COMMAND_POOL, 0); + op, false, offset / Tresor::BLOCK_SIZE, (uint64_t)data.start, + (uint32_t)(count / Tresor::BLOCK_SIZE), 0, + (Genode::uint32_t)tag, gen, COMMAND_POOL, 0); if (_verbose) { if (unaligned_request) { @@ -1307,7 +1301,7 @@ class Vfs_tresor::Wrapper Frontend_request _discard_snapshot_request { }; - bool discard_snapshot(Tresor::Generation id) + bool discard_snapshot(Generation snap_gen) { if (!_request_pool.constructed()) { _initialize_tresor(); @@ -1325,8 +1319,7 @@ class Vfs_tresor::Wrapper Tresor::Request::Operation::DISCARD_SNAPSHOT; _discard_snapshot_request.tresor_request = - Tresor::Request(op, false, 0, 0, 1, 0, 0, (uint32_t)id, - COMMAND_POOL, 0); + Tresor::Request(op, false, 0, 0, 1, 0, 0, snap_gen, COMMAND_POOL, 0); if (_verbose) { Genode::log("Req: (req: ", _discard_snapshot_request.tresor_request, ")"); @@ -1353,23 +1346,23 @@ class Vfs_tresor::Data_file_system : public Single_file_system private: Wrapper &_w; - uint32_t _snap_id; + Generation _snap_gen; public: struct Vfs_handle : Single_vfs_handle { Wrapper &_w; - uint32_t _snap_id { 0 }; + Generation _snap_gen { INVALID_GENERATION }; Vfs_handle(Directory_service &ds, - File_io_service &fs, + File_io_service &fs, Genode::Allocator &alloc, - Wrapper &w, - uint32_t snap_id) + Wrapper &w, + Generation snap_gen) : Single_vfs_handle(ds, fs, alloc, 0), - _w(w), _snap_id(snap_id) + _w(w), _snap_gen(snap_gen) { } Read_result read(Byte_range_ptr const &dst, size_t &out_count) override @@ -1387,7 +1380,7 @@ class Vfs_tresor::Data_file_system : public Single_file_system using Op = Tresor::Request::Operation; bool const accepted = - _w.submit_frontend_request(*this, dst, Op::READ, _snap_id); + _w.submit_frontend_request(*this, dst, Op::READ, _snap_gen); if (!accepted) { return READ_ERR_IO; } } @@ -1436,11 +1429,9 @@ class Vfs_tresor::Data_file_system : public Single_file_system using Op = Tresor::Request::Operation; bool const accepted = - _w.submit_frontend_request(*this, - Byte_range_ptr( - const_cast(src.start), - src.num_bytes), - Op::WRITE, _snap_id); + _w.submit_frontend_request( + *this, Byte_range_ptr(const_cast(src.start), src.num_bytes), + Op::WRITE, _snap_gen); if (!accepted) { return WRITE_ERR_IO; } } @@ -1518,11 +1509,11 @@ class Vfs_tresor::Data_file_system : public Single_file_system bool write_ready() const override { return true; } }; - Data_file_system(Wrapper &w, uint32_t snap_id) + Data_file_system(Wrapper &w, Generation snap_gen) : Single_file_system(Node_type::CONTINUOUS_FILE, type_name(), Node_rwx::rw(), Xml_node("")), - _w(w), _snap_id(snap_id) + _w(w), _snap_gen(snap_gen) { } ~Data_file_system() { /* XXX sync on close */ } @@ -1576,7 +1567,7 @@ class Vfs_tresor::Data_file_system : public Single_file_system } *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w, _snap_id); + new (alloc) Vfs_handle(*this, *this, alloc, _w, _snap_gen); return OPEN_OK; } @@ -2498,16 +2489,13 @@ class Vfs_tresor::Create_snapshot_file_system : public Vfs::Single_file_system bool create_snapshot { false }; Genode::ascii_to(src.start, create_snapshot); Genode::String<64> str(Genode::Cstring(src.start, src.num_bytes)); - - if (!create_snapshot) { + if (!create_snapshot) return WRITE_ERR_IO; - } if (!_w.create_snapshot()) { out_count = 0; return WRITE_OK; } - out_count = src.num_bytes; return WRITE_OK; } @@ -2596,18 +2584,15 @@ class Vfs_tresor::Discard_snapshot_file_system : public Vfs::Single_file_system size_t &out_count) override { out_count = 0; - - Genode::uint64_t id { 0 }; - Genode::ascii_to(src.start, id); - if (id == 0) { + Generation snap_gen { INVALID_GENERATION }; + Genode::ascii_to(src.start, snap_gen); + if (snap_gen == INVALID_GENERATION) return WRITE_ERR_IO; - } - if (!_w.discard_snapshot(Tresor::Generation { id })) { + if (!_w.discard_snapshot(snap_gen)) { out_count = 0; return WRITE_OK; } - return WRITE_ERR_IO; } @@ -2672,8 +2657,8 @@ struct Vfs_tresor::Snapshot_local_factory : File_system_factory Snapshot_local_factory(Vfs::Env & /* env */, Wrapper &tresor, - uint32_t snap_id) - : _block_fs(tresor, snap_id) { } + Generation snap_gen) + : _block_fs(tresor, snap_gen) { } Vfs::File_system *create(Vfs::Env&, Xml_node node) override { @@ -2690,20 +2675,17 @@ class Vfs_tresor::Snapshot_file_system : private Snapshot_local_factory, { private: - Genode::uint32_t _snap_id; + Generation _snap_gen; typedef String<128> Config; - static Config _config(Genode::uint32_t snap_id, bool readonly) + static Config _config(Generation snap_gen, bool readonly) { char buf[Config::capacity()] { }; Xml_generator xml(buf, sizeof(buf), "dir", [&] () { - xml.attribute("name", - !readonly ? String<16>("current") - : String<16>(snap_id)); - + xml.attribute("name", !readonly ? String<16>("current") : String<16>(snap_gen)); xml.node("data", [&] () { xml.attribute("readonly", readonly); }); @@ -2714,26 +2696,21 @@ class Vfs_tresor::Snapshot_file_system : private Snapshot_local_factory, public: - Snapshot_file_system(Vfs::Env &vfs_env, - Wrapper &tresor, - Genode::uint32_t snap_id, - bool readonly = false) + Snapshot_file_system(Vfs::Env &vfs_env, + Wrapper &tresor, + Generation snap_gen, + bool readonly = false) : - Snapshot_local_factory(vfs_env, tresor, snap_id), - Vfs::Dir_file_system(vfs_env, - Xml_node(_config(snap_id, readonly).string()), - *this), - _snap_id(snap_id) + Snapshot_local_factory(vfs_env, tresor, snap_gen), + Vfs::Dir_file_system(vfs_env, Xml_node(_config(snap_gen, readonly).string()), *this), + _snap_gen(snap_gen) { } static char const *type_name() { return "snapshot"; } char const *type() override { return type_name(); } - Genode::uint32_t snapshot_id() const - { - return _snap_id; - } + Generation snap_gen() const { return _snap_gen; } }; @@ -2794,34 +2771,32 @@ class Vfs_tresor::Snapshots_file_system : public Vfs::File_system return *fsp; } - Snapshot_file_system &_by_id(uint32_t id) + Snapshot_file_system &_by_gen(Generation snap_gen) { Snapshot_file_system *fsp { nullptr }; auto lookup = [&] (Snapshot_file_system &fs) { - if (fs.snapshot_id() == id) { + if (fs.snap_gen() == snap_gen) { fsp = &fs; } }; _registry.for_each(lookup); - if (fsp == nullptr) { + if (fsp == nullptr) throw Invalid_path(); - } + return *fsp; } Snapshot_file_system &by_path(char const *path) { - if (!path) { + if (!path) throw Invalid_path(); - } - if (path[0] == '/') { + if (path[0] == '/') path++; - } - uint32_t id { 0 }; - Genode::ascii_to(path, id); - return _by_id(id); + Generation snap_gen { INVALID_GENERATION }; + Genode::ascii_to(path, snap_gen); + return _by_gen(snap_gen); } }; @@ -2896,7 +2871,7 @@ class Vfs_tresor::Snapshots_file_system : public Vfs::File_system try { Snapshot_file_system const &fs = _snap_reg.by_index(index); - Genode::String<32> name { fs.snapshot_id() }; + Genode::String<32> name { fs.snap_gen() }; out = { .fileno = (Genode::addr_t)this | index, @@ -3572,13 +3547,13 @@ void Vfs_tresor::Snapshots_file_system::Snapshot_registry::update(Vfs::Env &vfs_ /* alloc new */ for (size_t i = 0; i < MAX_NR_OF_SNAPSHOTS; i++) { - uint32_t const id = (uint32_t)generations.items[i]; - if (!id) { + Generation const snap_gen = generations.items[i]; + if (snap_gen == INVALID_GENERATION) continue; - } + bool is_old = false; auto find_old = [&] (Snapshot_file_system const &fs) { - is_old |= (fs.snapshot_id() == id); + is_old |= (fs.snap_gen() == snap_gen); }; _registry.for_each(find_old); @@ -3586,7 +3561,7 @@ void Vfs_tresor::Snapshots_file_system::Snapshot_registry::update(Vfs::Env &vfs_ new (_alloc) Genode::Registered { - _registry, vfs_env, _wrapper, id, true }; + _registry, vfs_env, _wrapper, snap_gen, true }; ++_number_of_snapshots; trigger_watch_response = true; @@ -3598,10 +3573,11 @@ void Vfs_tresor::Snapshots_file_system::Snapshot_registry::update(Vfs::Env &vfs_ { bool is_stale = true; for (size_t i = 0; i < MAX_NR_OF_SNAPSHOTS; i++) { - uint32_t const id = (uint32_t)generations.items[i]; - if (!id) { continue; } + Generation const snap_gen = generations.items[i]; + if (snap_gen == INVALID_GENERATION) + continue; - if (fs.snapshot_id() == id) { + if (fs.snap_gen() == snap_gen) { is_stale = false; break; }