From d8a71e5978ede0ee0ca035804f3ce8178eb11601 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Fri, 4 Aug 2023 05:36:05 +0200 Subject: [PATCH] tresor: improved module framework and clean-up * Make command pool a proper module * The command pool used to be kind of a module but it was driven via custom tresor-tester specific code. Now, it becomes a proper module that is driven by the module framework instead. * Move the code for creating and handling the module-execution progress flag into Module_composition::execute_modules as the function is always used with this code surrounding it. * Reorganize files, remove deprecated files * A new class Module_channel is introduced in the module framework and all channel classes inherit from it. With that class in place, the formerly module-specific implementations of the following methods are replaced by new generic implementations in the Module framework: * ready_to_submit_request * submit_request * _peek_completed_request * _drop_completed_request * _peek_generated_request * _drop_generated_request * generated_request_complete * Module requests are now held for the duration of their lifetime at the module they originate from and not, like before, at their target module. As a result, modules can generate new requests inline (without having to wait for the target module), making code much simpler to read, reducing the amount of channel state, and allowing for non-copyable request types. * Introduce a sub-state-machine for securing a superblock in the superblock_control module in order to reduce redundancy. * Some modules, like free_tree, were completely re-designed in order to make them more readable. * Replace all conditional exceptions by using the macros in tresor/assertion.h . * Move methods that are used in multiple modules but that were implemented redundantly in each module to tresor/types.h. * Remove verbosity node and all that was related to it from tresor tester config as the targeted verbosity can be achieved with the VERBOSE_MODULE_COMMUNICATION flag in tresor/verbosity.h . * Extract the aspect of translating the byte-granular I/O-requests to tresor-block requests from the tresor VFS-plugin and move it to a new module called splitter. * Rename the files and interface of the hashing back-end to not reflect the used hashing algorithm/config anymore, while at the same time making the hashing interface strict regarding the used types. * Introduce the NONCOPYABLE macro that makes marking a class noncopyable short and clear. * Replace the former tresor/vfs_utilities.h/.cc with a new tresor/file.h that contains the classes Read_write_file and Write_only_file. These classes significantly simplify the modules crypto, block_io, and trust_anchor by moving the details of file access to a sub-state machine. * The former, rather trivial block allocator module is replaced by a normal object of type Pba_allocator that must be provided by the client of the Sb_initializer (reference in the Sb_initializer_request). Ref #5062 tresor: read uninitialized vbas as all zeroes Virtual addresses in a Tresor container that were not yet written by the user should always return a data block that is all-zeroes. This was the concept right from the beginning of the project. However, somehow this aspect either never got implement or got lost along the way. Some context for understanding the commit: The Tresor doesn't initialize the payload data blocks of a container when creating a new container as this would be rather expensive. Instead, it marks the leaf metadata nodes of the virtual-block-device tree (those that reference the payload data blocks in physical address space) with generation 0. Now, this commit ensures that, whenever the virtual-block-device module reads such a generation-0 leaf, instead of asking the block_io and crypto to deliver data from disc, it directly provides the user with 4K of zeroes. Ref #5062 --- repos/gems/lib/mk/tresor.mk | 5 +- repos/gems/lib/mk/vfs_tresor.mk | 2 +- .../gems/lib/mk/vfs_tresor_crypto_aes_cbc.mk | 8 +- .../gems/lib/mk/vfs_tresor_crypto_memcopy.mk | 8 +- repos/gems/recipes/api/tresor/used_apis | 1 - repos/gems/recipes/src/tresor/content.mk | 4 +- repos/gems/run/tresor_tester.run | 25 +- repos/gems/src/app/file_vault/main.cc | 12 +- repos/gems/src/app/file_vault/sandbox.h | 6 +- repos/gems/src/app/file_vault/types.h | 1 - repos/gems/src/app/tresor_check/main.cc | 2 +- .../include/tresor_init}/configuration.h | 57 +- repos/gems/src/app/tresor_init/main.cc | 241 +- repos/gems/src/app/tresor_init/target.mk | 7 +- .../app/tresor_init_trust_anchor/component.cc | 17 +- .../app/tresor_init_trust_anchor/target.mk | 8 +- repos/gems/src/app/tresor_tester/crypto.cc | 339 --- repos/gems/src/app/tresor_tester/main.cc | 1819 ++++-------- .../gems/src/app/tresor_tester/module_type.h | 75 - repos/gems/src/app/tresor_tester/target.mk | 1 + .../gems/src/app/tresor_tester/verbose_node.h | 63 - repos/gems/src/lib/tresor/block_allocator.cc | 197 -- repos/gems/src/lib/tresor/block_io.cc | 712 +---- repos/gems/src/lib/tresor/crypto.cc | 808 ++---- repos/gems/src/lib/tresor/free_tree.cc | 1295 +++------ repos/gems/src/lib/tresor/ft_check.cc | 531 +--- repos/gems/src/lib/tresor/ft_initializer.cc | 822 +----- repos/gems/src/lib/tresor/ft_resizing.cc | 843 ------ repos/gems/src/lib/tresor/hash.cc | 43 + .../tresor/include/tresor/block_allocator.h | 141 - .../src/lib/tresor/include/tresor/block_io.h | 216 +- .../lib/tresor/include/tresor/client_data.h | 77 +- .../tresor/include/tresor/construct_in_buf.h | 38 - .../src/lib/tresor/include/tresor/crypto.h | 248 +- .../gems/src/lib/tresor/include/tresor/file.h | 232 ++ .../src/lib/tresor/include/tresor/free_tree.h | 534 +--- .../src/lib/tresor/include/tresor/ft_check.h | 186 +- .../tresor/include/tresor/ft_initializer.h | 226 +- .../lib/tresor/include/tresor/ft_resizing.h | 257 -- .../gems/src/lib/tresor/include/tresor/hash.h | 29 + .../gems/src/lib/tresor/include/tresor/math.h | 15 +- .../src/lib/tresor/include/tresor/meta_tree.h | 236 +- .../src/lib/tresor/include/tresor/module.h | 318 +- .../lib/tresor/include/tresor/noncopyable.h | 21 + .../lib/tresor/include/tresor/request_pool.h | 588 +--- .../src/lib/tresor/include/tresor/sb_check.h | 147 +- .../tresor/include/tresor/sb_initializer.h | 205 +- .../tresor/include/tresor/sha256_4k_hash.h | 30 - .../include/tresor/superblock_control.h | 439 +-- .../lib/tresor/include/tresor/trust_anchor.h | 195 +- .../src/lib/tresor/include/tresor/types.h | 254 +- .../src/lib/tresor/include/tresor/vbd_check.h | 170 +- .../tresor/include/tresor/vbd_initializer.h | 192 +- .../src/lib/tresor/include/tresor/verbosity.h | 2 + .../lib/tresor/include/tresor/vfs_utilities.h | 35 - .../include/tresor/virtual_block_device.h | 449 +-- repos/gems/src/lib/tresor/meta_tree.cc | 833 ++---- repos/gems/src/lib/tresor/module.cc | 131 +- repos/gems/src/lib/tresor/request_pool.cc | 1083 ++----- repos/gems/src/lib/tresor/sb_check.cc | 551 +--- repos/gems/src/lib/tresor/sb_initializer.cc | 764 +---- repos/gems/src/lib/tresor/sha256_4k_hash.cc | 50 - .../gems/src/lib/tresor/superblock_control.cc | 2213 +++----------- repos/gems/src/lib/tresor/trust_anchor.cc | 623 +--- repos/gems/src/lib/tresor/vbd_check.cc | 546 +--- repos/gems/src/lib/tresor/vbd_initializer.cc | 645 +---- repos/gems/src/lib/tresor/vfs_utilities.cc | 55 - .../src/lib/tresor/virtual_block_device.cc | 2550 ++++------------- repos/gems/src/lib/vfs/tresor/splitter.cc | 225 ++ repos/gems/src/lib/vfs/tresor/splitter.h | 156 + repos/gems/src/lib/vfs/tresor/vfs.cc | 2035 ++++++------- .../tresor_crypto/{aes_cbc => }/aes_cbc.cc | 9 +- .../lib/vfs/tresor_crypto/aes_cbc/dummy.ads | 17 - .../crypto => vfs/tresor_crypto}/interface.h | 0 .../tresor_crypto/{memcopy => }/memcopy.cc | 6 +- repos/gems/src/lib/vfs/tresor_crypto/vfs.cc | 4 +- .../vfs => vfs/tresor_trust_anchor}/io_job.h | 0 .../src/lib/vfs/tresor_trust_anchor/vfs.cc | 6 +- 78 files changed, 6824 insertions(+), 19110 deletions(-) rename repos/gems/src/{lib/tresor/include/tresor/init => app/tresor_init/include/tresor_init}/configuration.h (56%) delete mode 100644 repos/gems/src/app/tresor_tester/crypto.cc delete mode 100644 repos/gems/src/app/tresor_tester/module_type.h delete mode 100644 repos/gems/src/app/tresor_tester/verbose_node.h delete mode 100644 repos/gems/src/lib/tresor/block_allocator.cc delete mode 100644 repos/gems/src/lib/tresor/ft_resizing.cc create mode 100644 repos/gems/src/lib/tresor/hash.cc delete mode 100644 repos/gems/src/lib/tresor/include/tresor/block_allocator.h delete mode 100644 repos/gems/src/lib/tresor/include/tresor/construct_in_buf.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/file.h delete mode 100644 repos/gems/src/lib/tresor/include/tresor/ft_resizing.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/hash.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/noncopyable.h delete mode 100644 repos/gems/src/lib/tresor/include/tresor/sha256_4k_hash.h delete mode 100644 repos/gems/src/lib/tresor/include/tresor/vfs_utilities.h delete mode 100644 repos/gems/src/lib/tresor/sha256_4k_hash.cc delete mode 100644 repos/gems/src/lib/tresor/vfs_utilities.cc create mode 100644 repos/gems/src/lib/vfs/tresor/splitter.cc create mode 100644 repos/gems/src/lib/vfs/tresor/splitter.h rename repos/gems/src/lib/vfs/tresor_crypto/{aes_cbc => }/aes_cbc.cc (98%) delete mode 100644 repos/gems/src/lib/vfs/tresor_crypto/aes_cbc/dummy.ads rename repos/gems/src/lib/{tresor/include/tresor/crypto => vfs/tresor_crypto}/interface.h (100%) rename repos/gems/src/lib/vfs/tresor_crypto/{memcopy => }/memcopy.cc (97%) rename repos/gems/src/lib/{tresor/include/tresor/vfs => vfs/tresor_trust_anchor}/io_job.h (100%) diff --git a/repos/gems/lib/mk/tresor.mk b/repos/gems/lib/mk/tresor.mk index 819df67069..bcf420be6f 100644 --- a/repos/gems/lib/mk/tresor.mk +++ b/repos/gems/lib/mk/tresor.mk @@ -2,7 +2,7 @@ TRESOR_DIR := $(REP_DIR)/src/lib/tresor SRC_CC += crypto.cc SRC_CC += request_pool.cc -SRC_CC += sha256_4k_hash.cc +SRC_CC += hash.cc SRC_CC += trust_anchor.cc SRC_CC += block_io.cc SRC_CC += meta_tree.cc @@ -10,12 +10,9 @@ SRC_CC += virtual_block_device.cc SRC_CC += superblock_control.cc SRC_CC += free_tree.cc SRC_CC += module.cc -SRC_CC += block_allocator.cc SRC_CC += vbd_initializer.cc SRC_CC += ft_initializer.cc SRC_CC += sb_initializer.cc -SRC_CC += vfs_utilities.cc -SRC_CC += ft_resizing.cc SRC_CC += sb_check.cc SRC_CC += vbd_check.cc SRC_CC += ft_check.cc diff --git a/repos/gems/lib/mk/vfs_tresor.mk b/repos/gems/lib/mk/vfs_tresor.mk index 549024bf5c..88ed1baf9e 100644 --- a/repos/gems/lib/mk/vfs_tresor.mk +++ b/repos/gems/lib/mk/vfs_tresor.mk @@ -1,6 +1,6 @@ LIB_DIR := $(REP_DIR)/src/lib/vfs/tresor -SRC_CC := vfs.cc +SRC_CC := vfs.cc splitter.cc INC_DIR += $(LIB_DIR) diff --git a/repos/gems/lib/mk/vfs_tresor_crypto_aes_cbc.mk b/repos/gems/lib/mk/vfs_tresor_crypto_aes_cbc.mk index b534ccdf57..48a5c79325 100644 --- a/repos/gems/lib/mk/vfs_tresor_crypto_aes_cbc.mk +++ b/repos/gems/lib/mk/vfs_tresor_crypto_aes_cbc.mk @@ -1,11 +1,11 @@ -SRC_CC := vfs.cc +SRC_CC += vfs.cc SRC_CC += aes_cbc.cc +vpath % $(REP_DIR)/src/lib/vfs/tresor_crypto + +INC_DIR += $(REP_DIR)/src/lib/vfs/tresor_crypto INC_DIR += $(REP_DIR)/src/lib/tresor/include LIBS += aes_cbc_4k -vpath vfs.cc $(REP_DIR)/src/lib/vfs/tresor_crypto/ -vpath % $(REP_DIR)/src/lib/vfs/tresor_crypto/aes_cbc - SHARED_LIB = yes diff --git a/repos/gems/lib/mk/vfs_tresor_crypto_memcopy.mk b/repos/gems/lib/mk/vfs_tresor_crypto_memcopy.mk index e1afc52178..d45b47a49c 100644 --- a/repos/gems/lib/mk/vfs_tresor_crypto_memcopy.mk +++ b/repos/gems/lib/mk/vfs_tresor_crypto_memcopy.mk @@ -1,9 +1,9 @@ -SRC_CC := vfs.cc +SRC_CC += vfs.cc SRC_CC += memcopy.cc +vpath %.cc $(REP_DIR)/src/lib/vfs/tresor_crypto + +INC_DIR += $(REP_DIR)/src/lib/vfs/tresor_crypto INC_DIR += $(REP_DIR)/src/lib/tresor/include -vpath vfs.cc $(REP_DIR)/src/lib/vfs/tresor_crypto/ -vpath %.cc $(REP_DIR)/src/lib/vfs/tresor_crypto/memcopy - SHARED_LIB = yes diff --git a/repos/gems/recipes/api/tresor/used_apis b/repos/gems/recipes/api/tresor/used_apis index 02144b4883..9e40e72e8c 100644 --- a/repos/gems/recipes/api/tresor/used_apis +++ b/repos/gems/recipes/api/tresor/used_apis @@ -1,6 +1,5 @@ aes_cbc_4k base -block_session libc openssl os diff --git a/repos/gems/recipes/src/tresor/content.mk b/repos/gems/recipes/src/tresor/content.mk index 346d7c720d..a6454fbe31 100644 --- a/repos/gems/recipes/src/tresor/content.mk +++ b/repos/gems/recipes/src/tresor/content.mk @@ -7,9 +7,7 @@ MIRROR_FROM_REP_DIR := \ lib/mk/vfs_tresor_crypto_memcopy.mk \ lib/mk/vfs_tresor_trust_anchor.mk \ src/lib/vfs/tresor \ - src/lib/vfs/tresor_crypto/vfs.cc \ - src/lib/vfs/tresor_crypto/aes_cbc \ - src/lib/vfs/tresor_crypto/memcopy \ + src/lib/vfs/tresor_crypto \ src/lib/vfs/tresor_trust_anchor \ src/app/tresor_init \ src/app/tresor_init_trust_anchor \ diff --git a/repos/gems/run/tresor_tester.run b/repos/gems/run/tresor_tester.run index 8b398626f8..fea87d9456 100644 --- a/repos/gems/run/tresor_tester.run +++ b/repos/gems/run/tresor_tester.run @@ -222,17 +222,6 @@ append config { - - @@ -349,11 +338,10 @@ append config { - + - - + @@ -382,7 +370,6 @@ append config { - @@ -392,7 +379,8 @@ append config { - + + @@ -1073,15 +1061,14 @@ if {[benchmark_blk_count] > 0} { } append config { - + - - + diff --git a/repos/gems/src/app/file_vault/main.cc b/repos/gems/src/app/file_vault/main.cc index 5d4b028467..9df6d65696 100644 --- a/repos/gems/src/app/file_vault/main.cc +++ b/repos/gems/src/app/file_vault/main.cc @@ -52,10 +52,10 @@ struct File_vault::Ui_config { using Version_string = String<80>; - Version_string const version { }; - Passphrase_string const passphrase { }; - Number_of_bytes const client_fs_size { 0 }; - Number_of_bytes const journaling_buf_size { 0 }; + Version_string const version { }; + Passphrase const passphrase { }; + Number_of_bytes const client_fs_size { 0 }; + Number_of_bytes const journaling_buf_size { 0 }; Ui_config() { } @@ -63,7 +63,7 @@ struct File_vault::Ui_config bool verbose) : version { node.attribute_value("version", Version_string { }) }, - passphrase { node.attribute_value("passphrase", Passphrase_string { }) }, + passphrase { node.attribute_value("passphrase", Passphrase { }) }, client_fs_size { node.attribute_value("client_fs_size", Number_of_bytes { 0 }) }, journaling_buf_size { node.attribute_value("journaling_buf_size", Number_of_bytes { 0 }) } { @@ -495,7 +495,7 @@ class File_vault::Main throw Exception_1 { }; } - Passphrase_string _ui_setup_obtain_params_passphrase() const + Passphrase _ui_setup_obtain_params_passphrase() const { switch (_user_interface) { case MENU_VIEW: return _setup_obtain_params_passphrase.plaintext().string(); diff --git a/repos/gems/src/app/file_vault/sandbox.h b/repos/gems/src/app/file_vault/sandbox.h index 84decbb735..0087da5a4d 100644 --- a/repos/gems/src/app/file_vault/sandbox.h +++ b/repos/gems/src/app/file_vault/sandbox.h @@ -642,9 +642,9 @@ namespace File_vault { }); } - void gen_tresor_init_trust_anchor_start_node(Xml_generator &xml, - Child_state const &child, - Passphrase_string const &passphrase) + void gen_tresor_init_trust_anchor_start_node(Xml_generator &xml, + Child_state const &child, + Passphrase const &passphrase) { child.gen_start_node(xml, [&] () { diff --git a/repos/gems/src/app/file_vault/types.h b/repos/gems/src/app/file_vault/types.h index 953271b018..80d45bfd2b 100644 --- a/repos/gems/src/app/file_vault/types.h +++ b/repos/gems/src/app/file_vault/types.h @@ -25,7 +25,6 @@ namespace File_vault { using namespace Genode; using Node_name = String<32>; - using Passphrase_string = String<64>; using File_path = String<32>; class Tree_geometry diff --git a/repos/gems/src/app/tresor_check/main.cc b/repos/gems/src/app/tresor_check/main.cc index 81066179a1..9cbb0a4838 100644 --- a/repos/gems/src/app/tresor_check/main.cc +++ b/repos/gems/src/app/tresor_check/main.cc @@ -1,5 +1,5 @@ /* - * \brief Integration of the Tresor block encryption + * \brief Verify the dimensions and hashes of a tresor container * \author Martin Stein * \author Josef Soentgen * \date 2020-11-10 diff --git a/repos/gems/src/lib/tresor/include/tresor/init/configuration.h b/repos/gems/src/app/tresor_init/include/tresor_init/configuration.h similarity index 56% rename from repos/gems/src/lib/tresor/include/tresor/init/configuration.h rename to repos/gems/src/app/tresor_init/include/tresor_init/configuration.h index fbfdfa263d..802a7e1bed 100644 --- a/repos/gems/src/lib/tresor/include/tresor/init/configuration.h +++ b/repos/gems/src/app/tresor_init/include/tresor_init/configuration.h @@ -12,8 +12,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _TRESOR__INIT__CONFIGURATION_H_ -#define _TRESOR__INIT__CONFIGURATION_H_ +#ifndef _TRESOR_INIT__CONFIGURATION_H_ +#define _TRESOR_INIT__CONFIGURATION_H_ /* base includes */ #include @@ -40,49 +40,35 @@ class Tresor_init::Configuration uint64_t _ft_nr_of_children { 0 }; uint64_t _ft_nr_of_leafs { 0 }; - static bool _is_power_of_2(uint64_t val) - { - for (; val && (val & 1) == 0; val >>= 1); - return val == 1; - } - public: struct Invalid : Exception { }; Configuration (Xml_node const &node) { - node.with_optional_sub_node("virtual-block-device", - [&] (Xml_node const &vbd) + node.with_optional_sub_node("virtual-block-device", [&] (Xml_node const &vbd) { - _vbd_nr_of_lvls = - vbd.attribute_value("nr_of_levels", (uint64_t)0); - _vbd_nr_of_children = - vbd.attribute_value("nr_of_children", (uint64_t)0); - _vbd_nr_of_leafs = - vbd.attribute_value("nr_of_leafs", (uint64_t)0); + _vbd_nr_of_lvls = vbd.attribute_value("nr_of_levels", (uint64_t)0); + _vbd_nr_of_children = vbd.attribute_value("nr_of_children", (uint64_t)0); + _vbd_nr_of_leafs = vbd.attribute_value("nr_of_leafs", (uint64_t)0); }); - node.with_optional_sub_node("free-tree", - [&] (Xml_node const &ft) + node.with_optional_sub_node("free-tree", [&] (Xml_node const &ft) { - _ft_nr_of_lvls = - ft.attribute_value("nr_of_levels", (uint64_t)0); - _ft_nr_of_children = - ft.attribute_value("nr_of_children", (uint64_t)0); - _ft_nr_of_leafs = - ft.attribute_value("nr_of_leafs", (uint64_t)0); + _ft_nr_of_lvls = ft.attribute_value("nr_of_levels", (uint64_t)0); + _ft_nr_of_children = ft.attribute_value("nr_of_children", (uint64_t)0); + _ft_nr_of_leafs = ft.attribute_value("nr_of_leafs", (uint64_t)0); }); ASSERT(_vbd_nr_of_lvls); ASSERT(_vbd_nr_of_lvls <= TREE_MAX_NR_OF_LEVELS); ASSERT(_vbd_nr_of_leafs); - ASSERT(_is_power_of_2(_vbd_nr_of_children)); - ASSERT(_vbd_nr_of_children <= NR_OF_T1_NODES_PER_BLK); + ASSERT(is_power_of_2(_vbd_nr_of_children)); + ASSERT(_vbd_nr_of_children <= NUM_NODES_PER_BLK); ASSERT(_ft_nr_of_lvls); ASSERT(_ft_nr_of_lvls <= TREE_MAX_NR_OF_LEVELS); ASSERT(_ft_nr_of_leafs); - ASSERT(_is_power_of_2(_ft_nr_of_children)); - ASSERT(_ft_nr_of_children <= NR_OF_T1_NODES_PER_BLK); - ASSERT(_ft_nr_of_children <= NR_OF_T2_NODES_PER_BLK); + ASSERT(is_power_of_2(_ft_nr_of_children)); + ASSERT(_ft_nr_of_children <= NUM_NODES_PER_BLK); + ASSERT(_ft_nr_of_children <= NUM_NODES_PER_BLK); } Configuration (Configuration const &other) @@ -101,17 +87,6 @@ class Tresor_init::Configuration uint64_t ft_nr_of_lvls () const { return _ft_nr_of_lvls ; } uint64_t ft_nr_of_children () const { return _ft_nr_of_children ; } uint64_t ft_nr_of_leafs () const { return _ft_nr_of_leafs ; } - - void print(Output &out) const - { - Genode::print(out, - "vbd=(lvls=", _vbd_nr_of_lvls, - " children=", _vbd_nr_of_children, - " leafs=", _vbd_nr_of_leafs, ")", - " ft=(lvls=", _ft_nr_of_lvls, - " children=", _ft_nr_of_children, - " leafs=", _ft_nr_of_leafs, ")"); - } }; -#endif /* _TRESOR__INIT__CONFIGURATION_H_ */ +#endif /* _TRESOR_INIT__CONFIGURATION_H_ */ diff --git a/repos/gems/src/app/tresor_init/main.cc b/repos/gems/src/app/tresor_init/main.cc index 6a45214c3a..2d818e8e04 100644 --- a/repos/gems/src/app/tresor_init/main.cc +++ b/repos/gems/src/app/tresor_init/main.cc @@ -16,221 +16,110 @@ #include #include #include -#include -#include -#include -#include #include /* tresor includes */ -#include -#include #include #include +#include #include #include -#include #include - -enum { VERBOSE = 0 }; +/* tresor init includes */ +#include using namespace Genode; using namespace Tresor; -static Block_allocator *_block_allocator_ptr; +namespace Tresor_init { class Main; } - -Genode::uint64_t block_allocator_first_block() -{ - if (!_block_allocator_ptr) { - struct Exception_1 { }; - throw Exception_1(); - } - - return _block_allocator_ptr->first_block(); -} - - -Genode::uint64_t block_allocator_nr_of_blks() -{ - if (!_block_allocator_ptr) { - struct Exception_1 { }; - throw Exception_1(); - } - - return _block_allocator_ptr->nr_of_blks(); -} - - -class Main -: - private Vfs::Env::User, - private Tresor::Module_composition, - public Tresor::Module +class Tresor_init::Main : private Vfs::Env::User, private Tresor::Module_composition, public Tresor::Module, public Module_channel { private: - /* - * Noncopyable - */ - Main(Main const &) = delete; - Main &operator = (Main const &) = delete; + enum State { INIT, REQ_GENERATED, INIT_SBS_SUCCEEDED }; Env &_env; Heap _heap { _env.ram(), _env.rm() }; - Attached_rom_dataspace _config_rom { _env, "config" }; - - Vfs::Simple_env _vfs_env { _env, _heap, _config_rom.xml().sub_node("vfs"), *this }; - Vfs::File_system &_vfs { _vfs_env.root_dir() }; - Signal_handler
_sigh { _env.ep(), *this, &Main::_execute }; - - Constructible _cfg { }; - - Trust_anchor _trust_anchor { _vfs_env, _config_rom.xml().sub_node("trust-anchor") }; - Crypto _crypto { _vfs_env, _config_rom.xml().sub_node("crypto") }; - Block_io _block_io { _vfs_env, _config_rom.xml().sub_node("block-io") }; - Block_allocator _block_allocator { NR_OF_SUPERBLOCK_SLOTS }; + Vfs::Simple_env _vfs_env { _env, _heap, _config_rom.xml().sub_node("vfs"), *this }; + Signal_handler
_sigh { _env.ep(), *this, &Main::_handle_signal }; + Constructible _cfg { }; + Trust_anchor _trust_anchor { _vfs_env, _config_rom.xml().sub_node("trust-anchor") }; + Crypto _crypto { _vfs_env, _config_rom.xml().sub_node("crypto") }; + Block_io _block_io { _vfs_env, _config_rom.xml().sub_node("block-io") }; + Pba_allocator _pba_alloc { NR_OF_SUPERBLOCK_SLOTS }; Vbd_initializer _vbd_initializer { }; - Ft_initializer _ft_initializer { }; - Sb_initializer _sb_initializer { }; + Ft_initializer _ft_initializer { }; + Sb_initializer _sb_initializer { }; + bool _generated_req_success { }; + State _state { INIT }; + + NONCOPYABLE(Main); + + void _generated_req_completed(State_uint state_uint) override + { + if (!_generated_req_success) { + error("command pool: request failed because generated request failed)"); + _env.parent().exit(-1); + return; + } + _state = (State)state_uint; + } - /** - * Vfs::Env::User interface - */ void wakeup_vfs_user() override { _sigh.local_submit(); } - void _execute() + void _wakeup_back_end_services() { _vfs_env.io().commit(); } + + void _handle_signal() { - bool progress { true }; - while (progress) { - - progress = false; - execute_modules(progress); - } - - _vfs_env.io().commit(); - - if (_state == COMPLETE) - _env.parent().exit(0); - } - - /**************** - ** Module API ** - ****************/ - - enum State { INVALID, PENDING, IN_PROGRESS, COMPLETE }; - - State _state { INVALID }; - - bool _peek_generated_request(Genode::uint8_t *buf_ptr, - Genode::size_t buf_size) override - { - if (_state != PENDING) - return false; - - Sb_initializer_request::create( - buf_ptr, buf_size, COMMAND_POOL, 0, - (unsigned long)Sb_initializer_request::INIT, - (Tree_level_index)_cfg->vbd_nr_of_lvls() - 1, - (Tree_degree)_cfg->vbd_nr_of_children(), - _cfg->vbd_nr_of_leafs(), - (Tree_level_index)_cfg->ft_nr_of_lvls() - 1, - (Tree_degree)_cfg->ft_nr_of_children(), - _cfg->ft_nr_of_leafs(), - (Tree_level_index)_cfg->ft_nr_of_lvls() - 1, - (Tree_degree)_cfg->ft_nr_of_children(), - _cfg->ft_nr_of_leafs()); - - return true; - } - - void _drop_generated_request(Module_request &mod_req) override - { - if (_state != PENDING) { - class Exception_1 { }; - throw Exception_1 { }; - } - - switch (mod_req.dst_module_id()) { - case SB_INITIALIZER: - _state = IN_PROGRESS; - break; - default: - class Exception_2 { }; - throw Exception_2 { }; - } - } - - void generated_request_complete(Module_request &mod_req) override - { - if (_state != IN_PROGRESS) { - class Exception_1 { }; - throw Exception_1 { }; - } - - switch (mod_req.dst_module_id()) { - case SB_INITIALIZER: - _state = COMPLETE; - break; - default: - class Exception_2 { }; - throw Exception_2 { }; - } + execute_modules(); + _wakeup_back_end_services(); } public: - Main(Env &env) : _env { env } + Main(Env &env) : Module_channel { COMMAND_POOL, 0 }, _env { env } { - add_module(COMMAND_POOL, *this); - add_module(CRYPTO, _crypto); - add_module(TRUST_ANCHOR, _trust_anchor); - add_module(BLOCK_IO, _block_io); - add_module(BLOCK_ALLOCATOR, _block_allocator); - add_module(VBD_INITIALIZER, _vbd_initializer); - add_module(FT_INITIALIZER, _ft_initializer); - add_module(SB_INITIALIZER, _sb_initializer); + add_module(COMMAND_POOL, *this); + add_module(CRYPTO, _crypto); + add_module(TRUST_ANCHOR, _trust_anchor); + add_module(BLOCK_IO, _block_io); + add_module(VBD_INITIALIZER, _vbd_initializer); + add_module(FT_INITIALIZER, _ft_initializer); + add_module(SB_INITIALIZER, _sb_initializer); + add_channel(*this); + _cfg.construct(_config_rom.xml()); + _handle_signal(); + } - _block_allocator_ptr = &_block_allocator; + void execute(bool &progress) override + { + switch(_state) { + case INIT: - Xml_node const &config { _config_rom.xml() }; - try { - _cfg.construct(config); - _state = PENDING; + generate_req( + INIT_SBS_SUCCEEDED, progress, (Tree_level_index)_cfg->vbd_nr_of_lvls() - 1, + (Tree_degree)_cfg->vbd_nr_of_children(), _cfg->vbd_nr_of_leafs(), + (Tree_level_index)_cfg->ft_nr_of_lvls() - 1, + (Tree_degree)_cfg->ft_nr_of_children(), _cfg->ft_nr_of_leafs(), + (Tree_level_index)_cfg->ft_nr_of_lvls() - 1, + (Tree_degree)_cfg->ft_nr_of_children(), _cfg->ft_nr_of_leafs(), _pba_alloc, + _generated_req_success); + _state = REQ_GENERATED; + break; - _execute(); - } - catch (Tresor_init::Configuration::Invalid) { - error("bad configuration"); - _env.parent().exit(-1); + case INIT_SBS_SUCCEEDED: _env.parent().exit(0); break; + default: break; } } }; +void Component::construct(Genode::Env &env) { static Tresor_init::Main main { env }; } -void Component::construct(Genode::Env &env) -{ - env.exec_static_constructors(); - - static Main main(env); -} - - -/* - * XXX Libc::Component::construct is needed for linking libcrypto - * because it depends on the libc but does not need to be - * executed. - */ namespace Libc { + struct Env; - - struct Component - { - void construct(Libc::Env &); - }; + struct Component { void construct(Libc::Env &) { } }; } - - -void Libc::Component::construct(Libc::Env &) { } diff --git a/repos/gems/src/app/tresor_init/target.mk b/repos/gems/src/app/tresor_init/target.mk index 4f8be3feda..c4f2e8a042 100644 --- a/repos/gems/src/app/tresor_init/target.mk +++ b/repos/gems/src/app/tresor_init/target.mk @@ -1,10 +1,7 @@ TARGET := tresor_init SRC_CC += main.cc - -INC_DIR += $(PRG_DIR) - -LIBS += base -LIBS += tresor +INC_DIR += $(PRG_DIR)/include +LIBS += base tresor CONFIG_XSD := config.xsd diff --git a/repos/gems/src/app/tresor_init_trust_anchor/component.cc b/repos/gems/src/app/tresor_init_trust_anchor/component.cc index bb26c33951..f15f8c0988 100644 --- a/repos/gems/src/app/tresor_init_trust_anchor/component.cc +++ b/repos/gems/src/app/tresor_init_trust_anchor/component.cc @@ -22,8 +22,11 @@ #include #include -/* Tresor includes */ -#include +/* tresor includes */ +#include + +/* vfs tresor trust anchor includes */ +#include using namespace Genode; @@ -44,8 +47,6 @@ class Main : Vfs::Env::User Vfs::File_system &_vfs { _vfs_env.root_dir() }; - using Initialize_file_buf = Genode::String<32 + 1>; - using String_path = Genode::String<256>; static String_path _config_ta_dir(Xml_node const &node) @@ -82,7 +83,7 @@ class Main : Vfs::Env::User Genode::Constructible _io_job { }; Util::Io_job::Buffer _io_buffer { }; - Initialize_file_buf _initialize_file_buf { }; + Tresor::Passphrase _initialize_file_buf { }; File(char const *base_path, char const *name, @@ -112,7 +113,7 @@ class Main : Vfs::Env::User _vfs.close(_vfs_handle); } - void write_passphrase(Initialize_file_buf const &passphrase) + void write_passphrase(Tresor::Passphrase const &passphrase) { /* copy */ _initialize_file_buf = passphrase; @@ -212,8 +213,8 @@ class Main : Vfs::Env::User { Xml_node const &config { _config_rom.xml() }; - Initialize_file_buf const passphrase = - config.attribute_value("passphrase", Initialize_file_buf()); + Tresor::Passphrase const passphrase = + config.attribute_value("passphrase", Tresor::Passphrase()); if (!passphrase.valid()) { error("mandatory 'passphrase' attribute missing"); diff --git a/repos/gems/src/app/tresor_init_trust_anchor/target.mk b/repos/gems/src/app/tresor_init_trust_anchor/target.mk index 10059681c8..091669dfe4 100644 --- a/repos/gems/src/app/tresor_init_trust_anchor/target.mk +++ b/repos/gems/src/app/tresor_init_trust_anchor/target.mk @@ -1,7 +1,9 @@ -TARGET:= tresor_init_trust_anchor +TARGET := tresor_init_trust_anchor + +SRC_CC += component.cc -SRC_CC := component.cc INC_DIR += $(PRG_DIR) +INC_DIR += $(REP_DIR)/src/lib/vfs/tresor_trust_anchor INC_DIR += $(REP_DIR)/src/lib/tresor/include -LIBS := base vfs +LIBS += base vfs diff --git a/repos/gems/src/app/tresor_tester/crypto.cc b/repos/gems/src/app/tresor_tester/crypto.cc deleted file mode 100644 index ae0c779ee6..0000000000 --- a/repos/gems/src/app/tresor_tester/crypto.cc +++ /dev/null @@ -1,339 +0,0 @@ -/* - * \brief Implementation of the Crypto module API using the Crypto VFS API - * \author Martin Stein - * \date 2020-10-29 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* local includes */ -#include - -using namespace Genode; -using namespace Tresor; -using namespace Vfs; - - -Crypto::Key_directory &Crypto::_get_unused_key_dir() -{ - for (Key_directory &key_dir : _key_dirs) { - if (key_dir.key_id == 0) { - return key_dir; - } - } - class Failed { }; - throw Failed { }; -} - - -Crypto::Key_directory &Crypto::_lookup_key_dir(uint32_t key_id) -{ - for (Key_directory &key_dir : _key_dirs) { - if (key_dir.key_id == key_id) { - return key_dir; - } - } - class Failed { }; - throw Failed { }; -} - - -Crypto::Crypto(Vfs::Env &env, Xml_node const &crypto) -: - _env { env }, - _path { crypto.attribute_value("path", String<32>()) }, - _add_key_handle { vfs_open_wo(env, { _path.string(), "/add_key" }) }, - _remove_key_handle { vfs_open_wo(env, { _path.string(), "/remove_key" }) } -{ } - - -bool Crypto::request_acceptable() const -{ - return _job.op == Operation::INVALID; -} - - -Crypto::Result Crypto::add_key(Key const &key) -{ - char buffer[sizeof (key.value) + sizeof (key.id.value)] { }; - memcpy(buffer, &key.id.value, sizeof (key.id.value)); - memcpy(buffer + sizeof (key.id.value), - key.value, sizeof (key.value)); - - _add_key_handle.seek(0); - - size_t written_bytes = 0; - - using Write_result = Vfs::File_io_service::Write_result; - - Const_byte_range_ptr const src(buffer, sizeof(buffer)); - - Write_result const result = - _add_key_handle.fs().write(&_add_key_handle, src, written_bytes); - - if (result == Write_result::WRITE_ERR_WOULD_BLOCK) - return Result::RETRY_LATER; - - Key_directory &key_dir { _get_unused_key_dir() }; - - key_dir.encrypt_handle = &vfs_open_rw( - _env, { _path.string(), "/keys/", key.id.value, "/encrypt" }); - - key_dir.decrypt_handle = &vfs_open_rw( - _env, { _path.string(), "/keys/", key.id.value, "/decrypt" }); - - key_dir.key_id = key.id.value; - return Result::SUCCEEDED; -} - - -Crypto::Result Crypto::remove_key(Tresor::Key::Id key_id) -{ - size_t written_bytes = 0; - _remove_key_handle.seek(0); - - Const_byte_range_ptr const src((char *)&key_id.value, sizeof(key_id.value)); - - using Write_result = Vfs::File_io_service::Write_result; - - Write_result const result = - _remove_key_handle.fs().write(&_remove_key_handle, src, written_bytes); - - if (result == Write_result::WRITE_ERR_WOULD_BLOCK) - return Result::RETRY_LATER; - - Key_directory &key_dir { _lookup_key_dir(key_id.value) }; - _env.root_dir().close(key_dir.encrypt_handle); - key_dir.encrypt_handle = nullptr; - _env.root_dir().close(key_dir.decrypt_handle); - key_dir.decrypt_handle = nullptr; - key_dir.key_id = 0; - return Result::SUCCEEDED; -} - - -void Crypto::submit_request(Tresor::Request const &request, - Operation op, - Crypto_plain_buffer::Index plain_buf_idx, - Crypto_cipher_buffer::Index cipher_buf_idx) -{ - switch (op) { - case Operation::ENCRYPT_BLOCK: - - _job.request = request; - _job.state = Job_state::SUBMITTED; - _job.op = op; - _job.cipher_buf_idx = cipher_buf_idx; - _job.plain_buf_idx = plain_buf_idx; - _job.handle = - _lookup_key_dir(request.key_id()).encrypt_handle; - - break; - - case Operation::DECRYPT_BLOCK: - - _job.request = request; - _job.state = Job_state::SUBMITTED; - _job.op = op; - _job.cipher_buf_idx = cipher_buf_idx; - _job.plain_buf_idx = plain_buf_idx; - _job.handle = - _lookup_key_dir(request.key_id()).decrypt_handle; - - break; - - case Operation::INVALID: - - class Bad_operation { }; - throw Bad_operation { }; - } -} - - -Tresor::Request Crypto::peek_completed_encryption_request() const -{ - if (_job.state != Job_state::COMPLETE || - _job.op != Operation::ENCRYPT_BLOCK) { - - return Tresor::Request { }; - } - return _job.request; -} - - -Tresor::Request Crypto::peek_completed_decryption_request() const -{ - if (_job.state != Job_state::COMPLETE || - _job.op != Operation::DECRYPT_BLOCK) { - - return Tresor::Request { }; - } - return _job.request; -} - - -void Crypto::drop_completed_request() -{ - if (_job.state != Job_state::COMPLETE) { - - class Bad_state { }; - throw Bad_state { }; - } - _job.op = Operation::INVALID; -} - - -void Crypto::_execute_decrypt_block(Job &job, - Crypto_plain_buffer &plain_buf, - Crypto_cipher_buffer &cipher_buf, - bool &progress) -{ - switch (job.state) { - case Job_state::SUBMITTED: - { - job.handle->seek(job.request.block_number() * Tresor::BLOCK_SIZE); - - size_t written_bytes = 0; - - Const_byte_range_ptr const src( - reinterpret_cast(&cipher_buf.item(job.cipher_buf_idx)), - sizeof(Tresor::Block)); - - job.handle->fs().write( job.handle, src, written_bytes); - - job.state = Job_state::OP_WRITTEN_TO_VFS_HANDLE; - progress = true; - return; - } - case Job_state::OP_WRITTEN_TO_VFS_HANDLE: - { - job.handle->seek(job.request.block_number() * Tresor::BLOCK_SIZE); - bool const success { - job.handle->fs().queue_read( - job.handle, sizeof (Tresor::Block)) }; - - if (!success) { - return; - } - job.state = Job_state::READING_VFS_HANDLE_SUCCEEDED; - progress = true; - break; - } - case Job_state::READING_VFS_HANDLE_SUCCEEDED: - { - size_t read_bytes = 0; - - Byte_range_ptr const dst( - reinterpret_cast(&plain_buf.item(job.plain_buf_idx)), - sizeof(Tresor::Block)); - - Read_result const result = - job.handle->fs().complete_read(job.handle, dst, read_bytes); - - switch (result) { - case Read_result::READ_QUEUED: return; - case Read_result::READ_ERR_WOULD_BLOCK: return; - default: break; - } - job.request.success(result == Read_result::READ_OK); - job.state = Job_state::COMPLETE; - progress = true; - return; - } - default: - - return; - } -} - - -void Crypto::_execute_encrypt_block(Job &job, - Crypto_plain_buffer &plain_buf, - Crypto_cipher_buffer &cipher_buf, - bool &progress) -{ - switch (job.state) { - case Job_state::SUBMITTED: - { - job.handle->seek(job.request.block_number() * Tresor::BLOCK_SIZE); - - size_t written_bytes = 0; - - Const_byte_range_ptr const src( - reinterpret_cast( - &plain_buf.item(job.plain_buf_idx)), - sizeof(Tresor::Block)); - - job.handle->fs().write(job.handle, src, written_bytes); - - job.state = Job_state::OP_WRITTEN_TO_VFS_HANDLE; - progress = true; - return; - } - case Job_state::OP_WRITTEN_TO_VFS_HANDLE: - { - job.handle->seek(job.request.block_number() * Tresor::BLOCK_SIZE); - bool success { - job.handle->fs().queue_read( - job.handle, sizeof (Tresor::Block)) }; - - if (!success) { - return; - } - job.state = Job_state::READING_VFS_HANDLE_SUCCEEDED; - progress = true; - return; - } - case Job_state::READING_VFS_HANDLE_SUCCEEDED: - { - size_t read_bytes = 0; - - Byte_range_ptr const dst( - reinterpret_cast(&cipher_buf.item(job.cipher_buf_idx)), - sizeof (Tresor::Block)); - - Read_result const result = - job.handle->fs().complete_read(job.handle, dst, read_bytes); - - switch (result) { - case Read_result::READ_QUEUED: return; - case Read_result::READ_ERR_WOULD_BLOCK: return; - default: break; - } - job.request.success(result == Read_result::READ_OK); - job.state = Job_state::COMPLETE; - progress = true; - return; - } - default: - - return; - } -} - - -void Crypto::execute(Crypto_plain_buffer &plain_buf, - Crypto_cipher_buffer &cipher_buf, - bool &progress) -{ - switch (_job.op) { - case Operation::ENCRYPT_BLOCK: - - _execute_encrypt_block(_job, plain_buf, cipher_buf, progress); - break; - - case Operation::DECRYPT_BLOCK: - - _execute_decrypt_block(_job, plain_buf, cipher_buf, progress); - break; - - case Operation::INVALID: - - break; - } -} diff --git a/repos/gems/src/app/tresor_tester/main.cc b/repos/gems/src/app/tresor_tester/main.cc index 5d4de78568..e89b01457b 100644 --- a/repos/gems/src/app/tresor_tester/main.cc +++ b/repos/gems/src/app/tresor_tester/main.cc @@ -12,16 +12,16 @@ */ /* base includes */ -#include #include #include #include #include -#include #include +/* tresor init includes */ +#include + /* tresor includes */ -#include #include #include #include @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include @@ -38,219 +37,141 @@ #include #include #include -#include - -/* tresor tester includes */ -#include - -using namespace Genode; -using namespace Tresor; -using namespace Vfs; namespace Tresor_tester { + using namespace Genode; + using namespace Tresor; + + using Salt = uint64_t; + + class Log_node; + class Benchmark_node; + class Benchmark; + class Trust_anchor_node; + class Request_node; + class Command; + class Snapshot_reference; + class Snapshot_reference_tree; + class Client_data; class Main; + + template + T read_attribute(Xml_node const &node, char const *attr) + { + T value { }; + ASSERT(node.has_attribute(attr)); + ASSERT(node.attribute(attr).value(value)); + return value; + } } -template -T read_attribute(Xml_node const &node, - char const *attr) +struct Tresor_tester::Log_node { - T value { }; + using String = Genode::String<128>; - if (!node.has_attribute(attr)) { + String const string; - error("<", node.type(), "> node misses attribute '", attr, "'"); - class Attribute_missing { }; - throw Attribute_missing { }; - } - if (!node.attribute(attr).value(value)) { + NONCOPYABLE(Log_node); - error("<", node.type(), "> node has malformed '", attr, "' attribute"); - class Malformed_attribute { }; - throw Malformed_attribute { }; - } - return value; -} - - -class Log_node -{ - private: - - String<128> const _string; - - public: - - Log_node(Xml_node const &node) - : - _string { node.attribute_value("string", String<128> { }) } - { } - - String<128> const &string() const { return _string; } - - void print(Genode::Output &out) const - { - Genode::print(out, "string=\"", _string, "\""); - } + Log_node(Xml_node const &node) : string { node.attribute_value("string", String { }) } { } }; -class Benchmark_node +struct Tresor_tester::Benchmark_node { - public: + using Label = String<128>; - using Label = String<128>; + enum Operation { START, STOP }; - enum Operation { START, STOP }; + Operation const op; + bool const label_avail; + Label const label; - private: + NONCOPYABLE(Benchmark_node); - Operation const _op; - bool const _label_avail; - Label const _label; + Operation read_op_attr(Xml_node const &node) + { + ASSERT(node.has_attribute("op")); + if (node.attribute("op").has_value("start")) return START; + if (node.attribute("op").has_value("stop")) return STOP; + ASSERT_NEVER_REACHED; + } - Operation _read_op_attr(Xml_node const &node) - { - class Attribute_missing { }; - if (!node.has_attribute("op")) { - throw Attribute_missing { }; - } - if (node.attribute("op").has_value("start")) { - return Operation::START; - } - if (node.attribute("op").has_value("stop")) { - return Operation::STOP; - } - class Malformed_attribute { }; - throw Malformed_attribute { }; - } + Benchmark_node(Xml_node const &node) + : + op { read_op_attr(node) }, label_avail { op == START && node.has_attribute("label") }, + label { label_avail ? node.attribute_value("label", Label { }) : Label { } } + { } - static char const *_op_to_string(Operation op) - { - switch (op) { - case START: return "start"; - case STOP: return "stop"; - } - return "?"; - } - - public: - - bool has_attr_label() const - { - return _op == Operation::START; - } - - Benchmark_node(Xml_node const &node) - : - _op { _read_op_attr(node) }, - _label_avail { has_attr_label() && node.has_attribute("label") }, - _label { _label_avail ? - node.attribute_value("label", Label { }) : - Label { } } - { } - - Operation op() const { return _op; } - bool label_avail() const { return _label_avail; } - Label const &label() const { return _label; } - - void print(Genode::Output &out) const - { - Genode::print(out, "op=", _op_to_string(_op)); - if (_label_avail) { - Genode::print(out, " label=", _label); - } - } + Benchmark_node(Operation op, bool label_avail, Label label) : op(op), label_avail(label_avail), label(label) { } }; -class Benchmark +class Tresor_tester::Benchmark { private: enum State { STARTED, STOPPED }; - Genode::Env &_env; - Timer::Connection _timer { _env }; - State _state { STOPPED }; - Microseconds _start_time { 0 }; - uint64_t _nr_of_virt_blks_read { 0 }; - uint64_t _nr_of_virt_blks_written { 0 }; - Constructible _start_node { }; - uint64_t _id { 0 }; + Genode::Env &_env; + Timer::Connection _timer { _env }; + State _state { STOPPED }; + Microseconds _start_time { 0 }; + Number_of_blocks _num_virt_blks_read { 0 }; + Number_of_blocks _num_virt_blks_written { 0 }; + Benchmark_node const *_start_node_ptr { }; + + NONCOPYABLE(Benchmark); public: Benchmark(Genode::Env &env) : _env { env } { } - void submit_request(Benchmark_node const &node) + void execute_cmd(Benchmark_node const &node) { - switch (node.op()) { + switch (node.op) { case Benchmark_node::START: - if (_state != STOPPED) { - class Bad_state_to_start { }; - throw Bad_state_to_start { }; - } - _id++; - _nr_of_virt_blks_read = 0; - _nr_of_virt_blks_written = 0; + ASSERT(_state == STOPPED); + _num_virt_blks_read = 0; + _num_virt_blks_written = 0; _state = STARTED; - _start_node.construct(node); + _start_node_ptr = &node; _start_time = _timer.curr_time().trunc_to_plain_us(); break; case Benchmark_node::STOP: - if (_state != STARTED) { - class Bad_state_to_stop { }; - throw Bad_state_to_stop { }; - } - uint64_t const stop_time_us { - _timer.curr_time().trunc_to_plain_us().value }; - + ASSERT(_state == STARTED); + uint64_t const stop_time_us { _timer.curr_time().trunc_to_plain_us().value }; log(""); - if (_start_node->label_avail()) { - log("Benchmark result \"", _start_node->label(), "\""); - } else { - log("Benchmark result (command ID ", _id, ")"); - } - - double const passed_time_sec { - (double)(stop_time_us - _start_time.value) / - (double)(1000 * 1000) }; + if (_start_node_ptr->label_avail) + log("Benchmark result \"", _start_node_ptr->label, "\""); + else + log("Benchmark result"); + double const passed_time_sec { (double)(stop_time_us - _start_time.value) / (double)(1000 * 1000) }; log(" Ran ", passed_time_sec, " seconds."); - if (_nr_of_virt_blks_read != 0) { - - uint64_t const bytes_read { - _nr_of_virt_blks_read * Tresor::BLOCK_SIZE }; - - double const mibyte_read { - (double)bytes_read / (double)(1024 * 1024) }; + if (_num_virt_blks_read) { + size_t const bytes_read { _num_virt_blks_read * Tresor::BLOCK_SIZE }; + double const mibyte_read { (double)bytes_read / (double)(1024 * 1024) }; double const mibyte_per_sec_read { - (double)bytes_read / (double)passed_time_sec / - (double)(1024 * 1024) }; + (double)bytes_read / (double)passed_time_sec / (double)(1024 * 1024) }; log(" Have read ", mibyte_read, " mebibyte in total."); log(" Have read ", mibyte_per_sec_read, " mebibyte per second."); } - if (_nr_of_virt_blks_written != 0) { - - uint64_t bytes_written { - _nr_of_virt_blks_written * Tresor::BLOCK_SIZE }; - - double const mibyte_written { - (double)bytes_written / (double)(1024 * 1024) }; + if (_num_virt_blks_written) { + size_t bytes_written { _num_virt_blks_written * Tresor::BLOCK_SIZE }; + double const mibyte_written { (double)bytes_written / (double)(1024 * 1024) }; double const mibyte_per_sec_written { - (double)bytes_written / (double)passed_time_sec / - (double)(1024 * 1024) }; + (double)bytes_written / (double)passed_time_sec / (double)(1024 * 1024) }; log(" Have written ", mibyte_written, " mebibyte in total."); log(" Have written ", mibyte_per_sec_written, " mebibyte per second."); @@ -261,236 +182,124 @@ class Benchmark } } - void raise_nr_of_virt_blks_read() { _nr_of_virt_blks_read++; } - void raise_nr_of_virt_blks_written() { _nr_of_virt_blks_written++; } + void raise_num_virt_blks_read() { _num_virt_blks_read++; } + void raise_num_virt_blks_written() { _num_virt_blks_written++; } }; -class Trust_anchor_node +struct Tresor_tester::Trust_anchor_node { - private: + using Operation = Trust_anchor_request::Type; - using Operation = Trust_anchor_request::Type; + Operation const op; + Passphrase const passphrase; - Operation const _op; - String<64> const _passphrase; + NONCOPYABLE(Trust_anchor_node); - Operation _read_op_attr(Xml_node const &node) - { - class Attribute_missing { }; - if (!node.has_attribute("op")) { - throw Attribute_missing { }; - } - if (node.attribute("op").has_value("initialize")) { - return Operation::INITIALIZE; - } - class Malformed_attribute { }; - throw Malformed_attribute { }; - } + Operation read_op_attr(Xml_node const &node) + { + ASSERT(node.has_attribute("op")); + if (node.attribute("op").has_value("initialize")) + return Operation::INITIALIZE; + ASSERT_NEVER_REACHED; + } - public: - - Trust_anchor_node(Xml_node const &node) - : - _op { _read_op_attr(node) }, - _passphrase { has_attr_passphrase() ? - node.attribute_value("passphrase", String<64>()) : - String<64>() } - { } - - Operation op() const { return _op; } - String<64> const &passphrase() const { return _passphrase; } - - bool has_attr_passphrase() const - { - return _op == Operation::INITIALIZE; - } - - void print(Genode::Output &out) const - { - Genode::print(out, "op=", - Trust_anchor_request::type_to_string(_op)); - - if (has_attr_passphrase()) { - Genode::print(out, " passphrase=", _passphrase); - } - } + Trust_anchor_node(Xml_node const &node) + : + op { read_op_attr(node) }, + passphrase { op == Operation::INITIALIZE ? node.attribute_value("passphrase", Passphrase()) : Passphrase() } + { } }; -class Request_node +struct Tresor_tester::Request_node { - private: + using Operation = Tresor::Request::Operation; - using Operation = Tresor::Request::Operation; + Operation const op; + Virtual_block_address const vba; + Number_of_blocks const count; + bool const sync; + bool const salt_avail; + Salt const salt; + Snapshot_id const snap_id; - Operation const _op; - Virtual_block_address const _vba; - Number_of_blocks const _count; - bool const _sync; - bool const _salt_avail; - uint64_t const _salt; - Snapshot_id const _snap_id; + NONCOPYABLE(Request_node); - Operation _read_op_attr(Xml_node const &node) - { - class Attribute_missing { }; - if (!node.has_attribute("op")) { - throw Attribute_missing { }; - } - if (node.attribute("op").has_value("read")) { - return Operation::READ; - } - if (node.attribute("op").has_value("write")) { - return Operation::WRITE; - } - if (node.attribute("op").has_value("sync")) { - return Operation::SYNC; - } - 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; - } - if (node.attribute("op").has_value("extend_vbd")) { - return Operation::EXTEND_VBD; - } - if (node.attribute("op").has_value("rekey")) { - return Operation::REKEY; - } - if (node.attribute("op").has_value("deinitialize")) { - return Operation::DEINITIALIZE; - } - class Malformed_attribute { }; - throw Malformed_attribute { }; - } + Operation read_op_attr(Xml_node const &node) + { + ASSERT(node.has_attribute("op")); + if (node.attribute("op").has_value("read")) return Operation::READ; + if (node.attribute("op").has_value("write")) return Operation::WRITE; + if (node.attribute("op").has_value("sync")) return Operation::SYNC; + 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; + if (node.attribute("op").has_value("extend_vbd")) return Operation::EXTEND_VBD; + if (node.attribute("op").has_value("rekey")) return Operation::REKEY; + if (node.attribute("op").has_value("deinitialize")) return Operation::DEINITIALIZE; + ASSERT_NEVER_REACHED; + } - public: + Request_node(Xml_node const &node) + : + op { read_op_attr(node) }, + vba { has_vba() ? read_attribute(node, "vba") : 0 }, + count { has_count() ? read_attribute(node, "count") : 0 }, + sync { read_attribute(node, "sync") }, + salt_avail { has_salt() ? node.has_attribute("salt") : false }, + salt { has_salt() && salt_avail ? read_attribute(node, "salt") : 0 }, + snap_id { has_snap_id() ? read_attribute(node, "id") : 0 } + { } - Request_node(Xml_node const &node) - : - _op { _read_op_attr(node) }, - _vba { has_attr_vba() ? - read_attribute(node, "vba") : 0 }, - _count { has_attr_count() ? - read_attribute(node, "count") : 0 }, - _sync { read_attribute(node, "sync") }, - _salt_avail { has_attr_salt() ? - node.has_attribute("salt") : false }, - _salt { has_attr_salt() && _salt_avail ? - read_attribute(node, "salt") : 0 }, - _snap_id { has_attr_snap_id() ? - read_attribute(node, "id") : 0 } - { } + bool has_vba() const { return op == Operation::READ || op == Operation::WRITE || op == Operation::SYNC; } - Operation op() const { return _op; } - Virtual_block_address vba() const { return _vba; } - Number_of_blocks count() const { return _count; } - 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_salt() const { return op == Operation::READ || op == Operation::WRITE; } - bool has_attr_vba() const - { - return _op == Operation::READ || - _op == Operation::WRITE || - _op == Operation::SYNC; - } + bool has_count() const + { + return op == Operation::READ || op == Operation::WRITE || op == Operation::SYNC || + op == Operation::EXTEND_FT || op == Operation::EXTEND_VBD; + } - bool has_attr_salt() const - { - return _op == Operation::READ || - _op == Operation::WRITE; - } + bool has_snap_id() const { return op == Operation::DISCARD_SNAPSHOT || op == Operation::CREATE_SNAPSHOT; } - bool has_attr_count() const - { - return _op == Operation::READ || - _op == Operation::WRITE || - _op == Operation::SYNC || - _op == Operation::EXTEND_FT || - _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)); - if (has_attr_vba()) { - Genode::print(out, " vba=", _vba); - } - if (has_attr_count()) { - Genode::print(out, " count=", _count); - } - Genode::print(out, " sync=", _sync); - if (_salt_avail) { - Genode::print(out, " salt=", _salt); - } - } + void print(Genode::Output &out) const { Genode::print(out, "op ", Tresor::Request::op_to_string(op)); } }; -class Command : public Fifo::Element +class Tresor_tester::Command : public Module_channel { public: - enum Type - { - INVALID, - REQUEST, - TRUST_ANCHOR, - BENCHMARK, - CONSTRUCT, - DESTRUCT, - INITIALIZE, - CHECK, - LIST_SNAPSHOTS, - LOG - }; + enum Type { INVALID, REQUEST, TRUST_ANCHOR, BENCHMARK, CONSTRUCT, DESTRUCT, INITIALIZE, CHECK, CHECK_SNAPSHOTS, LOG }; - enum State - { - PENDING, - IN_PROGRESS, - COMPLETED - }; + enum State { PENDING, IN_PROGRESS, CREATE_SNAP_COMPLETED, DISCARD_SNAP_COMPLETED, COMPLETED }; private: - Type _type { INVALID }; - uint32_t _id { 0 }; - State _state { PENDING }; - bool _success { false }; - bool _data_mismatch { false }; - Constructible _request_node { }; - Constructible _trust_anchor_node { }; - Constructible _benchmark_node { }; - Constructible _log_node { }; - Constructible _initialize { }; + using Type_string = String<64>; - char const *_state_to_string() const - { - switch (_state) { - case PENDING: return "pending"; - case IN_PROGRESS: return "in_progress"; - case COMPLETED: return "completed"; - } - return "?"; - } + Tresor_tester::Main &_main; + Type _type { INVALID }; + Module_channel_id _id { 0 }; + State _state { PENDING }; + bool _success { false }; + Generation _gen { INVALID_GENERATION }; + bool _data_mismatch { false }; + Constructible _request_node { }; + Constructible _trust_anchor_node { }; + Constructible _benchmark_node { }; + Constructible _log_node { }; + Constructible _initialize { }; - char const *_type_to_string() const + NONCOPYABLE(Command); + + void _generated_req_completed(State_uint state_uint) override; + + static char const *_type_to_string(Type type) { - switch (_type) { + switch (type) { case INITIALIZE: return "initialize"; case INVALID: return "invalid"; case REQUEST: return "request"; @@ -499,219 +308,180 @@ class Command : public Fifo::Element case CONSTRUCT: return "construct"; case DESTRUCT: return "destruct"; case CHECK: return "check"; - case LIST_SNAPSHOTS: return "list_snapshots"; + case CHECK_SNAPSHOTS: return "check_snapshots"; case LOG: return "log"; } - return "?"; + ASSERT_NEVER_REACHED; + } + + static Type _type_from_string(Type_string str) + { + if (str == "initialize") { return INITIALIZE; } + if (str == "request") { return REQUEST; } + if (str == "trust-anchor") { return TRUST_ANCHOR; } + if (str == "benchmark") { return BENCHMARK; } + if (str == "construct") { return CONSTRUCT; } + if (str == "destruct") { return DESTRUCT; } + if (str == "check") { return CHECK; } + if (str == "check-snapshots") { return CHECK_SNAPSHOTS; } + if (str == "log") { return LOG; } + ASSERT_NEVER_REACHED; } public: - Command() { } - - Command(Type type, - Xml_node const &node, - uint32_t id) + Command(Xml_node const &node, Tresor_tester::Main &main, Module_channel_id id) : - _type { type }, - _id { id } + Module_channel { COMMAND_POOL, id }, _main { main }, _type { _type_from_string(node.type()) }, _id { id } { switch (_type) { - case INITIALIZE: _initialize.construct(node); break; - case REQUEST: _request_node.construct(node); break; + case INITIALIZE: _initialize.construct(node); break; + case REQUEST: _request_node.construct(node); break; case TRUST_ANCHOR: _trust_anchor_node.construct(node); break; - case BENCHMARK: _benchmark_node.construct(node); break; - case LOG: _log_node.construct(node); break; - default: break; + case BENCHMARK: _benchmark_node.construct(node); break; + case LOG: _log_node.construct(node); break; + default: break; } } - Command(Command &other) - : - _type { other._type }, - _id { other._id }, - _state { other._state }, - _success { other._success } + bool may_have_data_mismatch() const { - switch (_type) { - case INITIALIZE: _initialize.construct(*other._initialize); break; - case REQUEST: _request_node.construct(*other._request_node); break; - case TRUST_ANCHOR: _trust_anchor_node.construct(*other._trust_anchor_node); break; - case BENCHMARK: _benchmark_node.construct(*other._benchmark_node); break; - case LOG: _log_node.construct(*other._log_node); break; - default: break; - } - } - - bool has_attr_data_mismatch() const - { - return - _type == REQUEST && - _request_node->op() == Tresor::Request::Operation::READ && - _request_node->salt_avail(); + return _type == REQUEST && _request_node->op == Tresor::Request::READ && _request_node->salt_avail; } bool synchronize() const { - class Bad_type { }; switch (_type) { - case INITIALIZE: return true; - case BENCHMARK: return true; - case CONSTRUCT: return true; - case DESTRUCT: return true; - case CHECK: return true; - case TRUST_ANCHOR: return true; - case LIST_SNAPSHOTS: return true; - case LOG: return true; - case REQUEST: return _request_node->sync(); - case INVALID: throw Bad_type { }; + case REQUEST: return _request_node->sync; + case INVALID: ASSERT_NEVER_REACHED; + default: return true; } - throw Bad_type { }; - } - - static Type type_from_string(String<64> str) - { - if (str == "initialize") { return INITIALIZE; } - if (str == "request") { return REQUEST; } - if (str == "trust-anchor") { return TRUST_ANCHOR; } - if (str == "benchmark") { return BENCHMARK; } - if (str == "construct") { return CONSTRUCT; } - if (str == "destruct") { return DESTRUCT; } - if (str == "check") { return CHECK; } - if (str == "list-snapshots") { return LIST_SNAPSHOTS; } - if (str == "log") { return LOG; } - class Bad_string { }; - throw Bad_string { }; + ASSERT_NEVER_REACHED; } void print(Genode::Output &out) const { - Genode::print(out, "id=", _id, " type=", _type_to_string()); - class Bad_type { }; - switch (_type) { - case INITIALIZE: Genode::print(out, " cfg=(", *_initialize, ")"); break; - case REQUEST: Genode::print(out, " cfg=(", *_request_node, ")"); break; - case TRUST_ANCHOR: Genode::print(out, " cfg=(", *_trust_anchor_node, ")"); break; - case BENCHMARK: Genode::print(out, " cfg=(", *_benchmark_node, ")"); break; - case LOG: Genode::print(out, " cfg=(", *_log_node, ")"); break; - case INVALID: break; - case CHECK: break; - case CONSTRUCT: break; - case DESTRUCT: break; - case LIST_SNAPSHOTS: break; - } - Genode::print(out, " succ=", _success); - if (has_attr_data_mismatch()) { - Genode::print(out, " bad_data=", _data_mismatch); - } - Genode::print(out, " state=", _state_to_string()); + Genode::print(out, "id ", _id, " type ", _type_to_string(_type)); + if (_type == REQUEST) + Genode::print(out, " ", *_request_node); } - Type type () const { return _type ; } - State state () const { return _state ; } - uint32_t id () const { return _id ; } - bool success () const { return _success ; } - bool data_mismatch () const { return _data_mismatch ; } - Request_node const &request_node () const { return *_request_node ; } - Trust_anchor_node const &trust_anchor_node () const { return *_trust_anchor_node; } - Benchmark_node const &benchmark_node () const { return *_benchmark_node ; } - Log_node const &log_node () const { return *_log_node ; } - Tresor_init::Configuration const &initialize () const { return *_initialize ; } + Type type() const { return _type ; } + State state() const { return _state ; } + Module_channel_id id() const { return _id ; } + bool success() const { return _success ; } + bool data_mismatch() const { return _data_mismatch ; } + Request_node const &request_node() const { return *_request_node ; } + Trust_anchor_node const &trust_anchor_node() const { return *_trust_anchor_node; } + Benchmark_node const &benchmark_node() const { return *_benchmark_node ; } + Log_node const &log_node() const { return *_log_node ; } + Tresor_init::Configuration const &initialize() const { return *_initialize ; } - void state (State state) { _state = state; } - void success (bool success) { _success = success; } + void state (State state) { _state = state; } + void success (bool success) { _success = success; } void data_mismatch (bool data_mismatch) { _data_mismatch = data_mismatch; } + + void execute(bool &progress); }; -class Snapshot_reference : public Genode::Avl_node +struct Tresor_tester::Snapshot_reference : public Genode::Avl_node { - private: + Snapshot_id const id; + Generation const gen; - Snapshot_id const _id; - Generation const _gen; + NONCOPYABLE(Snapshot_reference); - public: + Snapshot_reference(Snapshot_id id, Generation gen) : id { id }, gen { gen } { } - 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); + template + void with_ref(Snapshot_id target_id, FUNC && func) const + { + if (target_id != id) { + Snapshot_reference *child_ptr { Avl_node::child(target_id > id) }; + if (child_ptr) + child_ptr->with_ref(target_id, func); else - handle_no_match(); - } + ASSERT_NEVER_REACHED; + } else + func(*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 Command_pool : public Module { +struct Tresor_tester::Snapshot_reference_tree : public Avl_tree +{ + template + void with_ref(Snapshot_id id, FUNC && func) const + { + if (first()) + first()->with_ref(id, func); + else + ASSERT_NEVER_REACHED; + } +}; + +class Tresor_tester::Client_data : public Module, public Module_channel +{ private: - 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 }; + using Request = Client_data_request; + + Main &_main; + + NONCOPYABLE(Client_data); + + void _request_submitted(Module_request &) override; + + bool _request_complete() override { return true; } + + public: + + Client_data(Main &main) : Module_channel { CLIENT_DATA, 0 }, _main { main } { add_channel(*this); } +}; + + +class Tresor_tester::Main : private Vfs::Env::User, private Module_composition, public Module +{ + private: + + Genode::Env &_env; + Attached_rom_dataspace _config_rom { _env, "config" }; + Heap _heap { _env.ram(), _env.rm() }; + Vfs::Simple_env _vfs_env { _env, _heap, _config_rom.xml().sub_node("vfs"), *this }; + Signal_handler
_signal_handler { _env.ep(), *this, &Main::_handle_signal }; + Benchmark _benchmark { _env }; + Module_channel_id _next_command_id { 0 }; + unsigned long _num_uncompleted_cmds { 0 }; + unsigned long _num_errors { 0 }; Tresor::Block _blk_data { }; Snapshot_reference_tree _snap_refs { }; + Constructible _free_tree { }; + Constructible _vbd { }; + Constructible _sb_control { }; + Constructible _request_pool { }; + Constructible _client_data { }; + Constructible _meta_tree { }; + Trust_anchor _trust_anchor { _vfs_env, _config_rom.xml().sub_node("trust-anchor") }; + Crypto _crypto { _vfs_env, _config_rom.xml().sub_node("crypto") }; + Block_io _block_io { _vfs_env, _config_rom.xml().sub_node("block-io") }; + Pba_allocator _pba_alloc { NR_OF_SUPERBLOCK_SLOTS }; + Vbd_initializer _vbd_initializer { }; + Ft_initializer _ft_initializer { }; + Sb_initializer _sb_initializer { }; + Sb_check _sb_check { }; + Vbd_check _vbd_check { }; + Ft_check _ft_check { }; + bool _generated_req_success { false }; - void _read_cmd_node(Xml_node const &node, - Command::Type cmd_type) - { - Command &cmd { - *new (_alloc) Command(cmd_type, node, _next_command_id++) }; + NONCOPYABLE(Main); - _nr_of_uncompleted_cmds++; - _cmd_queue.enqueue(cmd); - - if (_verbose_node.cmd_pool_cmd_pending()) { - log("cmd pending: ", cmd); - } - } - - static void _generate_blk_data(Tresor::Block &blk_data, - Virtual_block_address vba, - uint64_t salt) + static void _generate_blk_data(Tresor::Block &blk_data, Virtual_block_address vba, Salt salt) { for (uint64_t idx { 0 }; idx + sizeof(vba) + sizeof(salt) <= BLOCK_SIZE; ) { @@ -724,807 +494,354 @@ class Command_pool : public Module { } } - - /************ - ** Module ** - ************/ - - bool _peek_generated_request(Genode::uint8_t *buf_ptr, - Genode::size_t buf_size) override + template + void _with_first_processable_cmd(FUNC && func) { + bool first_uncompleted_cmd { true }; + bool done { false }; + for_each_channel([&] (Command &cmd) { - Command const cmd { - peek_pending_command(Command::TRUST_ANCHOR) }; - - if (cmd.type() != Command::INVALID) { - - Trust_anchor_node const &node { cmd.trust_anchor_node() }; - switch (node.op()) { - case Trust_anchor_request::INITIALIZE: - - Trust_anchor_request::create( - buf_ptr, buf_size, COMMAND_POOL, cmd.id(), - Trust_anchor_request::INITIALIZE, - nullptr, nullptr, node.passphrase().string(), - nullptr); - - return true; - - default: break; - } - class Exception_1 { }; - throw Exception_1 { }; - } - } - - { - Command const cmd { - peek_pending_command(Command::INITIALIZE) }; - - if (cmd.type() != Command::INVALID) { - - Tresor_init::Configuration const &cfg { cmd.initialize() }; - - Sb_initializer_request::create( - buf_ptr, buf_size, COMMAND_POOL, cmd.id(), - Sb_initializer_request::INIT, - (Tree_level_index)(cfg.vbd_nr_of_lvls() - 1), - (Tree_degree)cfg.vbd_nr_of_children(), - cfg.vbd_nr_of_leafs(), - (Tree_level_index)cfg.ft_nr_of_lvls() - 1, - (Tree_degree)cfg.ft_nr_of_children(), - cfg.ft_nr_of_leafs(), - (Tree_level_index)cfg.ft_nr_of_lvls() - 1, - (Tree_degree)cfg.ft_nr_of_children(), - cfg.ft_nr_of_leafs()); - - return true; - } - } - - { - Command const cmd { - peek_pending_command(Command::CHECK) }; - - if (cmd.type() != Command::INVALID) { - - Sb_check_request::create( - buf_ptr, buf_size, COMMAND_POOL, cmd.id(), - Sb_check_request::CHECK); - - return true; - } - } - return false; - } - - void _drop_generated_request(Module_request &mod_req) override - { - switch (mod_req.dst_module_id()) { - case TRUST_ANCHOR: - { - Trust_anchor_request const &ta_req { - *static_cast(&mod_req)}; - - if (ta_req.type() != Trust_anchor_request::INITIALIZE) { - class Exception_2 { }; - throw Exception_2 { }; - } - mark_command_in_progress(ta_req.src_request_id()); - break; - } - case SB_INITIALIZER: - { - Sb_initializer_request const &sb_req { - *static_cast(&mod_req)}; - - if (sb_req.type() != Sb_initializer_request::INIT) { - class Exception_4 { }; - throw Exception_4 { }; - } - mark_command_in_progress(sb_req.src_request_id()); - break; - } - case SB_CHECK: - { - Sb_check_request const &req { - *static_cast(&mod_req)}; - - if (req.type() != Sb_check_request::CHECK) { - class Exception_3 { }; - throw Exception_3 { }; - } - mark_command_in_progress(req.src_request_id()); - break; - } - default: - { - class Exception_1 { }; - throw Exception_1 { }; - } - } - } - - 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) + if (done) return; - if (cmd.id() == cmd_id) { - handle_match_fn(cmd); - cmd_found = true; + if (cmd.state() == Command::PENDING) { + done = true; + if (first_uncompleted_cmd || !cmd.synchronize()) + func(cmd); + } + if (cmd.state() == Command::IN_PROGRESS) { + if (cmd.synchronize()) + done = true; + else + first_uncompleted_cmd = false; } }); - if (!cmd_found) - handle_no_match_fn(); } - void generated_request_complete(Module_request &mod_req) override + void _try_end_program() { - switch (mod_req.dst_module_id()) { - case TRUST_ANCHOR: - { - Trust_anchor_request const &ta_req { - *static_cast(&mod_req)}; + if (_num_uncompleted_cmds == 0) { + if (_num_errors > 0) { + for_each_channel([&] (Command &cmd) { + if (cmd.state() != Command::COMPLETED) + return; - if (ta_req.type() != Trust_anchor_request::INITIALIZE) { - class Exception_2 { }; - throw Exception_2 { }; - } - mark_command_completed( - ta_req.src_request_id(), ta_req.success()); - break; - } - case SB_INITIALIZER: - { - Sb_initializer_request const &sb_req { - *static_cast(&mod_req)}; + if (cmd.success() && (!cmd.may_have_data_mismatch() || !cmd.data_mismatch())) + return; - if (sb_req.type() != Sb_initializer_request::INIT) { - class Exception_2 { }; - throw Exception_2 { }; - } - mark_command_completed( - sb_req.src_request_id(), sb_req.success()); - break; + log("cmd failed: ", cmd); + }); + _env.parent().exit(-1); + } else + _env.parent().exit(0); } - case SB_CHECK: - { - Sb_check_request const &sb_req { - *static_cast(&mod_req)}; + } - if (sb_req.type() != Sb_check_request::CHECK) { - class Exception_2 { }; - throw Exception_2 { }; - } - mark_command_completed( - sb_req.src_request_id(), sb_req.success()); - break; - } - case REQUEST_POOL: - { - Request const &rp_req { - *static_cast(&mod_req)}; + void _wakeup_back_end_services() { _vfs_env.io().commit(); } - 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: - { - class Exception_1 { }; - throw Exception_1 { }; - } - } + void _handle_signal() + { + execute_modules(); + _try_end_program(); + _wakeup_back_end_services(); + } + + void wakeup_vfs_user() override { _signal_handler.local_submit(); } + + void execute(bool &progress) override + { + _with_first_processable_cmd([&] (Command &cmd) { + cmd.execute(progress); }); + } + + void _remove_snap_ref(Snapshot_reference &ref) + { + _snap_refs.remove(&ref); + ref.~Snapshot_reference(); + destroy(_heap, &ref); } public: - Command_pool(Allocator &alloc, - Xml_node const &config_xml, - Verbose_node const &verbose_node) - : - _alloc { alloc }, - _verbose_node { verbose_node } + Main(Genode::Env &env) : _env { env } { - config_xml.sub_node("commands").for_each_sub_node( - [&] (Xml_node const &node) - { - _read_cmd_node(node, Command::type_from_string(node.type())); + add_module(CRYPTO, _crypto); + add_module(TRUST_ANCHOR, _trust_anchor); + add_module(COMMAND_POOL, *this); + add_module(BLOCK_IO, _block_io); + add_module(VBD_INITIALIZER, _vbd_initializer); + add_module(FT_INITIALIZER, _ft_initializer); + add_module(SB_INITIALIZER, _sb_initializer); + add_module(SB_CHECK, _sb_check); + add_module(VBD_CHECK, _vbd_check); + add_module(FT_CHECK, _ft_check); + _config_rom.xml().sub_node("commands").for_each_sub_node([&] (Xml_node const &node) { + add_channel(*new (_heap) Command(node, *this, _next_command_id++)); + _num_uncompleted_cmds++; + }); + _handle_signal(); + } + + void mark_command_in_progress(Module_channel_id cmd_id) + { + with_channel(cmd_id, [&] (Command &cmd) { + ASSERT(cmd.state() == Command::PENDING); + cmd.state(Command::IN_PROGRESS); + }); + } + + void mark_command_completed(Module_channel_id cmd_id, bool success) + { + with_channel(cmd_id, [&] (Command &cmd) { + ASSERT(cmd.state() == Command::IN_PROGRESS); + cmd.state(Command::COMPLETED); + _num_uncompleted_cmds--; + cmd.success(success); + if (!cmd.success()) { + warning("cmd ", cmd, " failed"); + _num_errors++; + } }); } 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; }); + _snap_refs.with_ref(id, [&] (Snapshot_reference const &ref) { + gen = ref.gen; }); + return gen; } - Command peek_pending_command(Command::Type type) const + void add_snap_ref(Snapshot_id id, Generation gen) { _snap_refs.insert(new (_heap) Snapshot_reference { id, gen }); } + + void remove_snap_refs_with_same_gen(Snapshot_id id) { - Reconstructible resulting_cmd { }; - bool first_uncompleted_cmd { true }; - bool exit_loop { false }; - _cmd_queue.for_each([&] (Command &curr_cmd) - { - if (exit_loop) { - return; - } - switch (curr_cmd.state()) { - case Command::PENDING: + Generation gen { snap_id_to_gen(id) }; + while (1) { + Snapshot_reference *ref_ptr { nullptr }; + _snap_refs.for_each([&] (Snapshot_reference const &ref) { + if (!ref_ptr && ref.gen == gen) + ref_ptr = const_cast(&ref); + }); + if (ref_ptr) + _remove_snap_ref(*ref_ptr); + else + break; + } + } - /* - * Stop iterating at the first uncompleted command - * that needs to be synchronized. - */ - if (curr_cmd.synchronize()) { - if (curr_cmd.type() == type && first_uncompleted_cmd) { - resulting_cmd.construct(curr_cmd); - } - exit_loop = true; - return; - } - /* - * Select command and stop iterating if the command is of - * the desired type. - */ - if (curr_cmd.type() == type) { - resulting_cmd.construct(curr_cmd); - exit_loop = true; - } - first_uncompleted_cmd = false; - return; + void reset_snap_refs() + { + while (_snap_refs.first()) + _remove_snap_ref(*_snap_refs.first()); + } - case Command::IN_PROGRESS: + Pba_allocator &pba_alloc() { return _pba_alloc; } - /* - * Stop iterating at the first uncompleted command - * that needs to be synchronized. - */ - if (curr_cmd.synchronize()) { - exit_loop = true; - return; - } - first_uncompleted_cmd = false; - return; - - case Command::COMPLETED: - - return; - } + void generate_blk_data(Request_tag tresor_req_tag, Virtual_block_address vba, Tresor::Block &blk_data) + { + with_channel(tresor_req_tag, [&] (Command &cmd) { + ASSERT(cmd.type() == Command::REQUEST); + Request_node const &req_node { cmd.request_node() }; + if (req_node.salt_avail) + _generate_blk_data(blk_data, vba, req_node.salt); }); - return *resulting_cmd; + _benchmark.raise_num_virt_blks_written(); } - void mark_command_in_progress(Module_request_id cmd_id) + void verify_blk_data(Request_tag tresor_req_tag, Virtual_block_address vba, Tresor::Block &blk_data) { - find_cmd(cmd_id, [&] (Command &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) - { - find_cmd(cmd_id, [&] (Command &cmd) - { - 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 (_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) - { - find_cmd(tresor_req_tag, [&] (Command &cmd) - { + with_channel(tresor_req_tag, [&] (Command &cmd) { ASSERT(cmd.type() == Command::REQUEST); Request_node const &req_node { cmd.request_node() }; - if (req_node.salt_avail()) - _generate_blk_data(blk_data, vba, req_node.salt()); - }, - [&] () { ASSERT_NEVER_REACHED; }); - } - - void verify_blk_data(uint64_t tresor_req_tag, - Virtual_block_address vba, - Tresor::Block &blk_data) - { - find_cmd(tresor_req_tag, [&] (Command &cmd) - { - ASSERT(cmd.type() == Command::REQUEST); - Request_node const &req_node { cmd.request_node() }; - if (req_node.salt_avail()) { + if (req_node.salt_avail) { Tresor::Block gen_blk_data { }; - _generate_blk_data(gen_blk_data, vba, req_node.salt()); + _generate_blk_data(gen_blk_data, vba, req_node.salt); if (memcmp(&blk_data, &gen_blk_data, BLOCK_SIZE)) { - cmd.data_mismatch(true); - error("client data mismatch"); - _nr_of_errors++; - - if (_verbose_node.client_data_mismatch()) { - log("client data mismatch: vba=", vba, - " req_tag=(", tresor_req_tag, ")"); - log("client data should be: ", gen_blk_data); - log("client data is: ", blk_data); - class Client_data_mismatch { }; - throw Client_data_mismatch { }; - } + warning("client data mismatch: vba=", vba, " req_tag=", tresor_req_tag); + _num_errors++; } } - }, - [&] () { ASSERT_NEVER_REACHED; }); - } - - void print_failed_cmds() const - { - _cmd_queue.for_each([&] (Command &cmd) - { - if (cmd.state() != Command::COMPLETED) { - return; - } - if (cmd.success() && - (!cmd.has_attr_data_mismatch() || !cmd.data_mismatch())) { - - return; - } - log("cmd failed: ", cmd); }); + _benchmark.raise_num_virt_blks_read(); } - unsigned long nr_of_uncompleted_cmds() { return _nr_of_uncompleted_cmds; } - unsigned long nr_of_errors() { return _nr_of_errors; } -}; - - -static Block_allocator *_block_allocator_ptr; - - -Genode::uint64_t block_allocator_first_block() -{ - if (!_block_allocator_ptr) { - struct Exception_1 { }; - throw Exception_1(); - } - - return _block_allocator_ptr->first_block(); -} - - -Genode::uint64_t block_allocator_nr_of_blks() -{ - if (!_block_allocator_ptr) { - struct Exception_1 { }; - throw Exception_1(); - } - - return _block_allocator_ptr->nr_of_blks(); -} - - -class Tresor_tester::Main -: - private Vfs::Env::User, - private Tresor::Module_composition, - public Tresor::Module -{ - private: - - Genode::Env &_env; - Attached_rom_dataspace _config_rom { _env, "config" }; - Verbose_node _verbose_node { _config_rom.xml() }; - Heap _heap { _env.ram(), _env.rm() }; - Vfs::Simple_env _vfs_env { _env, _heap, _config_rom.xml().sub_node("vfs"), *this }; - Signal_handler
_sigh { _env.ep(), *this, &Main::_execute }; - Command_pool _cmd_pool { _heap, _config_rom.xml(), _verbose_node }; - Constructible _free_tree { }; - Constructible _vbd { }; - Constructible _sb_control { }; - Constructible _request_pool { }; - Constructible _ft_resizing { }; - Benchmark _benchmark { _env }; - Meta_tree _meta_tree { }; - Trust_anchor _trust_anchor { _vfs_env, _config_rom.xml().sub_node("trust-anchor") }; - Crypto _crypto { _vfs_env, _config_rom.xml().sub_node("crypto") }; - Block_io _block_io { _vfs_env, _config_rom.xml().sub_node("block-io") }; - Block_allocator _block_allocator { NR_OF_SUPERBLOCK_SLOTS }; - Vbd_initializer _vbd_initializer { }; - Ft_initializer _ft_initializer { }; - Sb_initializer _sb_initializer { }; - Sb_check _sb_check { }; - Vbd_check _vbd_check { }; - Ft_check _ft_check { }; - Client_data_request _client_data_request { }; - - /* - * Noncopyable - */ - Main(Main const &) = delete; - Main &operator = (Main const &) = delete; - - void _construct_tresor() + void construct_tresor_modules() { _free_tree.construct(); - add_module(FREE_TREE, *_free_tree); - _vbd.construct(); - add_module(VIRTUAL_BLOCK_DEVICE, *_vbd); - _sb_control.construct(); - add_module(SUPERBLOCK_CONTROL, *_sb_control); - _request_pool.construct(); + _client_data.construct(*this); + _meta_tree.construct(); + add_module(FREE_TREE, *_free_tree); + add_module(VIRTUAL_BLOCK_DEVICE, *_vbd); + add_module(SUPERBLOCK_CONTROL, *_sb_control); add_module(REQUEST_POOL, *_request_pool); - - _ft_resizing.construct(); - add_module(FT_RESIZING, *_ft_resizing); + add_module(CLIENT_DATA, *_client_data); + add_module(META_TREE, *_meta_tree); } - void _destruct_tresor() + void destruct_tresor_modules() { - remove_module(FT_RESIZING); - _ft_resizing.destruct(); - + remove_module(META_TREE); + remove_module(CLIENT_DATA); remove_module(REQUEST_POOL); - _request_pool.destruct(); - remove_module(SUPERBLOCK_CONTROL); - _sb_control.destruct(); - remove_module(VIRTUAL_BLOCK_DEVICE); - _vbd.destruct(); - remove_module(FREE_TREE); + _meta_tree.destruct(); + _client_data.destruct(); + _request_pool.destruct(); + _sb_control.destruct(); + _vbd.destruct(); _free_tree.destruct(); } - /** - * Vfs::Env::User interface - */ - void wakeup_vfs_user() override { _sigh.local_submit(); } - - bool ready_to_submit_request() override + void check_snapshots(Command &cmd, bool &progress) { - return _client_data_request._type == Client_data_request::INVALID; - } - - void submit_request(Module_request &req) override - { - if (_client_data_request._type != Client_data_request::INVALID) { - - class Exception_1 { }; - throw Exception_1 { }; - } - req.dst_request_id(0); - _client_data_request = *static_cast(&req); - switch (_client_data_request._type) { - case Client_data_request::OBTAIN_PLAINTEXT_BLK: - - _cmd_pool.generate_blk_data( - _client_data_request._client_req_tag, - _client_data_request._vba, - *(Tresor::Block *)_client_data_request._plaintext_blk_ptr); - - _benchmark.raise_nr_of_virt_blks_written(); - - if (_verbose_node.client_data_transferred()) - log("client data: vba=", _client_data_request._vba, - " req_tag=", _client_data_request._client_req_tag); - - _client_data_request._success = true; - break; - - case Client_data_request::SUPPLY_PLAINTEXT_BLK: - - _cmd_pool.verify_blk_data( - _client_data_request._client_req_tag, - _client_data_request._vba, - *(Tresor::Block *)_client_data_request._plaintext_blk_ptr); - - _benchmark.raise_nr_of_virt_blks_read(); - - if (_verbose_node.client_data_transferred()) - log("client data: vba=", _client_data_request._vba, - " req_tag=", _client_data_request._client_req_tag); - - _client_data_request._success = true; - break; - - case Client_data_request::INVALID: - - class Exception_2 { }; - throw Exception_2 { }; - } - } - - void execute(bool &) override { } - - bool _peek_completed_request(Genode::uint8_t *buf_ptr, - Genode::size_t buf_size) override - { - if (_client_data_request._type != Client_data_request::INVALID) { - if (sizeof(_client_data_request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - Genode::memcpy(buf_ptr, &_client_data_request, - sizeof(_client_data_request));; - return true; - } - return false; - } - - void _drop_completed_request(Module_request &) override - { - if (_client_data_request._type == Client_data_request::INVALID) { - class Exception_2 { }; - throw Exception_2 { }; - } - _client_data_request._type = Client_data_request::INVALID; - } - - void _cmd_pool_handle_pending_tresor_cmds(bool &progress) - { - while (true) { - - if (!_request_pool->ready_to_submit_request()) { - break; - } - Command const cmd { - _cmd_pool.peek_pending_command(Command::REQUEST) }; - - if (cmd.type() == Command::INVALID) { - break; - } - 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, - req_node.has_attr_vba() ? req_node.vba() : 0, - 0, - req_node.has_attr_count() ? req_node.count() : 0, - 0, - cmd.id(), gen, COMMAND_POOL, cmd.id() }; - - _request_pool->submit_request(tresor_req); - if (VERBOSE_MODULE_COMMUNICATION) - Genode::log( - module_name(tresor_req.src_module_id()), " ", - tresor_req.src_request_id_str(), - " --", tresor_req, "--> ", - module_name(tresor_req.dst_module_id()), " ", - tresor_req.dst_request_id_str()); - - _cmd_pool.mark_command_in_progress(cmd.id()); - progress = true; - } - } - - void _cmd_pool_handle_pending_construct_cmds(bool &progress) - { - while (true) { - - Command const cmd { - _cmd_pool.peek_pending_command(Command::CONSTRUCT) }; - - if (cmd.type() == Command::INVALID) { - break; - } - _construct_tresor(); - _cmd_pool.mark_command_in_progress(cmd.id()); - _cmd_pool.mark_command_completed(cmd.id(), true); - progress = true; - } - } - - void _cmd_pool_handle_pending_destruct_cmds(bool &progress) - { - while (true) { - - Command const cmd { - _cmd_pool.peek_pending_command(Command::DESTRUCT) }; - - if (cmd.type() == Command::INVALID) { - break; - } - _destruct_tresor(); - _cmd_pool.mark_command_in_progress(cmd.id()); - _cmd_pool.mark_command_completed(cmd.id(), true); - progress = true; - } - } - - void _cmd_pool_handle_pending_list_snapshots_cmds(bool &progress) - { - while (true) { - - Command const cmd { - _cmd_pool.peek_pending_command(Command::LIST_SNAPSHOTS) }; - - if (cmd.type() == Command::INVALID) { - break; - } - Snapshot_generations generations; - _sb_control->snapshot_generations(generations); - unsigned snap_nr { 0 }; - log(""); - log("List snapshots (command ID ", cmd.id(), ")"); - for (Generation const &gen : generations.items) { - if (gen != INVALID_GENERATION) { - log(" Snapshot #", snap_nr, " is generation ", gen); - snap_nr++; + mark_command_in_progress(cmd.id()); + bool success { true }; + Snapshots_info snap_info { _sb_control->snapshots_info() }; + bool snap_gen_ok[MAX_NR_OF_SNAPSHOTS] { false }; + _snap_refs.for_each([&] (Snapshot_reference const &snap_ref) { + bool snap_ref_ok { false }; + for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { + if (snap_info.generations[idx] == snap_ref.gen) { + snap_ref_ok = true; + snap_gen_ok[idx] = true; } } - log(""); - _cmd_pool.mark_command_in_progress(cmd.id()); - _cmd_pool.mark_command_completed(cmd.id(), true); - progress = true; - } - } - - void _cmd_pool_handle_pending_log_cmds(bool &progress) - { - while (true) { - - Command const cmd { - _cmd_pool.peek_pending_command(Command::LOG) }; - - if (cmd.type() == Command::INVALID) { - break; + if (!snap_ref_ok) { + warning("snap (", snap_ref, ") not known to tresor"); + _num_errors++; + success = false; } - log("\n", cmd.log_node().string(), "\n"); - _cmd_pool.mark_command_in_progress(cmd.id()); - _cmd_pool.mark_command_completed(cmd.id(), true); - progress = true; - } - } - - void _cmd_pool_handle_pending_benchmark_cmds(bool &progress) - { - while (true) { - - Command const cmd { - _cmd_pool.peek_pending_command(Command::BENCHMARK) }; - - if (cmd.type() == Command::INVALID) { - break; - } - _benchmark.submit_request(cmd.benchmark_node()); - _cmd_pool.mark_command_in_progress(cmd.id()); - _cmd_pool.mark_command_completed(cmd.id(), true); - progress = true; - } - } - - void _execute_command_pool(bool &progress) - { - if (_request_pool.constructed()) { - _cmd_pool_handle_pending_tresor_cmds(progress); - _cmd_pool_handle_pending_list_snapshots_cmds(progress); - } - _cmd_pool_handle_pending_log_cmds(progress); - _cmd_pool_handle_pending_benchmark_cmds(progress); - _cmd_pool_handle_pending_construct_cmds(progress); - _cmd_pool_handle_pending_destruct_cmds(progress); - - if (_cmd_pool.nr_of_uncompleted_cmds() == 0) { - - if (_cmd_pool.nr_of_errors() > 0) { - - _cmd_pool.print_failed_cmds(); - _env.parent().exit(-1); - - } else { - - _env.parent().exit(0); + }); + for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { + if (snap_info.generations[idx] != INVALID_GENERATION && !snap_gen_ok[idx]) { + warning("snap (idx ", idx, " gen ", snap_info.generations[idx], ") not known to tester"); + _num_errors++; + success = false; } } + mark_command_completed(cmd.id(), success); + progress = true; } - void _execute() - { - bool progress { true }; - while (progress) { - - progress = false; - _execute_command_pool(progress); - execute_modules(progress); - } - _vfs_env.io().commit(); - } - - public: - - Main(Genode::Env &env) - : - _env { env } - { - add_module(META_TREE, _meta_tree); - add_module(CRYPTO, _crypto); - add_module(TRUST_ANCHOR, _trust_anchor); - add_module(CLIENT_DATA, *this); - add_module(COMMAND_POOL, _cmd_pool); - add_module(BLOCK_IO, _block_io); - add_module(BLOCK_ALLOCATOR, _block_allocator); - add_module(VBD_INITIALIZER, _vbd_initializer); - add_module(FT_INITIALIZER, _ft_initializer); - add_module(SB_INITIALIZER, _sb_initializer); - add_module(SB_CHECK, _sb_check); - add_module(VBD_CHECK, _vbd_check); - add_module(FT_CHECK, _ft_check); - - _block_allocator_ptr = &_block_allocator; - - _execute(); - } + Benchmark &benchmark() { return _benchmark; } }; + +void Tresor_tester::Client_data::_request_submitted(Module_request &mod_req) +{ + Request &req { *static_cast(&mod_req) }; + switch (req._type) { + case Request::OBTAIN_PLAINTEXT_BLK: _main.generate_blk_data(req._req_tag, req._vba, req._blk); break; + case Request::SUPPLY_PLAINTEXT_BLK: _main.verify_blk_data(req._req_tag, req._vba, req._blk); break; + } + req._success = true; +} + + +void Tresor_tester::Command::_generated_req_completed(State_uint state_uint) +{ + if (state_uint == CREATE_SNAP_COMPLETED) + _main.add_snap_ref(request_node().snap_id, _gen); + + if (state_uint == DISCARD_SNAP_COMPLETED) + _main.remove_snap_refs_with_same_gen(request_node().snap_id); + + _main.mark_command_completed(id(), _success); +} + + +void Tresor_tester::Command::execute(bool &progress) +{ + switch (type()) { + case REQUEST: + { + Request_node const &node { request_node() }; + State state { COMPLETED }; + _gen = INVALID_GENERATION; + if (node.op == Request::DISCARD_SNAPSHOT) { + _gen = _main.snap_id_to_gen(node.snap_id); + state = DISCARD_SNAP_COMPLETED; + } + if (node.op == Request::CREATE_SNAPSHOT) + state = CREATE_SNAP_COMPLETED; + + generate_req( + state, progress, node.op, node.has_vba() ? node.vba : 0, + 0, node.has_count() ? node.count : 0, 0, id(), _gen, _success); + + _main.mark_command_in_progress(id()); + break; + } + case Command::TRUST_ANCHOR: + { + Trust_anchor_node const &node { trust_anchor_node() }; + ASSERT(node.op == Trust_anchor_request::INITIALIZE); + generate_req(COMPLETED, progress, node.passphrase, _success); + _main.mark_command_in_progress(id()); + break; + } + case Command::INITIALIZE: + { + _main.reset_snap_refs(); + Tresor_init::Configuration const &cfg { initialize() }; + generate_req(COMPLETED, progress, + (Tree_level_index)(cfg.vbd_nr_of_lvls() - 1), + (Tree_degree)cfg.vbd_nr_of_children(), cfg.vbd_nr_of_leafs(), + (Tree_level_index)cfg.ft_nr_of_lvls() - 1, + (Tree_degree)cfg.ft_nr_of_children(), cfg.ft_nr_of_leafs(), + (Tree_level_index)cfg.ft_nr_of_lvls() - 1, + (Tree_degree)cfg.ft_nr_of_children(), cfg.ft_nr_of_leafs(), _main.pba_alloc(), _success); + _main.mark_command_in_progress(id()); + break; + } + case Command::CHECK: + generate_req(COMPLETED, progress, _success); + _main.mark_command_in_progress(id()); + break; + case LOG: + log("\n", log_node().string, "\n"); + _main.mark_command_in_progress(id()); + _main.mark_command_completed(id(), true); + progress = true; + break; + case BENCHMARK: + _main.benchmark().execute_cmd(benchmark_node()); + _main.mark_command_in_progress(id()); + _main.mark_command_completed(id(), true); + progress = true; + break; + case CONSTRUCT: + _main.construct_tresor_modules(); + _main.mark_command_in_progress(id()); + _main.mark_command_completed(id(), true); + progress = true; + break; + case DESTRUCT: + _main.destruct_tresor_modules(); + _main.mark_command_in_progress(id()); + _main.mark_command_completed(id(), true); + progress = true; + break; + case CHECK_SNAPSHOTS: _main.check_snapshots(*this, progress); break; + default: break; + } +} + + +void Component::construct(Genode::Env &env) { static Tresor_tester::Main main(env); } + + namespace Libc { struct Env; - - struct Component - { - void construct(Libc::Env &); - }; -} - - -void Libc::Component::construct(Libc::Env &) { } - - -void Component::construct(Genode::Env &env) -{ - env.exec_static_constructors(); - - static Tresor_tester::Main main(env); - - (void)block_allocator_first_block(); - (void)block_allocator_nr_of_blks(); -} - -extern "C" int memcmp(const void *p0, const void *p1, Genode::size_t size) -{ - return Genode::memcmp(p0, p1, size); + struct Component { void construct(Libc::Env &) { } }; } diff --git a/repos/gems/src/app/tresor_tester/module_type.h b/repos/gems/src/app/tresor_tester/module_type.h deleted file mode 100644 index 8c47eea20e..0000000000 --- a/repos/gems/src/app/tresor_tester/module_type.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * \brief Identifiers for the Tresor modules used in the Tresor tester - * \author Martin Stein - * \date 2020-08-26 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _MODULE_TYPE_H_ -#define _MODULE_TYPE_H_ - -/* Genode includes */ -#include - -enum class Module_type : Genode::uint8_t -{ - TRESOR_INIT, - TRESOR_CHECK, - TRESOR, -}; - - -static Module_type module_type_from_uint32(Genode::uint32_t uint32) -{ - class Bad_tag { }; - switch (uint32) { - case 1: return Module_type::TRESOR_INIT; - case 2: return Module_type::TRESOR; - case 4: return Module_type::TRESOR_CHECK; - default: throw Bad_tag(); - } -} - - -static Genode::uint32_t module_type_to_uint32(Module_type type) -{ - class Bad_type { }; - switch (type) { - case Module_type::TRESOR_INIT : return 1; - case Module_type::TRESOR : return 2; - case Module_type::TRESOR_CHECK: return 4; - } - throw Bad_type(); -} - - -static Module_type tag_get_module_type(Genode::uint32_t tag) -{ - return module_type_from_uint32((tag >> 24) & 0xff); -} - - -static Genode::uint32_t tag_set_module_type(Genode::uint32_t tag, - Module_type type) -{ - if (tag >> 24) { - - class Bad_tag { }; - throw Bad_tag(); - } - return tag | (module_type_to_uint32(type) << 24); -} - - -static Genode::uint32_t tag_unset_module_type(Genode::uint32_t tag) -{ - return tag & 0xffffff; -} - -#endif /* _MODULE_TYPE_H_ */ diff --git a/repos/gems/src/app/tresor_tester/target.mk b/repos/gems/src/app/tresor_tester/target.mk index 4fdf22caf5..c73dfdffdb 100644 --- a/repos/gems/src/app/tresor_tester/target.mk +++ b/repos/gems/src/app/tresor_tester/target.mk @@ -3,6 +3,7 @@ TARGET := tresor_tester SRC_CC += main.cc INC_DIR += $(PRG_DIR) +INC_DIR += $(REP_DIR)/src/app/tresor_init/include LIBS += base LIBS += tresor diff --git a/repos/gems/src/app/tresor_tester/verbose_node.h b/repos/gems/src/app/tresor_tester/verbose_node.h deleted file mode 100644 index 6d6044726f..0000000000 --- a/repos/gems/src/app/tresor_tester/verbose_node.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * \brief Verbosity configuration of the Tresor tester - * \author Martin Stein - * \date 2020-10-29 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _TRESOR_TESTER__VERBOSE_NODE_H_ -#define _TRESOR_TESTER__VERBOSE_NODE_H_ - -/* Genode includes */ -#include - -class Verbose_node -{ - private: - - bool _cmd_pool_cmd_pending { false }; - bool _cmd_pool_cmd_in_progress { false }; - bool _cmd_pool_cmd_completed { false }; - bool _blk_io_req_in_progress { false }; - bool _blk_io_req_completed { false }; - bool _ta_req_in_progress { false }; - bool _ta_req_completed { false }; - bool _client_data_mismatch { false }; - bool _client_data_transferred { false }; - - public: - - Verbose_node(Genode::Xml_node const &config) - { - config.with_optional_sub_node("verbose", [&] (Genode::Xml_node const &verbose) - { - _cmd_pool_cmd_pending = verbose.attribute_value("cmd_pool_cmd_pending" , false); - _cmd_pool_cmd_in_progress = verbose.attribute_value("cmd_pool_cmd_in_progress", false); - _cmd_pool_cmd_completed = verbose.attribute_value("cmd_pool_cmd_completed" , false); - _blk_io_req_in_progress = verbose.attribute_value("blk_io_req_in_progress" , false); - _blk_io_req_completed = verbose.attribute_value("blk_io_req_completed" , false); - _ta_req_in_progress = verbose.attribute_value("ta_req_in_progress" , false); - _ta_req_completed = verbose.attribute_value("ta_req_completed" , false); - _client_data_mismatch = verbose.attribute_value("client_data_mismatch" , false); - _client_data_transferred = verbose.attribute_value("client_data_transferred" , false); - }); - } - - bool cmd_pool_cmd_pending () const { return _cmd_pool_cmd_pending ; } - bool cmd_pool_cmd_in_progress() const { return _cmd_pool_cmd_in_progress; } - bool cmd_pool_cmd_completed () const { return _cmd_pool_cmd_completed ; } - bool blk_io_req_in_progress () const { return _blk_io_req_in_progress ; } - bool blk_io_req_completed () const { return _blk_io_req_completed ; } - bool ta_req_in_progress () const { return _ta_req_in_progress ; } - bool ta_req_completed () const { return _ta_req_completed ; } - bool client_data_mismatch () const { return _client_data_mismatch ; } - bool client_data_transferred () const { return _client_data_transferred ; } -}; - -#endif /* _TRESOR_TESTER__VERBOSE_NODE_H_ */ diff --git a/repos/gems/src/lib/tresor/block_allocator.cc b/repos/gems/src/lib/tresor/block_allocator.cc deleted file mode 100644 index 4e76f40e32..0000000000 --- a/repos/gems/src/lib/tresor/block_allocator.cc +++ /dev/null @@ -1,197 +0,0 @@ -/* - * \brief Managing block allocation for the initialization of a Tresor device - * \author Josef Soentgen - * \date 2023-02-28 - */ - -/* - * Copyright (C) 2023 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* base includes */ -#include - -/* tresor includes */ -#include - -using namespace Tresor; - - -Block_allocator_request::Block_allocator_request(Module_id src_module_id, - Module_request_id src_request_id) -: - Module_request { src_module_id, src_request_id, BLOCK_ALLOCATOR } -{ } - - -void Block_allocator_request::print(Output &out) const -{ - Genode::print(out, type_to_string(_type)); -} - - -void Block_allocator_request::create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type) -{ - Block_allocator_request req { src_module_id, src_request_id }; - req._type = (Type)req_type; - - if (sizeof(req) > buf_size) { - class Bad_size_0 { }; - throw Bad_size_0 { }; - } - memcpy(buf_ptr, &req, sizeof(req)); -} - - -char const *Block_allocator_request::type_to_string(Type type) -{ - switch (type) { - case INVALID: return "invalid"; - case GET: return "get"; - } - return "?"; -} - - -void Block_allocator::_execute_get(Channel &channel, - bool &progress) -{ - Request &req { channel._request }; - switch (channel._state) { - case Channel::PENDING: - - if (_nr_of_blks <= MAX_PBA - _first_block) { - - req._blk_nr = _first_block + _nr_of_blks; - ++_nr_of_blks; - - _mark_req_successful(channel, progress); - - } else - - _mark_req_failed(channel, progress, " get next block number"); - - return; - - default: - return; - } -} - - -void Block_allocator::_mark_req_failed(Channel &channel, - bool &progress, - char const *str) -{ - error("request failed: failed to ", str); - channel._request._success = false; - channel._state = Channel::COMPLETE; - progress = true; -} - - -void Block_allocator::_mark_req_successful(Channel &channel, - bool &progress) -{ - channel._request._success = true; - channel._state = Channel::COMPLETE; - progress = true; -} - - -bool Block_allocator::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (Channel &channel : _channels) { - if (channel._state == Channel::COMPLETE) { - if (sizeof(channel._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &channel._request, sizeof(channel._request)); - return true; - } - } - return false; -} - - -void Block_allocator::_drop_completed_request(Module_request &req) -{ - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (_channels[id]._state != Channel::COMPLETE) { - class Exception_2 { }; - throw Exception_2 { }; - } - _channels[id]._state = Channel::INACTIVE; -} - - -Block_allocator::Block_allocator(uint64_t first_block) -: - _first_block { first_block }, - _nr_of_blks { 0 } -{ } - - -bool Block_allocator::ready_to_submit_request() -{ - for (Channel &channel : _channels) { - if (channel._state == Channel::INACTIVE) - return true; - } - return false; -} - - -void Block_allocator::submit_request(Module_request &req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - if (_channels[id]._state == Channel::INACTIVE) { - req.dst_request_id(id); - _channels[id]._request = *static_cast(&req); - _channels[id]._state = Channel::SUBMITTED; - return; - } - } - class Invalid_call { }; - throw Invalid_call { }; -} - - -void Block_allocator::execute(bool &progress) -{ - for (Channel &channel : _channels) { - - if (channel._state == Channel::INACTIVE) - continue; - - Request &req { channel._request }; - switch (req._type) { - case Request::GET: - - if (channel._state == Channel::SUBMITTED) - channel._state = Channel::PENDING; - - _execute_get(channel, progress); - - break; - default: - - class Exception_1 { }; - throw Exception_1 { }; - } - } -} diff --git a/repos/gems/src/lib/tresor/block_io.cc b/repos/gems/src/lib/tresor/block_io.cc index 9a739b4181..3d11c97966 100644 --- a/repos/gems/src/lib/tresor/block_io.cc +++ b/repos/gems/src/lib/tresor/block_io.cc @@ -11,679 +11,199 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base includes */ -#include -#include - /* tresor includes */ #include #include -#include +#include using namespace Tresor; - -/********************** - ** Block_io_request ** - **********************/ - -Block_io_request::Block_io_request(uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - uint64_t client_req_offset, - uint64_t client_req_tag, - uint32_t key_id, - uint64_t pba, - uint64_t vba, - uint64_t blk_count, - void *blk_ptr, - void *hash_ptr) +Block_io_request::Block_io_request(Module_id src_module_id, Module_channel_id src_chan_id, Type type, + Request_offset client_req_offset, Request_tag client_req_tag, Key_id key_id, + Physical_block_address pba, Virtual_block_address vba, Block &blk, Hash &hash, + bool &success) : - Module_request { src_module_id, src_request_id, BLOCK_IO }, - _type { (Type)req_type }, - _client_req_offset { client_req_offset }, - _client_req_tag { client_req_tag }, - _key_id { key_id }, - _pba { pba }, - _vba { vba }, - _blk_count { blk_count }, - _blk_ptr { (addr_t)blk_ptr }, - _hash_ptr { (addr_t)hash_ptr } + Module_request { src_module_id, src_chan_id, BLOCK_IO }, _type { type }, + _client_req_offset { client_req_offset }, _client_req_tag { client_req_tag }, + _key_id { key_id }, _pba { pba }, _vba { vba }, _blk { blk }, _hash { hash }, _success { success } { } -void Block_io_request::print(Output &out) const -{ - if (_blk_count > 1) - Genode::print(out, type_to_string(_type), " pbas ", _pba, "..", _pba + _blk_count - 1); - else - Genode::print(out, type_to_string(_type), " pba ", _pba); -} - - char const *Block_io_request::type_to_string(Type type) { switch (type) { - case INVALID: return "invalid"; case READ: return "read"; case WRITE: return "write"; case SYNC: return "sync"; case READ_CLIENT_DATA: return "read_client_data"; case WRITE_CLIENT_DATA: return "write_client_data"; } - return "?"; + ASSERT_NEVER_REACHED; } -/************** - ** Block_io ** - **************/ - -bool Block_io::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) +void Block_io_channel::_generated_req_completed(State_uint state_uint) { - for (uint32_t id { 0 }; id < NR_OF_CHANNELS; id++) { - - Channel const &channel { _channels[id] }; - Crypto_request::Type crypto_req_type { - channel._state == Channel::DECRYPT_CLIENT_DATA_PENDING ? - Crypto_request::DECRYPT_CLIENT_DATA : - channel._state == Channel::ENCRYPT_CLIENT_DATA_PENDING ? - Crypto_request::ENCRYPT_CLIENT_DATA : - Crypto_request::INVALID }; - - if (crypto_req_type != Crypto_request::INVALID) { - - Request const &req { channel._request }; - construct_in_buf( - buf_ptr, buf_size, BLOCK_IO, id, crypto_req_type, - req._client_req_offset, req._client_req_tag, - req._key_id, nullptr, req._pba, req._vba, nullptr, - (void *)&channel._blk_buf); - - return true; - } + if (!_generated_req_success) { + error("block io: request (", *_req_ptr, ") failed because generated request failed)"); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; + return; } - return false; + _state = (State)state_uint; } -void Block_io::_drop_generated_request(Module_request &req) -{ - Module_request_id const id { req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Bad_id { }; - throw Bad_id { }; - } - switch (_channels[id]._state) { - case Channel::DECRYPT_CLIENT_DATA_PENDING: - _channels[id]._state = Channel::DECRYPT_CLIENT_DATA_IN_PROGRESS; - break; - case Channel::ENCRYPT_CLIENT_DATA_PENDING: - _channels[id]._state = Channel::ENCRYPT_CLIENT_DATA_IN_PROGRESS; - break; - default: - class Exception_1 { }; - throw Exception_1 { }; - } -} - - -void Block_io::generated_request_complete(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - switch (mod_req.dst_module_id()) { - case CRYPTO: - { - Crypto_request const &gen_req { *static_cast(&mod_req) }; - switch (_channels[id]._state) { - case Channel::DECRYPT_CLIENT_DATA_IN_PROGRESS: - _channels[id]._state = Channel::DECRYPT_CLIENT_DATA_COMPLETE; - _channels[id]._generated_req_success = gen_req.success(); - break; - case Channel::ENCRYPT_CLIENT_DATA_IN_PROGRESS: - _channels[id]._state = Channel::ENCRYPT_CLIENT_DATA_COMPLETE; - _channels[id]._generated_req_success = gen_req.success(); - break; - default: - class Exception_2 { }; - throw Exception_2 { }; - } - break; - } - default: - class Exception_3 { }; - throw Exception_3 { }; - } -} - - -void Block_io::_mark_req_failed(Channel &channel, - bool &progress, - char const *str) +void Block_io_channel::_mark_req_failed(bool &progress, Error_string str) { error("request failed: failed to ", str); - channel._request._success = false; - channel._state = Channel::COMPLETE; + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; } -void Block_io::_mark_req_successful(Channel &channel, - bool &progress) +void Block_io_channel::_mark_req_successful(bool &progress) { - channel._request._success = true; - channel._state = Channel::COMPLETE; + Request &req { *_req_ptr }; + req._success = true; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; -} - - -void Block_io::_execute_read(Channel &channel, - bool &progress) -{ - using Result = Vfs::File_io_service::Read_result; - - Request &req { channel._request }; - switch (channel._state) { - case Channel::PENDING: - - enum : uint64_t { MAX_FILE_OFFSET = 0x7fffffffffffffff }; - if (req._pba > (size_t)MAX_FILE_OFFSET / (size_t)BLOCK_SIZE) { - - error("request failed: failed to seek file offset, pba: ", req._pba); - channel._state = Channel::COMPLETE; - req._success = false; - progress = true; - return; + if (VERBOSE_BLOCK_IO && (!VERBOSE_BLOCK_IO_PBA_FILTER || VERBOSE_BLOCK_IO_PBA == req._pba)) { + switch (req._type) { + case Request::READ: + case Request::WRITE: + log("block_io: ", req.type_to_string(req._type), " pba ", req._pba, " hash ", hash(req._blk)); + break; + default: break; } - _vfs_handle.seek(req._pba * BLOCK_SIZE + - channel._nr_of_processed_bytes); - - if (!_vfs_handle.fs().queue_read(&_vfs_handle, channel._nr_of_remaining_bytes)) { - return; - } - channel._state = Channel::IN_PROGRESS; - progress = true; - return; - - case Channel::IN_PROGRESS: - { - size_t nr_of_read_bytes { 0 }; - - Byte_range_ptr dst { - (char *)req._blk_ptr + channel._nr_of_processed_bytes, - channel._nr_of_remaining_bytes }; - - Result const result { - _vfs_handle.fs().complete_read( - &_vfs_handle, dst, nr_of_read_bytes) }; - - switch (result) { - case Result::READ_QUEUED: - case Result::READ_ERR_WOULD_BLOCK: - - return; - - case Result::READ_OK: - - if (nr_of_read_bytes == 0) { - - error("request failed: number of read bytes is 0"); - channel._state = Channel::COMPLETE; - req._success = false; - progress = true; - return; - } - channel._nr_of_processed_bytes += nr_of_read_bytes; - channel._nr_of_remaining_bytes -= nr_of_read_bytes; - - if (channel._nr_of_remaining_bytes == 0) { - - channel._state = Channel::COMPLETE; - req._success = true; - progress = true; - return; - - } else { - - channel._state = Channel::PENDING; - progress = true; - return; - } - - case Result::READ_ERR_IO: - case Result::READ_ERR_INVALID: - - error("request failed: failed to read from file"); - channel._state = Channel::COMPLETE; - req._success = false; - progress = true; - return; - - default: - - class Bad_complete_read_result { }; - throw Bad_complete_read_result { }; - } - } - default: return; } } -void Block_io::_execute_read_client_data(Channel &channel, - bool &progress) +void Block_io_channel::_read(bool &progress) { - using Result = Vfs::File_io_service::Read_result; - - Request &req { channel._request }; - switch (channel._state) { - case Channel::PENDING: - - _vfs_handle.seek(req._pba * BLOCK_SIZE + - channel._nr_of_processed_bytes); - - if (!_vfs_handle.fs().queue_read(&_vfs_handle, channel._nr_of_remaining_bytes)) { - return; - } - channel._state = Channel::IN_PROGRESS; - progress = true; - return; - - case Channel::IN_PROGRESS: - { - size_t nr_of_read_bytes { 0 }; - - Byte_range_ptr dst { - (char *)&channel._blk_buf + channel._nr_of_processed_bytes, - channel._nr_of_remaining_bytes }; - - Result const result { - _vfs_handle.fs().complete_read( - &_vfs_handle, dst, nr_of_read_bytes) }; - - switch (result) { - case Result::READ_QUEUED: - case Result::READ_ERR_WOULD_BLOCK: - - return; - - case Result::READ_OK: - - channel._nr_of_processed_bytes += nr_of_read_bytes; - channel._nr_of_remaining_bytes -= nr_of_read_bytes; - - if (channel._nr_of_remaining_bytes == 0) { - - channel._state = Channel::DECRYPT_CLIENT_DATA_PENDING; - progress = true; - return; - - } else { - - channel._state = Channel::PENDING; - progress = true; - return; - } - - case Result::READ_ERR_IO: - case Result::READ_ERR_INVALID: - - channel._state = Channel::COMPLETE; - req._success = false; - progress = true; - return; - - default: - - class Bad_complete_read_result { }; - throw Bad_complete_read_result { }; - } - } - case Channel::DECRYPT_CLIENT_DATA_COMPLETE: - - if (!channel._generated_req_success) { - _mark_req_failed(channel, progress, "decrypt client data"); - return; - } - _mark_req_successful(channel, progress); - return; - - default: return; + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: _file.read(READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); break; + case READ_OK: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: break; } } -void Block_io::_execute_write_client_data(Channel &channel, - bool &progress) +void Block_io_channel::_read_client_data(bool &progress) { - using Result = Vfs::File_io_service::Write_result; - Request &req { channel._request }; - switch (channel._state) { - case Channel::PENDING: + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: _file.read(READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress); break; + case READ_OK: - channel._state = Channel::ENCRYPT_CLIENT_DATA_PENDING; - progress = true; + _generate_req( + PLAINTEXT_BLK_SUPPLIED, progress, Crypto_request::DECRYPT_CLIENT_DATA, req._client_req_offset, + req._client_req_tag, req._key_id, *(Key_value *)0, req._pba, req._vba, _blk); return; - case Channel::ENCRYPT_CLIENT_DATA_COMPLETE: - - if (!channel._generated_req_success) { - _mark_req_failed(channel, progress, "encrypt client data"); - return; - } - calc_sha256_4k_hash(channel._blk_buf, *(Hash *)req._hash_ptr); - _vfs_handle.seek(req._pba * BLOCK_SIZE + - channel._nr_of_processed_bytes); - - channel._state = Channel::IN_PROGRESS; - progress = true; - return; - - case Channel::IN_PROGRESS: - { - size_t nr_of_written_bytes { 0 }; - - Const_byte_range_ptr src { - (char const *)&channel._blk_buf + channel._nr_of_processed_bytes, - channel._nr_of_remaining_bytes }; - - Result const result = - _vfs_handle.fs().write( - &_vfs_handle, src, nr_of_written_bytes); - - switch (result) { - case Result::WRITE_ERR_WOULD_BLOCK: - return; - - case Result::WRITE_OK: - - channel._nr_of_processed_bytes += nr_of_written_bytes; - channel._nr_of_remaining_bytes -= nr_of_written_bytes; - - if (channel._nr_of_remaining_bytes == 0) { - - channel._state = Channel::COMPLETE; - req._success = true; - progress = true; - return; - - } else { - - channel._state = Channel::PENDING; - progress = true; - return; - } - - case Result::WRITE_ERR_IO: - case Result::WRITE_ERR_INVALID: - - channel._state = Channel::COMPLETE; - req._success = false; - progress = true; - return; - - default: - - class Bad_write_result { }; - throw Bad_write_result { }; - } - - } - default: return; + case PLAINTEXT_BLK_SUPPLIED: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: break; } } -void Block_io::_execute_write(Channel &channel, - bool &progress) +void Block_io_channel::_write_client_data(bool &progress) { - using Result = Vfs::File_io_service::Write_result; + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: - Request &req { channel._request }; - switch (channel._state) { - case Channel::PENDING: - - _vfs_handle.seek(req._pba * BLOCK_SIZE + - channel._nr_of_processed_bytes); - - channel._state = Channel::IN_PROGRESS; - progress = true; + _generate_req( + CIPHERTEXT_BLK_OBTAINED, progress, Crypto_request::ENCRYPT_CLIENT_DATA, req._client_req_offset, + req._client_req_tag, req._key_id, *(Key_value *)0, req._pba, req._vba, _blk); break; - case Channel::IN_PROGRESS: - { - size_t nr_of_written_bytes { 0 }; + case CIPHERTEXT_BLK_OBTAINED: - Const_byte_range_ptr src { - (char const *)req._blk_ptr + channel._nr_of_processed_bytes, - channel._nr_of_remaining_bytes }; + calc_hash(_blk, req._hash); + _file.write(WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress); break; + break; - Result const result = - _vfs_handle.fs().write( - &_vfs_handle, src, nr_of_written_bytes); - - switch (result) { - case Result::WRITE_ERR_WOULD_BLOCK: - return; - - case Result::WRITE_OK: - - channel._nr_of_processed_bytes += nr_of_written_bytes; - channel._nr_of_remaining_bytes -= nr_of_written_bytes; - - if (channel._nr_of_remaining_bytes == 0) { - - channel._state = Channel::COMPLETE; - req._success = true; - progress = true; - return; - - } else { - - channel._state = Channel::PENDING; - progress = true; - return; - } - - case Result::WRITE_ERR_IO: - case Result::WRITE_ERR_INVALID: - - channel._state = Channel::COMPLETE; - req._success = false; - progress = true; - return; - - default: - - class Bad_write_result { }; - throw Bad_write_result { }; - } - - } - default: return; + case WRITE_OK: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: break; } } -void Block_io::_execute_sync(Channel &channel, - bool &progress) + +void Block_io_channel::_write(bool &progress) { - using Result = Vfs::File_io_service::Sync_result; - Request &req { channel._request }; - switch (channel._state) { - case Channel::PENDING: - - if (!_vfs_handle.fs().queue_sync(&_vfs_handle)) { - return; - } - channel._state = Channel::IN_PROGRESS; - progress = true; - break;; - - case Channel::IN_PROGRESS: - - switch (_vfs_handle.fs().complete_sync(&_vfs_handle)) { - case Result::SYNC_QUEUED: - - return; - - case Result::SYNC_ERR_INVALID: - - req._success = false; - channel._state = Channel::COMPLETE; - progress = true; - return; - - case Result::SYNC_OK: - - req._success = true; - channel._state = Channel::COMPLETE; - progress = true; - return; - - default: - - class Bad_sync_result { }; - throw Bad_sync_result { }; - } - - default: return; + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: _file.write(WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); break; + case WRITE_OK: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: break; } } + +void Block_io_channel::_sync(bool &progress) +{ + switch (_state) { + case REQ_SUBMITTED: _file.sync(SYNC_OK, FILE_ERR, progress); break; + case SYNC_OK: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: break; + } +} + + +void Block_io_channel::execute(bool &progress) +{ + if (!_req_ptr) + return; + + switch (_req_ptr->_type) { + case Request::READ: _read(progress); break; + case Request::WRITE: _write(progress); break; + case Request::SYNC: _sync(progress); break; + case Request::READ_CLIENT_DATA: _read_client_data(progress); break; + case Request::WRITE_CLIENT_DATA: _write_client_data(progress); break; + } +} + + void Block_io::execute(bool &progress) { - for (Channel &channel : _channels) { - - if (channel._state == Channel::INACTIVE) - continue; - - Request &req { channel._request }; - if (channel._state == Channel::SUBMITTED) { - - uint64_t const nr_of_remaining_bytes { - req._blk_count * BLOCK_SIZE }; - - if (nr_of_remaining_bytes > ~(size_t)0) { - class Exception_2 { }; - throw Exception_2 { }; - } - channel._state = Channel::PENDING; - channel._nr_of_processed_bytes = 0; - channel._nr_of_remaining_bytes = (size_t)nr_of_remaining_bytes; - } - switch (req._type) { - case Request::READ: _execute_read(channel, progress); break; - case Request::WRITE: _execute_write(channel, progress); break; - case Request::SYNC: _execute_sync(channel, progress); break; - case Request::READ_CLIENT_DATA: _execute_read_client_data(channel, progress); break; - case Request::WRITE_CLIENT_DATA: _execute_write_client_data(channel, progress); break; - default: - class Exception_1 { }; - throw Exception_1 { }; - } - } + for_each_channel([&] (Channel &chan) { + chan.execute(progress); }); } -Block_io::Block_io(Vfs::Env &vfs_env, - Xml_node const &xml_node) +void Block_io_channel::_request_submitted(Module_request &mod_req) +{ + _req_ptr = static_cast(&mod_req); + _state = REQ_SUBMITTED; +} + + +Block_io_channel::Block_io_channel(Module_channel_id id, Vfs::Env &vfs_env, Xml_node const &xml_node) : - _path { xml_node.attribute_value("path", String<32> { "" } ) }, - _vfs_env { vfs_env } + Module_channel { BLOCK_IO, id }, _vfs_env { vfs_env }, _path { xml_node.attribute_value("path", Tresor::Path()) } { } -bool Block_io::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) +Block_io::Block_io(Vfs::Env &vfs_env, Xml_node const &xml_node) { - for (Channel &channel : _channels) { - if (channel._state == Channel::COMPLETE) { - Request &req { channel._request }; - if (sizeof(req) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &req, sizeof(req)); - - if (VERBOSE_BLOCK_IO && - (!VERBOSE_BLOCK_IO_PBA_FILTER || - VERBOSE_BLOCK_IO_PBA == req._pba)) { - - switch (req._type) { - case Request::READ: - case Request::WRITE: - { - Hash hash; - calc_sha256_4k_hash(*(Block *)req._blk_ptr, hash); - log("block_io: ", req.type_name(), " pba ", req._pba, - " data ", *(Block *)req._blk_ptr, " hash ", hash); - - break; - } - case Request::READ_CLIENT_DATA: - case Request::WRITE_CLIENT_DATA: - { - Hash hash; - calc_sha256_4k_hash(channel._blk_buf, hash); - log("block_io: ", req.type_name(), " pba ", req._pba, - " data ", channel._blk_buf, - " hash ", hash); - - break; - } - default: - break; - } - } - return true; - } + Module_channel_id id { 0 }; + for (Constructible &chan : _channels) { + chan.construct(id++, vfs_env, xml_node); + add_channel(*chan); } - return false; -} - - -void Block_io::_drop_completed_request(Module_request &req) -{ - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (_channels[id]._state != Channel::COMPLETE) { - class Exception_2 { }; - throw Exception_2 { }; - } - _channels[id]._state = Channel::INACTIVE; -} - - -bool Block_io::ready_to_submit_request() -{ - for (Channel &channel : _channels) { - if (channel._state == Channel::INACTIVE) - return true; - } - return false; -} - -void Block_io::submit_request(Module_request &req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - if (_channels[id]._state == Channel::INACTIVE) { - req.dst_request_id(id); - _channels[id]._request = *static_cast(&req); - _channels[id]._state = Channel::SUBMITTED; - return; - } - } - class Invalid_call { }; - throw Invalid_call { }; } diff --git a/repos/gems/src/lib/tresor/crypto.cc b/repos/gems/src/lib/tresor/crypto.cc index 9def677a4d..8a2f7e2a64 100644 --- a/repos/gems/src/lib/tresor/crypto.cc +++ b/repos/gems/src/lib/tresor/crypto.cc @@ -11,51 +11,42 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base includes */ -#include -#include - /* tresor includes */ #include #include -#include +#include using namespace Tresor; - -/******************** - ** Crypto_request ** - ********************/ - -Crypto_request::Crypto_request(uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - uint64_t client_req_offset, - uint64_t client_req_tag, - uint32_t key_id, - void *key_plaintext_ptr, - uint64_t pba, - uint64_t vba, - void *plaintext_blk_ptr, - void *ciphertext_blk_ptr) +Crypto_request::Crypto_request(Module_id src_module_id, Module_channel_id src_chan_id, Type type, + Request_offset client_req_offset, Request_tag client_req_tag, Key_id key_id, + Key_value const &key_plaintext, Physical_block_address pba, Virtual_block_address vba, + Block &blk, bool &success) : - Module_request { src_module_id, src_request_id, CRYPTO }, - _type { (Type)req_type }, - _client_req_offset { client_req_offset }, - _client_req_tag { client_req_tag }, - _pba { pba }, - _vba { vba }, - _key_id { key_id }, - _key_plaintext_ptr { (addr_t)key_plaintext_ptr }, - _plaintext_blk_ptr { (addr_t)plaintext_blk_ptr }, - _ciphertext_blk_ptr { (addr_t)ciphertext_blk_ptr } + Module_request { src_module_id, src_chan_id, CRYPTO }, _type { type }, _client_req_offset { client_req_offset }, + _client_req_tag { client_req_tag }, _pba { pba }, _vba { vba }, _key_id { key_id }, _key_plaintext { key_plaintext }, + _blk { blk }, _success { success } { } +void Crypto_request::print(Output &out) const +{ + Genode::print(out, type_to_string(_type)); + switch (_type) { + case ADD_KEY: + case REMOVE_KEY: Genode::print(out, " ", _key_id); break; + case DECRYPT: + case ENCRYPT: + case DECRYPT_CLIENT_DATA: + case ENCRYPT_CLIENT_DATA: Genode::print(out, " pba ", _pba); break; + default: break; + } +} + + char const *Crypto_request::type_to_string(Type type) { switch (type) { - case INVALID: return "invalid"; case ADD_KEY: return "add_key"; case REMOVE_KEY: return "remove_key"; case ENCRYPT_CLIENT_DATA: return "encrypt_client_data"; @@ -63,671 +54,276 @@ char const *Crypto_request::type_to_string(Type type) case ENCRYPT: return "encrypt"; case DECRYPT: return "decrypt"; } - return "?"; + ASSERT_NEVER_REACHED; } -/************ - ** Crypto ** - ************/ - -bool Crypto::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) +void Crypto_channel::_generated_req_completed(State_uint state_uint) { - for (uint32_t id { 0 }; id < NR_OF_CHANNELS; id++) { - - Channel const &chan { _channels[id] }; - Client_data_request::Type cd_req_type { - chan._state == Channel::OBTAIN_PLAINTEXT_BLK_PENDING ? - Client_data_request::OBTAIN_PLAINTEXT_BLK : - chan._state == Channel::SUPPLY_PLAINTEXT_BLK_PENDING ? - Client_data_request::SUPPLY_PLAINTEXT_BLK : - Client_data_request::INVALID }; - - if (cd_req_type != Client_data_request::INVALID) { - - Request const &req { chan._request }; - Client_data_request const cd_req { - CRYPTO, id, cd_req_type, req._client_req_offset, - req._client_req_tag, req._pba, req._vba, - (addr_t)&chan._blk_buf }; - - if (sizeof(cd_req) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &cd_req, sizeof(cd_req));; - return true; - } + if (!_generated_req_success) { + error("crypto: request (", *_req_ptr, ") failed because generated request failed)"); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; + return; } - return false; + _state = (State)state_uint; } -void Crypto::_drop_generated_request(Module_request &req) +Constructible &Crypto_channel::_key_dir(Key_id key_id) { - Module_request_id const id { req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Bad_id { }; - throw Bad_id { }; - } - switch (_channels[id]._state) { - case Channel::OBTAIN_PLAINTEXT_BLK_PENDING: - _channels[id]._state = Channel::OBTAIN_PLAINTEXT_BLK_IN_PROGRESS; - break; - case Channel::SUPPLY_PLAINTEXT_BLK_PENDING: - _channels[id]._state = Channel::SUPPLY_PLAINTEXT_BLK_IN_PROGRESS; - break; - default: - class Exception_1 { }; - throw Exception_1 { }; - } -} - - -Crypto::Key_directory &Crypto::_lookup_key_dir(uint32_t key_id) -{ - for (Key_directory &key_dir : _key_dirs) { - if (key_dir.key_id == key_id) { + for (Constructible &key_dir : _key_dirs) + if (key_dir.constructed() && key_dir->key_id == key_id) return key_dir; - } - } - class Exception_1 { }; - throw Exception_1 { }; + ASSERT_NEVER_REACHED; } -void Crypto::_mark_req_failed(Channel &channel, - bool &progress, - char const *str) +void Crypto_channel::_mark_req_failed(bool &progress, char const *str) { - error("crypto: request (", channel._request, ") failed at step \"", str, "\""); - channel._request._success = false; - channel._state = Channel::COMPLETE; + error("crypto: request (", *_req_ptr, ") failed at step \"", str, "\""); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; } -void Crypto::_mark_req_successful(Channel &channel, - bool &progress) +void Crypto_channel::_mark_req_successful(bool &progress) { - channel._request._success = true; - channel._state = Channel::COMPLETE; + Request &req { *_req_ptr }; + req._success = true; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; -} + if (VERBOSE_WRITE_VBA && req._type == Request::ENCRYPT_CLIENT_DATA) + log(" encrypt leaf data: plaintext ", _blk, " hash ", hash(_blk), + "\n update branch:\n ", Branch_lvl_prefix("leaf data: "), req._blk); + if (VERBOSE_READ_VBA && req._type == Request::DECRYPT_CLIENT_DATA) + log(" ", Branch_lvl_prefix("leaf data: "), req._blk, + "\n decrypt leaf data: plaintext ", _blk, " hash ", hash(_blk)); -void Crypto::_execute_add_key(Channel &channel, - bool &progress) -{ - Request &req { channel._request }; - switch (channel._state) { - case Channel::SUBMITTED: - { - _add_key_handle.seek(0); - - char buf[sizeof(req._key_id) + KEY_SIZE] { }; - memcpy(buf, &req._key_id, sizeof(req._key_id)); - memcpy(buf + sizeof(req._key_id), (void *)req._key_plaintext_ptr, KEY_SIZE); - - Const_byte_range_ptr const src(buf, sizeof(buf)); - size_t nr_of_written_bytes { 0 }; - Write_result const write_result { - _add_key_handle.fs().write( - &_add_key_handle, src, nr_of_written_bytes) }; - - switch (write_result) { - case Write_result::WRITE_OK: - { - Key_directory *key_dir_ptr { nullptr }; - for (Key_directory &key_dir : _key_dirs) { - if (key_dir.key_id == 0) - key_dir_ptr = &key_dir; - } - if (key_dir_ptr == nullptr) { - - _mark_req_failed(channel, progress, "find unused key dir"); - return; - } - key_dir_ptr->key_id = req._key_id; - key_dir_ptr->encrypt_handle = - &vfs_open_rw( - _vfs_env, - { _path.string(), "/keys/", req._key_id, "/encrypt" }); - - key_dir_ptr->decrypt_handle = - &vfs_open_rw( - _vfs_env, - { _path.string(), "/keys/", req._key_id, "/decrypt" }); - - _mark_req_successful(channel, progress); - return; + if (VERBOSE_CRYPTO) { + switch (req._type) { + case Request::DECRYPT_CLIENT_DATA: + case Request::ENCRYPT_CLIENT_DATA: + log("crypto: ", req.type_to_string(req._type), " pba ", req._pba, " vba ", req._vba, + " plain ", _blk, " cipher ", req._blk); + break; + default: break; } - case Write_result::WRITE_ERR_WOULD_BLOCK: - case Write_result::WRITE_ERR_INVALID: - case Write_result::WRITE_ERR_IO: - - _mark_req_failed(channel, progress, "write command"); - return; - } - return; } - default: - - return; + if (VERBOSE_BLOCK_IO && (!VERBOSE_BLOCK_IO_PBA_FILTER || VERBOSE_BLOCK_IO_PBA == req._pba)) { + switch (req._type) { + case Request::DECRYPT_CLIENT_DATA: + log("block_io: read pba ", req._pba, " hash ", hash(req._blk), " (plaintext hash ", hash(_blk), ")"); + break; + case Request::ENCRYPT_CLIENT_DATA: + log("block_io: write pba ", req._pba, " hash ", hash(req._blk), " (plaintext hash ", hash(_blk), ")"); + break; + default: break; + } } } -void Crypto::_execute_remove_key(Channel &channel, - bool &progress) +void Crypto_channel::_add_key(bool &progress) { - Request &req { channel._request }; - switch (channel._state) { - case Channel::SUBMITTED: + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: + + memcpy(_add_key_buf, &req._key_id, sizeof(Key_id)); + memcpy(_add_key_buf + sizeof(Key_id), &req._key_plaintext, KEY_SIZE); + _add_key_file.write(WRITE_OK, FILE_ERR, 0, { _add_key_buf, sizeof(_add_key_buf) }, progress); + break; + + case WRITE_OK: { - _remove_key_handle.seek(0); - - Const_byte_range_ptr src { - (char const*)&req._key_id, sizeof(req._key_id) }; - - size_t nr_of_written_bytes { 0 }; - Write_result const result = - _remove_key_handle.fs().write( - &_remove_key_handle, src, nr_of_written_bytes); - - switch (result) { - case Write_result::WRITE_OK: - { - Key_directory &key_dir { _lookup_key_dir(req._key_id) }; - _vfs_env.root_dir().close(key_dir.encrypt_handle); - key_dir.encrypt_handle = nullptr; - _vfs_env.root_dir().close(key_dir.decrypt_handle); - key_dir.decrypt_handle = nullptr; - key_dir.key_id = 0; - - _mark_req_successful(channel, progress); - return; - } - case Write_result::WRITE_ERR_WOULD_BLOCK: - case Write_result::WRITE_ERR_INVALID: - case Write_result::WRITE_ERR_IO: - - _mark_req_failed(channel, progress, "write command"); - return; + Constructible *key_dir_ptr { nullptr }; + for (Constructible &key_dir : _key_dirs) + if (!key_dir.constructed()) + key_dir_ptr = &key_dir; + if (!key_dir_ptr) { + _mark_req_failed(progress, "find unused key dir"); + break; } + key_dir_ptr->construct(*this, req._key_id); + _mark_req_successful(progress); + break; } - default: - - return; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: break; } } -void Crypto::_execute_encrypt_client_data(Channel &channel, - bool &progress) +void Crypto_channel::_remove_key(bool &progress) { - Request &req { channel._request }; - switch (channel._state) { - case Channel::SUBMITTED: + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: _remove_key_file.write(WRITE_OK, FILE_ERR, 0, { (char *)&req._key_id, sizeof(Key_id) }, progress); break; + case WRITE_OK: - channel._state = Channel::OBTAIN_PLAINTEXT_BLK_PENDING; - progress = true; - return; + _key_dir(req._key_id).destruct(); + _mark_req_successful(progress); + break; - case Channel::OBTAIN_PLAINTEXT_BLK_COMPLETE: - { - if (!channel._generated_req_success) { - - _mark_req_failed(channel, progress, "obtain plaintext block"); - return; - } - channel._vfs_handle = _lookup_key_dir(req._key_id).encrypt_handle; - channel._vfs_handle->seek(req._pba * BLOCK_SIZE); - size_t nr_of_written_bytes { 0 }; - - Const_byte_range_ptr dst { - (char *)&channel._blk_buf, BLOCK_SIZE }; - - channel._vfs_handle->fs().write( - channel._vfs_handle, dst, nr_of_written_bytes); - - channel._state = Channel::OP_WRITTEN_TO_VFS_HANDLE; - progress = true; - return; - } - case Channel::OP_WRITTEN_TO_VFS_HANDLE: - { - channel._vfs_handle->seek(req._pba * BLOCK_SIZE); - bool success { - channel._vfs_handle->fs().queue_read( - channel._vfs_handle, BLOCK_SIZE) }; - - if (!success) - return; - - channel._state = Channel::QUEUE_READ_SUCCEEDED; - progress = true; - return; - } - case Channel::QUEUE_READ_SUCCEEDED: - { - size_t nr_of_read_bytes { 0 }; - - Byte_range_ptr dst { - (char *)req._ciphertext_blk_ptr, BLOCK_SIZE }; - - Read_result const result { - channel._vfs_handle->fs().complete_read( - channel._vfs_handle, dst, nr_of_read_bytes) }; - - switch (result) { - case Read_result::READ_OK: - - _mark_req_successful(channel, progress); - return; - - case Read_result::READ_QUEUED: - case Read_result::READ_ERR_WOULD_BLOCK: - - return; - - case Read_result::READ_ERR_IO: - case Read_result::READ_ERR_INVALID: - - _mark_req_failed(channel, progress, "read ciphertext data"); - return; - } - } - default: - - return; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: return; } } -void Crypto::_execute_encrypt(Channel &channel, - bool &progress) +void Crypto_channel::_encrypt_client_data(bool &progress) { - Request &req { channel._request }; - switch (channel._state) { - case Channel::SUBMITTED: - { - channel._vfs_handle = _lookup_key_dir(req._key_id).encrypt_handle; - channel._vfs_handle->seek(req._pba * BLOCK_SIZE); - size_t nr_of_written_bytes { 0 }; + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: - Const_byte_range_ptr src { - (char *)req._plaintext_blk_ptr, BLOCK_SIZE }; + _generate_req( + PLAINTEXT_BLK_OBTAINED, progress, Client_data_request::OBTAIN_PLAINTEXT_BLK, + req._client_req_offset, req._client_req_tag, req._pba, req._vba, _blk);; + break; - channel._vfs_handle->fs().write( - channel._vfs_handle, src, nr_of_written_bytes); + case PLAINTEXT_BLK_OBTAINED: - channel._state = Channel::OP_WRITTEN_TO_VFS_HANDLE; - progress = true; - return; - } - case Channel::OP_WRITTEN_TO_VFS_HANDLE: - { - channel._vfs_handle->seek(req._pba * BLOCK_SIZE); - bool success { - channel._vfs_handle->fs().queue_read( - channel._vfs_handle, BLOCK_SIZE) }; + _key_dir(req._key_id)->encrypt_file.write( + WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress); + break; - if (!success) - return; + case WRITE_OK: - channel._state = Channel::QUEUE_READ_SUCCEEDED; - progress = true; - return; - } - case Channel::QUEUE_READ_SUCCEEDED: - { - size_t nr_of_read_bytes { 0 }; + _key_dir(req._key_id)->encrypt_file.read( + READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + break; - Byte_range_ptr dst { (char *)req._ciphertext_blk_ptr, BLOCK_SIZE }; - - Read_result const result { - channel._vfs_handle->fs().complete_read( - channel._vfs_handle, dst, nr_of_read_bytes) }; - - switch (result) { - case Read_result::READ_OK: - - _mark_req_successful(channel, progress); - return; - - case Read_result::READ_QUEUED: - case Read_result::READ_ERR_WOULD_BLOCK: - - return; - - case Read_result::READ_ERR_IO: - case Read_result::READ_ERR_INVALID: - - _mark_req_failed(channel, progress, "read ciphertext data"); - return; - } - } - default: - - return; + case READ_OK: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation"); break; + default: break; } } -void Crypto::_execute_decrypt(Channel &channel, - bool &progress) +void Crypto_channel::_encrypt(bool &progress) { - Request &req { channel._request }; - switch (channel._state) { - case Channel::SUBMITTED: - { - channel._vfs_handle = _lookup_key_dir(req._key_id).decrypt_handle; - channel._vfs_handle->seek(req._pba * BLOCK_SIZE); + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: - size_t nr_of_written_bytes { 0 }; + _key_dir(req._key_id)->encrypt_file.write( + WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + break; - Const_byte_range_ptr src { - (char *)channel._request._ciphertext_blk_ptr, BLOCK_SIZE }; + case WRITE_OK: - channel._vfs_handle->fs().write( - channel._vfs_handle, src, nr_of_written_bytes); + _key_dir(req._key_id)->encrypt_file.read( + READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + break; - channel._state = Channel::OP_WRITTEN_TO_VFS_HANDLE; - progress = true; - return; - } - case Channel::OP_WRITTEN_TO_VFS_HANDLE: - { - channel._vfs_handle->seek(req._pba * BLOCK_SIZE); - - bool success { - channel._vfs_handle->fs().queue_read( - channel._vfs_handle, BLOCK_SIZE) }; - - if (!success) - return; - - channel._state = Channel::QUEUE_READ_SUCCEEDED; - progress = true; - return; - } - case Channel::QUEUE_READ_SUCCEEDED: - { - size_t nr_of_read_bytes { 0 }; - Byte_range_ptr dst { - (char *)req._plaintext_blk_ptr, BLOCK_SIZE }; - - Read_result const result { - channel._vfs_handle->fs().complete_read( - channel._vfs_handle, dst, nr_of_read_bytes) }; - - switch (result) { - case Read_result::READ_OK: - - _mark_req_successful(channel, progress); - return; - - case Read_result::READ_QUEUED: - case Read_result::READ_ERR_WOULD_BLOCK: - - return; - - case Read_result::READ_ERR_IO: - case Read_result::READ_ERR_INVALID: - - _mark_req_failed(channel, progress, "read plaintext data"); - return; - } - return; - } - default: - - return; + case READ_OK: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation"); break; + default: break; } } -void Crypto::_execute_decrypt_client_data(Channel &channel, - bool &progress) +void Crypto_channel::_decrypt(bool &progress) { - Request &req { channel._request }; - switch (channel._state) { - case Channel::SUBMITTED: - { - channel._vfs_handle = _lookup_key_dir(req._key_id).decrypt_handle; - if (channel._vfs_handle == nullptr) { - _mark_req_failed(channel, progress, "lookup key dir"); - return; - } - channel._vfs_handle->seek(req._pba * BLOCK_SIZE); + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: - size_t nr_of_written_bytes { 0 }; - Const_byte_range_ptr src { - (char *)channel._request._ciphertext_blk_ptr, BLOCK_SIZE }; + _key_dir(req._key_id)->decrypt_file.write( + WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + break; - channel._vfs_handle->fs().write( - channel._vfs_handle, src, nr_of_written_bytes); + case WRITE_OK: - channel._state = Channel::OP_WRITTEN_TO_VFS_HANDLE; - progress = true; - return; + _key_dir(req._key_id)->decrypt_file.read( + READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + break; + + case READ_OK: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation"); break; + default: break; } - case Channel::OP_WRITTEN_TO_VFS_HANDLE: - { - channel._vfs_handle->seek(req._pba * BLOCK_SIZE); +} - bool success { - channel._vfs_handle->fs().queue_read( - channel._vfs_handle, BLOCK_SIZE) }; - if (!success) - return; +void Crypto_channel::_decrypt_client_data(bool &progress) +{ + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: - channel._state = Channel::QUEUE_READ_SUCCEEDED; - progress = true; - return; + _key_dir(req._key_id)->decrypt_file.write( + WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + break; + + case WRITE_OK: + + _key_dir(req._key_id)->decrypt_file.read( + READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress); + break; + + case READ_OK: + + _generate_req( + PLAINTEXT_BLK_SUPPLIED, progress, Client_data_request::SUPPLY_PLAINTEXT_BLK, + req._client_req_offset, req._client_req_tag, req._pba, req._vba, _blk);; + break; + + case PLAINTEXT_BLK_SUPPLIED: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: break; } - case Channel::QUEUE_READ_SUCCEEDED: - { - size_t nr_of_read_bytes { 0 }; - Byte_range_ptr dst { - (char *)&channel._blk_buf, BLOCK_SIZE }; +} - Read_result const result { - channel._vfs_handle->fs().complete_read( - channel._vfs_handle, dst, nr_of_read_bytes) }; - switch (result) { - case Read_result::READ_OK: +void Crypto_channel::_request_submitted(Module_request &mod_req) +{ + _req_ptr = static_cast(&mod_req); + _state = REQ_SUBMITTED; +} - channel._state = Channel::SUPPLY_PLAINTEXT_BLK_PENDING; - progress = true; - return; - case Read_result::READ_QUEUED: - case Read_result::READ_ERR_WOULD_BLOCK: - - return; - - case Read_result::READ_ERR_IO: - case Read_result::READ_ERR_INVALID: - - _mark_req_failed(channel, progress, "read plaintext data"); - return; - } - return; - } - case Channel::SUPPLY_PLAINTEXT_BLK_COMPLETE: - - if (!channel._generated_req_success) { - - _mark_req_failed(channel, progress, "supply plaintext block"); - return; - } - _mark_req_successful(channel, progress); +void Crypto_channel::execute(bool &progress) +{ + if (!_req_ptr) return; - default: - - return; + switch (_req_ptr->_type) { + case Request::ADD_KEY: _add_key(progress); break; + case Request::REMOVE_KEY: _remove_key(progress); break; + case Request::DECRYPT: _decrypt(progress); break; + case Request::ENCRYPT: _encrypt(progress); break; + case Request::DECRYPT_CLIENT_DATA: _decrypt_client_data(progress); break; + case Request::ENCRYPT_CLIENT_DATA: _encrypt_client_data(progress); break; } } void Crypto::execute(bool &progress) { - for (Channel &channel : _channels) { - - if (channel._state == Channel::INACTIVE) - continue; - - switch (channel._request._type) { - case Request::ADD_KEY: _execute_add_key(channel, progress); break; - case Request::REMOVE_KEY: _execute_remove_key(channel, progress); break; - case Request::DECRYPT: _execute_decrypt(channel, progress); break; - case Request::ENCRYPT: _execute_encrypt(channel, progress); break; - case Request::DECRYPT_CLIENT_DATA: _execute_decrypt_client_data(channel, progress); break; - case Request::ENCRYPT_CLIENT_DATA: _execute_encrypt_client_data(channel, progress); break; - default: - class Exception_1 { }; - throw Exception_1 { }; - } - } + for_each_channel([&] (Channel &chan) { + chan.execute(progress); }); } -Crypto::Crypto(Vfs::Env &vfs_env, - Xml_node const &xml_node) +Crypto_channel::Crypto_channel(Module_channel_id id, Vfs::Env &vfs_env, Xml_node const &xml_node) : - _vfs_env { vfs_env }, - _path { xml_node.attribute_value("path", String<32>()) }, - _add_key_handle { vfs_open_wo(_vfs_env, { _path.string(), "/add_key" }) }, - _remove_key_handle { vfs_open_wo(_vfs_env, { _path.string(), "/remove_key" }) } + Module_channel { CRYPTO, id }, _vfs_env { vfs_env }, _path { xml_node.attribute_value("path", Tresor::Path()) } { } -void Crypto::generated_request_complete(Module_request &mod_req) +Crypto::Crypto(Vfs::Env &vfs_env, Xml_node const &xml_node) { - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - switch (mod_req.dst_module_id()) { - case CLIENT_DATA: - { - Client_data_request const &gen_req { *static_cast(&mod_req) }; - switch (_channels[id]._state) { - case Channel::OBTAIN_PLAINTEXT_BLK_IN_PROGRESS: - _channels[id]._state = Channel::OBTAIN_PLAINTEXT_BLK_COMPLETE; - _channels[id]._generated_req_success = gen_req.success(); - break; - case Channel::SUPPLY_PLAINTEXT_BLK_IN_PROGRESS: - _channels[id]._state = Channel::SUPPLY_PLAINTEXT_BLK_COMPLETE; - _channels[id]._generated_req_success = gen_req.success(); - break; - default: - class Exception_2 { }; - throw Exception_2 { }; - } - break; - } - default: - class Exception_3 { }; - throw Exception_3 { }; + Module_channel_id id { 0 }; + for (Constructible &chan : _channels) { + chan.construct(id++, vfs_env, xml_node); + add_channel(*chan); } } - - -bool Crypto::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (Channel &channel : _channels) { - if (channel._state == Channel::COMPLETE) { - if (sizeof(channel._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &channel._request, sizeof(channel._request)); - - Request &req { channel._request }; - if (VERBOSE_WRITE_VBA && req._type == Request::ENCRYPT_CLIENT_DATA) { - - Hash hash { }; - calc_sha256_4k_hash(*(Block *)channel._blk_buf, hash); - log(" encrypt leaf data: plaintext ", *(Block *)channel._blk_buf, " hash ", hash); - log(" update branch:"); - log(" ", Branch_lvl_prefix("leaf data: "), *(Block *)req._ciphertext_blk_ptr); - } - if (VERBOSE_READ_VBA && req._type == Request::DECRYPT_CLIENT_DATA) { - - Hash hash { }; - calc_sha256_4k_hash(*(Block *)channel._blk_buf, hash); - log(" ", Branch_lvl_prefix("leaf data: "), *(Block *)req._ciphertext_blk_ptr); - log(" decrypt leaf data: plaintext ", *(Block *)channel._blk_buf, " hash ", hash); - } - if (VERBOSE_CRYPTO) { - - switch (req._type) { - case Request::DECRYPT_CLIENT_DATA: - case Request::ENCRYPT_CLIENT_DATA: - { - log("crypto: ", req.type_to_string(req._type), - " pba ", req._pba, - " vba ", req._vba, - " plain ", *(Block *)channel._blk_buf, - " cipher ", *(Block *)req._ciphertext_blk_ptr); - - break; - } - default: - break; - } - } - return true; - } - } - return false; -} - - -void Crypto::_drop_completed_request(Module_request &req) -{ - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (_channels[id]._state != Channel::COMPLETE) { - class Exception_2 { }; - throw Exception_2 { }; - } - _channels[id]._state = Channel::INACTIVE; -} - - -bool Crypto::ready_to_submit_request() -{ - for (Channel &channel : _channels) { - if (channel._state == Channel::INACTIVE) - return true; - } - return false; -} - -void Crypto::submit_request(Module_request &req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - if (_channels[id]._state == Channel::INACTIVE) { - req.dst_request_id(id); - _channels[id]._request = *static_cast(&req); - _channels[id]._state = Channel::SUBMITTED; - return; - } - } - class Invalid_call { }; - throw Invalid_call { }; -} diff --git a/repos/gems/src/lib/tresor/free_tree.cc b/repos/gems/src/lib/tresor/free_tree.cc index fb5fe95947..2b08554122 100644 --- a/repos/gems/src/lib/tresor/free_tree.cc +++ b/repos/gems/src/lib/tresor/free_tree.cc @@ -15,997 +15,502 @@ #include #include #include -#include +#include using namespace Tresor; - -/*************** - ** Utilities ** - ***************/ - -static Virtual_block_address -vbd_node_lowest_vba(Tree_degree_log_2 vbd_degree_log_2, - Tree_level_index vbd_level, - Virtual_block_address vbd_leaf_vba) -{ - return vbd_leaf_vba & - (0xffff'ffff'ffff'ffff << - ((uint32_t)vbd_degree_log_2 * (uint32_t)vbd_level)); -} - - -static Number_of_blocks vbd_node_nr_of_vbas(Tree_degree_log_2 vbd_degree_log_2, - Tree_level_index vbd_level) -{ - return (Number_of_blocks)1 << (vbd_level * vbd_degree_log_2); -} - - -static Virtual_block_address -vbd_node_highest_vba(Tree_degree_log_2 vbd_degree_log_2, - Tree_level_index vbd_level, - Virtual_block_address vbd_leaf_vba) -{ - return - vbd_node_lowest_vba(vbd_degree_log_2, vbd_level, vbd_leaf_vba) + - (vbd_node_nr_of_vbas(vbd_degree_log_2, vbd_level) - 1); -} - - -/*********************** - ** Free_tree_request ** - ***********************/ - char const *Free_tree_request::type_to_string(Type type) { switch (type) { - case INVALID: return "invalid"; case ALLOC_FOR_NON_RKG: return "alloc_for_non_rkg"; case ALLOC_FOR_RKG_CURR_GEN_BLKS: return "alloc_for_rkg_curr_gen_blks"; case ALLOC_FOR_RKG_OLD_GEN_BLKS: return "alloc_for_rkg_old_gen_blks"; + case EXTENSION_STEP: return "extension_step"; } - return "?"; + ASSERT_NEVER_REACHED; } -Free_tree_request::Free_tree_request(uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - addr_t ft_root_pba_ptr, - addr_t ft_root_gen_ptr, - addr_t ft_root_hash_ptr, - uint64_t ft_max_level, - uint64_t ft_degree, - uint64_t ft_leaves, - addr_t mt_root_pba_ptr, - addr_t mt_root_gen_ptr, - addr_t mt_root_hash_ptr, - uint64_t mt_max_level, - uint64_t mt_degree, - uint64_t mt_leaves, - Snapshots const *snapshots_ptr, - Generation last_secured_generation, - uint64_t current_gen, - uint64_t free_gen, - uint64_t requested_blocks, - addr_t new_blocks_ptr, - addr_t old_blocks_ptr, - uint64_t max_level, - uint64_t vba, - uint64_t vbd_degree, - uint64_t vbd_highest_vba, - bool rekeying, - uint32_t previous_key_id, - uint32_t current_key_id, - uint64_t rekeying_vba) +Free_tree_request::Free_tree_request(Module_id src_module_id, Module_channel_id src_chan_id, Type type, + Tree_root &ft, Tree_root &mt, Snapshots const &snapshots, Generation last_secured_gen, + Generation curr_gen, Generation free_gen, Number_of_blocks num_required_pbas, + Tree_walk_pbas &new_blocks, Type_1_node_walk const &old_blocks, + Tree_level_index max_lvl, Virtual_block_address vba, Tree_degree vbd_degree, + Virtual_block_address vbd_max_vba, bool rekeying, Key_id prev_key_id, + Key_id curr_key_id, Virtual_block_address rekeying_vba, Physical_block_address &pba, + Number_of_blocks &num_pbas, bool &success) + : - Module_request { src_module_id, src_request_id, FREE_TREE }, - _type { (Type)req_type }, - _ft_root_pba_ptr { (addr_t)ft_root_pba_ptr }, - _ft_root_gen_ptr { (addr_t)ft_root_gen_ptr }, - _ft_root_hash_ptr { (addr_t)ft_root_hash_ptr }, - _ft_max_level { ft_max_level }, - _ft_degree { ft_degree }, - _ft_leaves { ft_leaves }, - _mt_root_pba_ptr { (addr_t)mt_root_pba_ptr }, - _mt_root_gen_ptr { (addr_t)mt_root_gen_ptr }, - _mt_root_hash_ptr { (addr_t)mt_root_hash_ptr }, - _mt_max_level { mt_max_level }, - _mt_degree { mt_degree }, - _mt_leaves { mt_leaves }, - _current_gen { current_gen }, - _free_gen { free_gen }, - _requested_blocks { requested_blocks }, - _new_blocks_ptr { (addr_t)new_blocks_ptr }, - _old_blocks_ptr { (addr_t)old_blocks_ptr }, - _max_level { max_level }, - _vba { vba }, - _vbd_degree { vbd_degree }, - _vbd_highest_vba { vbd_highest_vba }, - _rekeying { rekeying }, - _previous_key_id { previous_key_id }, - _current_key_id { current_key_id }, - _rekeying_vba { rekeying_vba }, - _snapshots_ptr { (addr_t)snapshots_ptr }, - _last_secured_generation { last_secured_generation } + Module_request { src_module_id, src_chan_id, FREE_TREE }, _type { type }, _ft { ft }, _mt { mt }, + _curr_gen { curr_gen }, _free_gen { free_gen }, _num_required_pbas { num_required_pbas }, _new_blocks { new_blocks }, + _old_blocks { old_blocks }, _max_lvl { max_lvl }, _vba { vba }, _vbd_degree { vbd_degree }, _vbd_max_vba { vbd_max_vba }, + _rekeying { rekeying }, _prev_key_id { prev_key_id }, _curr_key_id { curr_key_id }, _rekeying_vba { rekeying_vba }, + _success { success }, _snapshots { snapshots }, _last_secured_gen { last_secured_gen }, _pba { pba }, _num_pbas { num_pbas } { } -/*************** - ** Free_tree ** - ***************/ - void Free_tree::execute(bool &progress) { - for (Channel &channel : _channels) { - _execute( - channel, *(Snapshots *)channel._request._snapshots_ptr, - channel._request._last_secured_generation, progress); - } + for_each_channel([&] (Channel &chan) { + chan.execute(progress); }); } -Free_tree::Local_cache_request Free_tree::_new_cache_request(Physical_block_address pba, - Local_cache_request::Op op, - Tree_level_index lvl) +bool Free_tree_channel::_can_alloc_pba_of(Type_2_node &node) { - return Local_cache_request { - Local_cache_request::PENDING, op, false, - pba, lvl }; -} - - -void Free_tree::_check_type_2_stack(Type_2_info_stack &stack, - Type_1_info_stack &stack_next, - Node_queue &leaves, - Number_of_blocks &found) -{ - if (!stack.empty()) { - while (!stack.empty()) { - Type_2_info const info { stack.peek_top() }; - if (!leaves.full()) { - leaves.enqueue(info); - } - found++; - stack.pop(); - } - } - if (!stack_next.empty()) { - Type_1_info n { stack_next.peek_top() }; - - /* - * Only when the node is in read state we actually have to acknowledge - * checking the leaf nodes. - */ - if (n.state == Type_1_info::READ) { - n.state = Type_1_info::COMPLETE; - stack_next.update_top(n); - } - } -} - - -void Free_tree::_populate_lower_n_stack(Type_1_info_stack &stack, - Type_1_node_block &entries, - Block const &block_data, - Generation current_gen) -{ - stack.reset(); - entries.decode_from_blk(block_data); - - for (Tree_node_index idx = 0; idx < NR_OF_T1_NODES_PER_BLK; idx++) { - - if (entries.nodes[idx].pba != 0) { - - stack.push({ - Type_1_info::INVALID, entries.nodes[idx], idx, - _node_volatile(entries.nodes[idx], current_gen) }); - } - } -} - - -bool -Free_tree::_check_type_2_leaf_usable(Snapshots const &snapshots, - Generation last_secured_gen, - Type_2_node const &node, - bool rekeying, - Key_id previous_key_id, - Virtual_block_address rekeying_vba) -{ - if (node.pba == 0 || - node.pba == INVALID_PBA || - node.free_gen > last_secured_gen) + Request &req { *_req_ptr }; + if (node.pba == 0 || node.pba == INVALID_PBA || node.free_gen > req._last_secured_gen) return false; if (!node.reserved) return true; - if (rekeying && - node.last_key_id == previous_key_id && - node.last_vba < rekeying_vba) + if (req._rekeying && node.last_key_id == req._prev_key_id && node.last_vba < req._rekeying_vba) return true; - for (Snapshot const &snap : snapshots.items) { - if (snap.valid && - node.free_gen > snap.gen && - node.alloc_gen < snap.gen + 1) + for (Snapshot const &snap : req._snapshots.items) + if (snap.valid && node.free_gen > snap.gen && node.alloc_gen < snap.gen + 1) return false; - } + return true; } -void Free_tree::_populate_level_0_stack(Type_2_info_stack &stack, - Type_2_node_block &entries, - Block const &block_data, - Snapshots const &active_snaps, - Generation secured_gen, - bool rekeying, - Key_id previous_key_id, - Virtual_block_address rekeying_vba) +void Free_tree_channel::_generated_req_completed(State_uint state_uint) { - stack.reset(); - entries.decode_from_blk(block_data); - - for (Tree_node_index idx = 0; idx < NR_OF_T1_NODES_PER_BLK; idx++) { - if (_check_type_2_leaf_usable(active_snaps, secured_gen, - entries.nodes[idx], rekeying, - previous_key_id, rekeying_vba)) { - - stack.push({ Type_2_info::INVALID, entries.nodes[idx], idx }); - } - } -} - - -void Free_tree::_execute_scan(Channel &chan, - Snapshots const &active_snaps, - Generation last_secured_gen, - bool &progress) -{ - Request &req { chan._request }; - bool end_of_tree = false; - bool enough_found = false; - - // handle level 0 - { - Number_of_blocks found_blocks = 0; - _check_type_2_stack( - chan._level_0_stack, chan._level_n_stacks[FIRST_LVL_N_STACKS_IDX], - chan._type_2_leafs, found_blocks); - - chan._found_blocks += found_blocks; - } - - // handle level 1 - n - for (Tree_level_index lvl = FIRST_LVL_N_STACKS_IDX; lvl <= MAX_LVL_N_STACKS_IDX; lvl++) { - - if (!chan._level_n_stacks[lvl].empty()) { - - Type_1_info t1_info = chan._level_n_stacks[lvl].peek_top(); - switch (t1_info.state) { - case Type_1_info::INVALID: - - if (chan._cache_request.state != Local_cache_request::INVALID) { - class Exception_1 { }; - throw Exception_1 { }; - } - chan._cache_request = _new_cache_request( - t1_info.node.pba, Local_cache_request::READ, lvl); - - progress = true; - break; - - case Type_1_info::AVAILABLE: - - chan._cache_request.state = Local_cache_request::INVALID; - if (lvl >= 2) { - _populate_lower_n_stack( - chan._level_n_stacks[lvl - 1], - chan._level_n_node, chan._cache_block_data, - req._current_gen); - } else { - _populate_level_0_stack( - chan._level_0_stack, - chan._level_0_node, chan._cache_block_data, - active_snaps, last_secured_gen, - req._rekeying, req._previous_key_id, - req._rekeying_vba); - } - t1_info.state = Type_1_info::READ; - chan._level_n_stacks[lvl].update_top(t1_info); - progress = true; - break; - - case Type_1_info::READ: - - t1_info.state = Type_1_info::COMPLETE; - chan._level_n_stacks[lvl].update_top(t1_info); - progress = true; - break; - - case Type_1_info::WRITE: - - class Exception_1 { }; - throw Exception_1 { }; - - case Type_1_info::COMPLETE: - - if (lvl == req._ft_max_level) - end_of_tree = true; - - if (chan._found_blocks >= chan._needed_blocks) - enough_found = true; - - chan._level_n_stacks[lvl].pop(); - progress = true; - break; - } - break; - } - } - - if (chan._state != Channel::SCAN) + if (!_generated_req_success) { + error("free tree: request (", *_req_ptr, ") failed because generated request failed)"); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; return; - - if (enough_found) { - chan._state = Channel::SCAN_COMPLETE; - - for (Type_1_info_stack &stack : chan._level_n_stacks) - stack = { }; - - for (Type_1_node_block &blk : chan._level_n_nodes) - blk = { }; - - chan._level_n_stacks[req._ft_max_level].push( - Type_1_info { - Type_1_info::INVALID, chan._root_node(), 0, - _node_volatile(chan._root_node(), req._current_gen) }); } - - if (end_of_tree && !enough_found) - chan._state = Channel::NOT_ENOUGH_FREE_BLOCKS; + _state = (State)state_uint; } -void -Free_tree::_exchange_type_2_leaves(Generation free_gen, - Tree_level_index max_level, - Type_1_node_walk const &old_blocks, - Tree_walk_pbas &new_blocks, - Virtual_block_address vba, - Tree_degree_log_2 vbd_degree_log_2, - Request::Type req_type, - Type_2_info_stack &stack, - Type_2_node_block &entries, - Number_of_blocks &exchanged, - bool &handled, - Virtual_block_address vbd_highest_vba, - bool rekeying, - Key_id previous_key_id, - Key_id current_key_id, - Virtual_block_address rekeying_vba) +void Free_tree_channel::_alloc_pba_of(Type_2_node &t2_node) { - Number_of_blocks local_exchanged { 0 }; - handled = false; + Request &req { *_req_ptr }; + Tree_level_index vbd_lvl { 0 }; + for (; vbd_lvl <= req._max_lvl && req._new_blocks.pbas[vbd_lvl]; vbd_lvl++); - for (Tree_level_index i = 0; i <= max_level; i++) { + Virtual_block_address node_min_vba { vbd_node_min_vba(_vbd_degree_log_2, vbd_lvl, req._vba) }; + req._new_blocks.pbas[vbd_lvl] = t2_node.pba; + t2_node.alloc_gen = req._old_blocks.nodes[vbd_lvl].gen; + t2_node.free_gen = req._free_gen; + Virtual_block_address rkg_vba { req._rekeying_vba }; + switch (req._type) { + case Request::ALLOC_FOR_NON_RKG: - if (new_blocks.pbas[i] == 0) { + t2_node.reserved = true; + t2_node.pba = req._old_blocks.nodes[vbd_lvl].pba; + t2_node.last_vba = node_min_vba; + if (req._rekeying) { + if (req._vba < rkg_vba) + t2_node.last_key_id = req._curr_key_id; + else + t2_node.last_key_id = req._prev_key_id; + } else + t2_node.last_key_id = req._curr_key_id; + break; - if (!stack.empty()) { + case Request::ALLOC_FOR_RKG_CURR_GEN_BLKS: - Type_2_info const info { stack.peek_top() }; - Type_2_node &t2_node { entries.nodes[info.index] }; - if (t2_node.pba != info.node.pba) { - class Exception_1 { }; - throw Exception_1 { }; - } - switch (req_type) { - case Request::ALLOC_FOR_NON_RKG: + t2_node.reserved = false; + t2_node.pba = req._old_blocks.nodes[vbd_lvl].pba; + t2_node.last_vba = node_min_vba; + t2_node.last_key_id = req._prev_key_id; + break; - new_blocks.pbas[i] = t2_node.pba; - t2_node.pba = old_blocks.nodes[i].pba; - t2_node.alloc_gen = old_blocks.nodes[i].gen; - t2_node.free_gen = free_gen; - t2_node.last_vba = - vbd_node_lowest_vba(vbd_degree_log_2, i, vba); - - if (rekeying) { - - if (vba < rekeying_vba) - t2_node.last_key_id = current_key_id; - else - t2_node.last_key_id = previous_key_id; - - } else { - - t2_node.last_key_id = current_key_id; - } - t2_node.reserved = true; - break; - - case Request::ALLOC_FOR_RKG_CURR_GEN_BLKS: - - new_blocks.pbas[i] = t2_node.pba; - - t2_node.pba = old_blocks.nodes[i].pba; - t2_node.alloc_gen = old_blocks.nodes[i].gen; - t2_node.free_gen = free_gen; - t2_node.last_vba = - vbd_node_lowest_vba (vbd_degree_log_2, i, vba); - - t2_node.last_key_id = previous_key_id; - t2_node.reserved = false; - break; - - case Request::ALLOC_FOR_RKG_OLD_GEN_BLKS: - { - new_blocks.pbas[i] = t2_node.pba; - - t2_node.alloc_gen = old_blocks.nodes[i].gen; - t2_node.free_gen = free_gen; - - Virtual_block_address const node_highest_vba { - vbd_node_highest_vba(vbd_degree_log_2, i, vba) }; - - if (rekeying_vba < node_highest_vba && - rekeying_vba < vbd_highest_vba) - { - t2_node.last_key_id = previous_key_id; - t2_node.last_vba = rekeying_vba + 1; - - } else if (rekeying_vba == node_highest_vba || - rekeying_vba == vbd_highest_vba) { - - t2_node.last_key_id = current_key_id; - t2_node.last_vba = - vbd_node_lowest_vba (vbd_degree_log_2, i, vba); - - } else { - - class Exception_1 { }; - throw Exception_1 { }; - } - t2_node.reserved = true; - break; - } - default: - - class Exception_2 { }; - throw Exception_2 { }; - } - - local_exchanged = local_exchanged + 1; - stack.pop(); - handled = true; - - } else { - - break; - } - } - } - exchanged = local_exchanged; -} - - -Free_tree::Local_meta_tree_request -Free_tree::_new_meta_tree_request(Physical_block_address pba) -{ - return { - Local_meta_tree_request::PENDING, Local_meta_tree_request::READ, pba }; -} - - -void Free_tree::_update_upper_n_stack(Type_1_info const &t, - Generation gen, - Block const &block_data, - Type_1_node_block &entries) -{ - entries.nodes[t.index].pba = t.node.pba; - entries.nodes[t.index].gen = gen; - calc_sha256_4k_hash(block_data, entries.nodes[t.index].hash); -} - - -void Free_tree::_execute_update(Channel &chan, - Snapshots const &active_snaps, - Generation last_secured_gen, - bool &progress) -{ - Request &req { chan._request }; - bool exchange_finished { false }; - bool update_finished { false }; - Number_of_blocks exchanged; - - /* handle level 0 */ + case Request::ALLOC_FOR_RKG_OLD_GEN_BLKS: { - bool handled; - - _exchange_type_2_leaves( - req._free_gen, (Tree_level_index)req._max_level, - *(Type_1_node_walk *)req._old_blocks_ptr, - *(Tree_walk_pbas *)req._new_blocks_ptr, - req._vba, (Tree_degree_log_2)chan._vbd_degree_log_2, req._type, chan._level_0_stack, - chan._level_0_node, exchanged, handled, req._vbd_highest_vba, - req._rekeying, req._previous_key_id, req._current_key_id, - req._rekeying_vba); - - if (handled) { - if (exchanged > 0) { - chan._exchanged_blocks += exchanged; - } else { - Type_1_info n { chan._level_n_stacks[FIRST_LVL_N_STACKS_IDX].peek_top() }; - n.state = Type_1_info::COMPLETE; - chan._level_n_stacks[FIRST_LVL_N_STACKS_IDX].update_top(n); - } - } + t2_node.reserved = true; + Virtual_block_address node_max_vba { vbd_node_max_vba(_vbd_degree_log_2, vbd_lvl, req._vba) }; + if (rkg_vba < node_max_vba && rkg_vba < req._vbd_max_vba) { + t2_node.last_key_id = req._prev_key_id; + t2_node.last_vba = rkg_vba + 1; + } else if (rkg_vba == node_max_vba || rkg_vba == req._vbd_max_vba) { + t2_node.last_key_id = req._curr_key_id; + t2_node.last_vba = node_min_vba; + } else + ASSERT_NEVER_REACHED; + break; } - if (chan._exchanged_blocks == chan._needed_blocks) { - exchange_finished = true; + default: ASSERT_NEVER_REACHED; } - /* handle level 1..N */ - for (Tree_level_index l { FIRST_LVL_N_STACKS_IDX }; l <= MAX_LVL_N_STACKS_IDX; l++) { - - Type_1_info_stack &stack { chan._level_n_stacks[l] }; - - if (!stack.empty()) { - - Type_1_info n { stack.peek_top() }; - switch (n.state) { - case Type_1_info::INVALID: - - if (chan._cache_request.state != Local_cache_request::INVALID) { - class Exception_1 { }; - throw Exception_1 { }; - } - chan._cache_request = - _new_cache_request( - n.node.pba, Local_cache_request::READ, l); - - progress = true; - break; - - case Type_1_info::AVAILABLE: - - chan._cache_request.state = Local_cache_request::INVALID; - if (l >= 2) { - - _populate_lower_n_stack( - chan._level_n_stacks[l - 1], - chan._level_n_nodes[l - 1], chan._cache_block_data, - req._current_gen); - - if (!chan._level_n_stacks[l - 1].empty()) - n.state = Type_1_info::WRITE; - else - n.state = Type_1_info::COMPLETE; - - } else { - - _populate_level_0_stack( - chan._level_0_stack, chan._level_0_node, - chan._cache_block_data, active_snaps, last_secured_gen, - req._rekeying, req._previous_key_id, - req._rekeying_vba); - - if (!chan._level_0_stack.empty()) - n.state = Type_1_info::WRITE; - else - n.state = Type_1_info::COMPLETE; - } - stack.update_top(n); - progress = true; - break; - - case Type_1_info::READ: - - class Exception_2 { }; - throw Exception_2 { }; - - case Type_1_info::WRITE: - - if (!n.volatil) { - - Local_meta_tree_request &mtr { chan._meta_tree_request }; - if (mtr.state == Local_meta_tree_request::INVALID) { - - mtr = _new_meta_tree_request(n.node.pba); - progress = true; - break; - - } else if (mtr.state == Local_meta_tree_request::COMPLETE) { - - mtr.state = Local_meta_tree_request::INVALID; - n.volatil = true; - n.node.pba = mtr.pba; - stack.update_top(n); - - } else { - - class Exception_3 { }; - throw Exception_3 { }; - } - } - if (l >= 2) { - - chan._level_n_nodes[l - 1].encode_to_blk(chan._cache_block_data); - - if (l < req._ft_max_level) { - _update_upper_n_stack( - n, req._current_gen, chan._cache_block_data, - chan._level_n_nodes[l]); - } else { - calc_sha256_4k_hash(chan._cache_block_data, - *(Hash *)req._ft_root_hash_ptr); - - *(Generation *)req._ft_root_gen_ptr = req._current_gen; - *(Physical_block_address *)req._ft_root_pba_ptr = - n.node.pba; - } - } else { - chan._level_0_node.encode_to_blk(chan._cache_block_data); - - _update_upper_n_stack( - n, req._current_gen, chan._cache_block_data, - chan._level_n_nodes[l]); - } - chan._cache_request = _new_cache_request( - n.node.pba, Local_cache_request::WRITE, l); - - progress = true; - break; - - case Type_1_info::COMPLETE: - - chan._cache_request.state = Local_cache_request::INVALID; - stack.pop(); - - if (exchange_finished) - while (!stack.empty()) - stack.pop(); - - if (l == req._ft_max_level) - update_finished = true; - - progress = true; - break; - } - break; - } - } - if (chan._state != Channel::UPDATE) - return; - - if (exchange_finished && update_finished) - chan._state = Channel::UPDATE_COMPLETE; } -void Free_tree::_mark_req_failed(Channel &chan, - bool &progress, - char const *str) +void Free_tree_channel::_mark_req_failed(bool &progress, char const *str) { - error(chan._request.type_name(), " request failed, reason: \"", str, "\""); - chan._request._success = false; - chan._state = Channel::COMPLETE; + error(Request::type_to_string(_req_ptr->_type), " request failed, reason: \"", str, "\""); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; } -void Free_tree::_mark_req_successful(Channel &channel, - bool &progress) +void Free_tree_channel::_mark_req_successful(bool &progress) { - channel._request._success = true; - channel._state = Channel::COMPLETE; + _req_ptr->_success = true; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; } -void Free_tree::_execute(Channel &chan, - Snapshots const &active_snaps, - Generation last_secured_gen, - bool &progress) +void Free_tree_channel::_start_tree_traversal(bool &progress) { - if (chan._meta_tree_request.state == Local_meta_tree_request::PENDING || - chan._meta_tree_request.state == Local_meta_tree_request::IN_PROGRESS) - return; + Request &req { *_req_ptr }; + _num_pbas = 0; + _lvl = req._ft.max_lvl; + _node_idx[_lvl] = 0; + _t1_blks[_lvl].nodes[_node_idx[_lvl]] = req._ft.t1_node(); + _generate_req(SEEK_DOWN, progress, req._ft.pba, _blk); +} - if (chan._cache_request.state == Local_cache_request::PENDING || - chan._cache_request.state == Local_cache_request::IN_PROGRESS) - return; - switch (chan._state) { - case Channel::INVALID: - break; - case Channel::SCAN: - _execute_scan(chan, active_snaps, last_secured_gen, progress); - break; - case Channel::SCAN_COMPLETE: - chan._state = Channel::UPDATE; +void Free_tree_channel::_traverse_curr_node(bool &progress) +{ + if (_lvl) { + Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] }; + if (t1_node.pba) + _generate_req(SEEK_DOWN, progress, t1_node.pba, _blk); + else { + _state = SEEK_LEFT_OR_UP; + progress = true; + } + } else { + Type_2_node &t2_node { _t2_blk.nodes[_node_idx[_lvl]] }; + if (_num_pbas < _req_ptr->_num_required_pbas && _can_alloc_pba_of(t2_node)) { + if (_apply_allocation) + _alloc_pba_of(t2_node); + _num_pbas++; + } + _state = SEEK_LEFT_OR_UP; progress = true; - break; - case Channel::UPDATE: - _execute_update(chan, active_snaps, last_secured_gen, progress); - break; - case Channel::UPDATE_COMPLETE: - _mark_req_successful(chan, progress); - break; - case Channel::COMPLETE: - break; - case Channel::NOT_ENOUGH_FREE_BLOCKS: - _mark_req_failed(chan, progress, "not enough free blocks"); - break; - case Channel::TREE_HASH_MISMATCH: - _mark_req_failed(chan, progress, "node hash mismatch"); - break; } } -bool Free_tree::ready_to_submit_request() +void Free_tree_channel::_alloc_pbas(bool &progress) { - for (Channel &channel : _channels) { - if (channel._state == Channel::INVALID) - return true; - } - return false; -} + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: + _vbd_degree_log_2 = log2(req._vbd_degree); + _apply_allocation = false; + _start_tree_traversal(progress); + break; -void Free_tree::_reset_block_state(Channel &chan) -{ - Request &req { chan._request }; - chan._needed_blocks = req._requested_blocks; - chan._found_blocks = 0; - for (Type_1_info_stack &stack : chan._level_n_stacks) - stack = { }; - - for (Type_1_node_block &blk : chan._level_n_nodes) - blk = { }; - - chan._level_0_stack = { }; - chan._level_n_node = { }; - chan._level_0_node = { }; -} - - -bool Free_tree::_node_volatile(Type_1_node const &node, - uint64_t gen) -{ - return node.gen == 0 || node.gen == gen; -} - - -void Free_tree::submit_request(Module_request &mod_req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - Channel &chan { _channels[id] }; - if (chan._state == Channel::INVALID) { - - mod_req.dst_request_id(id); - - chan._request = *static_cast(&mod_req); - chan._exchanged_blocks = 0; - _reset_block_state(chan); - - Request &req { chan._request }; - Type_1_node root_node { }; - root_node.pba = *(uint64_t *)req._ft_root_pba_ptr; - root_node.gen = *(uint64_t *)req._ft_root_gen_ptr; - memcpy(&root_node.hash, (void *)req._ft_root_hash_ptr, - HASH_SIZE); - - chan._level_n_stacks[req._ft_max_level].push( - { Type_1_info::INVALID, root_node, 0, - _node_volatile(root_node, req._current_gen) }); - - chan._state = Channel::SCAN; - chan._vbd_degree_log_2 = log2(req._vbd_degree); - return; - } - } - class Exception_1 { }; - throw Exception_1 { }; -} - -bool Free_tree::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (uint32_t id { 0 }; id < NR_OF_CHANNELS; id++) { - - Channel &channel { _channels[id] }; - Local_cache_request const &local_crq { channel._cache_request }; - if (local_crq.state == Local_cache_request::PENDING) { - - Block_io_request::Type blk_io_req_type { - local_crq.op == Local_cache_request::READ ? - Block_io_request::READ : - Local_cache_request::WRITE ? - Block_io_request::WRITE : - Block_io_request::INVALID }; - - if (blk_io_req_type == Block_io_request::INVALID) { - class Exception_1 { }; - throw Exception_1 { }; - } - construct_in_buf( - buf_ptr, buf_size, FREE_TREE, id, blk_io_req_type, 0, 0, 0, - local_crq.pba, 0, 1, &channel._cache_block_data, nullptr); - - return true; - } - - Local_meta_tree_request const &local_mtr { channel._meta_tree_request }; - if (local_mtr.state == Local_meta_tree_request::PENDING) { - - Meta_tree_request::Type mt_req_type { - local_mtr.op == Local_meta_tree_request::READ ? - Meta_tree_request::UPDATE : - Meta_tree_request::INVALID }; - - if (mt_req_type == Meta_tree_request::INVALID) { - class Exception_1 { }; - throw Exception_1 { }; - } - Meta_tree_request::create( - buf_ptr, buf_size, FREE_TREE, id, mt_req_type, - (void*)channel._request._mt_root_pba_ptr, - (void*)channel._request._mt_root_gen_ptr, - (void*)channel._request._mt_root_hash_ptr, - channel._request._mt_max_level, - channel._request._mt_degree, - channel._request._mt_leaves, - channel._request._current_gen, - local_mtr.pba); - - return true; - } - } - return false; -} - -void Free_tree::_drop_generated_request(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - switch (mod_req.dst_module_id()) { - case BLOCK_IO: + case SEEK_DOWN: { - Local_cache_request &local_req { _channels[id]._cache_request }; - if (local_req.state != Local_cache_request::PENDING) { - class Exception_2 { }; - throw Exception_2 { }; + if (!check_hash(_blk, _t1_blks[_lvl].nodes[_node_idx[_lvl]].hash)) { + _mark_req_failed(progress, "hash mismatch"); + break; } - local_req.state = Local_cache_request::IN_PROGRESS; + _lvl--; + _node_idx[_lvl] = req._ft.degree - 1; + if (_lvl) + _t1_blks[_lvl].decode_from_blk(_blk); + else + _t2_blk.decode_from_blk(_blk); + _traverse_curr_node(progress); break; } - case META_TREE: - { - Local_meta_tree_request &local_req { _channels[id]._meta_tree_request }; - if (local_req.state != Local_meta_tree_request::PENDING) { - class Exception_3 { }; - throw Exception_3 { }; - } - local_req.state = Local_meta_tree_request::IN_PROGRESS; - break; - } - default: - - class Exception_4 { }; - throw Exception_4 { }; - } -} - -void Free_tree::generated_request_complete(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - switch (mod_req.dst_module_id()) { - case BLOCK_IO: - { - Local_cache_request &local_req { _channels[id]._cache_request }; - if (local_req.state != Local_cache_request::IN_PROGRESS) { - class Exception_2 { }; - throw Exception_2 { }; - } - Block_io_request &blk_io_req { *static_cast(&mod_req) }; - Channel &channel { _channels[id] }; - if (!blk_io_req.success()) { - class Exception_3 { }; - throw Exception_3 { }; - } - Type_1_info n { channel._level_n_stacks[local_req.level].peek_top() }; - local_req.state = Local_cache_request::COMPLETE; - - switch (local_req.op) { - case Local_cache_request::SYNC: - - class Exception_4 { }; - throw Exception_4 { }; - - case Local_cache_request::READ: - - if (check_sha256_4k_hash(channel._cache_block_data, n.node.hash)) { - - n.state = Type_1_info::AVAILABLE; - channel._level_n_stacks[local_req.level].update_top(n); + case SEEK_LEFT_OR_UP: + if (_lvl < req._ft.max_lvl) { + if (_node_idx[_lvl] && _num_pbas < _req_ptr->_num_required_pbas) { + _node_idx[_lvl]--; + _traverse_curr_node(progress); } else { - - channel._state = Channel::TREE_HASH_MISMATCH; + _lvl++; + Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] }; + if (_apply_allocation) + if (t1_node.is_volatile(req._curr_gen)) { + _state = WRITE_BLK; + progress = true; + } else + _generate_req(WRITE_BLK, progress, req._mt, req._curr_gen, t1_node.pba); + else { + _state = SEEK_LEFT_OR_UP; + progress = true; + } + } + } else { + if (_apply_allocation) { + req._ft.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]); + _mark_req_successful(progress); + } else { + if (_num_pbas < req._num_required_pbas) + _mark_req_failed(progress, "not enough free pbas"); + else { + _apply_allocation = true; + _start_tree_traversal(progress); + } } - break; - - case Local_cache_request::WRITE: - - n.state = Type_1_info::COMPLETE; - channel._level_n_stacks[local_req.level].update_top(n); - break; } break; - } - case META_TREE: + + case WRITE_BLK: { - Local_meta_tree_request &local_req { _channels[id]._meta_tree_request }; - if (local_req.state != Local_meta_tree_request::IN_PROGRESS) { - class Exception_5 { }; - throw Exception_5 { }; - } - Meta_tree_request &mt_req { *static_cast(&mod_req) }; - if (!mt_req.success()) { - class Exception_6 { }; - throw Exception_6 { }; - } - local_req.pba = mt_req.new_pba(); - local_req.state = Local_meta_tree_request::COMPLETE; + if (_lvl > 1) + _t1_blks[_lvl - 1].encode_to_blk(_blk); + else + _t2_blk.encode_to_blk(_blk); + Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] }; + t1_node.gen = req._curr_gen; + calc_hash(_blk, t1_node.hash); + _generate_req(SEEK_LEFT_OR_UP, progress, t1_node.pba, _blk); break; } - default: - - class Exception_7 { }; - throw Exception_7 { }; + default: break; } } -bool Free_tree::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) +void Free_tree_channel::execute(bool &progress) { - for (Channel &channel : _channels) { - if (channel._state == Channel::COMPLETE) { - if (sizeof(channel._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &channel._request, sizeof(channel._request)); - return true; + if (!_req_ptr) + return; + + switch(_req_ptr->_type) { + case Request::ALLOC_FOR_NON_RKG: + case Request::ALLOC_FOR_RKG_CURR_GEN_BLKS: + case Request::ALLOC_FOR_RKG_OLD_GEN_BLKS: _alloc_pbas(progress); break; + case Request::EXTENSION_STEP: _extension_step(progress); break; + } +} + + +void Free_tree_channel::_generate_write_blk_req(bool &progress) +{ + if (_lvl > 1) + _t1_blks[_lvl].encode_to_blk(_blk); + else + _t2_blk.encode_to_blk(_blk); + + _generate_req(WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _blk); + if (VERBOSE_FT_EXTENSION) + log(" lvl ", _lvl, " write to pba ", _new_pbas.pbas[_lvl]); +} + + +void Free_tree_channel::_add_new_root_lvl() +{ + Request &req { *_req_ptr }; + ASSERT(req._ft.max_lvl < TREE_MAX_LEVEL); + req._ft.max_lvl++; + _t1_blks[req._ft.max_lvl] = { }; + _t1_blks[req._ft.max_lvl].nodes[0] = req._ft.t1_node(); + _new_pbas.pbas[req._ft.max_lvl] = alloc_pba_from_range(req._pba, req._num_pbas); + req._ft.t1_node({ _new_pbas.pbas[req._ft.max_lvl], req._curr_gen }); + if (VERBOSE_FT_EXTENSION) + log(" set root: ", req._ft, "\n set lvl ", req._ft.max_lvl, " node 0: ", + _t1_blks[req._ft.max_lvl].nodes[0]); +} + + +void Free_tree_channel::_add_new_branch_at(Tree_level_index dst_lvl, Tree_node_index dst_node_idx) +{ + Request &req { *_req_ptr }; + _num_leaves = 0; + _lvl = dst_lvl; + if (dst_lvl > 1) { + for (Tree_level_index lvl = 1; lvl < dst_lvl; lvl++) { + if (lvl > 1) + _t1_blks[lvl] = Type_1_node_block { }; + else + _t2_blk = Type_2_node_block { }; + + if (VERBOSE_FT_EXTENSION) + log(" reset lvl ", lvl); } } - return false; + for (; _lvl && req._num_pbas; _lvl--) { + Tree_node_index node_idx = (_lvl == dst_lvl) ? dst_node_idx : 0; + if (_lvl > 1) { + _new_pbas.pbas[_lvl - 1] = alloc_pba_from_range(req._pba, req._num_pbas); + _t1_blks[_lvl].nodes[node_idx] = { _new_pbas.pbas[_lvl - 1], req._curr_gen }; + if (VERBOSE_FT_EXTENSION) + log(" set _lvl d ", _lvl, " node ", node_idx, ": ", _t1_blks[_lvl].nodes[node_idx]); + + } else { + for (; node_idx < req._ft.degree && req._num_pbas; node_idx++) { + _t2_blk.nodes[node_idx] = { alloc_pba_from_range(req._pba, req._num_pbas) }; + _num_leaves++; + if (VERBOSE_FT_EXTENSION) + log(" set _lvl e ", _lvl, " node ", node_idx, ": ", _t2_blk.nodes[node_idx]); + } + } + } + if (!_lvl) + _lvl = 1; } -void Free_tree::_drop_completed_request(Module_request &req) +void Free_tree_channel::_extension_step(bool &progress) { - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: + + _num_leaves = 0; + _vba = req._ft.num_leaves; + _old_pbas = { }; + _old_generations = { }; + _new_pbas = { }; + _lvl = req._ft.max_lvl; + _old_pbas.pbas[_lvl] = req._ft.pba; + _old_generations.items[_lvl] = req._ft.gen; + if (_vba <= tree_max_max_vba(req._ft.degree, req._ft.max_lvl)) { + + _generate_req(READ_BLK_SUCCEEDED, progress, req._ft.pba, _blk); + if (VERBOSE_FT_EXTENSION) + log(" root (", req._ft, "): load to lvl ", _lvl); + } else { + _add_new_root_lvl(); + _add_new_branch_at(req._ft.max_lvl, 1); + _generate_write_blk_req(progress); + if (VERBOSE_FT_EXTENSION) + log(" pbas allocated: curr gen ", req._curr_gen); + } + break; + + case READ_BLK_SUCCEEDED: + + if (_lvl > 1) { + + _t1_blks[_lvl].decode_from_blk(_blk); + if (_lvl < req._ft.max_lvl) { + Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree); + if (!check_hash(_blk, _t1_blks[_lvl + 1].nodes[node_idx].hash)) + _mark_req_failed(progress, "hash mismatch"); + } else + if (!check_hash(_blk, req._ft.hash)) + _mark_req_failed(progress, "hash mismatch"); + + Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl, req._ft.degree); + Type_1_node &t1_node = _t1_blks[_lvl].nodes[node_idx]; + if (t1_node.valid()) { + + _lvl--; + _old_pbas.pbas [_lvl] = t1_node.pba; + _old_generations.items[_lvl] = t1_node.gen; + _generate_req(READ_BLK_SUCCEEDED, progress, t1_node.pba, _blk); + if (VERBOSE_FT_EXTENSION) + log(" lvl ", _lvl + 1, " node ", node_idx, " (", t1_node, "): load to lvl ", _lvl); + } else { + _alloc_lvl = _lvl; + _add_new_branch_at(_lvl, node_idx); + if (_old_generations.items[_alloc_lvl] == req._curr_gen) { + + _alloc_pba = _old_pbas.pbas[_alloc_lvl]; + _state = ALLOC_PBA_SUCCEEDED; + progress = true; + } else { + _alloc_pba = _old_pbas.pbas[_alloc_lvl]; + _generate_req( + ALLOC_PBA_SUCCEEDED, progress, Meta_tree_request::ALLOC_PBA, req._mt, req._curr_gen, _alloc_pba); + } + } + } else { + _t2_blk.decode_from_blk(_blk); + Tree_node_index t1_node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree); + if (!check_hash(_blk, _t1_blks[_lvl + 1].nodes[t1_node_idx].hash)) + _mark_req_failed(progress, "hash mismatch"); + + Tree_node_index t2_node_idx = t2_node_idx_for_vba(_vba, req._ft.degree); + if (_t2_blk.nodes[t2_node_idx].valid()) + _mark_req_failed(progress, "t2 node valid"); + + _add_new_branch_at(_lvl, t2_node_idx); + _alloc_lvl = _lvl; + if (VERBOSE_FT_EXTENSION) + log(" alloc lvl ", _alloc_lvl); + + _alloc_pba = _old_pbas.pbas[_alloc_lvl]; + _generate_req( + ALLOC_PBA_SUCCEEDED, progress, Meta_tree_request::ALLOC_PBA, req._mt, req._curr_gen, _alloc_pba); + } + break; + + case ALLOC_PBA_SUCCEEDED: + + _new_pbas.pbas[_alloc_lvl] = _alloc_pba; + if (_alloc_lvl < req._ft.max_lvl) { + + _alloc_lvl++; + if (_old_generations.items[_alloc_lvl] == req._curr_gen) { + + _alloc_pba = _old_pbas.pbas[_alloc_lvl]; + _state = ALLOC_PBA_SUCCEEDED; + progress = true; + } else { + _alloc_pba = _old_pbas.pbas[_alloc_lvl]; + _generate_req( + ALLOC_PBA_SUCCEEDED, progress, Meta_tree_request::ALLOC_PBA, req._mt, req._curr_gen, _alloc_pba); + } + } else { + _generate_write_blk_req(progress); + if (VERBOSE_FT_EXTENSION) + log(" pbas allocated: curr gen ", req._curr_gen); + } + break; + + case WRITE_BLK_SUCCEEDED: + + if (_lvl < req._ft.max_lvl) { + if (_lvl > 1) { + Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree); + Type_1_node &t1_node { _t1_blks[_lvl + 1].nodes[node_idx] }; + t1_node = { _new_pbas.pbas[_lvl], req._curr_gen }; + calc_hash(_blk, t1_node.hash); + if (VERBOSE_FT_EXTENSION) + log(" set lvl ", _lvl + 1, " node ", node_idx, ": ", t1_node); + + _lvl++; + _generate_write_blk_req(progress); + } else { + Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree); + Type_1_node &t1_node = _t1_blks[_lvl + 1].nodes[node_idx]; + t1_node = { _new_pbas.pbas[_lvl], req._curr_gen }; + calc_hash(_blk, t1_node.hash); + if (VERBOSE_FT_EXTENSION) + log(" set lvl ", _lvl + 1, " t1_node ", node_idx, ": ", t1_node); + + _lvl++; + _generate_write_blk_req(progress); + } + } else { + req._ft.t1_node({ _new_pbas.pbas[_lvl], req._curr_gen }); + calc_hash(_blk, req._ft.hash); + req._ft.num_leaves += _num_leaves; + _mark_req_successful(progress); + } + break; + + default: break; + } +} + + +void Free_tree_channel::_request_submitted(Module_request &mod_req) +{ + _req_ptr = static_cast(&mod_req); + _state = REQ_SUBMITTED; +} + + +Free_tree::Free_tree() +{ + Module_channel_id id { 0 }; + for (Constructible &chan : _channels) { + chan.construct(id++); + add_channel(*chan); } - if (_channels[id]._state != Channel::COMPLETE) { - class Exception_2 { }; - throw Exception_2 { }; - } - _channels[id]._state = Channel::INVALID; } diff --git a/repos/gems/src/lib/tresor/ft_check.cc b/repos/gems/src/lib/tresor/ft_check.cc index 73340589de..ce24a19097 100644 --- a/repos/gems/src/lib/tresor/ft_check.cc +++ b/repos/gems/src/lib/tresor/ft_check.cc @@ -11,493 +11,172 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base includes */ -#include - /* tresor includes */ #include #include -#include +#include using namespace Tresor; - -/********************** - ** Ft_check_request ** - **********************/ - -Ft_check_request::Ft_check_request(uint64_t src_module_id, - uint64_t src_request_id, - Type type, - Tree_level_index max_lvl, - Tree_node_index max_child_idx, - Number_of_leaves nr_of_leaves, - Type_1_node root) +Ft_check_request::Ft_check_request(Module_id src_mod, Module_channel_id src_chan, Tree_root const &ft, bool &success) : - Module_request { src_module_id, src_request_id, FT_CHECK }, - _type { type }, - _max_lvl { max_lvl }, - _max_child_idx { max_child_idx }, - _nr_of_leaves { nr_of_leaves }, - _root { root } + Module_request { src_mod, src_chan, FT_CHECK }, _ft { ft }, _success { success } { } -char const *Ft_check_request::type_to_string(Type type) +bool Ft_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) { - switch (type) { - case INVALID: return "invalid"; - case CHECK: return "check"; - } - return "?"; -} + bool &check_node { _check_node[lvl][node_idx] }; + if (check_node == false) + return false; -/************** - ** Ft_check ** - **************/ + Request &req { *_req_ptr }; + switch (_state) { + case REQ_IN_PROGRESS: -void Ft_check::_execute_inner_t2_child(Channel &chan, - Tree_level_index lvl, - Tree_node_index child_idx, - bool &progress) -{ - Request &req { chan._request }; - Child_state &child_state { chan._t1_lvls[lvl].children_state[child_idx] }; - Type_1_node const &child { chan._t1_lvls[lvl].children.nodes[child_idx] }; - Type_2_level &child_lvl { chan._t2_lvl }; - - if (child_state == Channel::READ_BLOCK) { - - if (!child.valid()) { - - if (chan._nr_of_leaves == 0) { - - child_state = Channel::DONE; + if (lvl == 1) { + Type_2_node const &node { _t2_blk.nodes[node_idx] }; + if (!_num_remaining_leaves) { + if (node.valid()) { + _mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, + ") valid but no leaves remaining" }); + break; + } + check_node = false; progress = true; - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " unused"); - - } else { - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " unexpectedly in use"); - - _mark_req_failed(chan, progress, "check for valid child"); + log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused"); + break; } - - } else if (!chan._gen_prim.valid()) { - - chan._gen_prim = { - .success = false, - .tag = Channel::BLOCK_IO, - .blk_nr = child.pba, - .dropped = false }; - - chan._lvl_to_read = lvl - 1; + _num_remaining_leaves--; + check_node = false; progress = true; - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " (", child, "): load to lvl ", lvl - 1); - - } else if (chan._gen_prim.tag != Channel::BLOCK_IO || - chan._gen_prim.blk_nr != child.pba) { - - class Exception_1 { }; - throw Exception_1 { }; - - } else if (!chan._gen_prim.success) { - + log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " done"); } else { - - for (Child_state &state : child_lvl.children_state) { - state = Channel::READ_BLOCK; - } - chan._gen_prim = { }; - child_state = Channel::CHECK_HASH; - progress = true; - } - - } else if (child_state == Channel::CHECK_HASH) { - - Block blk { }; - child_lvl.children.encode_to_blk(blk); - - if (child.gen == INITIAL_GENERATION || - check_sha256_4k_hash(blk, child.hash)) { - - child_state = Channel::DONE; - progress = true; - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " has good hash"); - - } else { - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " has bad hash"); - - _mark_req_failed(chan, progress, "check inner hash"); - } - } -} - - -void Ft_check::_execute_inner_t1_child(Channel &chan, - Type_1_node const &child, - Type_1_level &child_lvl, - Child_state &child_state, - Tree_level_index lvl, - Tree_node_index child_idx, - bool &progress) -{ - Request &req { chan._request }; - if (child_state == Channel::READ_BLOCK) { - - if (!child.valid()) { - - if (chan._nr_of_leaves == 0) { - - child_state = Channel::DONE; + Type_1_node const &node { _t1_blks.items[lvl].nodes[node_idx] }; + if (!node.valid()) { + if (_num_remaining_leaves) { + _mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " invalid but ", + _num_remaining_leaves, " leaves remaining" }); + break; + } + check_node = false; progress = true; - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " unused"); - - } else { - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " unexpectedly in use"); - - _mark_req_failed(chan, progress, "check for valid child"); + log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused"); + break; } - - } else if (!chan._gen_prim.valid()) { - - chan._gen_prim = { - .success = false, - .tag = Channel::BLOCK_IO, - .blk_nr = child.pba, - .dropped = false }; - - chan._lvl_to_read = lvl - 1; - progress = true; - + _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _blk); if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " (", child, "): load to lvl ", lvl - 1); - - } else if (chan._gen_prim.tag != Channel::BLOCK_IO || - chan._gen_prim.blk_nr != child.pba) { - - class Exception_1 { }; - throw Exception_1 { }; - - } else if (!chan._gen_prim.success) { - - } else { - - for (Child_state &state : child_lvl.children_state) { - state = Channel::READ_BLOCK; - } - chan._gen_prim = { }; - child_state = Channel::CHECK_HASH; - progress = true; + log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, + " (", node, "): load to lvl ", lvl - 1); } + break; - } else if (child_state == Channel::CHECK_HASH) { - - Block blk { }; - child_lvl.children.encode_to_blk(blk); - - if (child.gen == INITIAL_GENERATION || - check_sha256_4k_hash(blk, child.hash)) { - - child_state = Channel::DONE; - if (&child_state == &chan._root_state) { - chan._request._success = true; - } - progress = true; - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " has good hash"); - - } else { - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " has bad hash"); - - _mark_req_failed(chan, progress, "check inner hash"); + case READ_BLK_SUCCEEDED: + { + Type_1_node const &node { _t1_blks.items[lvl].nodes[node_idx] }; + if (node.gen != INITIAL_GENERATION && !check_hash(_blk, node.hash)) { + _mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, ") has bad hash" }); + break; } + if (lvl == 2) + _t2_blk.decode_from_blk(_blk); + else + _t1_blks.items[lvl - 1].decode_from_blk(_blk); + for (bool &cn : _check_node[lvl - 1]) + cn = true; + + _state = REQ_IN_PROGRESS; + check_node = false; + progress = true; + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " has good hash"); + break; } + default: break; + } + return true; } -void Ft_check::_execute_leaf_child(Channel &chan, - Tree_node_index child_idx, - bool &progress) +void Ft_check_channel::execute(bool &progress) { - Request &req { chan._request }; - Type_2_node const &child { chan._t2_lvl.children.nodes[child_idx] }; - Child_state &child_state { chan._t2_lvl.children_state[child_idx] }; + if (!_req_ptr) + return; - if (child_state == Channel::READ_BLOCK) { + if (_state == REQ_SUBMITTED) { + for (Tree_level_index lvl { 1 }; lvl <= _req_ptr->_ft.max_lvl + 1; lvl++) + for (Tree_node_index node_idx { 0 }; node_idx < _req_ptr->_ft.degree; node_idx++) + _check_node[lvl][node_idx] = false; - if (chan._nr_of_leaves == 0) { - - if (child.valid()) { - - if (VERBOSE_CHECK) - log(Level_indent { 1, req._max_lvl }, - " lvl 1 child ", child_idx, " unexpectedly in use"); - - _mark_req_failed(chan, progress, "check for unused child"); - - } else { - - child_state = Channel::DONE; - progress = true; - - if (VERBOSE_CHECK) - log(Level_indent { 1, req._max_lvl }, - " lvl 1 child ", child_idx, " unused"); - } - - } else { - - chan._nr_of_leaves--; - child_state = Channel::DONE; - progress = true; - - if (VERBOSE_CHECK) - log(Level_indent { 1, req._max_lvl }, - " lvl 1 child ", child_idx, " done"); - - } + _num_remaining_leaves = _req_ptr->_ft.num_leaves; + _t1_blks.items[_req_ptr->_ft.max_lvl + 1].nodes[0] = _req_ptr->_ft.t1_node(); + _check_node[_req_ptr->_ft.max_lvl + 1][0] = true; + _state = REQ_IN_PROGRESS; } -} - - -void Ft_check::_execute_check(Channel &chan, - bool &progress) -{ - Request &req { chan._request }; - for (Tree_node_index child_idx { 0 }; - child_idx <= req._max_child_idx; - child_idx++) { - - if (chan._t2_lvl.children_state[child_idx] != Channel::DONE) { - - _execute_leaf_child(chan, child_idx, progress); - return; - } - } - for (Tree_level_index lvl { FT_LOWEST_T1_LVL }; lvl <= req._max_lvl; lvl++) { - - for (Tree_node_index child_idx { 0 }; - child_idx <= req._max_child_idx; - child_idx++) { - - Type_1_level &t1_lvl { chan._t1_lvls[lvl] }; - if (t1_lvl.children_state[child_idx] != Channel::DONE) { - - if (lvl == FT_LOWEST_T1_LVL) - _execute_inner_t2_child( - chan, lvl, child_idx, progress); - else - _execute_inner_t1_child( - chan, - chan._t1_lvls[lvl].children.nodes[child_idx], - chan._t1_lvls[lvl - 1], - chan._t1_lvls[lvl].children_state[child_idx], - lvl, child_idx, progress); - + for (Tree_level_index lvl { 1 }; lvl <= _req_ptr->_ft.max_lvl + 1; lvl++) + for (Tree_node_index node_idx { 0 }; node_idx < _req_ptr->_ft.degree; node_idx++) + if (_execute_node(lvl, node_idx, progress)) return; - } - } - } - if (chan._root_state != Channel::DONE) { - _execute_inner_t1_child( - chan, req._root, chan._t1_lvls[req._max_lvl], chan._root_state, - req._max_lvl + 1, 0, progress); + _mark_req_successful(progress); +} + +void Ft_check_channel::_generated_req_completed(State_uint state_uint) +{ + if (!_generated_req_success) { + error("ft check: request (", *_req_ptr, ") failed because generated request failed)"); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; return; } + _state = (State)state_uint; } -void Ft_check::_mark_req_failed(Channel &chan, - bool &progress, - char const *str) +void Ft_check_channel::_mark_req_failed(bool &progress, Error_string str) { - error("ft check: request (", chan._request, ") failed at step \"", str, "\""); - chan._request._success = false; - chan._root_state = Channel::DONE; + error("ft check request (", *_req_ptr, ") failed: ", str); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; } -bool Ft_check::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) +void Ft_check_channel::_mark_req_successful(bool &progress) { - for (Channel &chan : _channels) { - - if (chan._request._type != Request::INVALID && - chan._root_state == Channel::DONE) { - - if (sizeof(chan._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &chan._request, sizeof(chan._request)); - return true; - } - } - return false; + _req_ptr->_success = true; + _state = REQ_COMPLETE; + _req_ptr = nullptr; + progress = true; } -void Ft_check::_drop_completed_request(Module_request &req) +void Ft_check_channel::_request_submitted(Module_request &mod_req) { - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - if (chan._request._type == Request::INVALID && - chan._root_state != Channel::DONE) { - - class Exception_2 { }; - throw Exception_2 { }; - } - chan = Channel { }; + _req_ptr = static_cast(&mod_req); + _state = REQ_SUBMITTED; } -bool Ft_check::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) +Ft_check::Ft_check() { - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - - Channel &chan { _channels[id] }; - - if (!chan._gen_prim.valid() || chan._gen_prim.dropped) - continue; - - switch (chan._gen_prim.tag) { - case Channel::BLOCK_IO: - - construct_in_buf( - buf_ptr, buf_size, FT_CHECK, id, - Block_io_request::READ, 0, 0, 0, - chan._gen_prim.blk_nr, 0, 1, - (void *)&chan._encoded_blk, nullptr); - - return true; - - default: - - class Exception_1 { }; - throw Exception_1 { }; - } + Module_channel_id id { 0 }; + for (Constructible &chan : _channels) { + chan.construct(id++); + add_channel(*chan); } - return false; -} - - -void Ft_check::_drop_generated_request(Module_request &req) -{ - Module_request_id const id { req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_0 { }; - throw Exception_0 { }; - } - Channel &chan { _channels[id] }; - chan._gen_prim.dropped = true; -} - - -void Ft_check::generated_request_complete(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - switch (mod_req.dst_module_id()) { - case BLOCK_IO: - { - Block_io_request &gen_req { *static_cast(&mod_req) }; - chan._gen_prim.success = gen_req.success(); - if (chan._lvl_to_read == 1) - chan._t2_lvl.children.decode_from_blk(chan._encoded_blk); - else - chan._t1_lvls[chan._lvl_to_read].children.decode_from_blk(chan._encoded_blk); - break; - } - default: - class Exception_8 { }; - throw Exception_8 { }; - } -} - - -bool Ft_check::ready_to_submit_request() -{ - for (Channel &chan : _channels) { - if (chan._request._type == Request::INVALID) - return true; - } - return false; -} - - -void Ft_check::submit_request(Module_request &req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - Channel &chan { _channels[id] }; - if (chan._request._type == Request::INVALID) { - req.dst_request_id(id); - chan._request = *static_cast(&req); - chan._nr_of_leaves = chan._request._nr_of_leaves; - chan._root_state = Channel::READ_BLOCK; - return; - } - } - class Exception_1 { }; - throw Exception_1 { }; } void Ft_check::execute(bool &progress) { - for (Channel &chan : _channels) { - - Request &req { chan._request }; - switch (req._type) { - case Request::CHECK: - - _execute_check(chan, progress); - break; - - default: - - break; - } - } + for_each_channel([&] (Channel &chan) { + chan.execute(progress); }); } diff --git a/repos/gems/src/lib/tresor/ft_initializer.cc b/repos/gems/src/lib/tresor/ft_initializer.cc index 4df42f8f2f..e092ba7a28 100644 --- a/repos/gems/src/lib/tresor/ft_initializer.cc +++ b/repos/gems/src/lib/tresor/ft_initializer.cc @@ -1,5 +1,6 @@ /* * \brief Module for initializing the free tree + * \author Martin Stein * \author Josef Soentgen * \date 2023-03-09 */ @@ -11,751 +12,222 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base includes */ -#include - /* tresor includes */ -#include #include -#include +#include #include using namespace Tresor; -static constexpr bool DEBUG = false; - - -Ft_initializer_request::Ft_initializer_request(Module_id src_module_id, - Module_request_id src_request_id) +Ft_initializer_request::Ft_initializer_request(Module_id src_mod, Module_channel_id src_chan, + Tree_root &ft, Pba_allocator &pba_alloc, bool &success) : - Module_request { src_module_id, src_request_id, FT_INITIALIZER } + Module_request { src_mod, src_chan, FT_INITIALIZER }, _ft { ft }, _pba_alloc { pba_alloc }, _success { success } { } -void Ft_initializer_request::create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - uint64_t max_level_idx, - uint64_t max_child_idx, - uint64_t nr_of_leaves) +bool Ft_initializer_channel::_execute_t2_node(Tree_node_index node_idx, bool &progress) { - Ft_initializer_request req { src_module_id, src_request_id }; + Node_state &node_state { _t2_node_states[node_idx] }; + Type_2_node &node { _t2_blk.nodes[node_idx] }; + switch (node_state) { + case DONE: return false; + case INIT_BLOCK: - req._type = (Type)req_type; - req._max_level_idx = max_level_idx; - req._max_child_idx = max_child_idx; - req._nr_of_leaves = nr_of_leaves; - - if (sizeof(req) > buf_size) { - class Bad_size_0 { }; - throw Bad_size_0 { }; - } - memcpy(buf_ptr, &req, sizeof(req)); -} - - -char const *Ft_initializer_request::type_to_string(Type type) -{ - switch (type) { - case INVALID: return "invalid"; - case INIT: return "init"; - } - return "?"; -} - - -void Ft_initializer::_execute_leaf_child(Channel &channel, - bool &progress, - uint64_t &nr_of_leaves, - Type_2_node &child, - Ft_initializer_channel::Child_state &child_state, - uint64_t child_index) -{ - using CS = Ft_initializer_channel::Child_state; - - switch (child_state) { - case CS::INIT_BLOCK: - child_state = CS::INIT_NODE; + node_state = INIT_NODE; progress = true; - return; + break; - case CS::INIT_NODE: - if (nr_of_leaves == 0) { + case INIT_NODE: - if (DEBUG) - log("[ft_init] node: ", 1, " ", child_index, - " assign pba 0, leaf unused"); - - Ft_initializer_channel::reset_node(child); - child_state = CS::DONE; - progress = true; - } else { - - switch (channel._state) { - case Channel::IN_PROGRESS: - channel._state = Channel::BLOCK_ALLOC_PENDING; - progress = true; - break; - - case Channel::BLOCK_ALLOC_PENDING: - break; - - case Channel::BLOCK_ALLOC_IN_PROGRESS: - break; - - case Channel::BLOCK_ALLOC_COMPLETE: - /* bail early in case the allocator failed */ - if (!channel._generated_req_success) { - _mark_req_failed(channel, progress, - "allocate block for FT initialization"); - break; - } - channel._state = Channel::IN_PROGRESS; - - Ft_initializer_channel::reset_node(child); - - child.pba = channel._blk_nr; - child_state = CS::DONE; - --nr_of_leaves; - progress = true; - - if (DEBUG) - log("[ft_init] node: ", 1, " ", child_index, - " assign pba: ", channel._blk_nr, " leaves left: ", - nr_of_leaves); - break; - - default: + if (_num_remaining_leaves) { + node = { }; + if (!_req_ptr->_pba_alloc.alloc(node.pba)) { + _mark_req_failed(progress, "allocate pba"); break; } + node_state = DONE; + _num_remaining_leaves--; + progress = true; + if (VERBOSE_FT_INIT) + log("[ft_init] node: ", 1, " ", node_idx, " assign pba: ", node.pba, " leaves left: ", _num_remaining_leaves); + } else { + node = { }; + node_state = DONE; + progress = true; + if (VERBOSE_FT_INIT) + log("[ft_init] node: ", 1, " ", node_idx, " assign pba 0, leaf unused"); } - default: break; + + case WRITE_BLK: ASSERT_NEVER_REACHED; } + return true; } -void Ft_initializer::_execute_inner_t2_child(Channel &channel, - bool &progress, - uint64_t nr_of_leaves, - uint64_t &level_to_write, - Type_1_node &child, - Ft_initializer_channel::Type_2_level &child_level, - Ft_initializer_channel::Child_state &child_state, - uint64_t level_index, - uint64_t child_index) - +bool Ft_initializer_channel::_execute_t1_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) { - using CS = Ft_initializer_channel::Child_state; + Type_1_node &node { _t1_blks.items[lvl].nodes[node_idx] }; + Node_state &node_state { _t1_node_states[lvl][node_idx] }; + switch (node_state) { + case DONE: return false; + case INIT_BLOCK: - switch (child_state) { - case CS::INIT_BLOCK: - - if (nr_of_leaves == 0) { - - if (DEBUG) - log("[ft_init] node: ", level_index, " ", child_index, - " assign pba 0, inner node unused"); - - Ft_initializer_channel::reset_node(child); - child_state = CS::DONE; + if (_num_remaining_leaves) { + _reset_level(lvl - 1, INIT_BLOCK); + node_state = INIT_NODE; progress = true; - return; + if (VERBOSE_FT_INIT) + log("[ft_init] node: ", lvl, " ", node_idx, " reset level: ", lvl - 1); } else { - - if (DEBUG) - log("[ft_init] node: ", level_index, " ", child_index, - " reset level: ", level_index - 1); - - Ft_initializer_channel::reset_level(child_level, CS::INIT_BLOCK); - child_state = CS::INIT_NODE; + node = { }; + node_state = DONE; progress = true; - return; + if (VERBOSE_FT_INIT) + log("[ft_init] node: ", lvl, " ", node_idx, " assign pba 0, unused"); } break; - case CS::INIT_NODE: - - switch (channel._state) { - case Channel::IN_PROGRESS: - channel._state = Channel::BLOCK_ALLOC_PENDING; - progress = true; - break; - - case Channel::BLOCK_ALLOC_PENDING: - break; - - case Channel::BLOCK_ALLOC_IN_PROGRESS: - break; - - case Channel::BLOCK_ALLOC_COMPLETE: - { - /* bail early in case the allocator failed */ - if (!channel._generated_req_success) { - _mark_req_failed(channel, progress, - "allocate block for FT initialization"); - break; - } - channel._state = Channel::IN_PROGRESS; - - Ft_initializer_channel::reset_node(child); - child.pba = channel._blk_nr; - - Block blk { }; - child_level.children.encode_to_blk(blk); - calc_sha256_4k_hash(blk, child.hash); - - child_state = CS::WRITE_BLOCK; - progress = true; - - if (DEBUG) - log("[ft_init] node: ", level_index, " ", child_index, - " assign pba: ", channel._blk_nr); + case INIT_NODE: + { + node = { }; + if (!_req_ptr->_pba_alloc.alloc(node.pba)) { + _mark_req_failed(progress, "allocate pba"); break; } - default: - break; - } - break; - - case CS::WRITE_BLOCK: - - switch (channel._state) { - case Channel::IN_PROGRESS: - { - channel._state = Channel::BLOCK_IO_PENDING; - channel._child_pba = child.pba; - level_to_write = level_index - 1; - progress = true; - break; - } - - case Channel::BLOCK_IO_PENDING: - break; - - case Channel::BLOCK_IO_IN_PROGRESS: - break; - - case Channel::BLOCK_IO_COMPLETE: - /* bail early in case the allocator failed */ - if (!channel._generated_req_success) { - _mark_req_failed(channel, progress, - "write block for FT initialization"); - break; - } - channel._state = Channel::IN_PROGRESS; - - child_state = CS::DONE; - progress = true; - - if (DEBUG) - log("[ft_init] node: ", level_index, " ", child_index, - " write pba: ", channel._child_pba, " level: ", - level_index -1, " (child: ", child, ")"); - break; - default: - break; - } - - break; - - default: + if (lvl == 2) + _t2_blk.encode_to_blk(_blk); + else + _t1_blks.items[lvl - 1].encode_to_blk(_blk); + calc_hash(_blk, node.hash); + generate_req(EXECUTE_NODES, progress, node.pba, _blk, _generated_req_success); + _state = REQ_GENERATED; + node_state = WRITE_BLK; + progress = true; + if (VERBOSE_FT_INIT) + log("[ft_init] node: ", lvl, " ", node_idx, " assign pba: ", node.pba); break; } + case WRITE_BLK: + + node_state = DONE; + progress = true; + if (VERBOSE_FT_INIT) + log("[ft_init] node: ", lvl, " ", node_idx, " write pba: ", node.pba, " level: ", lvl - 1, " (node: ", node, ")"); + break; + } + return true; } -void Ft_initializer::_execute_inner_t1_child(Channel &channel, - bool &progress, - uint64_t nr_of_leaves, - uint64_t &level_to_write, - Type_1_node &child, - Ft_initializer_channel::Type_1_level &child_level, - Ft_initializer_channel::Child_state &child_state, - uint64_t level_index, - uint64_t child_index) - +void Ft_initializer_channel::_generated_req_completed(State_uint state_uint) { - using CS = Ft_initializer_channel::Child_state; - - switch (child_state) { - case CS::INIT_BLOCK: - - if (nr_of_leaves == 0) { - - if (DEBUG) - log("[ft_init] node: ", level_index, " ", child_index, - " assign pba 0, inner node unused"); - - Ft_initializer_channel::reset_node(child); - child_state = CS::DONE; - progress = true; - return; - } else { - - if (DEBUG) - log("[ft_init] node: ", level_index, " ", child_index, - " reset level: ", level_index - 1); - - Ft_initializer_channel::reset_level(child_level, CS::INIT_BLOCK); - child_state = CS::INIT_NODE; - progress = true; - return; - } - break; - - case CS::INIT_NODE: - - switch (channel._state) { - case Channel::IN_PROGRESS: - channel._state = Channel::BLOCK_ALLOC_PENDING; - progress = true; - break; - - case Channel::BLOCK_ALLOC_PENDING: - break; - - case Channel::BLOCK_ALLOC_IN_PROGRESS: - break; - - case Channel::BLOCK_ALLOC_COMPLETE: - { - /* bail early in case the allocator failed */ - if (!channel._generated_req_success) { - _mark_req_failed(channel, progress, - "allocate block for FT initialization"); - break; - } - channel._state = Channel::IN_PROGRESS; - - Ft_initializer_channel::reset_node(child); - child.pba = channel._blk_nr; - - Block blk { }; - child_level.children.encode_to_blk(blk); - calc_sha256_4k_hash(blk, child.hash); - - child_state = CS::WRITE_BLOCK; - progress = true; - - if (DEBUG) - log("[ft_init] node: ", level_index, " ", child_index, - " assign pba: ", channel._blk_nr); - break; - } - default: - break; - } - break; - - case CS::WRITE_BLOCK: - - switch (channel._state) { - case Channel::IN_PROGRESS: - { - channel._state = Channel::BLOCK_IO_PENDING; - channel._child_pba = child.pba; - level_to_write = level_index - 1; - progress = true; - break; - } - - case Channel::BLOCK_IO_PENDING: - break; - - case Channel::BLOCK_IO_IN_PROGRESS: - break; - - case Channel::BLOCK_IO_COMPLETE: - /* bail early in case the allocator failed */ - if (!channel._generated_req_success) { - _mark_req_failed(channel, progress, - "write block for FT initialization"); - break; - } - channel._state = Channel::IN_PROGRESS; - - child_state = CS::DONE; - progress = true; - - if (DEBUG) - log("[ft_init] node: ", level_index, " ", child_index, - " write pba: ", channel._child_pba, " level: ", - level_index -1, " (child: ", child, ")"); - break; - default: - break; - } - - break; - - default: - break; - } -} - - -void Ft_initializer::_execute(Channel &channel, - bool &progress) -{ - Request &req { channel._request }; - - /* - * First handle all leaf child nodes that starts after - * triggering the inner T2 nodes below. - */ - for (uint64_t child_idx = 0; child_idx <= req._max_child_idx; child_idx++) { - - Ft_initializer_channel::Child_state &state = - channel._t2_level.children_state[child_idx]; - - if (state != Ft_initializer_channel::Child_state::DONE) { - - Type_2_node &child = - channel._t2_level.children.nodes[child_idx]; - - _execute_leaf_child(channel, progress, req._nr_of_leaves, - child, state, child_idx); - } - } - - /* - * Second handle all inner child nodes that starts after - * triggering the root node below. - */ - for (uint64_t level_idx = 1; level_idx <= req._max_level_idx; level_idx++) { - - for (uint64_t child_idx = 0; child_idx <= req._max_child_idx; child_idx++) { - - Ft_initializer_channel::Child_state &state = - channel._t1_levels[level_idx].children_state[child_idx]; - - if (state != Ft_initializer_channel::Child_state::DONE) { - - Type_1_node &child = - channel._t1_levels[level_idx].children.nodes[child_idx]; - - if (level_idx == 2) { - Ft_initializer_channel::Type_2_level &t2_level = - channel._t2_level; - - _execute_inner_t2_child(channel, progress, - req._nr_of_leaves, - channel._level_to_write, - child, t2_level, state, - level_idx, child_idx); - } else { - - Ft_initializer_channel::Type_1_level &t1_level = - channel._t1_levels[level_idx - 1]; - - _execute_inner_t1_child(channel, progress, - req._nr_of_leaves, - channel._level_to_write, - child, t1_level, state, - level_idx, child_idx); - } - return; - } - } - } - - /* - * Checking the root node will trigger the initialization process as - * well as will finish it. - */ - if (channel._root_node.state != Ft_initializer_channel::Child_state::DONE) { - - Ft_initializer_channel::Type_1_level &t1_level = - channel._t1_levels[req._max_level_idx]; - - _execute_inner_t1_child(channel, progress, - req._nr_of_leaves, - channel._level_to_write, - channel._root_node.node, t1_level, channel._root_node.state, - req._max_level_idx + 1, 0); + if (!_generated_req_success) { + error("ft initializer request (", *_req_ptr, ") failed because generated request failed"); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; return; } + _state = (State)state_uint; +} - /* - * We will end up here when the root state is 'DONE'. - */ - if (req._nr_of_leaves == 0) - _mark_req_successful(channel, progress); + +void Ft_initializer_channel::_mark_req_failed(bool &progress, char const *str) +{ + error("ft initializer request (", *_req_ptr, ") failed because: ", str); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; + progress = true; +} + + +void Ft_initializer_channel::_mark_req_successful(bool &progress) +{ + _req_ptr->_ft.t1_node(_t1_blks.items[_req_ptr->_ft.max_lvl + 1].nodes[0]); + _req_ptr->_success = true; + _state = REQ_COMPLETE; + _req_ptr = nullptr; + progress = true; +} + + +void Ft_initializer_channel::_reset_level(Tree_level_index lvl, Node_state node_state) +{ + if (lvl == 1) + for (Tree_node_index idx = 0; idx < NUM_NODES_PER_BLK; idx++) { + _t2_blk.nodes[idx] = { }; + _t2_node_states[idx] = node_state; + } else - _mark_req_failed(channel, progress, "initialize FT"); + for (Tree_node_index idx = 0; idx < NUM_NODES_PER_BLK; idx++) { + _t1_blks.items[lvl].nodes[idx] = { }; + _t1_node_states[lvl][idx] = node_state; + } } -void Ft_initializer::_execute_init(Channel &channel, - bool &progress) +void Ft_initializer_channel::execute(bool &progress) { - switch (channel._state) { - case Channel::SUBMITTED: - - /* clean residual state */ - for (unsigned int i = 0; i < TREE_MAX_LEVEL; i++) { - Ft_initializer_channel::reset_level(channel._t1_levels[i], - Ft_initializer_channel::Child_state::DONE); - } - channel._level_to_write = 0; - - channel._state = Channel::PENDING; - channel._root_node.state = Ft_initializer_channel::Child_state::INIT_BLOCK; - progress = true; - + if (!_req_ptr) return; - case Channel::PENDING: + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: - channel._state = Channel::IN_PROGRESS; + _num_remaining_leaves = req._ft.num_leaves; + for (Tree_level_index lvl = 0; lvl < TREE_MAX_LEVEL; lvl++) + _reset_level(lvl, DONE); + + _t1_node_states[req._ft.max_lvl + 1][0] = INIT_BLOCK; + _state = EXECUTE_NODES; progress = true; return; - case Channel::IN_PROGRESS: + case EXECUTE_NODES: - _execute(channel, progress); + for (Tree_node_index node_idx = 0; node_idx < req._ft.degree; node_idx++) + if (_execute_t2_node(node_idx, progress)) + return; + + for (Tree_level_index lvl = 1; lvl <= req._ft.max_lvl + 1; lvl++) + for (Tree_node_index node_idx = 0; node_idx < req._ft.degree; node_idx++) + if (_execute_t1_node(lvl, node_idx, progress)) + return; + + if (_num_remaining_leaves) + _mark_req_failed(progress, "leaves remaining"); + else + _mark_req_successful(progress); return; - case Channel::BLOCK_ALLOC_COMPLETE: - - _execute(channel, progress); - return; - - case Channel::BLOCK_IO_COMPLETE: - - _execute(channel, progress); - return; - - default: - /* - * Omit other states related to ALLOC and IO as those - * are handled via Module API. - */ - return; + default: return; } } -void Ft_initializer::_mark_req_failed(Channel &channel, - bool &progress, - char const *str) +void Ft_initializer_channel::_request_submitted(Module_request &mod_req) { - error("request failed: failed to ", str); - channel._request._success = false; - channel._state = Channel::COMPLETE; - progress = true; -} - - -void Ft_initializer::_mark_req_successful(Channel &channel, - bool &progress) -{ - Request &req { channel._request }; - - memcpy(req._root_node, &channel._root_node.node, sizeof (req._root_node)); - req._success = true; - - channel._state = Channel::COMPLETE; - progress = true; -} - - -bool Ft_initializer::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (Channel &channel : _channels) { - if (channel._state == Channel::COMPLETE) { - if (sizeof(channel._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &channel._request, sizeof(channel._request)); - return true; - } - } - return false; -} - - -void Ft_initializer::_drop_completed_request(Module_request &req) -{ - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (_channels[id]._state != Channel::COMPLETE) { - class Exception_2 { }; - throw Exception_2 { }; - } - _channels[id]._state = Channel::INACTIVE; -} - - -bool Ft_initializer::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - - Channel &channel { _channels[id] }; - - if (channel._state != Ft_initializer_channel::State::INACTIVE) - - switch (channel._state) { - case Ft_initializer_channel::State::BLOCK_ALLOC_PENDING: - { - Block_allocator_request::Type const block_allocator_req_type { - Block_allocator_request::GET }; - - Block_allocator_request::create( - buf_ptr, buf_size, FT_INITIALIZER, id, - block_allocator_req_type); - - return true; - } - case Ft_initializer_channel::State::BLOCK_IO_PENDING: - { - Block_io_request::Type const block_io_req_type { - Block_io_request::WRITE }; - - if (channel._level_to_write == 1) - channel._t2_level.children.encode_to_blk(channel._encoded_blk); - else - channel._t1_levels[channel._level_to_write].children.encode_to_blk(channel._encoded_blk); - - construct_in_buf( - buf_ptr, buf_size, FT_INITIALIZER, id, block_io_req_type, 0, - 0, 0, channel._child_pba, 0, 1, - (void *)&channel._encoded_blk, nullptr); - - if (DEBUG) { - log("BLOCK_IO_PENDING write ", channel._child_pba); - if (channel._level_to_write == 1) - Ft_initializer_channel::dump(channel._t2_level.children); - else - Ft_initializer_channel::dump(channel._t1_levels[channel._level_to_write].children); - } - - return true; - } - default: - break; - } - } - return false; -} - - -void Ft_initializer::_drop_generated_request(Module_request &req) -{ - Module_request_id const id { req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Bad_id { }; - throw Bad_id { }; - } - switch (_channels[id]._state) { - case Ft_initializer_channel::State::BLOCK_ALLOC_PENDING: - _channels[id]._state = Ft_initializer_channel::State::BLOCK_ALLOC_IN_PROGRESS; - break; - case Ft_initializer_channel::State::BLOCK_IO_PENDING: - _channels[id]._state = Ft_initializer_channel::State::BLOCK_IO_IN_PROGRESS; - break; - default: - class Exception_1 { }; - throw Exception_1 { }; - } -} - - -void Ft_initializer::generated_request_complete(Module_request &req) -{ - Module_request_id const id { req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - switch (_channels[id]._state) { - case Channel::BLOCK_ALLOC_IN_PROGRESS: - { - if (req.dst_module_id() != BLOCK_ALLOCATOR) { - class Exception_3 { }; - throw Exception_3 { }; - } - Block_allocator_request const *block_allocator_req = static_cast(&req); - _channels[id]._state = Channel::BLOCK_ALLOC_COMPLETE; - _channels[id]._blk_nr = block_allocator_req->blk_nr(); - _channels[id]._generated_req_success = block_allocator_req->success(); - break; - } - case Channel::BLOCK_IO_IN_PROGRESS: - { - if (req.dst_module_id() != BLOCK_IO) { - class Exception_4 { }; - throw Exception_4 { }; - } - Block_io_request const *block_io_req = static_cast(&req); - _channels[id]._state = Channel::BLOCK_IO_COMPLETE; - _channels[id]._generated_req_success = block_io_req->success(); - break; - } - default: - class Exception_2 { }; - throw Exception_2 { }; - } + _req_ptr = static_cast(&mod_req); + _state = REQ_SUBMITTED; } Ft_initializer::Ft_initializer() -{ } - - -bool Ft_initializer::ready_to_submit_request() { - for (Channel &channel : _channels) { - if (channel._state == Channel::INACTIVE) - return true; + Module_channel_id id { 0 }; + for (Constructible &chan : _channels) { + chan.construct(id++); + add_channel(*chan); } - return false; -} - - -void Ft_initializer::submit_request(Module_request &req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - if (_channels[id]._state == Channel::INACTIVE) { - req.dst_request_id(id); - _channels[id]._request = *static_cast(&req); - _channels[id]._state = Channel::SUBMITTED; - return; - } - } - class Invalid_call { }; - throw Invalid_call { }; } void Ft_initializer::execute(bool &progress) { - for (Channel &channel : _channels) { - - if (channel._state == Channel::INACTIVE) - continue; - - Request &req { channel._request }; - switch (req._type) { - case Request::INIT: - - _execute_init(channel, progress); - - break; - default: - - class Exception_1 { }; - throw Exception_1 { }; - } - } + for_each_channel([&] (Channel &chan) { + chan.execute(progress); }); } diff --git a/repos/gems/src/lib/tresor/ft_resizing.cc b/repos/gems/src/lib/tresor/ft_resizing.cc deleted file mode 100644 index bdcffcab74..0000000000 --- a/repos/gems/src/lib/tresor/ft_resizing.cc +++ /dev/null @@ -1,843 +0,0 @@ -/* - * \brief Module for re-sizing the free tree - * \author Martin Stein - * \date 2023-05-09 - */ - -/* - * Copyright (C) 2023 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* base includes */ -#include - -/* tresor tester includes */ -#include -#include -#include -#include - -using namespace Tresor; - - -/************************* - ** Ft_resizing_request ** - *************************/ - -Ft_resizing_request:: -Ft_resizing_request(uint64_t src_module_id, - uint64_t src_request_id, - Type type, - Generation curr_gen, - Type_1_node ft_root, - Tree_level_index ft_max_lvl, - Number_of_leaves ft_nr_of_leaves, - Tree_degree ft_degree, - addr_t mt_root_pba_ptr, - addr_t mt_root_gen_ptr, - addr_t mt_root_hash_ptr, - Tree_level_index mt_max_level, - Tree_degree mt_degree, - Number_of_leaves mt_leaves, - Physical_block_address pba, - Number_of_blocks nr_of_pbas) -: - Module_request { src_module_id, src_request_id, FT_RESIZING }, - _type { type }, - _curr_gen { curr_gen }, - _ft_root { ft_root }, - _ft_max_lvl { ft_max_lvl }, - _ft_nr_of_leaves { ft_nr_of_leaves }, - _ft_degree { ft_degree }, - _mt_root_pba_ptr { mt_root_pba_ptr }, - _mt_root_gen_ptr { mt_root_gen_ptr }, - _mt_root_hash_ptr { mt_root_hash_ptr }, - _mt_max_level { mt_max_level }, - _mt_degree { mt_degree }, - _mt_leaves { mt_leaves }, - _pba { pba }, - _nr_of_pbas { nr_of_pbas } -{ } - -char const *Ft_resizing_request::type_to_string(Type op) -{ - switch (op) { - case INVALID: return "invalid"; - case FT_EXTENSION_STEP: return "ft_ext_step"; - } - return "?"; -} - - -/************************* - ** Ft_resizing_request ** - *************************/ - -void Ft_resizing::_execute_ft_ext_step_read_inner_node_completed(Channel &channel, - unsigned const job_idx, - bool &progress) -{ - Request &req { channel._request }; - if (not channel._generated_prim.succ) { - class Primitive_not_successfull_ft_resizing { }; - throw Primitive_not_successfull_ft_resizing { }; - } - - if (channel._lvl_idx > 1) { - - if (channel._lvl_idx == req._ft_max_lvl) { - - if (not check_sha256_4k_hash(channel._encoded_blk, - req._ft_root.hash)) { - class Program_error_ft_resizing_hash_mismatch { }; - throw Program_error_ft_resizing_hash_mismatch { }; - } - - } else { - - Tree_level_index const parent_lvl_idx = channel._lvl_idx + 1; - Tree_node_index const child_idx = t1_child_idx_for_vba(channel._vba, parent_lvl_idx, req._ft_degree); - Type_1_node const &child = channel._t1_blks.items[parent_lvl_idx].nodes[child_idx]; - - if (not check_sha256_4k_hash(channel._encoded_blk, - child.hash)) { - class Program_error_ft_resizing_hash_mismatch_2 { }; - throw Program_error_ft_resizing_hash_mismatch_2 { }; - } - - } - - Tree_level_index const parent_lvl_idx = channel._lvl_idx; - Tree_level_index const child_lvl_idx = channel._lvl_idx - 1; - Tree_node_index const child_idx = t1_child_idx_for_vba(channel._vba, parent_lvl_idx, req._ft_degree); - Type_1_node const &child = channel._t1_blks.items[parent_lvl_idx].nodes[child_idx]; - - if (child.valid()) { - - channel._lvl_idx = child_lvl_idx; - channel._old_pbas.pbas [child_lvl_idx] = child.pba; - channel._old_generations.items[child_lvl_idx] = child.gen; - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_FT_RSZG_CACHE, - .blk_nr = child.pba, - .idx = job_idx - }; - - channel._state = Channel::State::READ_INNER_NODE_PENDING; - progress = true; - - if (VERBOSE_FT_EXTENSION) - log(" lvl ", parent_lvl_idx, " child ", child_idx, - " (", child, "): load to lvl ", channel._lvl_idx); - - } else { - - _add_new_branch_to_ft_using_pba_contingent(parent_lvl_idx, - child_idx, - req._ft_degree, - req._curr_gen, - req._pba, - req._nr_of_pbas, - channel._t1_blks, - channel._t2_blk, - channel._new_pbas, - channel._lvl_idx, - req._nr_of_leaves); - - channel._alloc_lvl_idx = parent_lvl_idx; - - if (channel._old_generations.items[channel._alloc_lvl_idx] == req._curr_gen) { - - channel._new_pbas.pbas[channel._alloc_lvl_idx] = - channel._old_pbas.pbas[channel._alloc_lvl_idx]; - - channel._state = Channel::State::ALLOC_PBA_COMPLETED; - progress = true; - - } else { - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_FT_RSZG_MT_ALLOC, - .blk_nr = 0, - .idx = job_idx - }; - - channel._state = Channel::State::ALLOC_PBA_PENDING; - progress = true; - - } - } - } else { - - { - Tree_level_index const parent_lvl_idx = channel._lvl_idx + 1; - Tree_node_index const child_idx = t1_child_idx_for_vba(channel._vba, parent_lvl_idx, req._ft_degree); - - if (not check_sha256_4k_hash(channel._encoded_blk, - channel._t1_blks.items[parent_lvl_idx].nodes[child_idx].hash)) { - class Program_error_ft_resizing_hash_mismatch_3 { }; - throw Program_error_ft_resizing_hash_mismatch_3 { }; - } - } - - { - Tree_level_index const parent_lvl_idx = channel._lvl_idx; - Tree_node_index const child_idx = t2_child_idx_for_vba(channel._vba, req._ft_degree); - Type_2_node const &child = channel._t2_blk.nodes[child_idx]; - - if (child.valid()) { - class Program_error_ft_resizing_t2_valid { }; - throw Program_error_ft_resizing_t2_valid { }; - } - - _add_new_branch_to_ft_using_pba_contingent(parent_lvl_idx, - child_idx, - req._ft_degree, - req._curr_gen, - req._pba, - req._nr_of_pbas, - channel._t1_blks, - channel._t2_blk, - channel._new_pbas, - channel._lvl_idx, - req._nr_of_leaves); - - channel._alloc_lvl_idx = parent_lvl_idx; - - if (VERBOSE_FT_EXTENSION) - log(" alloc lvl ", channel._alloc_lvl_idx); - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_FT_RSZG_MT_ALLOC, - .blk_nr = 0, - .idx = job_idx - }; - - channel._state = Channel::State::ALLOC_PBA_PENDING; - progress = true; - } - } -} - - -void Ft_resizing::_set_args_for_write_back_of_inner_lvl(Tree_level_index const max_lvl_idx, - Tree_level_index const lvl_idx, - Physical_block_address const pba, - unsigned const prim_idx, - Channel::State &job_state, - bool &progress, - Channel::Generated_prim &prim) -{ - if (lvl_idx == 0) { - class Program_error_ft_resizing_lvl_idx_zero { }; - throw Program_error_ft_resizing_lvl_idx_zero { }; - } - - if (lvl_idx > max_lvl_idx) { - class Program_error_ft_resizing_lvl_idx_large { }; - throw Program_error_ft_resizing_lvl_idx_large { }; - } - - prim = { - .op = Channel::Generated_prim::Type::WRITE, - .succ = false, - .tg = Channel::Tag_type::TAG_FT_RSZG_CACHE, - .blk_nr = pba, - .idx = prim_idx - }; - - if (VERBOSE_FT_EXTENSION) - log(" lvl ", lvl_idx, " write to pba ", pba); - - if (lvl_idx < max_lvl_idx) { - job_state = Channel::State::WRITE_INNER_NODE_PENDING; - progress = true; - } else { - job_state = Channel::State::WRITE_ROOT_NODE_PENDING; - progress = true; - } -} - - -void Ft_resizing::_add_new_root_lvl_to_ft_using_pba_contingent(Type_1_node &ft_root, - Tree_level_index &ft_max_lvl_idx, - Number_of_leaves const ft_nr_of_leaves, - Generation const curr_gen, - Channel::Type_1_node_blocks &t1_blks, - Tree_walk_pbas &new_pbas, - Physical_block_address &first_pba, - Number_of_blocks &nr_of_pbas) -{ - if (ft_max_lvl_idx >= TREE_MAX_LEVEL) { - class Program_error_ft_resizing_max_level { }; - throw Program_error_ft_resizing_max_level { }; - } - - ft_max_lvl_idx += 1; - - t1_blks.items[ft_max_lvl_idx] = { }; - t1_blks.items[ft_max_lvl_idx].nodes[0] = ft_root; - - new_pbas.pbas[ft_max_lvl_idx] = alloc_pba_from_resizing_contingent(first_pba, nr_of_pbas); - - ft_root = { - .pba = new_pbas.pbas[ft_max_lvl_idx], - .gen = curr_gen, - .hash = { }, - }; - - if (VERBOSE_FT_EXTENSION) { - log(" set ft root: ", ft_root, " leaves ", ft_nr_of_leaves, - " max lvl ", ft_max_lvl_idx); - - log(" set lvl ", ft_max_lvl_idx, - " child 0: ", t1_blks.items[ft_max_lvl_idx].nodes[0]); - } - (void)ft_nr_of_leaves; -} - - -void Ft_resizing::_add_new_branch_to_ft_using_pba_contingent(Tree_level_index const mount_point_lvl_idx, - Tree_node_index const mount_point_child_idx, - Tree_degree const ft_degree, - Generation const curr_gen, - Physical_block_address &first_pba, - Number_of_blocks &nr_of_pbas, - Channel::Type_1_node_blocks &t1_blks, - Type_2_node_block &t2_blk, - Tree_walk_pbas &new_pbas, - Tree_level_index &stopped_at_lvl_idx, - Number_of_leaves &nr_of_leaves) -{ - nr_of_leaves = 0; - stopped_at_lvl_idx = mount_point_lvl_idx; - - if (mount_point_lvl_idx > 1) { - for (unsigned lvl_idx = 1; lvl_idx <= mount_point_lvl_idx - 1; lvl_idx++) { - if (lvl_idx > 1) - t1_blks.items[lvl_idx] = Type_1_node_block { }; - else - t2_blk = Type_2_node_block { }; - - if (VERBOSE_FT_EXTENSION) - log(" reset lvl ", lvl_idx); - } - } - - if (nr_of_pbas > 0) { - - for (unsigned lvl_idx = mount_point_lvl_idx; lvl_idx >= 1; lvl_idx --) { - stopped_at_lvl_idx = lvl_idx; - - if (lvl_idx > 1) { - - if (nr_of_pbas == 0) - break; - - Tree_node_index const child_idx = (lvl_idx == mount_point_lvl_idx) ? mount_point_child_idx : 0; - Tree_level_index const child_lvl_idx = lvl_idx - 1; - - new_pbas.pbas[child_lvl_idx] = alloc_pba_from_resizing_contingent(first_pba, nr_of_pbas); - - t1_blks.items[lvl_idx].nodes[child_idx] = { - .pba = new_pbas.pbas[child_lvl_idx], - .gen = curr_gen, - .hash = { } - }; - - if (VERBOSE_FT_EXTENSION) - log(" set lvl d ", lvl_idx, " child ", child_idx, - ": ", t1_blks.items[lvl_idx].nodes[child_idx]); - - } else { - Tree_node_index const first_child_idx = (lvl_idx == mount_point_lvl_idx) ? mount_point_child_idx : 0; - - for (Tree_node_index child_idx = first_child_idx; child_idx <= ft_degree - 1; child_idx++) { - - if (nr_of_pbas == 0) - break; - - Physical_block_address child_pba = alloc_pba_from_resizing_contingent(first_pba, nr_of_pbas); - - t2_blk.nodes[child_idx] = { - .pba = child_pba, - .last_vba = INVALID_VBA, - .alloc_gen = INITIAL_GENERATION, - .free_gen = INITIAL_GENERATION, - .last_key_id = INVALID_KEY_ID, - .reserved = false - }; - - if (VERBOSE_FT_EXTENSION) - log(" set lvl e ", lvl_idx, " child ", child_idx, - ": ", t2_blk.nodes[child_idx]); - - nr_of_leaves = nr_of_leaves + 1; - } - } - } - } -} - - -void Ft_resizing::_execute_ft_extension_step(Channel &chan, - unsigned const chan_idx, - bool &progress) -{ - Request &req { chan._request }; - switch (chan._state) { - case Channel::State::SUBMITTED: - - req._nr_of_leaves = 0; - chan._vba = req._ft_nr_of_leaves; - - chan._old_pbas = { }; - chan._old_generations = { }; - chan._new_pbas = { }; - - chan._lvl_idx = req._ft_max_lvl; - chan._old_pbas.pbas[chan._lvl_idx] = req._ft_root.pba; - chan._old_generations.items[chan._lvl_idx] = req._ft_root.gen; - - if (chan._vba <= tree_max_max_vba(req._ft_degree, req._ft_max_lvl)) { - - chan._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_FT_RSZG_CACHE, - .blk_nr = req._ft_root.pba, - .idx = chan_idx - }; - - if (VERBOSE_FT_EXTENSION) - log(" root (", req._ft_root, - " leaves ", req._ft_nr_of_leaves, - " max lvl ", req._ft_max_lvl, - "): load to lvl ", chan._lvl_idx); - - chan._state = Channel::State::READ_ROOT_NODE_PENDING; - progress = true; - - } else { - - _add_new_root_lvl_to_ft_using_pba_contingent(req._ft_root, - req._ft_max_lvl, - req._ft_nr_of_leaves, - req._curr_gen, - chan._t1_blks, - chan._new_pbas, - req._pba, - req._nr_of_pbas); - - _add_new_branch_to_ft_using_pba_contingent(req._ft_max_lvl, - 1, - req._ft_degree, - req._curr_gen, - req._pba, - req._nr_of_pbas, - chan._t1_blks, - chan._t2_blk, - chan._new_pbas, - chan._lvl_idx, - req._nr_of_leaves); - - if (VERBOSE_FT_EXTENSION) - log(" pbas allocated: curr gen ", req._curr_gen); - - _set_args_for_write_back_of_inner_lvl(req._ft_max_lvl, - chan._lvl_idx, - chan._new_pbas.pbas[chan._lvl_idx], - chan_idx, - chan._state, - progress, - chan._generated_prim); - - } - - break; - case Channel::State::READ_ROOT_NODE_COMPLETED: - _execute_ft_ext_step_read_inner_node_completed(chan, chan_idx, progress); - break; - case Channel::State::READ_INNER_NODE_COMPLETED: - _execute_ft_ext_step_read_inner_node_completed(chan, chan_idx, progress); - break; - case Channel::State::ALLOC_PBA_COMPLETED: - if (chan._alloc_lvl_idx < req._ft_max_lvl) { - - chan._alloc_lvl_idx = chan._alloc_lvl_idx + 1; - - if (chan._old_generations.items[chan._alloc_lvl_idx] == req._curr_gen) { - - chan._new_pbas.pbas[chan._alloc_lvl_idx] = chan._old_pbas.pbas[chan._alloc_lvl_idx]; - - chan._state = Channel::State::ALLOC_PBA_COMPLETED; - progress = true; - - } else { - - chan._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_FT_RSZG_MT_ALLOC, - .blk_nr = 0, - .idx = chan_idx - }; - - chan._state = Channel::State::ALLOC_PBA_PENDING; - progress = true; - - } - - } else { - - if (VERBOSE_FT_EXTENSION) - log(" pbas allocated: curr gen ", req._curr_gen); - - _set_args_for_write_back_of_inner_lvl(req._ft_max_lvl, - chan._lvl_idx, - chan._new_pbas.pbas[chan._lvl_idx], - chan_idx, - chan._state, - progress, - chan._generated_prim); - - } - break; - case Channel::State::WRITE_INNER_NODE_COMPLETED: - - if (not chan._generated_prim.succ) { - class Primitive_not_successfull_ft_resizing_write_inner { }; - throw Primitive_not_successfull_ft_resizing_write_inner { }; - } - - if (chan._lvl_idx > 1) { - - Tree_level_index const parent_lvl_idx = chan._lvl_idx + 1; - Tree_level_index const child_lvl_idx = chan._lvl_idx; - Tree_node_index const child_idx = t1_child_idx_for_vba(chan._vba, parent_lvl_idx, req._ft_degree); - - Type_1_node &child { - chan._t1_blks.items[parent_lvl_idx].nodes[child_idx] }; - - child = { - .pba = chan._new_pbas.pbas[child_lvl_idx], - .gen = req._curr_gen, - .hash = { }, - }; - - calc_sha256_4k_hash(chan._encoded_blk, child.hash); - - if (VERBOSE_FT_EXTENSION) - log(" set lvl a ", parent_lvl_idx, " child ", child_idx, - ": ", child); - - _set_args_for_write_back_of_inner_lvl(req._ft_max_lvl, - parent_lvl_idx, - chan._new_pbas.pbas[parent_lvl_idx], - chan_idx, - chan._state, - progress, - chan._generated_prim); - - chan._lvl_idx += 1; - - } else { - - Tree_level_index const parent_lvl_idx = chan._lvl_idx + 1; - Tree_level_index const child_lvl_idx = chan._lvl_idx; - Tree_node_index const child_idx = t1_child_idx_for_vba(chan._vba, parent_lvl_idx, req._ft_degree); - Type_1_node &child = chan._t1_blks.items[parent_lvl_idx].nodes[child_idx]; - child = { - .pba = chan._new_pbas.pbas[child_lvl_idx], - .gen = req._curr_gen, - }; - - calc_sha256_4k_hash(chan._encoded_blk, child.hash); - - if (VERBOSE_FT_EXTENSION) - log(" set lvl b ", parent_lvl_idx, " child ", child_idx, - ": ", child); - - _set_args_for_write_back_of_inner_lvl(req._ft_max_lvl, - parent_lvl_idx, - chan._new_pbas.pbas[parent_lvl_idx], - chan_idx, - chan._state, - progress, - chan._generated_prim); - - chan._lvl_idx += 1; // = 2 - - } - break; - case Channel::State::WRITE_ROOT_NODE_COMPLETED: { - - if (not chan._generated_prim.succ) { - class Primitive_not_successfull_ft_resizing_write_root { }; - throw Primitive_not_successfull_ft_resizing_write_root { }; - } - - Tree_level_index const child_lvl_idx = chan._lvl_idx; - Physical_block_address const child_pba = chan._new_pbas.pbas[child_lvl_idx]; - - req._ft_root = { - .pba = child_pba, - .gen = req._curr_gen, - }; - - calc_sha256_4k_hash(chan._encoded_blk, req._ft_root.hash); - - req._ft_nr_of_leaves += req._nr_of_leaves; - - req._success = true; - - chan._state = Channel::State::COMPLETED; - progress = true; - - break; - } - default: - break; - } -} - - -void Ft_resizing::execute(bool &progress) -{ - for (unsigned idx = 0; idx < NR_OF_CHANNELS; idx++) { - - Channel &channel = _channels[idx]; - Request &request { channel._request }; - - switch (request._type) { - case Request::INVALID: - break; - case Request::FT_EXTENSION_STEP: - _execute_ft_extension_step(channel, idx, progress); - break; - } - } -} - - -bool Ft_resizing::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (Channel &channel : _channels) { - if (channel._request._type != Request::INVALID && - channel._state == Channel::COMPLETED) { - - if (sizeof(channel._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &channel._request, sizeof(channel._request)); - return true; - } - } - return false; -} - - -void Ft_resizing::_drop_completed_request(Module_request &req) -{ - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - if (chan._request._type == Request::INVALID || - chan._state != Channel::COMPLETED) { - - class Exception_2 { }; - throw Exception_2 { }; - } - chan._request._type = Request::INVALID; -} - - -bool Ft_resizing::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (uint32_t id { 0 }; id < NR_OF_CHANNELS; id++) { - - Channel &chan { _channels[id] }; - Request &req { chan._request }; - if (req._type == Request::INVALID) - continue; - - switch (chan._state) { - case Channel::WRITE_ROOT_NODE_PENDING: - case Channel::WRITE_INNER_NODE_PENDING: - - if (chan._lvl_idx > 1) - chan._t1_blks.items[chan._lvl_idx].encode_to_blk(chan._encoded_blk); - else - chan._t2_blk.encode_to_blk(chan._encoded_blk); - construct_in_buf( - buf_ptr, buf_size, FT_RESIZING, id, - Block_io_request::WRITE, 0, 0, 0, - chan._generated_prim.blk_nr, 0, 1, - (void *)&chan._encoded_blk, nullptr); - - return true; - - case Channel::READ_ROOT_NODE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, FT_RESIZING, id, - Block_io_request::READ, 0, 0, 0, - chan._generated_prim.blk_nr, 0, 1, - (void *)&chan._encoded_blk, nullptr); - - return true; - - case Channel::READ_INNER_NODE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, FT_RESIZING, id, - Block_io_request::READ, 0, 0, 0, - chan._generated_prim.blk_nr, 0, 1, (void *)&chan._encoded_blk, - nullptr); - - return true; - - case Channel::State::ALLOC_PBA_PENDING: - - Meta_tree_request::create( - buf_ptr, buf_size, FT_RESIZING, id, Meta_tree_request::UPDATE, - (void *)req._mt_root_pba_ptr, - (void *)req._mt_root_gen_ptr, - (void *)req._mt_root_hash_ptr, - req._mt_max_level, - req._mt_degree, - req._mt_leaves, - req._curr_gen, - chan._old_pbas.pbas[chan._alloc_lvl_idx]); - - return true; - - case Channel::EXTEND_MT_BY_ONE_LEAF_PENDING: - - class Exception_10 { }; - throw Exception_10 { }; - - default: break; - } - } - return false; -} - - -void Ft_resizing::_drop_generated_request(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - switch (chan._state) { - case Channel::READ_ROOT_NODE_PENDING: chan._state = Channel::READ_ROOT_NODE_IN_PROGRESS; break; - case Channel::READ_INNER_NODE_PENDING: chan._state = Channel::READ_INNER_NODE_IN_PROGRESS; break; - case Channel::WRITE_ROOT_NODE_PENDING: chan._state = Channel::WRITE_ROOT_NODE_IN_PROGRESS; break; - case Channel::WRITE_INNER_NODE_PENDING: chan._state = Channel::WRITE_INNER_NODE_IN_PROGRESS; break; - case Channel::ALLOC_PBA_PENDING: chan._state = Channel::ALLOC_PBA_IN_PROGRESS; break; - default: - class Exception_2 { }; - throw Exception_2 { }; - } -} - - -void Ft_resizing::generated_request_complete(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - switch (mod_req.dst_module_id()) { - case BLOCK_IO: - { - Block_io_request &blk_io_req { *static_cast(&mod_req) }; - chan._generated_prim.succ = blk_io_req.success(); - switch (chan._state) { - case Channel::READ_ROOT_NODE_IN_PROGRESS: - chan._t1_blks.items[chan._lvl_idx].decode_from_blk(chan._encoded_blk); - chan._state = Channel::READ_ROOT_NODE_COMPLETED; - break; - case Channel::READ_INNER_NODE_IN_PROGRESS: - if (chan._lvl_idx > 1) - chan._t1_blks.items[chan._lvl_idx].decode_from_blk(chan._encoded_blk); - else - chan._t2_blk.decode_from_blk(chan._encoded_blk); - chan._state = Channel::READ_INNER_NODE_COMPLETED; - break; - case Channel::WRITE_ROOT_NODE_IN_PROGRESS: chan._state = Channel::WRITE_ROOT_NODE_COMPLETED; break; - case Channel::WRITE_INNER_NODE_IN_PROGRESS: chan._state = Channel::WRITE_INNER_NODE_COMPLETED; break; - default: - class Exception_4 { }; - throw Exception_4 { }; - } - break; - } - case META_TREE: - { - Meta_tree_request &mt_req { *static_cast(&mod_req) }; - chan._generated_prim.succ = mt_req.success(); - switch (chan._state) { - case Channel::ALLOC_PBA_IN_PROGRESS: - chan._new_pbas.pbas[chan._alloc_lvl_idx] = mt_req.new_pba(); - chan._state = Channel::ALLOC_PBA_COMPLETED; - break; - default: - class Exception_7 { }; - throw Exception_7 { }; - } - break; - } - default: - class Exception_5 { }; - throw Exception_5 { }; - } -} - - -bool Ft_resizing::ready_to_submit_request() -{ - for (Channel &channel : _channels) { - if (channel._request._type == Request::INVALID) - return true; - } - return false; -} - - -void Ft_resizing::submit_request(Module_request &mod_req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - Channel &chan { _channels[id] }; - if (chan._request._type == Request::INVALID) { - mod_req.dst_request_id(id); - chan._request = *static_cast(&mod_req); - chan._state = Channel::SUBMITTED; - return; - } - } - class Invalid_call { }; - throw Invalid_call { }; -} diff --git a/repos/gems/src/lib/tresor/hash.cc b/repos/gems/src/lib/tresor/hash.cc new file mode 100644 index 0000000000..b3ca504784 --- /dev/null +++ b/repos/gems/src/lib/tresor/hash.cc @@ -0,0 +1,43 @@ +/* + * \brief Calculate and check hashes of tresor data blocks + * \author Martin Stein + * \date 2023-02-13 + */ + +/* + * Copyright (C) 2023 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* tresor includes */ +#include +#include + +/* libcrypto */ +#include + +bool Tresor::check_hash(Block const &blk, Hash const &expected_hash) +{ + Hash got_hash; + calc_hash(blk, got_hash); + return got_hash == expected_hash; +} + + +void Tresor::calc_hash(Block const &blk, Hash &hash) +{ + SHA256_CTX context { }; + ASSERT(SHA256_Init(&context)); + ASSERT(SHA256_Update(&context, &blk, BLOCK_SIZE)); + ASSERT(SHA256_Final((unsigned char *)(&hash), &context)); +} + + +Tresor::Hash Tresor::hash(Block const &blk) +{ + Hash hash { }; + calc_hash(blk, hash); + return hash; +} diff --git a/repos/gems/src/lib/tresor/include/tresor/block_allocator.h b/repos/gems/src/lib/tresor/include/tresor/block_allocator.h deleted file mode 100644 index 90954fcc33..0000000000 --- a/repos/gems/src/lib/tresor/include/tresor/block_allocator.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * \brief Managing block allocation for the initialization of a Tresor device - * \author Josef Soentgen - * \date 2023-02-28 - */ - -/* - * Copyright (C) 2023 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _TRESOR__BLOCK_ALLOCATOR_H_ -#define _TRESOR__BLOCK_ALLOCATOR_H_ - -/* tresor includes */ -#include -#include - -namespace Tresor { - - class Block_allocator; - class Block_allocator_request; - class Block_allocator_channel; -} - - -class Tresor::Block_allocator_request : public Module_request -{ - public: - - enum Type { INVALID = 0, GET = 1, }; - - private: - - friend class Block_allocator; - friend class Block_allocator_channel; - - Type _type { INVALID }; - uint64_t _blk_nr { 0 }; - bool _success { false }; - - public: - - Block_allocator_request() { } - - Block_allocator_request(Module_id src_module_id, - Module_request_id src_request_id); - - static void create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type); - - uint64_t blk_nr() const { return _blk_nr; } - - Type type() const { return _type; } - - bool success() const { return _success; } - - static char const *type_to_string(Type type); - - - /******************** - ** Module_request ** - ********************/ - - void print(Output &out) const override; -}; - - -class Tresor::Block_allocator_channel -{ - private: - - friend class Block_allocator; - - enum State { INACTIVE, SUBMITTED, PENDING, COMPLETE }; - - State _state { INACTIVE }; - Block_allocator_request _request { }; -}; - - -class Tresor::Block_allocator : public Module -{ - private: - - using Request = Block_allocator_request; - using Channel = Block_allocator_channel; - - uint64_t const _first_block; - uint64_t _nr_of_blks; - - enum { NR_OF_CHANNELS = 1 }; - - Channel _channels[NR_OF_CHANNELS] { }; - - void _execute_get(Channel &channel, - bool &progress); - - void _mark_req_failed(Channel &channel, - bool &progress, - char const *str); - - void _mark_req_successful(Channel &channel, - bool &progress); - - - /************ - ** Module ** - ************/ - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; - - public: - - Block_allocator(uint64_t first_block); - - uint64_t first_block() const { return _first_block; } - - uint64_t nr_of_blks() const { return _nr_of_blks; } - - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &req) override; - - void execute(bool &) override; - -}; - -#endif /* _TRESOR__BLOCK_ALLOCATOR_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/block_io.h b/repos/gems/src/lib/tresor/include/tresor/block_io.h index a3500fadec..1adf5601bc 100644 --- a/repos/gems/src/lib/tresor/include/tresor/block_io.h +++ b/repos/gems/src/lib/tresor/include/tresor/block_io.h @@ -16,8 +16,7 @@ /* tresor includes */ #include -#include -#include +#include namespace Tresor { @@ -28,82 +27,88 @@ namespace Tresor { class Tresor::Block_io_request : public Module_request { + friend class Block_io_channel; + public: - enum Type { - INVALID = 0, READ = 1, WRITE = 2, SYNC = 3, READ_CLIENT_DATA = 4, - WRITE_CLIENT_DATA = 5 }; + enum Type { READ, WRITE, SYNC, READ_CLIENT_DATA, WRITE_CLIENT_DATA }; private: - friend class Block_io; - friend class Block_io_channel; + Type const _type; + Request_offset const _client_req_offset; + Request_tag const _client_req_tag; + Key_id const _key_id; + Physical_block_address const _pba; + Virtual_block_address const _vba; + Block &_blk; + Hash &_hash; + bool &_success; - Type _type { INVALID }; - uint64_t _client_req_offset { 0 }; - uint64_t _client_req_tag { 0 }; - uint32_t _key_id { 0 }; - uint64_t _pba { 0 }; - uint64_t _vba { 0 }; - uint64_t _blk_count { 0 }; - addr_t _blk_ptr { 0 }; - addr_t _hash_ptr { 0 }; - bool _success { false }; + NONCOPYABLE(Block_io_request); public: - Block_io_request() { } + Block_io_request(Module_id, Module_channel_id, Type, Request_offset, Request_tag, Key_id, + Physical_block_address, Virtual_block_address, Block &, Hash &, bool &); - Block_io_request(uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - uint64_t client_req_offset, - uint64_t client_req_tag, - uint32_t key_id, - uint64_t pba, - uint64_t vba, - uint64_t blk_count, - void *blk_ptr, - void *hash_ptr); + static char const *type_to_string(Type); - Type type() const { return _type; } - - bool success() const { return _success; } - - static char const *type_to_string(Type type); - - char const *type_name() const { return type_to_string(_type); } - - - /******************** - ** Module_request ** - ********************/ - - void print(Output &out) const override; + void print(Output &out) const override { Genode::print(out, type_to_string(_type), " pba ", _pba); } }; -class Tresor::Block_io_channel +class Tresor::Block_io_channel : public Module_channel { private: - friend class Block_io; + using Request = Block_io_request; enum State { - INACTIVE, SUBMITTED, PENDING, IN_PROGRESS, COMPLETE, - ENCRYPT_CLIENT_DATA_PENDING, - ENCRYPT_CLIENT_DATA_IN_PROGRESS, - ENCRYPT_CLIENT_DATA_COMPLETE, - DECRYPT_CLIENT_DATA_PENDING, - DECRYPT_CLIENT_DATA_IN_PROGRESS, - DECRYPT_CLIENT_DATA_COMPLETE - }; + REQ_SUBMITTED, REQ_COMPLETE, CIPHERTEXT_BLK_OBTAINED, PLAINTEXT_BLK_SUPPLIED, REQ_GENERATED, + READ_OK, WRITE_OK, SYNC_OK, FILE_ERR }; - State _state { INACTIVE }; - Block_io_request _request { }; - Vfs::file_offset _nr_of_processed_bytes { 0 }; - size_t _nr_of_remaining_bytes { 0 }; - Block _blk_buf { }; - bool _generated_req_success { false }; + State _state { REQ_COMPLETE }; + Block _blk { }; + bool _generated_req_success { false }; + Block_io_request *_req_ptr { }; + Vfs::Env &_vfs_env; + Tresor::Path const _path; + Read_write_file _file { _state, _vfs_env, _path }; + + NONCOPYABLE(Block_io_channel); + + void _generated_req_completed(State_uint) override; + + template + void _generate_req(State_uint state, bool &progress, ARGS &&... args) + { + _state = REQ_GENERATED; + generate_req(state, progress, args..., _generated_req_success); + } + + void _request_submitted(Module_request &) override; + + bool _request_complete() override { return _state == REQ_COMPLETE; } + + void _read(bool &); + + void _write(bool &); + + void _read_client_data(bool &); + + void _write_client_data(bool &); + + void _sync(bool &); + + void _mark_req_failed(bool &, Error_string); + + void _mark_req_successful(bool &); + + public: + + Block_io_channel(Module_channel_id, Vfs::Env &, Xml_node const &); + + void execute(bool &); }; class Tresor::Block_io : public Module @@ -112,67 +117,48 @@ class Tresor::Block_io : public Module using Request = Block_io_request; using Channel = Block_io_channel; - using Read_result = Vfs::File_io_service::Read_result; - using Write_result = Vfs::File_io_service::Write_result; - using file_size = Vfs::file_size; - using file_offset = Vfs::file_offset; - enum { NR_OF_CHANNELS = 1 }; + Constructible _channels[1] { }; - String<32> const _path; - Vfs::Env &_vfs_env; - Vfs::Vfs_handle &_vfs_handle { vfs_open_rw(_vfs_env, _path) }; - Channel _channels[NR_OF_CHANNELS] { }; - - void _execute_read(Channel &channel, - bool &progress); - - void _execute_write(Channel &channel, - bool &progress); - - void _execute_read_client_data(Channel &channel, - bool &progress); - - void _execute_write_client_data(Channel &channel, - bool &progress); - - void _execute_sync(Channel &channel, - bool &progress); - - void _mark_req_failed(Channel &channel, - bool &progress, - char const *str); - - void _mark_req_successful(Channel &channel, - bool &progress); - - - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &req) override; - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; - - void execute(bool &) override; - - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_generated_request(Module_request &mod_req) override; - - void generated_request_complete(Module_request &req) override; + NONCOPYABLE(Block_io); public: - Block_io(Vfs::Env &vfs_env, - Xml_node const &xml_node); + struct Read : Request + { + Read(Module_id m, Module_channel_id c, Physical_block_address a, Block &b, bool &s) + : Request(m, c, Request::READ, 0, 0, 0, a, 0, b, *(Hash*)0, s) { } + }; + + struct Write : Request + { + Write(Module_id m, Module_channel_id c, Physical_block_address a, Block const &b, bool &s) + : Request(m, c, Request::WRITE, 0, 0, 0, a, 0, *const_cast(&b), *(Hash*)0, s) { } + }; + + struct Sync : Request + { + Sync(Module_id m, Module_channel_id c, bool &s) + : Request(m, c, Request::SYNC, 0, 0, 0, 0, 0, *(Block*)0, *(Hash*)0, s) { } + }; + + struct Write_client_data : Request + { + Write_client_data(Module_id m, Module_channel_id c, Physical_block_address p, Virtual_block_address v, + Key_id k, Request_tag t, Request_offset o, Block const &b, Hash &h, bool &s) + : Request(m, c, Request::WRITE_CLIENT_DATA, o, t, k, p, v, *const_cast(&b), h, s) { } + }; + + struct Read_client_data : Request + { + Read_client_data(Module_id m, Module_channel_id c, Physical_block_address p, Virtual_block_address v, + Key_id k, Request_tag t, Request_offset o, Block &b, bool &s) + : Request(m, c, Request::READ_CLIENT_DATA, o, t, k, p, v, b, *(Hash*)0, s) { } + }; + + Block_io(Vfs::Env &, Xml_node const &); + + void execute(bool &) override; }; #endif /* _TRESOR__BLOCK_IO_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/client_data.h b/repos/gems/src/lib/tresor/include/tresor/client_data.h index 5255d40100..f7f7a53d09 100644 --- a/repos/gems/src/lib/tresor/include/tresor/client_data.h +++ b/repos/gems/src/lib/tresor/include/tresor/client_data.h @@ -16,88 +16,53 @@ /* tresor includes */ #include -#include -namespace Tresor { +namespace Tresor { class Client_data_request; } - class Client_data_request; -} +namespace Vfs_tresor { class Client_data; } -namespace Vfs_tresor { - - class Wrapper; -} - -namespace Tresor_tester { - - class Main; -} +namespace Tresor_tester { class Client_data; } class Tresor::Client_data_request : public Module_request { + friend class ::Vfs_tresor::Client_data; + friend class ::Tresor_tester::Client_data; + public: - enum Type { INVALID, OBTAIN_PLAINTEXT_BLK, SUPPLY_PLAINTEXT_BLK }; + enum Type { OBTAIN_PLAINTEXT_BLK, SUPPLY_PLAINTEXT_BLK }; private: - friend class ::Vfs_tresor::Wrapper; - friend class ::Tresor_tester::Main; + Type const _type; + Request_offset const _req_off; + Request_tag const _req_tag; + Physical_block_address const _pba; + Virtual_block_address const _vba; + Block &_blk; + bool &_success; - Type _type { INVALID }; - uint64_t _client_req_offset { 0 }; - uint64_t _client_req_tag { 0 }; - uint64_t _pba { 0 }; - uint64_t _vba { 0 }; - addr_t _plaintext_blk_ptr { 0 }; - bool _success { false }; + NONCOPYABLE(Client_data_request); public: - Client_data_request() { } - - Type type() const { return _type; } - - - /***************************************************** - ** can be removed once the tresor translation is done ** - *****************************************************/ - - Client_data_request(Module_id src_module_id, - Module_request_id src_request_id, - Type type, - uint64_t client_req_offset, - uint64_t client_req_tag, - uint64_t pba, - uint64_t vba, - addr_t plaintext_blk_ptr) + Client_data_request(Module_id src_mod_id, Module_channel_id src_chan_id, Type type, + Request_offset req_off, Request_tag req_tag, Physical_block_address pba, + Virtual_block_address vba, Block &blk, bool &success) : - Module_request { src_module_id, src_request_id, CLIENT_DATA }, - _type { type }, - _client_req_offset { client_req_offset }, - _client_req_tag { client_req_tag }, - _pba { pba }, - _vba { vba }, - _plaintext_blk_ptr { plaintext_blk_ptr } + Module_request { src_mod_id, src_chan_id, CLIENT_DATA }, _type { type }, _req_off { req_off }, + _req_tag { req_tag }, _pba { pba }, _vba { vba }, _blk { blk }, _success { success } { } - bool success() const { return _success; } - static char const *type_to_string(Type type) { switch (type) { - case INVALID: return "invalid"; case OBTAIN_PLAINTEXT_BLK: return "obtain_plaintext_blk"; case SUPPLY_PLAINTEXT_BLK: return "supply_plaintext_blk"; } - return "?"; + ASSERT_NEVER_REACHED; } - - /******************** - ** Module_request ** - ********************/ - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } }; diff --git a/repos/gems/src/lib/tresor/include/tresor/construct_in_buf.h b/repos/gems/src/lib/tresor/include/tresor/construct_in_buf.h deleted file mode 100644 index 53102f54dc..0000000000 --- a/repos/gems/src/lib/tresor/include/tresor/construct_in_buf.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * \brief Size protected wrapper for the manual placement of objects - * \author Martin Stein - * \date 2023-03-23 - */ - -/* - * Copyright (C) 2023 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _TRESOR__CONSTRUCT_IN_BUF_H_ -#define _TRESOR__CONSTRUCT_IN_BUF_H_ - -/* base includes */ -#include - -namespace Tresor { - - using namespace Genode; - - template - static inline void construct_in_buf(void *buf_ptr, - size_t buf_size, - ARGS &&... args) - { - if (sizeof(T) > buf_size) { - class Buffer_too_small { }; - throw Buffer_too_small { }; - } - construct_at(buf_ptr, args...); - } -} - -#endif /* _TRESOR__CONSTRUCT_IN_BUF_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/crypto.h b/repos/gems/src/lib/tresor/include/tresor/crypto.h index be98c9f289..0098ab9083 100644 --- a/repos/gems/src/lib/tresor/include/tresor/crypto.h +++ b/repos/gems/src/lib/tresor/include/tresor/crypto.h @@ -16,8 +16,7 @@ /* tresor includes */ #include -#include -#include +#include namespace Tresor { @@ -28,97 +27,107 @@ namespace Tresor { class Tresor::Crypto_request : public Module_request { + friend class Crypto_channel; + public: - enum Type { - INVALID = 0, ADD_KEY = 1, REMOVE_KEY = 2, DECRYPT = 3, ENCRYPT = 4, - DECRYPT_CLIENT_DATA = 5, ENCRYPT_CLIENT_DATA = 6 }; + enum Type { ADD_KEY, REMOVE_KEY, DECRYPT, ENCRYPT, DECRYPT_CLIENT_DATA, ENCRYPT_CLIENT_DATA }; private: - friend class Crypto; - friend class Crypto_channel; + Type const _type; + Request_offset const _client_req_offset; + Request_tag const _client_req_tag; + Physical_block_address const _pba; + Virtual_block_address const _vba; + Key_id const _key_id; + Key_value const &_key_plaintext; + Block &_blk; + bool &_success; - Type _type { INVALID }; - uint64_t _client_req_offset { 0 }; - uint64_t _client_req_tag { 0 }; - uint64_t _pba { 0 }; - uint64_t _vba { 0 }; - uint32_t _key_id { 0 }; - addr_t _key_plaintext_ptr { 0 }; - addr_t _plaintext_blk_ptr { 0 }; - addr_t _ciphertext_blk_ptr { 0 }; - bool _success { false }; + NONCOPYABLE(Crypto_request); public: - Crypto_request() { } + Crypto_request(Module_id, Module_channel_id, Type, Request_offset, Request_tag, Key_id, + Key_value const &, Physical_block_address, Virtual_block_address, Block &, bool &); - Type type() const { return _type; } + static const char *type_to_string(Type); - Crypto_request(uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - uint64_t client_req_offset, - uint64_t client_req_tag, - uint32_t key_id, - void *key_plaintext_ptr, - uint64_t pba, - uint64_t vba, - void *plaintext_blk_ptr, - void *ciphertext_blk_ptr); - - bool success() const { return _success; } - - static const char *type_to_string(Type type); - - - /******************** - ** Module_request ** - ********************/ - - void print(Output &out) const override - { - Genode::print(out, type_to_string(_type)); - switch (_type) { - case ADD_KEY: - case REMOVE_KEY: - Genode::print(out, " ", _key_id); - break; - case DECRYPT: - case ENCRYPT: - case DECRYPT_CLIENT_DATA: - case ENCRYPT_CLIENT_DATA: - Genode::print(out, " pba ", _pba); - break; - default: - break; - } - } + void print(Output &) const override; }; -class Tresor::Crypto_channel +class Tresor::Crypto_channel : public Module_channel { private: - friend class Crypto; + using Request = Crypto_request; enum State { - INACTIVE, SUBMITTED, COMPLETE, OBTAIN_PLAINTEXT_BLK_PENDING, - OBTAIN_PLAINTEXT_BLK_IN_PROGRESS, OBTAIN_PLAINTEXT_BLK_COMPLETE, - SUPPLY_PLAINTEXT_BLK_PENDING, SUPPLY_PLAINTEXT_BLK_IN_PROGRESS, - SUPPLY_PLAINTEXT_BLK_COMPLETE, OP_WRITTEN_TO_VFS_HANDLE, - QUEUE_READ_SUCCEEDED }; + REQ_SUBMITTED, REQ_COMPLETE, PLAINTEXT_BLK_OBTAINED, PLAINTEXT_BLK_SUPPLIED, REQ_GENERATED, + READ_OK, WRITE_OK, FILE_ERR }; - State _state { INACTIVE }; - Crypto_request _request { }; - bool _generated_req_success { false }; - Vfs::Vfs_handle *_vfs_handle { nullptr }; - char _blk_buf[BLOCK_SIZE] { 0 }; + struct Key_directory + { + Crypto_channel &chan; + Key_id key_id; + Read_write_file encrypt_file { chan._state, chan._vfs_env, { chan._path, "/keys/", key_id, "/encrypt" } }; + Read_write_file decrypt_file { chan._state, chan._vfs_env, { chan._path, "/keys/", key_id, "/decrypt" } }; + + NONCOPYABLE(Key_directory); + + Key_directory(Crypto_channel &chan, Key_id key_id) : chan { chan }, key_id { key_id } { } + }; + + Vfs::Env &_vfs_env; + Tresor::Path const _path; + char _add_key_buf[sizeof(Key_id) + KEY_SIZE] { }; + Write_only_file _add_key_file { _state, _vfs_env, { _path, "/add_key" } }; + Write_only_file _remove_key_file { _state, _vfs_env, { _path, "/remove_key" } }; + Constructible _key_dirs[2] { }; + State _state { REQ_COMPLETE }; + bool _generated_req_success { false }; + Block _blk { }; + Request *_req_ptr { }; + + NONCOPYABLE(Crypto_channel); + + void _generated_req_completed(State_uint) override; + + void _request_submitted(Module_request &) override; + + bool _request_complete() override { return _state == REQ_COMPLETE; } + + template + void _generate_req(State_uint state, bool &progress, ARGS &&... args) + { + _state = REQ_GENERATED; + generate_req(state, progress, args..., _generated_req_success); + } + + void _add_key(bool &); + + void _remove_key(bool &); + + void _decrypt(bool &); + + void _encrypt(bool &); + + void _encrypt_client_data(bool &); + + void _decrypt_client_data(bool &); + + void _mark_req_failed(bool &, char const *); + + void _mark_req_successful(bool &); + + Constructible &_key_dir(Key_id key_id); public: - Crypto_request const &request() const { return _request; } + Crypto_channel(Module_channel_id, Vfs::Env &, Xml_node const &); + + void execute(bool &); }; class Tresor::Crypto : public Module @@ -127,79 +136,40 @@ class Tresor::Crypto : public Module using Request = Crypto_request; using Channel = Crypto_channel; - using Write_result = Vfs::File_io_service::Write_result; - using Read_result = Vfs::File_io_service::Read_result; - enum { NR_OF_CHANNELS = 4 }; + Constructible _channels[1] { }; - struct Key_directory - { - Vfs::Vfs_handle *encrypt_handle { nullptr }; - Vfs::Vfs_handle *decrypt_handle { nullptr }; - uint32_t key_id { 0 }; - }; - - Vfs::Env &_vfs_env; - String<32> const _path; - Vfs::Vfs_handle &_add_key_handle; - Vfs::Vfs_handle &_remove_key_handle; - Channel _channels[NR_OF_CHANNELS] { }; - Key_directory _key_dirs[2] { }; - - Key_directory &_lookup_key_dir(uint32_t key_id); - - void _execute_add_key(Channel &channel, - bool &progress); - - void _execute_remove_key(Channel &channel, - bool &progress); - - void _execute_decrypt(Channel &channel, - bool &progress); - - void _execute_encrypt(Channel &channel, - bool &progress); - - void _execute_encrypt_client_data(Channel &channel, - bool &progress); - - void _execute_decrypt_client_data(Channel &channel, - bool &progress); - - void _mark_req_failed(Channel &channel, - bool &progress, - char const *str); - - void _mark_req_successful(Channel &channel, - bool &progress); - - - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &req) override; - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; - - void execute(bool &) override; - - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_generated_request(Module_request &mod_req) override; - - void generated_request_complete(Module_request &req) override; + NONCOPYABLE(Crypto); public: - Crypto(Vfs::Env &vfs_env, - Xml_node const &xml_node); + struct Add_key : Request + { + Add_key(Module_id src_mod, Module_channel_id src_chan, Key &key, bool &succ) + : Request(src_mod, src_chan, Request::ADD_KEY, 0, 0, key.id, key.value, 0, 0, *(Block*)0, succ) { } + }; + + struct Remove_key : Request + { + Remove_key(Module_id src_mod, Module_channel_id src_chan, Key_id key, bool &succ) + : Request(src_mod, src_chan, Request::REMOVE_KEY, 0, 0, key, *(Key_value*)0, 0, 0, *(Block*)0, succ) { } + }; + + struct Decrypt : Request + { + Decrypt(Module_id src_mod, Module_channel_id src_chan, Key_id key, Physical_block_address pba, Block &blk, bool &succ) + : Request(src_mod, src_chan, Request::DECRYPT, 0, 0, key, *(Key_value*)0, pba, 0, blk, succ) { } + }; + + struct Encrypt : Request + { + Encrypt(Module_id src_mod, Module_channel_id src_chan, Key_id key, Physical_block_address pba, Block &blk, bool &succ) + : Request(src_mod, src_chan, Request::ENCRYPT, 0, 0, key, *(Key_value*)0, pba, 0, blk, succ) { } + }; + + Crypto(Vfs::Env &, Xml_node const &); + + void execute(bool &) override; }; #endif /* _TRESOR__CRYPTO_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/file.h b/repos/gems/src/lib/tresor/include/tresor/file.h new file mode 100644 index 0000000000..188865e87b --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/file.h @@ -0,0 +1,232 @@ +/* + * \brief Tresor-local utilities for accessing VFS files + * \author Martin Stein + * \date 2020-10-29 + */ + +/* + * Copyright (C) 2023 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _TRESOR__FILE_H_ +#define _TRESOR__FILE_H_ + +/* base includes */ +#include + +/* os includes */ +#include +#include + +/* tresor includes */ +#include + +namespace Tresor { + + using namespace Genode; + + using Path = String<128>; + + template class File; + template class Read_write_file; + template class Write_only_file; +} + +template +class Tresor::File +{ + private: + + using Read_result = Vfs::File_io_service::Read_result; + using Write_result = Vfs::File_io_service::Write_result; + using Sync_result = Vfs::File_io_service::Sync_result; + using Open_result = Vfs::Directory_service::Open_result; + + enum State { IDLE, SYNC_QUEUED, READ_QUEUED, READ_INITIALIZED, WRITE_INITIALIZED, WRITE_OFFSET_APPLIED }; + + Vfs::Env &_env; + HOST_STATE &_host_state; + State _state { IDLE }; + Vfs::Vfs_handle &_handle; + Vfs::file_size _num_processed_bytes { 0 }; + + Vfs::Vfs_handle &_open(Tresor::Path path, Vfs::Directory_service::Open_mode mode) + { + Vfs::Vfs_handle *handle { nullptr }; + ASSERT(_env.root_dir().open(path.string(), mode, &handle, _env.alloc()) == Open_result::OPEN_OK); + return *handle; + } + + public: + + File(HOST_STATE &host_state, Vfs::Vfs_handle &handle) : _host_state { host_state }, _handle { handle } { } + + File(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path path, Vfs::Directory_service::Open_mode mode) + : _env { env }, _host_state { host_state }, _handle { _open(path, mode) } { } + + ~File() + { + ASSERT(_state == IDLE); + _env.root_dir().close(&_handle); + } + + void read(HOST_STATE succeeded, HOST_STATE failed, Vfs::file_offset off, Byte_range_ptr dst, bool &progress) + { + switch (_state) { + case IDLE: + + _num_processed_bytes = 0; + _state = READ_INITIALIZED; + progress = true; + break; + + case READ_INITIALIZED: + + _handle.seek(off + _num_processed_bytes); + if (!_handle.fs().queue_read(&_handle, dst.num_bytes - _num_processed_bytes)) + break; + + _state = READ_QUEUED; + progress = true; + break; + + case READ_QUEUED: + { + size_t num_read_bytes { 0 }; + Byte_range_ptr curr_dst { dst.start + _num_processed_bytes, dst.num_bytes - _num_processed_bytes }; + switch (_handle.fs().complete_read(&_handle, curr_dst, num_read_bytes)) { + case Read_result::READ_QUEUED: + case Read_result::READ_ERR_WOULD_BLOCK: break; + case Read_result::READ_OK: + + _num_processed_bytes += num_read_bytes; + if (_num_processed_bytes < dst.num_bytes) { + _state = READ_INITIALIZED; + progress = true; + break; + } + ASSERT(_num_processed_bytes == dst.num_bytes); + _state = IDLE; + _host_state = succeeded; + progress = true; + break; + + default: + + error("read failed"); + _host_state = failed; + _state = IDLE; + progress = true; + break; + } + break; + } + default: ASSERT_NEVER_REACHED; + } + } + + void write(HOST_STATE succeeded, HOST_STATE failed, Vfs::file_offset off, Const_byte_range_ptr src, bool &progress) + { + switch (_state) { + case IDLE: + + _num_processed_bytes = 0; + _state = WRITE_INITIALIZED; + progress = true; + break; + + case WRITE_INITIALIZED: + + _handle.seek(off + _num_processed_bytes); + _state = WRITE_OFFSET_APPLIED; + progress = true; + break; + + case WRITE_OFFSET_APPLIED: + { + size_t num_written_bytes { 0 }; + Const_byte_range_ptr curr_src { src.start + _num_processed_bytes, src.num_bytes - _num_processed_bytes }; + switch (_handle.fs().write(&_handle, curr_src, num_written_bytes)) { + case Write_result::WRITE_ERR_WOULD_BLOCK: break; + case Write_result::WRITE_OK: + + _num_processed_bytes += num_written_bytes; + if (_num_processed_bytes < src.num_bytes) { + _state = WRITE_INITIALIZED; + progress = true; + break; + } + ASSERT(_num_processed_bytes == src.num_bytes); + _state = IDLE; + _host_state = succeeded; + progress = true; + break; + + default: + + error("write failed"); + _host_state = failed; + _state = IDLE; + progress = true; + break; + } + break; + } + default: ASSERT_NEVER_REACHED; + } + } + + void sync(HOST_STATE succeeded, HOST_STATE failed, bool &progress) + { + switch (_state) { + case IDLE: + + if (!_handle.fs().queue_sync(&_handle)) + break; + + _state = SYNC_QUEUED; + progress = true; + break; + + case SYNC_QUEUED: + + switch (_handle.fs().complete_sync(&_handle)) { + case Sync_result::SYNC_QUEUED: break; + case Sync_result::SYNC_OK: + + _state = IDLE; + _host_state = succeeded; + progress = true; + break; + + default: + + error("sync failed"); + _host_state = failed; + _state = IDLE; + progress = true; + break; + } + default: break; + } + } +}; + +template +struct Tresor::Read_write_file : public File +{ + Read_write_file(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path path) + : File { host_state, env, path, Vfs::Directory_service::OPEN_MODE_RDWR } { } +}; + +template +struct Tresor::Write_only_file : public File +{ + Write_only_file(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path path) + : File { host_state, env, path, Vfs::Directory_service::OPEN_MODE_WRONLY } { } +}; + +#endif /* _TRESOR__FILE_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/free_tree.h b/repos/gems/src/lib/tresor/include/tresor/free_tree.h index bbea27314a..c2618e86be 100644 --- a/repos/gems/src/lib/tresor/include/tresor/free_tree.h +++ b/repos/gems/src/lib/tresor/include/tresor/free_tree.h @@ -16,8 +16,6 @@ /* tresor includes */ #include -#include -#include namespace Tresor { @@ -28,470 +26,150 @@ namespace Tresor { class Tresor::Free_tree_request : public Module_request { + friend class Free_tree_channel; + public: - enum Type { - INVALID = 0, ALLOC_FOR_NON_RKG = 1, ALLOC_FOR_RKG_CURR_GEN_BLKS = 2, - ALLOC_FOR_RKG_OLD_GEN_BLKS = 3 }; + enum Type { ALLOC_FOR_NON_RKG, ALLOC_FOR_RKG_CURR_GEN_BLKS, ALLOC_FOR_RKG_OLD_GEN_BLKS, EXTENSION_STEP }; private: - friend class Free_tree; - friend class Free_tree_channel; + Type const _type; + Tree_root &_ft; + Tree_root &_mt; + Generation const _curr_gen; + Generation const _free_gen; + Number_of_blocks const _num_required_pbas; + Tree_walk_pbas &_new_blocks; + Type_1_node_walk const &_old_blocks; + Tree_level_index const _max_lvl; + Virtual_block_address const _vba; + Tree_degree const _vbd_degree; + Virtual_block_address const _vbd_max_vba; + bool const _rekeying; + Key_id const _prev_key_id; + Key_id const _curr_key_id; + Virtual_block_address const _rekeying_vba; + bool &_success; + Snapshots const &_snapshots; + Generation const _last_secured_gen; + Physical_block_address &_pba; + Number_of_blocks &_num_pbas; - Type _type { INVALID }; - addr_t _ft_root_pba_ptr { 0 }; - addr_t _ft_root_gen_ptr { 0 }; - addr_t _ft_root_hash_ptr { 0 }; - uint64_t _ft_max_level { 0 }; - uint64_t _ft_degree { 0 }; - uint64_t _ft_leaves { 0 }; - addr_t _mt_root_pba_ptr { 0 }; - addr_t _mt_root_gen_ptr { 0 }; - addr_t _mt_root_hash_ptr { 0 }; - uint64_t _mt_max_level { 0 }; - uint64_t _mt_degree { 0 }; - uint64_t _mt_leaves { 0 }; - uint64_t _current_gen { 0 }; - uint64_t _free_gen { 0 }; - uint64_t _requested_blocks { 0 }; - addr_t _new_blocks_ptr { 0 }; - addr_t _old_blocks_ptr { 0 }; - uint64_t _max_level { 0 }; - uint64_t _vba { INVALID_VBA }; - uint64_t _vbd_degree { 0 }; - uint64_t _vbd_highest_vba { 0 }; - bool _rekeying { 0 }; - uint32_t _previous_key_id { 0 }; - uint32_t _current_key_id { 0 }; - uint64_t _rekeying_vba { 0 }; - bool _success { false }; - addr_t _snapshots_ptr { 0 }; - Generation _last_secured_generation { INVALID_GENERATION }; + NONCOPYABLE(Free_tree_request); public: - Free_tree_request() { } + Free_tree_request(Module_id, Module_channel_id, Type, Tree_root &, Tree_root &, Snapshots const &, + Generation, Generation, Generation, Number_of_blocks, Tree_walk_pbas &, Type_1_node_walk const &, + Tree_level_index, Virtual_block_address, Tree_degree, Virtual_block_address, + bool, Key_id, Key_id, Virtual_block_address, Physical_block_address &, Number_of_blocks &, bool &); - Free_tree_request(uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - addr_t ft_root_pba_ptr, - addr_t ft_root_gen_ptr, - addr_t ft_root_hash_ptr, - uint64_t ft_max_level, - uint64_t ft_degree, - uint64_t ft_leaves, - addr_t mt_root_pba_ptr, - addr_t mt_root_gen_ptr, - addr_t mt_root_hash_ptr, - uint64_t mt_max_level, - uint64_t mt_degree, - uint64_t mt_leaves, - Snapshots const *snapshots, - Generation last_secured_generation, - uint64_t current_gen, - uint64_t free_gen, - uint64_t requested_blocks, - addr_t new_blocks_ptr, - addr_t old_blocks_ptr, - uint64_t max_level, - uint64_t vba, - uint64_t vbd_degree, - uint64_t vbd_highest_vba, - bool rekeying, - uint32_t previous_key_id, - uint32_t current_key_id, - uint64_t rekeying_vba); - - Type type() const { return _type; } - - bool success() const { return _success; } - - static char const *type_to_string(Type type); - - char const *type_name() const { return type_to_string(_type); } - - - /******************** - ** Module_request ** - ********************/ + static char const *type_to_string(Type); void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } }; -class Tresor::Free_tree_channel +class Tresor::Free_tree_channel : public Module_channel { private: - friend class Free_tree; - using Request = Free_tree_request; enum State { - INVALID, - SCAN, - SCAN_COMPLETE, - UPDATE, - UPDATE_COMPLETE, - COMPLETE, - NOT_ENOUGH_FREE_BLOCKS, - TREE_HASH_MISMATCH - }; + REQ_SUBMITTED, REQ_GENERATED, SEEK_DOWN, SEEK_LEFT_OR_UP, WRITE_BLK, READ_BLK_SUCCEEDED, + ALLOC_PBA_SUCCEEDED, WRITE_BLK_SUCCEEDED, REQ_COMPLETE }; - struct Type_1_info + Request *_req_ptr { nullptr }; + State _state { REQ_COMPLETE }; + Virtual_block_address _vba { }; + Tree_walk_pbas _old_pbas { }; + Tree_walk_pbas _new_pbas { }; + Tree_walk_generations _old_generations { }; + Number_of_leaves _num_leaves { 0 }; + Physical_block_address _alloc_pba { 0 }; + Tree_level_index _alloc_lvl { 0 }; + Number_of_blocks _num_pbas { 0 }; + Block _blk { }; + Tree_node_index _node_idx[TREE_MAX_NR_OF_LEVELS] { }; + bool _apply_allocation { false }; + Type_1_node_block _t1_blks[TREE_MAX_NR_OF_LEVELS] { }; + Type_2_node_block _t2_blk { }; + Tree_degree_log_2 _vbd_degree_log_2 { 0 }; + Tree_level_index _lvl { 0 }; + bool _generated_req_success { false }; + + NONCOPYABLE(Free_tree_channel); + + void _generated_req_completed(State_uint) override; + + template + void _generate_req(State_uint state, bool &progress, ARGS &&... args) { - enum State { - INVALID, AVAILABLE, READ, WRITE, COMPLETE }; - - State state { INVALID }; - Type_1_node node { }; - Tree_node_index index { INVALID_NODE_INDEX }; - bool volatil { false }; - }; - - struct Type_2_info - { - enum State { - INVALID, AVAILABLE, READ, WRITE, COMPLETE }; - - State state { INVALID }; - Type_2_node node { }; - Tree_node_index index { INVALID_NODE_INDEX }; - }; - - struct Local_cache_request - { - enum State { INVALID, PENDING, IN_PROGRESS, COMPLETE }; - enum Op { READ, WRITE, SYNC }; - - State state { INVALID }; - Op op { READ }; - bool success { false }; - uint64_t pba { 0 }; - uint64_t level { 0 }; - }; - - struct Local_meta_tree_request - { - enum State { INVALID, PENDING, IN_PROGRESS, COMPLETE }; - enum Op { READ, WRITE, SYNC }; - - State state { INVALID }; - Op op { READ }; - uint64_t pba { 0 }; - }; - - class Type_1_info_stack { - - private: - - enum { MIN = 1, MAX = TREE_MAX_DEGREE, }; - - Type_1_info _container[MAX + 1] { }; - uint64_t _top { MIN - 1 }; - - public: - - bool empty() const { return _top < MIN; } - - bool full() const { return _top >= MAX; } - - Type_1_info peek_top() const - { - if (empty()) { - class Exception_1 { }; - throw Exception_1 { }; - } - return _container[_top]; - } - - void reset() { _top = MIN - 1; } - - void pop() - { - if (empty()) { - class Exception_1 { }; - throw Exception_1 { }; - } - _top--; - } - - void push(Type_1_info val) - { - if (full()) { - class Exception_1 { }; - throw Exception_1 { }; - } - _top++; - _container[_top] = val; - } - - void update_top(Type_1_info val) - { - if (empty()) { - class Exception_1 { }; - throw Exception_1 { }; - } - _container[_top] = val; - } - }; - - class Type_2_info_stack { - - private: - - enum { MIN = 1, MAX = TREE_MAX_DEGREE, }; - - Type_2_info _container[MAX + 1] { }; - uint64_t _top { MIN - 1 }; - - public: - - bool empty() const { return _top < MIN; } - - bool full() const { return _top >= MAX; } - - Type_2_info peek_top() const - { - if (empty()) { - class Exception_1 { }; - throw Exception_1 { }; - } - return _container[_top]; - } - - void reset() { _top = MIN - 1; } - - void pop() - { - if (empty()) { - class Exception_1 { }; - throw Exception_1 { }; - } - _top--; - } - - void push(Type_2_info val) - { - if (full()) { - class Exception_1 { }; - throw Exception_1 { }; - } - _top++; - _container[_top] = val; - } - - void update_top(Type_2_info val) - { - if (empty()) { - class Exception_1 { }; - throw Exception_1 { }; - } - _container[_top] = val; - } - }; - - class Node_queue - { - private: - - enum { - FIRST_CONTAINER_IDX = 1, - MAX_CONTAINER_IDX = TREE_MAX_DEGREE, - MAX_USED_VALUE = TREE_MAX_DEGREE - 1, - FIRST_USED_VALUE = 0, - }; - - uint64_t _head { FIRST_CONTAINER_IDX }; - uint64_t _tail { FIRST_CONTAINER_IDX }; - Type_2_info _container[MAX_CONTAINER_IDX + 1] { }; - uint64_t _used { FIRST_USED_VALUE }; - - public: - - void enqueue(Type_2_info const &node) - { - _container[_tail] = node; - if (_tail < MAX_CONTAINER_IDX) - _tail++; - else - _tail = FIRST_CONTAINER_IDX; - - _used++; - } - - void dequeue_head() - { - if (_head < MAX_CONTAINER_IDX) - _head++; - else - _head = FIRST_CONTAINER_IDX; - - _used--; - } - - Type_2_info const &head() const { return _container[_head]; } - - bool empty() const { return _used == FIRST_USED_VALUE; }; - - bool full() const { return _used == MAX_USED_VALUE; }; - }; - - State _state { INVALID }; - Request _request { }; - uint64_t _needed_blocks { 0 }; - uint64_t _found_blocks { 0 }; - uint64_t _exchanged_blocks { 0 }; - Local_meta_tree_request _meta_tree_request { }; - Local_cache_request _cache_request { }; - Block _cache_block_data { }; - Type_1_info_stack _level_n_stacks[TREE_MAX_NR_OF_LEVELS] { }; - Type_2_info_stack _level_0_stack { }; - Type_1_node_block _level_n_nodes[TREE_MAX_NR_OF_LEVELS] { }; - Type_1_node_block _level_n_node { }; - Type_2_node_block _level_0_node { }; - Node_queue _type_2_leafs { }; - uint64_t _vbd_degree_log_2 { 0 }; - bool _wb_data_prim_success { false }; - - Type_1_node _root_node() const - { - Type_1_node node { }; - node.pba = *(Physical_block_address *)_request._ft_root_pba_ptr; - node.gen = *(Generation *)_request._ft_root_gen_ptr; - memcpy(&node.hash, (void *)_request._ft_root_hash_ptr, HASH_SIZE); - return node; + _state = REQ_GENERATED; + generate_req(state, progress, args..., _generated_req_success); } + + void _request_submitted(Module_request &) override; + + bool _request_complete() override { return _state == REQ_COMPLETE; } + + void _mark_req_failed(bool &, char const *); + + bool _can_alloc_pba_of(Type_2_node &); + + void _alloc_pba_of(Type_2_node &); + + void _traverse_curr_node(bool &); + + void _mark_req_successful(bool &); + + void _start_tree_traversal(bool &); + + void _advance_to_next_node(); + + void _add_new_branch_at(Tree_level_index, Tree_node_index); + + void _add_new_root_lvl(); + + void _generate_write_blk_req(bool &); + + void _extension_step(bool &); + + void _alloc_pbas(bool &); + + public: + + Free_tree_channel(Module_channel_id id) : Module_channel { FREE_TREE, id } { } + + void execute(bool &); }; class Tresor::Free_tree : public Module { private: - using Request = Free_tree_request; using Channel = Free_tree_channel; - using Local_cache_request = Channel::Local_cache_request; - using Local_meta_tree_request = Channel::Local_meta_tree_request; - using Type_1_info = Channel::Type_1_info; - using Type_2_info = Channel::Type_2_info; - using Type_1_info_stack = Channel::Type_1_info_stack; - using Type_2_info_stack = Channel::Type_2_info_stack; - using Node_queue = Channel::Node_queue; + using Request = Free_tree_request; - enum { FIRST_LVL_N_STACKS_IDX = 1 }; - enum { MAX_LVL_N_STACKS_IDX = TREE_MAX_LEVEL }; - enum { FIRST_LVL_N_NODES_IDX = 1 }; - enum { NR_OF_CHANNELS = 1 }; + Constructible _channels[1] { }; - Channel _channels[NR_OF_CHANNELS] { }; - - void _reset_block_state(Channel &chan); - - static Local_meta_tree_request - _new_meta_tree_request(Physical_block_address pba); - - void _update_upper_n_stack(Type_1_info const &t, - Generation gen, - Block const &block_data, - Type_1_node_block &entries); - - void _mark_req_failed(Channel &chan, - bool &progress, - char const *str); - - void _mark_req_successful(Channel &chan, - bool &progress); - - void - _exchange_type_2_leaves(Generation free_gen, - Tree_level_index max_level, - Type_1_node_walk const &old_blocks, - Tree_walk_pbas &new_blocks, - Virtual_block_address vba, - Tree_degree_log_2 vbd_degree_log_2, - Request::Type req_type, - Type_2_info_stack &stack, - Type_2_node_block &entries, - Number_of_blocks &exchanged, - bool &handled, - Virtual_block_address vbd_highest_vba, - bool rekeying, - Key_id previous_key_id, - Key_id current_key_id, - Virtual_block_address rekeying_vba); - - void _populate_lower_n_stack(Type_1_info_stack &stack, - Type_1_node_block &entries, - Block const &block_data, - Generation current_gen); - - bool - _check_type_2_leaf_usable(Snapshots const &snapshots, - Generation last_secured_gen, - Type_2_node const &node, - bool rekeying, - Key_id previous_key_id, - Virtual_block_address rekeying_vba); - - void _populate_level_0_stack(Type_2_info_stack &stack, - Type_2_node_block &entries, - Block const &block_data, - Snapshots const &active_snaps, - Generation secured_gen, - bool rekeying, - Key_id previous_key_id, - Virtual_block_address rekeying_vba); - - void _execute_update(Channel &chan, - Snapshots const &active_snaps, - Generation last_secured_gen, - bool &progress); - - bool _node_volatile(Type_1_node const &node, - uint64_t gen); - - void _execute_scan(Channel &chan, - Snapshots const &active_snaps, - Generation last_secured_gen, - bool &progress); - - void _execute(Channel &chan, - Snapshots const &active_snaps, - Generation last_secured_gen, - bool &progress); - - void _check_type_2_stack(Type_2_info_stack &stack, - Type_1_info_stack &stack_next, - Node_queue &leaves, - Number_of_blocks &found); - - Local_cache_request _new_cache_request(Physical_block_address pba, - Local_cache_request::Op op, - Tree_level_index lvl); - - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &req) override; - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; + NONCOPYABLE(Free_tree); void execute(bool &) override; - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; + public: - void _drop_generated_request(Module_request &mod_req) override; + struct Extension_step : Request + { + Extension_step(Module_id mod_id, Module_channel_id chan_id, Generation curr_gen, Tree_root &ft, Tree_root &mt, + Physical_block_address &pba, Number_of_blocks &num_pbas, bool &succ) + : Request(mod_id, chan_id, Request::EXTENSION_STEP, ft, mt, *(Snapshots *)0, 0, curr_gen, 0, 0, *(Tree_walk_pbas*)0, + *(Type_1_node_walk*)0, 0, 0, 0, 0, 0, 0, 0, 0, pba, num_pbas, succ) { } + }; - void generated_request_complete(Module_request &req) override; + Free_tree(); }; #endif /* _TRESOR__FREE_TREE_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/ft_check.h b/repos/gems/src/lib/tresor/include/tresor/ft_check.h index 5de5f26c70..a8168311e7 100644 --- a/repos/gems/src/lib/tresor/include/tresor/ft_check.h +++ b/repos/gems/src/lib/tresor/include/tresor/ft_check.h @@ -14,12 +14,8 @@ #ifndef _TRESOR__FT_CHECK_H_ #define _TRESOR__FT_CHECK_H_ -/* base includes */ -#include - /* tresor includes */ #include -#include namespace Tresor { @@ -31,107 +27,66 @@ namespace Tresor { class Tresor::Ft_check_request : public Module_request { - public: - - enum Type { INVALID = 0, CHECK = 1, }; + friend class Ft_check_channel; private: - friend class Ft_check; - friend class Ft_check_channel; + Tree_root const &_ft; + bool &_success; - Type _type { INVALID }; - Tree_level_index _max_lvl { 0 }; - Tree_node_index _max_child_idx { 0 }; - Number_of_leaves _nr_of_leaves { 0 }; - Type_1_node _root { }; - bool _success { false }; + NONCOPYABLE(Ft_check_request); public: - Ft_check_request() { } + Ft_check_request(Module_id, Module_channel_id, Tree_root const &, bool &); - Ft_check_request(uint64_t src_module_id, - uint64_t src_request_id, - Type type, - Tree_level_index max_lvl, - Tree_node_index max_child_idx, - Number_of_leaves nr_of_leaves, - Type_1_node root); - - Type type() const { return _type; } - - bool success() const { return _success; } - - static char const *type_to_string(Type type); - - - /******************** - ** Module_request ** - ********************/ - - void print(Output &out) const override - { - Genode::print(out, type_to_string(_type), " root ", _root); - } + void print(Output &out) const override { Genode::print(out, "check ", _ft); } }; -class Tresor::Ft_check_channel +class Tresor::Ft_check_channel : public Module_channel { private: - friend class Ft_check; - using Request = Ft_check_request; - enum Child_state { - READ_BLOCK = 0, CHECK_HASH = 1, DONE = 2 }; + enum State : State_uint { REQ_SUBMITTED, REQ_IN_PROGRESS, REQ_COMPLETE, REQ_GENERATED, READ_BLK_SUCCEEDED }; - struct Type_1_level + State _state { REQ_COMPLETE }; + Type_1_node_block_walk _t1_blks { }; + Type_2_node_block _t2_blk { }; + bool _check_node[TREE_MAX_NR_OF_LEVELS + 1][NUM_NODES_PER_BLK] { }; + Number_of_leaves _num_remaining_leaves { 0 }; + Request *_req_ptr { }; + Block _blk { }; + bool _generated_req_success { false }; + + NONCOPYABLE(Ft_check_channel); + + void _generated_req_completed(State_uint) override; + + void _request_submitted(Module_request &) override; + + bool _request_complete() override { return _state == REQ_COMPLETE; } + + void _mark_req_failed(bool &, Error_string); + + void _mark_req_successful(bool &); + + bool _execute_node(Tree_level_index, Tree_node_index, bool &); + + template + void _generate_req(State_uint state, bool &progress, ARGS &&... args) { - Child_state children_state[NR_OF_T1_NODES_PER_BLK] { }; - Type_1_node_block children { }; + _state = REQ_GENERATED; + generate_req(state, progress, args..., _generated_req_success); + } - Type_1_level() - { - for (Child_state &state : children_state) - state = DONE; - } - }; + public: - struct Type_2_level - { - Child_state children_state[NR_OF_T1_NODES_PER_BLK] { }; - Type_2_node_block children { }; + Ft_check_channel(Module_channel_id id) : Module_channel { FT_CHECK, id } { } - Type_2_level() - { - for (Child_state &state : children_state) - state = DONE; - } - }; - - enum Primitive_tag { INVALID, BLOCK_IO }; - - struct Generated_primitive - { - bool success { false }; - Primitive_tag tag { INVALID }; - Physical_block_address blk_nr { 0 }; - bool dropped { false }; - - bool valid() const { return tag != INVALID; } - }; - - Generated_primitive _gen_prim { }; - Tree_level_index _lvl_to_read { 0 }; - Child_state _root_state { DONE }; - Type_2_level _t2_lvl { }; - Type_1_level _t1_lvls[TREE_MAX_LEVEL] { }; - Number_of_leaves _nr_of_leaves { 0 }; - Request _request { }; - Block _encoded_blk { }; + void execute(bool &); }; @@ -139,74 +94,17 @@ class Tresor::Ft_check : public Module { private: - using Request = Ft_check_request; using Channel = Ft_check_channel; - using Child_state = Ft_check_channel::Child_state; - using Type_1_level = Ft_check_channel::Type_1_level; - using Type_2_level = Ft_check_channel::Type_2_level; - enum { NR_OF_CHANNELS = 1 }; - - Channel _channels[NR_OF_CHANNELS] { }; - - void _execute_inner_t2_child(Channel &chan, - Tree_level_index lvl, - Tree_node_index child_idx, - bool &progress); - - void _execute_check(Channel &channel, - bool &progress); - - void _mark_req_failed(Channel &channel, - bool &progress, - char const *str); - - void _mark_req_successful(Channel &channel, - bool &progress); - - void _execute_inner_t1_child(Channel &chan, - Type_1_node const &child, - Type_1_level &child_lvl, - Child_state &child_state, - Tree_level_index lvl, - Tree_node_index child_idx, - bool &progress); - - - void _execute_leaf_child(Channel &chan, - Tree_node_index child_idx, - bool &progress); - - - /************ - ** Module ** - ************/ - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; - - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_generated_request(Module_request &mod_req) override; - - void generated_request_complete(Module_request &req) override; + Constructible _channels[1] { }; + NONCOPYABLE(Ft_check); public: - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &req) override; + Ft_check(); void execute(bool &) override; - }; #endif /* _TRESOR__FT_CHECK_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/ft_initializer.h b/repos/gems/src/lib/tresor/include/tresor/ft_initializer.h index 2fb457f65c..6b07ff3a2e 100644 --- a/repos/gems/src/lib/tresor/include/tresor/ft_initializer.h +++ b/repos/gems/src/lib/tresor/include/tresor/ft_initializer.h @@ -1,5 +1,6 @@ /* * \brief Module for initializing the FT + * \author Martin Stein * \author Josef Soentgen * \date 2023-03-09 */ @@ -14,11 +15,8 @@ #ifndef _TRESOR__FT_INITIALIZER_H_ #define _TRESOR__FT_INITIALIZER_H_ -/* base includes */ -#include - /* tresor includes */ -#include +#include namespace Tresor { @@ -30,146 +28,67 @@ namespace Tresor { class Tresor::Ft_initializer_request : public Module_request { - public: - - enum Type { INVALID = 0, INIT = 1, }; + friend class Ft_initializer_channel; private: - friend class Ft_initializer; - friend class Ft_initializer_channel; - - Type _type { INVALID }; - uint8_t _root_node[sizeof(Type_1_node)] { 0 }; - uint64_t _max_level_idx { 0 }; - uint64_t _max_child_idx { 0 }; - uint64_t _nr_of_leaves { 0 }; - bool _success { false }; + Tree_root &_ft; + Pba_allocator &_pba_alloc; + bool &_success; + NONCOPYABLE(Ft_initializer_request); public: - Ft_initializer_request() { } + Ft_initializer_request(Module_id, Module_channel_id, Tree_root &, Pba_allocator &, bool &); - Ft_initializer_request(Module_id src_module_id, - Module_request_id src_request_id); - - static void create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - uint64_t max_level_idx, - uint64_t max_child_idx, - uint64_t nr_of_leaves); - - void *root_node() { return _root_node; } - - Type type() const { return _type; } - - bool success() const { return _success; } - - static char const *type_to_string(Type type); - - - /******************** - ** Module_request ** - ********************/ - - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } + void print(Output &out) const override { Genode::print(out, "init"); } }; -class Tresor::Ft_initializer_channel +class Tresor::Ft_initializer_channel : public Module_channel { private: - friend class Ft_initializer; + using Request = Ft_initializer_request; - enum State { - INACTIVE, SUBMITTED, PENDING, IN_PROGRESS, COMPLETE, - BLOCK_ALLOC_PENDING, - BLOCK_ALLOC_IN_PROGRESS, - BLOCK_ALLOC_COMPLETE, - BLOCK_IO_PENDING, - BLOCK_IO_IN_PROGRESS, - BLOCK_IO_COMPLETE, - }; + enum State { REQ_GENERATED, REQ_SUBMITTED, EXECUTE_NODES, REQ_COMPLETE }; - enum Child_state { DONE, INIT_BLOCK, INIT_NODE, WRITE_BLOCK, }; + enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITE_BLK }; - struct Type_1_level - { - Type_1_node_block children { }; - Child_state children_state[NR_OF_T1_NODES_PER_BLK] { DONE }; - }; + State _state { REQ_COMPLETE }; + Request *_req_ptr { }; + Type_2_node_block _t2_blk { }; + Type_1_node_block_walk _t1_blks { }; + Node_state _t1_node_states[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { }; + Node_state _t2_node_states[NUM_NODES_PER_BLK] { }; + Number_of_leaves _num_remaining_leaves { 0 }; + bool _generated_req_success { false }; + Block _blk { }; - struct Type_2_level - { - Type_2_node_block children { }; - Child_state children_state[NR_OF_T2_NODES_PER_BLK] { DONE }; - }; + NONCOPYABLE(Ft_initializer_channel); - struct Root_node - { - Type_1_node node { }; - Child_state state { DONE }; - }; + void _reset_level(Tree_level_index, Node_state); - State _state { INACTIVE }; - Ft_initializer_request _request { }; - Root_node _root_node { }; - Type_1_level _t1_levels[TREE_MAX_LEVEL] { }; - Type_2_level _t2_level { }; - uint64_t _level_to_write { 0 }; - uint64_t _blk_nr { 0 }; - uint64_t _child_pba { 0 }; - bool _generated_req_success { false }; - Block _encoded_blk { }; + void _generated_req_completed(State_uint) override; - static void reset_node(Tresor::Type_1_node &node) - { - memset(&node, 0, sizeof(Type_1_node)); - } + bool _request_complete() override { return _state == REQ_COMPLETE; } - static void reset_node(Tresor::Type_2_node &node) - { - memset(&node, 0, sizeof(Type_2_node)); - } + void _request_submitted(Module_request &) override; - static void reset_level(Type_1_level &level, - Child_state state) - { - for (unsigned int i = 0; i < NR_OF_T1_NODES_PER_BLK; i++) { - reset_node(level.children.nodes[i]); - level.children_state[i] = state; - } - } + bool _execute_t2_node(Tree_node_index, bool &); - static void reset_level(Type_2_level &level, - Child_state state) - { - for (unsigned int i = 0; i < NR_OF_T2_NODES_PER_BLK; i++) { - reset_node(level.children.nodes[i]); - level.children_state[i] = state; - } - } + bool _execute_t1_node(Tree_level_index, Tree_node_index, bool &); - static void dump(Type_1_node_block const &node_block) - { - for (auto v : node_block.nodes) { - if (v.pba != 0) - log(v); - } - } + void _mark_req_failed(bool &, char const *); - static void dump(Type_2_node_block const &node_block) - { - for (auto v : node_block.nodes) { - if (v.pba != 0) - log(v); - } - } + void _mark_req_successful(bool &); + + public: + + Ft_initializer_channel(Module_channel_id id) : Module_channel { FT_INITIALIZER, id } { } + + void execute(bool &); }; @@ -177,83 +96,16 @@ class Tresor::Ft_initializer : public Module { private: - using Request = Ft_initializer_request; using Channel = Ft_initializer_channel; - enum { NR_OF_CHANNELS = 1 }; - - Channel _channels[NR_OF_CHANNELS] { }; - - void _execute_leaf_child(Channel &channel, - bool &progress, - uint64_t &nr_of_leaves, - Tresor::Type_2_node &child, - Ft_initializer_channel::Child_state &child_state, - uint64_t child_index); - - void _execute_inner_t2_child(Channel &channel, - bool &progress, - uint64_t nr_of_leaves, - uint64_t &level_to_write, - Tresor::Type_1_node &child, - Ft_initializer_channel::Type_2_level &child_level, - Ft_initializer_channel::Child_state &child_state, - uint64_t level_index, - uint64_t child_index); - - void _execute_inner_t1_child(Channel &channel, - bool &progress, - uint64_t nr_of_leaves, - uint64_t &level_to_write, - Tresor::Type_1_node &child, - Ft_initializer_channel::Type_1_level &child_level, - Ft_initializer_channel::Child_state &child_state, - uint64_t level_index, - uint64_t child_index); - - void _execute(Channel &channel, - bool &progress); - - void _execute_init(Channel &channel, - bool &progress); - - void _mark_req_failed(Channel &channel, - bool &progress, - char const *str); - - void _mark_req_successful(Channel &channel, - bool &progress); - - - /************ - ** Module ** - ************/ - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; - - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_generated_request(Module_request &mod_req) override; - - void generated_request_complete(Module_request &req) override; + Constructible _channels[1] { }; + NONCOPYABLE(Ft_initializer); public: Ft_initializer(); - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &req) override; - void execute(bool &) override; }; diff --git a/repos/gems/src/lib/tresor/include/tresor/ft_resizing.h b/repos/gems/src/lib/tresor/include/tresor/ft_resizing.h deleted file mode 100644 index 4d582f9c75..0000000000 --- a/repos/gems/src/lib/tresor/include/tresor/ft_resizing.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * \brief Module for file tree resizing - * \author Martin Stein - * \date 2023-03-09 - */ - -/* - * Copyright (C) 2023 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _TRESOR__FT_RESIZING_H_ -#define _TRESOR__FT_RESIZING_H_ - -/* tresor includes */ -#include -#include -#include - -namespace Tresor { - - class Ft_resizing; - class Ft_resizing_request; - class Ft_resizing_channel; -} - - -class Tresor::Ft_resizing_request : public Module_request -{ - public: - - enum Type { INVALID = 0, FT_EXTENSION_STEP = 1 }; - - private: - - friend class Ft_resizing; - friend class Ft_resizing_channel; - - Type _type { INVALID }; - Generation _curr_gen { INVALID_GENERATION }; - Type_1_node _ft_root { }; - Tree_level_index _ft_max_lvl { 0 }; - Number_of_leaves _ft_nr_of_leaves { 0 }; - Tree_degree _ft_degree { TREE_MIN_DEGREE }; - addr_t _mt_root_pba_ptr { 0 }; - addr_t _mt_root_gen_ptr { 0 }; - addr_t _mt_root_hash_ptr { 0 }; - Tree_level_index _mt_max_level { 0 }; - Tree_degree _mt_degree { 0 }; - Number_of_leaves _mt_leaves { 0 }; - Physical_block_address _pba { 0 }; - Number_of_blocks _nr_of_pbas { 0 }; - Number_of_leaves _nr_of_leaves { 0 }; - bool _success { false }; - - public: - - Ft_resizing_request() { } - - Ft_resizing_request(uint64_t src_module_id, - uint64_t src_request_id, - Type type, - Generation curr_gen, - Type_1_node ft_root, - Tree_level_index ft_max_lvl, - Number_of_leaves ft_nr_of_leaves, - Tree_degree ft_degree, - addr_t mt_root_pba_ptr, - addr_t mt_root_gen_ptr, - addr_t mt_root_hash_ptr, - Tree_level_index mt_max_level, - Tree_degree mt_degree, - Number_of_leaves mt_leaves, - Physical_block_address pba, - Number_of_blocks nr_of_pbas); - - Type type() const { return _type; } - - bool success() const { return _success; } - - static char const *type_to_string(Type type); - - Type_1_node ft_root() const { return _ft_root; } - Tree_level_index ft_max_lvl() const { return _ft_max_lvl; } - Number_of_leaves ft_nr_of_leaves() const { return _ft_nr_of_leaves; } - Number_of_leaves nr_of_leaves() const { return _nr_of_leaves; } - Physical_block_address pba() const { return _pba; } - Number_of_blocks nr_of_pbas() const { return _nr_of_pbas; } - - - /******************** - ** Module_request ** - ********************/ - - void print(Output &out) const override - { - Genode::print(out, type_to_string(_type), " root ", _ft_root, " leaves ", _ft_nr_of_leaves, " max_lvl ", _ft_max_lvl); - } -}; - -class Tresor::Ft_resizing_channel -{ - private: - - friend class Ft_resizing; - - enum State { - SUBMITTED, - - READ_ROOT_NODE_PENDING, - READ_ROOT_NODE_IN_PROGRESS, - READ_ROOT_NODE_COMPLETED, - - READ_INNER_NODE_PENDING, - READ_INNER_NODE_IN_PROGRESS, - READ_INNER_NODE_COMPLETED, - - ALLOC_PBA_PENDING, - ALLOC_PBA_IN_PROGRESS, - ALLOC_PBA_COMPLETED, - - EXTEND_MT_BY_ONE_LEAF_PENDING, - EXTEND_MT_BY_ONE_LEAF_IN_PROGRESS, - EXTEND_MT_BY_ONE_LEAF_COMPLETED, - - WRITE_INNER_NODE_PENDING, - WRITE_INNER_NODE_IN_PROGRESS, - WRITE_INNER_NODE_COMPLETED, - - WRITE_ROOT_NODE_PENDING, - WRITE_ROOT_NODE_IN_PROGRESS, - WRITE_ROOT_NODE_COMPLETED, - - COMPLETED - }; - - enum Tag_type - { - TAG_INVALID, - TAG_FT_RSZG_CACHE, - TAG_FT_RSZG_MT_ALLOC, - }; - - struct Generated_prim - { - enum Type { READ, WRITE }; - - Type op { READ }; - bool succ { false }; - Tag_type tg { TAG_INVALID }; - uint64_t blk_nr { 0 }; - uint64_t idx { 0 }; - }; - - struct Type_1_node_blocks - { - Type_1_node_block items[TREE_MAX_LEVEL] { }; - }; - - struct Generations - { - Generation items[TREE_MAX_LEVEL + 1] { }; - }; - - Ft_resizing_request _request { }; - State _state { SUBMITTED }; - Generated_prim _generated_prim { }; - Type_1_node_blocks _t1_blks { }; - Type_2_node_block _t2_blk { }; - Tree_level_index _lvl_idx { 0 }; - Tree_level_index _alloc_lvl_idx { 0 }; - Virtual_block_address _vba { }; - Tree_walk_pbas _old_pbas { }; - Generations _old_generations { }; - Tree_walk_pbas _new_pbas { }; - Block _encoded_blk { }; -}; - -class Tresor::Ft_resizing : public Module -{ - private: - - using Request = Ft_resizing_request; - using Channel = Ft_resizing_channel; - - enum { NR_OF_CHANNELS = 1 }; - - Channel _channels[NR_OF_CHANNELS] { }; - - void _set_args_for_write_back_of_inner_lvl(Tree_level_index const, - Tree_level_index const, - Physical_block_address const, - unsigned const prim_idx, - Channel::State &, - bool &progress, - Channel::Generated_prim &); - - void _add_new_root_lvl_to_ft_using_pba_contingent(Type_1_node &, - Tree_level_index &, - Number_of_leaves const, - Generation const, - Channel::Type_1_node_blocks &, - Tree_walk_pbas &, - Physical_block_address &, - Number_of_blocks &); - - void _add_new_branch_to_ft_using_pba_contingent(Tree_level_index const, - Tree_node_index const, - Tree_degree const, - Generation const, - Physical_block_address &, - Number_of_blocks &, - Channel::Type_1_node_blocks &, - Type_2_node_block &, - Tree_walk_pbas &, - Tree_level_index &, - Number_of_leaves &); - - void _execute_ft_extension_step(Channel &, unsigned const idx, bool &); - - void _execute_ft_ext_step_read_inner_node_completed(Channel &, - unsigned const job_idx, - bool &progress); - - /************ - ** Module ** - ************/ - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; - - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_generated_request(Module_request &mod_req) override; - - void generated_request_complete(Module_request &req) override; - - - public: - - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &req) override; - - void execute(bool &) override; -}; - -#endif /* _TRESOR__FT_RESIZING_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/hash.h b/repos/gems/src/lib/tresor/include/tresor/hash.h new file mode 100644 index 0000000000..7ab7b92e25 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/hash.h @@ -0,0 +1,29 @@ +/* + * \brief Calculate and check hashes of tresor data blocks + * \author Martin Stein + * \date 2023-02-13 + */ + +/* + * Copyright (C) 2023 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _TRESOR__HASH_H_ +#define _TRESOR__HASH_H_ + +namespace Tresor { + + class Block; + class Hash; + + void calc_hash(Block const &, Hash &); + + bool check_hash(Block const &, Hash const &); + + Hash hash(Block const &); +} + +#endif /* _TRESOR__HASH_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/math.h b/repos/gems/src/lib/tresor/include/tresor/math.h index 0c8c758f69..df567c3603 100644 --- a/repos/gems/src/lib/tresor/include/tresor/math.h +++ b/repos/gems/src/lib/tresor/include/tresor/math.h @@ -14,15 +14,15 @@ #ifndef _TRESOR__MATH_H_ #define _TRESOR__MATH_H_ +/* tresor includes */ +#include + namespace Tresor { template constexpr T to_the_power_of(T base, T exponent) { - if (exponent < 0) { - class Negative_exponent { }; - throw Negative_exponent { }; - } + ASSERT(exponent >= 0); if (exponent == 0) return 1; @@ -32,6 +32,13 @@ namespace Tresor { return result; } + + template + bool is_power_of_2(T val) + { + for (; val && (val & 1) == 0; val >>= 1); + return val == 1; + } } #endif /* _TRESOR__MATH_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/meta_tree.h b/repos/gems/src/lib/tresor/include/tresor/meta_tree.h index 13036f9b85..d529b56ce6 100644 --- a/repos/gems/src/lib/tresor/include/tresor/meta_tree.h +++ b/repos/gems/src/lib/tresor/include/tresor/meta_tree.h @@ -1,5 +1,5 @@ /* - * \brief Module for doing free tree COW allocations on the meta tree + * \brief Module for doing VBD COW allocations on the meta tree * \author Martin Stein * \date 2023-02-13 */ @@ -16,8 +16,6 @@ /* tresor includes */ #include -#include -#include namespace Tresor { @@ -28,226 +26,102 @@ namespace Tresor { class Tresor::Meta_tree_request : public Module_request { + friend class Meta_tree_channel; + public: - enum Type { INVALID = 0, UPDATE = 1 }; + enum Type { ALLOC_PBA }; private: - friend class Meta_tree; - friend class Meta_tree_channel; + Type const _type; + Tree_root &_mt; + Generation const _curr_gen; + Physical_block_address &_pba; + bool &_success; - Type _type { INVALID }; - addr_t _mt_root_pba_ptr { 0 }; - addr_t _mt_root_gen_ptr { 0 }; - addr_t _mt_root_hash_ptr { 0 }; - uint64_t _mt_max_lvl { 0 }; - uint64_t _mt_edges { 0 }; - uint64_t _mt_leaves { 0 }; - uint64_t _current_gen { 0 }; - uint64_t _old_pba { INVALID_PBA }; - uint64_t _new_pba { INVALID_PBA }; - bool _success { false }; + NONCOPYABLE(Meta_tree_request); public: - Meta_tree_request() { } + Meta_tree_request(Module_id, Module_channel_id, Type, Tree_root &, Generation, Physical_block_address &, bool &); - Meta_tree_request(Module_id src_module_id, - Module_request_id src_request_id); - - static void create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - void *mt_root_pba_ptr, - void *mt_root_gen_ptr, - void *mt_root_hash_ptr, - uint64_t mt_max_lvl, - uint64_t mt_edges, - uint64_t mt_leaves, - uint64_t curr_gen, - uint64_t old_pba); - - uint64_t new_pba() { return _new_pba; } - - Type type() const { return _type; } - - bool success() const { return _success; } - - static char const *type_to_string(Type type); - - char const *type_name() const { return type_to_string(_type); } - - - /******************** - ** Module_request ** - ********************/ + static char const *type_to_string(Type); void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } }; - -class Tresor::Meta_tree_channel +class Tresor::Meta_tree_channel : public Module_channel { private: - friend class Meta_tree; + using Request = Meta_tree_request; - enum State { - INVALID, - UPDATE, - COMPLETE, - TREE_HASH_MISMATCH - }; + enum State { REQ_SUBMITTED, REQ_GENERATED, SEEK_DOWN, SEEK_LEFT_OR_UP, WRITE_BLK, COMPLETE }; - struct Type_1_info + State _state { COMPLETE }; + Request *_req_ptr { nullptr }; + Block _blk { }; + Tree_node_index _node_idx[TREE_MAX_NR_OF_LEVELS] { }; + Type_1_node_block _t1_blks[TREE_MAX_NR_OF_LEVELS] { }; + Type_2_node_block _t2_blk { }; + Tree_level_index _lvl { 0 }; + bool _generated_req_success { false }; + + NONCOPYABLE(Meta_tree_channel); + + void _generated_req_completed(State_uint) override; + + template + void _generate_req(State_uint state, bool &progress, ARGS &&... args) { - enum State { - INVALID, READ, READ_COMPLETE, WRITE, WRITE_COMPLETE, COMPLETE }; + _state = REQ_GENERATED; + generate_req(state, progress, args..., _generated_req_success); + } - State state { INVALID }; - Type_1_node node { }; - Type_1_node_block entries { }; - uint8_t index { INVALID_NODE_INDEX }; - bool dirty { false }; - bool volatil { false }; - }; + void _request_submitted(Module_request &) override; - struct Type_2_info - { - enum State { - INVALID, READ, READ_COMPLETE, WRITE, WRITE_COMPLETE, COMPLETE }; + bool _request_complete() override { return _state == COMPLETE; } - State state { INVALID }; - Type_1_node node { }; - Type_2_node_block entries { }; - uint8_t index { INVALID_NODE_INDEX }; - bool volatil { false }; - }; + void _mark_req_failed(bool &, char const *); - struct Local_cache_request - { - enum State { INVALID, PENDING, IN_PROGRESS }; - enum Op { READ, WRITE, SYNC }; + bool _can_alloc_pba_of(Type_2_node &); - State state { INVALID }; - Op op { READ }; - bool success { false }; - uint64_t pba { 0 }; - uint64_t level { 0 }; - Block block_data { }; + void _alloc_pba_of(Type_2_node &, Physical_block_address &); - Local_cache_request(State state, - Op op, - bool success, - uint64_t pba, - uint64_t level, - Block const *blk_ptr) - : - state { state }, - op { op }, - success { success }, - pba { pba }, - level { level } - { - if (blk_ptr != nullptr) { - block_data = *blk_ptr; - } - } + void _traverse_curr_node(bool &); - Local_cache_request() { } - }; + void _mark_req_successful(bool &); - State _state { INVALID }; - Meta_tree_request _request { }; - Local_cache_request _cache_request { }; - Type_2_info _level_1_node { }; - Type_1_info _level_n_nodes[TREE_MAX_NR_OF_LEVELS] { }; /* index starts at 2 */ - bool _finished { false }; - bool _root_dirty { false }; + void _start_tree_traversal(bool &); + + public: + + Meta_tree_channel(Module_channel_id id) : Module_channel { META_TREE, id } { } + + void execute(bool &); }; class Tresor::Meta_tree : public Module { private: - using Request = Meta_tree_request; using Channel = Meta_tree_channel; - using Local_cache_request = Channel::Local_cache_request; - using Type_1_info = Channel::Type_1_info; - using Type_2_info = Channel::Type_2_info; - enum { NR_OF_CHANNELS = 1 }; + Constructible _channels[1] { }; - Channel _channels[NR_OF_CHANNELS] { }; - - void _handle_level_n_nodes(Channel &channel, - bool &handled); - - void _handle_level_1_node(Channel &channel, - bool &handled); - - void _exchange_request_pba(Channel &channel, - Type_2_node &t2_entry); - - void _exchange_nv_inner_nodes(Channel &channel, - Type_2_node &t2_entry, - bool &exchanged); - - void _exchange_nv_level_1_node(Channel &channel, - Type_2_node &t2_entry, - bool &exchanged); - - bool _node_volatile(Type_1_node const &node, - uint64_t gen); - - void _handle_level_0_nodes(Channel &channel, - bool &handled); - - void _update_parent(Type_1_node &node, - Block const &blk, - uint64_t gen, - uint64_t pba); - - void _handle_level_0_nodes(bool &handled); - - void _execute_update(Channel &channel, - bool &progress); - - void _mark_req_failed(Channel &channel, - bool &progress, - char const *str); - - void _mark_req_successful(Channel &channel, - bool &progress); - - - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &req) override; - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; + NONCOPYABLE(Meta_tree); void execute(bool &) override; - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_generated_request(Module_request &mod_req) override; - - void generated_request_complete(Module_request &req) override; - public: + struct Alloc_pba : Meta_tree_request + { + Alloc_pba(Module_id src_mod, Module_channel_id src_chan, Tree_root &mt, Generation gen, Physical_block_address &pba, bool &succ) + : Meta_tree_request(src_mod, src_chan, Meta_tree_request::ALLOC_PBA, mt, gen, pba, succ) { } + }; + Meta_tree(); }; diff --git a/repos/gems/src/lib/tresor/include/tresor/module.h b/repos/gems/src/lib/tresor/include/tresor/module.h index 697e949ca3..9c960c32fb 100644 --- a/repos/gems/src/lib/tresor/include/tresor/module.h +++ b/repos/gems/src/lib/tresor/include/tresor/module.h @@ -15,52 +15,31 @@ #define _TRESOR__MODULE_H_ /* base includes */ -#include -#include +#include /* tresor includes */ #include -#include +#include +#include namespace Tresor { using namespace Genode; using Module_id = uint64_t; - using Module_request_id = uint64_t; + using Module_channel_id = uint64_t; - enum { - INVALID_MODULE_ID = ~0UL, - INVALID_MODULE_REQUEST_ID = ~0UL, - }; + enum { INVALID_MODULE_ID = ~(Module_id)0, INVALID_MODULE_CHANNEL_ID = ~(Module_channel_id)0 }; - enum Module_id_enum : Module_id - { - CRYPTO = 0, - CLIENT_DATA = 1, - TRUST_ANCHOR = 2, - COMMAND_POOL = 3, - BLOCK_IO = 4, - CACHE = 5, - META_TREE = 6, - FREE_TREE = 7, - VIRTUAL_BLOCK_DEVICE = 8, - SUPERBLOCK_CONTROL = 9, - BLOCK_ALLOCATOR = 10, - VBD_INITIALIZER = 11, - FT_INITIALIZER = 12, - SB_INITIALIZER = 13, - REQUEST_POOL = 14, - SB_CHECK = 15, - VBD_CHECK = 16, - FT_CHECK = 17, - FT_RESIZING = 18, - MAX_MODULE_ID = 18, - }; + enum Module_id_enum : Module_id { + CRYPTO = 0, CLIENT_DATA = 1, TRUST_ANCHOR = 2, COMMAND_POOL = 3, BLOCK_IO = 4, CACHE = 5, META_TREE = 6, + FREE_TREE = 7, VIRTUAL_BLOCK_DEVICE = 8, SUPERBLOCK_CONTROL = 9, VBD_INITIALIZER = 10, FT_INITIALIZER = 11, + SB_INITIALIZER = 12, REQUEST_POOL = 13, SB_CHECK = 14, VBD_CHECK = 15, FT_CHECK = 16, SPLITTER = 17, MAX_MODULE_ID = 17 }; char const *module_name(Module_id module_id); class Module_request; + class Module_channel; class Module; class Module_composition; } @@ -70,38 +49,96 @@ class Tresor::Module_request : public Interface { private: - Module_id _src_module_id { INVALID_MODULE_ID }; - Module_request_id _src_request_id { INVALID_MODULE_REQUEST_ID }; - Module_id _dst_module_id { INVALID_MODULE_ID }; - Module_request_id _dst_request_id { INVALID_MODULE_REQUEST_ID }; + Module_id _src_module_id; + Module_channel_id _src_chan_id; + Module_id _dst_module_id; + Module_channel_id _dst_chan_id { INVALID_MODULE_CHANNEL_ID }; + + NONCOPYABLE(Module_request); public: - Module_request() { } + Module_request(Module_id, Module_channel_id, Module_id); - Module_request(Module_id src_module_id, - Module_request_id src_request_id, - Module_id dst_module_id); + void dst_chan_id(Module_channel_id id) { _dst_chan_id = id; } - void dst_request_id(Module_request_id id) { _dst_request_id = id; } - - String<32> src_request_id_str() const; - - String<32> dst_request_id_str() const; + Module_id src_module_id() const { return _src_module_id; } + Module_channel_id src_chan_id() const { return _src_chan_id; } + Module_id dst_module_id() const { return _dst_module_id; } + Module_channel_id dst_chan_id() const { return _dst_chan_id; } virtual void print(Output &) const = 0; virtual ~Module_request() { } +}; - /*************** - ** Accessors ** - ***************/ +class Tresor::Module_channel : private Avl_node +{ + friend class Module; + friend class Avl_node; + friend class Avl_tree; - Module_id src_module_id() const { return _src_module_id; } - Module_request_id src_request_id() const { return _src_request_id; } - Module_id dst_module_id() const { return _dst_module_id; } - Module_request_id dst_request_id() const { return _dst_request_id; } + public: + + using State_uint = uint64_t; + + private: + + enum { GEN_REQ_BUF_SIZE = 4000 }; + + enum Generated_request_state { NONE, PENDING, IN_PROGRESS }; + + Module_request *_req_ptr { nullptr }; + Module_id _module_id; + Module_channel_id _id; + Generated_request_state _gen_req_state { NONE }; + uint8_t _gen_req_buf[GEN_REQ_BUF_SIZE] { }; + State_uint _gen_req_complete_state { 0 }; + + NONCOPYABLE(Module_channel); + + bool higher(Module_channel *ptr) { return ptr->_id > _id; } + + virtual void _generated_req_completed(State_uint) { ASSERT_NEVER_REACHED; } + + virtual void _request_submitted(Module_request &) { ASSERT_NEVER_REACHED; } + + virtual bool _request_complete() { ASSERT_NEVER_REACHED; } + + public: + + Module_channel(Module_id module_id, Module_channel_id id) : _module_id { module_id }, _id { id } { }; + + template + void generate_req(State_uint complete_state, bool &progress, ARGS &&... args) + { + ASSERT(_gen_req_state == NONE); + static_assert(sizeof(REQUEST) <= GEN_REQ_BUF_SIZE); + construct_at(_gen_req_buf, _module_id, _id, args...); + _gen_req_state = PENDING; + _gen_req_complete_state = complete_state; + progress = true; + } + + template + void with_channel(Module_channel_id id, FUNC && func) + { + if (id != _id) { + Module_channel *chan_ptr { Avl_node::child(id > _id) }; + ASSERT(chan_ptr); + chan_ptr->with_channel(id, func); + } else + func(*static_cast(this)); + } + + void generated_req_completed(); + + bool try_submit_request(Module_request &); + + Module_channel_id id() const { return _id; } + + virtual ~Module_channel() { } }; @@ -109,86 +146,62 @@ class Tresor::Module : public Interface { private: - virtual bool _peek_completed_request(uint8_t *, - size_t ) - { - return false; - } + Avl_tree _channels { }; - virtual void _drop_completed_request(Module_request &) - { - class Exception_1 { }; - throw Exception_1 { }; - } - - virtual bool _peek_generated_request(uint8_t *, - size_t ) - { - return false; - } - - virtual void _drop_generated_request(Module_request &) - { - class Exception_1 { }; - throw Exception_1 { }; - } + NONCOPYABLE(Module); public: - enum Handle_request_result { REQUEST_HANDLED, REQUEST_NOT_HANDLED }; - - typedef Handle_request_result ( - *Handle_request_function)(Module_request &req); - - virtual bool ready_to_submit_request() { return false; }; - - virtual void submit_request(Module_request &) + template + void with_channel(Module_channel_id id, FUNC && func) { - class Exception_1 { }; - throw Exception_1 { }; + ASSERT(_channels.first()); + _channels.first()->with_channel(id, func); } - virtual void execute(bool &) { } + template + void for_each_channel(FUNC && func) + { + _channels.for_each([&] (Module_channel const &const_chan) { + func(*static_cast(const_cast(&const_chan))); }); + } template void for_each_generated_request(FUNC && handle_request) { - uint8_t buf[4000]; - while (_peek_generated_request(buf, sizeof(buf))) { - - Module_request &req = *(Module_request *)buf; - switch (handle_request(req)) { - case Module::REQUEST_HANDLED: - - _drop_generated_request(req); - break; - - case Module::REQUEST_NOT_HANDLED: + for_each_channel([&] (Module_channel &chan) { + if (chan._gen_req_state != Module_channel::PENDING) + return; + Module_request &req = *(Module_request *)chan._gen_req_buf; + if (handle_request(req)) { + chan._gen_req_state = Module_channel::IN_PROGRESS; return; } - } - } - - virtual void generated_request_complete(Module_request &) - { - class Exception_1 { }; - throw Exception_1 { }; + }); } template void for_each_completed_request(FUNC && handle_request) { - uint8_t buf[4000]; - while (_peek_completed_request(buf, sizeof(buf))) { - - Module_request &req = *(Module_request *)buf; - handle_request(req); - _drop_completed_request(req); - } + for_each_channel([&] (Module_channel &chan) { + if (chan._req_ptr && chan._request_complete()) { + handle_request(*chan._req_ptr); + chan._req_ptr = nullptr; + } + }); + return; } + bool try_submit_request(Module_request &); + + void add_channel(Module_channel &chan) { _channels.insert(&chan); } + + Module() { } + virtual ~Module() { } + + virtual void execute(bool &) { } }; @@ -200,92 +213,11 @@ class Tresor::Module_composition public: - void add_module(Module_id module_id, - Module &module) - { - if (module_id > MAX_MODULE_ID) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (_module_ptrs[module_id] != nullptr) { - class Exception_2 { }; - throw Exception_2 { }; - } - _module_ptrs[module_id] = &module; - } + void add_module(Module_id module_id, Module &mod); - void remove_module(Module_id module_id) - { - if (module_id > MAX_MODULE_ID) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (_module_ptrs[module_id] == nullptr) { - class Exception_2 { }; - throw Exception_2 { }; - } - _module_ptrs[module_id] = nullptr; - } + void remove_module(Module_id module_id); - void execute_modules(bool &progress) - { - for (Module_id id { 0 }; id <= MAX_MODULE_ID; id++) { - - if (_module_ptrs[id] == nullptr) - continue; - - Module *module_ptr { _module_ptrs[id] }; - module_ptr->execute(progress); - module_ptr->for_each_generated_request([&] (Module_request &req) { - if (req.dst_module_id() > MAX_MODULE_ID) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (_module_ptrs[req.dst_module_id()] == nullptr) { - class Exception_2 { }; - throw Exception_2 { }; - } - Module &dst_module { *_module_ptrs[req.dst_module_id()] }; - if (!dst_module.ready_to_submit_request()) { - - if (VERBOSE_MODULE_COMMUNICATION) - log( - module_name(id), " ", req.src_request_id_str(), - " --", req, "-| ", - module_name(req.dst_module_id())); - - return Module::REQUEST_NOT_HANDLED; - } - dst_module.submit_request(req); - - if (VERBOSE_MODULE_COMMUNICATION) - log( - module_name(id), " ", req.src_request_id_str(), - " --", req, "--> ", - module_name(req.dst_module_id()), " ", - req.dst_request_id_str()); - - progress = true; - return Module::REQUEST_HANDLED; - }); - module_ptr->for_each_completed_request([&] (Module_request &req) { - if (req.src_module_id() > MAX_MODULE_ID) { - class Exception_3 { }; - throw Exception_3 { }; - } - if (VERBOSE_MODULE_COMMUNICATION) - log( - module_name(req.src_module_id()), " ", - req.src_request_id_str(), " <--", req, - "-- ", module_name(id), " ", - req.dst_request_id_str()); - - Module &src_module { *_module_ptrs[req.src_module_id()] }; - src_module.generated_request_complete(req); - progress = true; - }); - } - } + void execute_modules(); }; #endif /* _TRESOR__MODULE_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/noncopyable.h b/repos/gems/src/lib/tresor/include/tresor/noncopyable.h new file mode 100644 index 0000000000..1ff52ef79c --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/noncopyable.h @@ -0,0 +1,21 @@ +/* + * \brief Macro to make a class non-copyable + * \author Martin Stein + * \date 2023-06-09 + */ + +/* + * Copyright (C) 2023 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _TRESOR__NONCOPYABLE_H_ +#define _TRESOR__NONCOPYABLE_H_ + +#define NONCOPYABLE(class_name) \ + class_name(class_name const &) = delete; \ + class_name &operator = (class_name const &) = delete; \ + +#endif /* _TRESOR__NONCOPYABLE_H_ */ 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 d0eb71ceaf..93a1dd9969 100644 --- a/repos/gems/src/lib/tresor/include/tresor/request_pool.h +++ b/repos/gems/src/lib/tresor/include/tresor/request_pool.h @@ -15,474 +15,166 @@ #define _TRESOR__REQUEST_POOL_H_ /* tresor includes */ -#include #include -#include +#include namespace Tresor { + class Request; class Request_pool; - class Request_pool_request; class Request_pool_channel; - - - class Request : public Module_request - { - friend class Request_pool; - - public: - - enum Operation : uint32_t { - INVALID = 0, - READ = 1, - WRITE = 2, - SYNC = 3, - CREATE_SNAPSHOT = 4, - DISCARD_SNAPSHOT = 5, - REKEY = 6, - EXTEND_VBD = 7, - EXTEND_FT = 8, - RESUME_REKEYING = 10, - DEINITIALIZE = 11, - INITIALIZE = 12, - }; - - private: - - Operation _operation; - bool _success; - uint64_t _block_number; - uint64_t _offset; - Number_of_blocks _count; - uint32_t _key_id; - uint32_t _tag; - Generation _gen; - - public: - - Request(Operation operation, - bool success, - uint64_t block_number, - uint64_t offset, - Number_of_blocks count, - uint32_t key_id, - uint32_t tag, - Generation gen, - Module_id src_module_id, - Module_request_id src_request_id) - : - Module_request { src_module_id, src_request_id, REQUEST_POOL }, - _operation { operation }, - _success { success }, - _block_number { block_number }, - _offset { offset }, - _count { count }, - _key_id { key_id }, - _tag { tag }, - _gen { gen } - { } - - Request() - : - Module_request { }, - _operation { Operation::INVALID }, - _success { false }, - _block_number { 0 }, - _offset { 0 }, - _count { 0 }, - _key_id { 0 }, - _tag { 0 }, - _gen { 0 } - { } - - bool valid() const - { - return _operation != Operation::INVALID; - } - - - /*************** - ** Accessors ** - ***************/ - - bool read() const { return _operation == Operation::READ; } - bool write() const { return _operation == Operation::WRITE; } - bool sync() const { return _operation == Operation::SYNC; } - bool create_snapshot() const { return _operation == Operation::CREATE_SNAPSHOT; } - bool discard_snapshot() const { return _operation == Operation::DISCARD_SNAPSHOT; } - bool rekey() const { return _operation == Operation::REKEY; } - bool extend_vbd() const { return _operation == Operation::EXTEND_VBD; } - bool extend_ft() const { return _operation == Operation::EXTEND_FT; } - bool resume_rekeying() const { return _operation == Operation::RESUME_REKEYING; } - bool deinitialize() const { return _operation == Operation::DEINITIALIZE; } - bool initialize() const { return _operation == Operation::INITIALIZE; } - - Operation operation() const { return _operation; } - bool success() const { return _success; } - uint64_t block_number() const { return _block_number; } - uint64_t offset() const { return _offset; } - Number_of_blocks count() const { return _count; } - uint32_t key_id() const { return _key_id; } - uint32_t tag() const { return _tag; } - 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 gen(Generation arg) { _gen = arg; } - - static char const *op_to_string(Operation op); - - - /******************** - ** Module_request ** - ********************/ - - void print(Output &out) const override - { - Genode::print(out, op_to_string(_operation)); - switch (_operation) { - case READ: - case WRITE: - case SYNC: - if (_count > 1) - Genode::print(out, " vbas ", _block_number, "..", _block_number + _count - 1); - else - Genode::print(out, " vba ", _block_number); - break; - default: - break; - } - } - }; + class Request_pool_channel_queue; } -class Tresor::Request_pool_channel +class Tresor::Request : public Module_request { - private: + NONCOPYABLE(Request); - friend class Request_pool; - - enum State { - INVALID, - SUBMITTED, - SUBMITTED_RESUME_REKEYING, - REKEY_INIT_PENDING, - REKEY_INIT_IN_PROGRESS, - REKEY_INIT_COMPLETE, - PREPONE_REQUESTS_PENDING, - PREPONE_REQUESTS_COMPLETE, - VBD_EXTENSION_STEP_PENDING, - FT_EXTENSION_STEP_PENDING, - TREE_EXTENSION_STEP_IN_PROGRESS, - TREE_EXTENSION_STEP_COMPLETE, - CREATE_SNAP_AT_SB_CTRL_PENDING, - CREATE_SNAP_AT_SB_CTRL_IN_PROGRESS, - CREATE_SNAP_AT_SB_CTRL_COMPLETE, - SYNC_AT_SB_CTRL_PENDING, - SYNC_AT_SB_CTRL_IN_PROGRESS, - SYNC_AT_SB_CTRL_COMPLETE, - READ_VBA_AT_SB_CTRL_PENDING, - READ_VBA_AT_SB_CTRL_IN_PROGRESS, - READ_VBA_AT_SB_CTRL_COMPLETE, - WRITE_VBA_AT_SB_CTRL_PENDING, - WRITE_VBA_AT_SB_CTRL_IN_PROGRESS, - WRITE_VBA_AT_SB_CTRL_COMPLETE, - DISCARD_SNAP_AT_SB_CTRL_PENDING, - DISCARD_SNAP_AT_SB_CTRL_IN_PROGRESS, - DISCARD_SNAP_AT_SB_CTRL_COMPLETE, - REKEY_VBA_PENDING, - REKEY_VBA_IN_PROGRESS, - REKEY_VBA_COMPLETE, - INITIALIZE_SB_CTRL_PENDING, - INITIALIZE_SB_CTRL_IN_PROGRESS, - INITIALIZE_SB_CTRL_COMPLETE, - DEINITIALIZE_SB_CTRL_PENDING, - DEINITIALIZE_SB_CTRL_IN_PROGRESS, - DEINITIALIZE_SB_CTRL_COMPLETE, - COMPLETE - }; - - enum Tag_type { - TAG_POOL_SB_CTRL_TREE_EXT_STEP, - TAG_POOL_SB_CTRL_READ_VBA, - TAG_POOL_SB_CTRL_WRITE_VBA, - TAG_POOL_SB_CTRL_SYNC, - TAG_POOL_SB_CTRL_INITIALIZE, - 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; - - struct Generated_prim { - enum Type { READ, WRITE }; - - Type op; - bool succ; - Tag_type tg; - Pool_index pl_idx; - uint64_t blk_nr; - uint64_t idx; - }; - - Tresor::Request _request { }; - State _state { INVALID }; - Generated_prim _prim { }; - uint64_t _nr_of_blks { 0 }; - Superblock::State _sb_state { Superblock::INVALID }; - uint32_t _nr_of_requests_preponed { 0 }; - bool _request_finished { false }; - - void invalidate() - { - _request = { }; - _state = { INVALID }; - _prim = { }; - _nr_of_blks = 0; - _sb_state = { Superblock::INVALID }; - } -}; - -class Tresor::Request_pool : public Module -{ - private: - - enum { MAX_NR_OF_REQUESTS_PREPONED_AT_A_TIME = 8 }; - - using Channel = Request_pool_channel; - using Request = Tresor::Request; - using Slots_index = uint32_t; - using Pool_index = Channel::Pool_index; - using Generated_prim = Channel::Generated_prim; - - enum { NR_OF_CHANNELS = 16 }; - - struct Index_queue - { - using Index = Slots_index; - - Slots_index _head { 0 }; - Slots_index _tail { 0 }; - unsigned _nr_of_used_slots { 0 }; - Slots_index _slots[NR_OF_CHANNELS] { 0 }; - - bool empty() const { return _nr_of_used_slots == 0; } - - bool full() const { - return _nr_of_used_slots >= NR_OF_CHANNELS; } - - Slots_index head() const - { - if (empty()) { - class Index_queue_empty_head { }; - throw Index_queue_empty_head { }; - } - return _slots[_head]; - } - - void enqueue(Slots_index const idx) - { - if (full()) { - class Index_queue_enqueue_full { }; - throw Index_queue_enqueue_full { }; - } - - _slots[_tail] = idx; - - _tail = (_tail + 1) % NR_OF_CHANNELS; - - _nr_of_used_slots += 1; - } - - void move_one_item_towards_tail(Index idx) - { - Slots_index slot_idx { _head }; - Slots_index next_slot_idx; - Index next_idx; - - if (empty()) { - class Exception_1 { }; - throw Exception_1 { }; - } - while (true) { - - if (slot_idx < NR_OF_CHANNELS - 1) - next_slot_idx = slot_idx + 1; - else - next_slot_idx = 0; - - if (next_slot_idx == _tail) { - class Exception_2 { }; - throw Exception_2 { }; - } - if (_slots[slot_idx] == idx) { - next_idx = _slots[next_slot_idx]; - _slots[next_slot_idx] = _slots[slot_idx]; - _slots[slot_idx] = next_idx; - return; - } else - slot_idx = next_slot_idx; - } - } - - bool item_is_tail(Slots_index idx) const - { - Slots_index slot_idx; - - if (empty()) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (_tail > 0) - slot_idx = _tail - 1; - else - slot_idx = NR_OF_CHANNELS - 1; - - return _slots[slot_idx] == idx; - } - - Index next_item(Index idx) const - { - Slots_index slot_idx { _head }; - Slots_index next_slot_idx; - if (empty()) { - class Exception_1 { }; - throw Exception_1 { }; - } - while (true) { - - if (slot_idx < NR_OF_CHANNELS - 1) - next_slot_idx = slot_idx + 1; - else - next_slot_idx = 0; - - if (next_slot_idx == _tail) { - class Exception_2 { }; - throw Exception_2 { }; - } - if (_slots[slot_idx] == idx) - return _slots[next_slot_idx]; - else - slot_idx = next_slot_idx; - } - } - - void dequeue(Slots_index const idx) - { - if (empty() or head() != idx) { - class Index_queue_dequeue_error { }; - throw Index_queue_dequeue_error { }; - } - - _head = (_head + 1) % NR_OF_CHANNELS; - - _nr_of_used_slots -= 1; - } - }; - - static char const *_state_to_step_label(Channel::State state); - - void _mark_req_successful(Channel &chan, - Slots_index idx, - bool &progress); - - bool _handle_failed_generated_req(Channel &chan, - bool &progress); - - void _mark_req_failed(Channel &chan, - bool &progress, - char const *str); - - Channel _channels[NR_OF_CHANNELS] { }; - Index_queue _indices { }; - - void _execute_read (Channel &, Index_queue &, Slots_index const, bool &); - - void _execute_write(Channel &, Index_queue &, Slots_index const, bool &); - - 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, - bool &progress); - - void _execute_extend_tree(Channel &chan, - Slots_index idx, - Channel::State tree_ext_step_pending, - bool &progress); - - void _execute_initialize(Channel &, Index_queue &, Slots_index const, - bool &); - void _execute_deinitialize(Channel &, Index_queue &, Slots_index const, - bool &); - - - /************ - ** Module ** - ************/ - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; - - void execute(bool &) override; - - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_generated_request(Module_request &mod_req) override; - - void generated_request_complete(Module_request &req) override; + friend class Request_pool_channel; public: - Request_pool(); + enum Operation { + READ, WRITE, SYNC, CREATE_SNAPSHOT, DISCARD_SNAPSHOT, REKEY, EXTEND_VBD, + EXTEND_FT, RESUME_REKEYING, DEINITIALIZE, INITIALIZE, }; + private: - /************ - ** Module ** - ************/ + Operation _op; + Virtual_block_address const _vba; + Request_offset const _offset; + Number_of_blocks const _count; + Key_id const _key_id; + Request_tag const _tag; + Generation &_gen; + bool &_success; - bool ready_to_submit_request() override { return !_indices.full(); } + public: - void submit_request(Module_request &req) override; + static char const *op_to_string(Operation); + + Request(Module_id, Module_channel_id, Operation, Virtual_block_address, Request_offset, + Number_of_blocks, Key_id, Request_tag, Generation &, bool &); + + void print(Output &) const override; +}; + +class Tresor::Request_pool_channel : public Module_channel +{ + private: + + enum State : State_uint { + INVALID, REQ_SUBMITTED, REQ_RESUMED, REQ_GENERATED, REKEY_INIT_SUCCEEDED, PREPONED_REQUESTS_COMPLETE, + TREE_EXTENSION_STEP_SUCCEEDED, FORWARD_TO_SB_CTRL_SUCCEEDED, ACCESS_VBA_AT_SB_CTRL_SUCCEEDED, + REKEY_VBA_SUCCEEDED, INITIALIZE_SB_CTRL_SUCCEEDED, DEINITIALIZE_SB_CTRL_SUCCEEDED, REQ_COMPLETE }; + + State _state { INVALID }; + Number_of_blocks _num_blks { 0 }; + Superblock::State _sb_state { Superblock::INVALID }; + uint32_t _num_requests_preponed { 0 }; + bool _request_finished { false }; + bool _generated_req_success { false }; + Request_pool_channel_queue &_chan_queue; + Request *_req_ptr { nullptr }; + + NONCOPYABLE(Request_pool_channel); + + void _generated_req_completed(State_uint) override; + + void _request_submitted(Module_request &req) override; + + bool _request_complete() override { return _state == REQ_COMPLETE; } + + void _access_vbas(bool &, Superblock_control_request::Type); + + void _forward_to_sb_ctrl(bool &, Superblock_control_request::Type); + + void _gen_sb_control_req(bool &, Superblock_control_request::Type, State, Virtual_block_address); + + void _rekey(bool &); + + void _mark_req_successful(bool &); + + void _reset(); + + void _try_prepone_requests(bool &); + + void _extend_tree(Superblock_control_request::Type, bool &); + + void _initialize(bool &); + + void _resume_request(bool &, Request::Operation); + + public: + + Request_pool_channel(Module_channel_id id, Request_pool_channel_queue &chan_queue) : Module_channel { REQUEST_POOL, id }, _chan_queue { chan_queue } { } + + void execute(bool &); }; -inline char const *to_string(Tresor::Request::Operation op) +class Tresor::Request_pool_channel_queue { - switch (op) { - case Tresor::Request::INVALID: return "invalid"; - case Tresor::Request::READ: return "read"; - case Tresor::Request::WRITE: return "write"; - case Tresor::Request::SYNC: return "sync"; - case Tresor::Request::CREATE_SNAPSHOT: return "create_snapshot"; - case Tresor::Request::DISCARD_SNAPSHOT: return "discard_snapshot"; - case Tresor::Request::REKEY: return "rekey"; - case Tresor::Request::EXTEND_VBD: return "extend_vbd"; - case Tresor::Request::EXTEND_FT: return "extend_ft"; - case Tresor::Request::RESUME_REKEYING: return "resume_rekeying"; - case Tresor::Request::DEINITIALIZE: return "deinitialize"; - case Tresor::Request::INITIALIZE: return "initialize"; - } - class Exception_1 { }; - throw Exception_1 { }; -} + NONCOPYABLE(Request_pool_channel_queue); + + public: + + enum { NUM_SLOTS = 16 }; + + private: + + using Channel = Request_pool_channel; + using Slot_index = uint64_t; + using Number_of_slots = uint64_t; + + Slot_index _head { 0 }; + Slot_index _tail { 0 }; + Number_of_slots _num_used_slots { 0 }; + Channel *_slots[NUM_SLOTS] { 0 }; + + public: + + Request_pool_channel_queue() { } + + bool empty() const { return _num_used_slots == 0; } + + bool full() const { return _num_used_slots >= NUM_SLOTS; } + + Channel &head() const; + + void enqueue(Channel &); + + void move_one_slot_towards_tail(Channel const &); + + bool is_tail(Channel const &) const; + + Channel &next(Channel const &) const; + + void dequeue(Channel const &); +}; + + +class Tresor::Request_pool : public Module +{ + NONCOPYABLE(Request_pool); + + private: + + using Channel = Request_pool_channel; + + enum { NUM_CHANNELS = Request_pool_channel_queue::NUM_SLOTS }; + + bool _init_success { false }; + Generation _init_gen { INVALID_GENERATION }; + Request _init_req { INVALID_MODULE_ID, INVALID_MODULE_CHANNEL_ID, Request::INITIALIZE, 0, 0, 0, 0, 0, _init_gen, _init_success }; + Constructible _channels[NUM_CHANNELS] { }; + Request_pool_channel_queue _chan_queue { }; + + public: + + void execute(bool &) override; + + Request_pool(); +}; #endif /* _TRESOR__REQUEST_POOL_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/sb_check.h b/repos/gems/src/lib/tresor/include/tresor/sb_check.h index d2d9ed2b9a..76dad0a18a 100644 --- a/repos/gems/src/lib/tresor/include/tresor/sb_check.h +++ b/repos/gems/src/lib/tresor/include/tresor/sb_check.h @@ -14,12 +14,8 @@ #ifndef _TRESOR__SB_CHECK_H_ #define _TRESOR__SB_CHECK_H_ -/* base includes */ -#include - /* tresor includes */ #include -#include namespace Tresor { @@ -31,78 +27,66 @@ namespace Tresor { class Tresor::Sb_check_request : public Module_request { - public: - - enum Type { INVALID = 0, CHECK = 1, }; + friend class Sb_check_channel; private: - friend class Sb_check; - friend class Sb_check_channel; - - Type _type { INVALID }; - bool _success { false }; + bool &_success; + NONCOPYABLE(Sb_check_request); public: - Sb_check_request() { } + Sb_check_request(Module_id, Module_channel_id, bool &); - Sb_check_request(Module_id src_module_id, - Module_request_id src_request_id); - - static void create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type); - - Type type() const { return _type; } - - bool success() const { return _success; } - - static char const *type_to_string(Type type); - - - /******************** - ** Module_request ** - ********************/ - - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } + void print(Output &out) const override { Genode::print(out, "check"); } }; -class Tresor::Sb_check_channel +class Tresor::Sb_check_channel : public Module_channel { private: - friend class Sb_check; - using Request = Sb_check_request; - enum State { INSPECT_SBS, CHECK_SB }; + enum State { REQ_SUBMITTED, REQ_COMPLETE, READ_BLK_SUCCESSFUL, REQ_GENERATED, CHECK_VBD_SUCCESSFUL, CHECK_FT_SUCCESSFUL, CHECK_MT_SUCCESSFUL}; - enum Sb_slot_state { - INACTIVE, INIT, DONE, - READ_STARTED, READ_DROPPED, READ_DONE, - VBD_CHECK_STARTED, VBD_CHECK_DROPPED, VBD_CHECK_DONE, - FT_CHECK_STARTED, FT_CHECK_DROPPED, FT_CHECK_DONE, - MT_CHECK_STARTED, MT_CHECK_DROPPED, MT_CHECK_DONE }; + State _state { REQ_COMPLETE }; + Request *_req_ptr { }; + Generation _highest_gen { 0 }; + Superblock_index _highest_gen_sb_idx { 0 }; + bool _scan_for_highest_gen_sb_done { false }; + Superblock_index _sb_idx { 0 }; + Superblock _sb { }; + Snapshot_index _snap_idx { 0 }; + Constructible _tree_root { }; + Block _blk { }; + bool _generated_req_success { false }; - State _state { INSPECT_SBS }; - Request _request { }; - Generation _highest_gen { 0 }; - Superblock_index _last_sb_slot_idx { 0 }; - Sb_slot_state _sb_slot_state { INACTIVE }; - Superblock_index _sb_slot_idx { 0 }; - Superblock _sb_slot { }; - Snapshot_index _snap_idx { 0 }; - Type_1_node _vbd { }; - Type_1_node _ft { }; - Type_1_node _mt { }; - Physical_block_address _gen_prim_blk_nr { 0 }; - bool _gen_prim_success { false }; - Block _encoded_blk { }; + NONCOPYABLE(Sb_check_channel); + + void _generated_req_completed(State_uint) override; + + void _request_submitted(Module_request &) override; + + bool _request_complete() override { return _state == REQ_COMPLETE; } + + template + void _generate_req(State_uint state, bool &progress, ARGS &&... args) + { + _state = REQ_GENERATED; + generate_req(state, progress, args..., _generated_req_success); + } + + void _mark_req_failed(bool &, char const *); + + void _mark_req_successful(bool &); + + public: + + Sb_check_channel(Module_channel_id id) : Module_channel { SB_CHECK, id } { } + + void execute(bool &); }; @@ -110,58 +94,17 @@ class Tresor::Sb_check : public Module { private: - using Request = Sb_check_request; using Channel = Sb_check_channel; - enum { NR_OF_CHANNELS = 1 }; - - Channel _channels[NR_OF_CHANNELS] { }; - - static char const *_state_to_step_label(Channel::Sb_slot_state state); - - bool _handle_failed_generated_req(Channel &chan, - bool &progress); - - void _execute_check(Channel &channel, - bool &progress); - - void _mark_req_failed(Channel &channel, - bool &progress, - char const *str); - - void _mark_req_successful(Channel &channel, - bool &progress); - - - /************ - ** Module ** - ************/ - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; - - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_generated_request(Module_request &mod_req) override; - - void generated_request_complete(Module_request &req) override; + Constructible _channels[1] { }; + NONCOPYABLE(Sb_check); public: - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &req) override; + Sb_check(); void execute(bool &) override; - }; #endif /* _TRESOR__SB_CHECK_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/sb_initializer.h b/repos/gems/src/lib/tresor/include/tresor/sb_initializer.h index 2ef86d80e4..c387ab0d0c 100644 --- a/repos/gems/src/lib/tresor/include/tresor/sb_initializer.h +++ b/repos/gems/src/lib/tresor/include/tresor/sb_initializer.h @@ -1,5 +1,6 @@ /* * \brief Module for initializing the superblocks of a new Tresor + * \author Martin Stein * \author Josef Soentgen * \date 2023-03-14 */ @@ -14,11 +15,8 @@ #ifndef _TRESOR__SB_INITIALIZER_H_ #define _TRESOR__SB_INITIALIZER_H_ -/* base includes */ -#include - /* tresor includes */ -#include +#include namespace Tresor { @@ -30,124 +28,78 @@ namespace Tresor { class Tresor::Sb_initializer_request : public Module_request { - public: - - enum Type { INVALID = 0, INIT = 1, }; + friend class Sb_initializer_channel; private: - friend class Sb_initializer; - friend class Sb_initializer_channel; - - Type _type { INVALID }; - Tree_level_index _vbd_max_level_idx { 0 }; - Tree_degree _vbd_max_child_idx { 0 }; - Number_of_leaves _vbd_nr_of_leaves { 0 }; - Tree_level_index _ft_max_level_idx { 0 }; - Tree_degree _ft_max_child_idx { 0 }; - Number_of_leaves _ft_nr_of_leaves { 0 }; - Tree_level_index _mt_max_level_idx { 0 }; - Tree_degree _mt_max_child_idx { 0 }; - Number_of_leaves _mt_nr_of_leaves { 0 }; - bool _success { false }; + Tree_level_index _vbd_max_lvl; + Tree_degree _vbd_degree; + Number_of_leaves _vbd_num_leaves; + Tree_level_index _ft_max_lvl; + Tree_degree _ft_degree; + Number_of_leaves _ft_num_leaves; + Tree_level_index _mt_max_lvl; + Tree_degree _mt_degree; + Number_of_leaves _mt_num_leaves; + Pba_allocator &_pba_alloc; + bool &_success; + NONCOPYABLE(Sb_initializer_request); public: - Sb_initializer_request() { } + Sb_initializer_request(Module_id, Module_channel_id, Tree_level_index, Tree_degree, Number_of_leaves, + Tree_level_index, Tree_degree, Number_of_leaves, Tree_level_index, Tree_degree, + Number_of_leaves, Pba_allocator &, bool &); - Sb_initializer_request(Module_id src_module_id, - Module_request_id src_request_id); - - static void create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - Tree_level_index vbd_max_level_idx, - Tree_degree vbd_max_child_idx, - Number_of_leaves vbd_nr_of_leaves, - Tree_level_index ft_max_level_idx, - Tree_degree ft_max_child_idx, - Number_of_leaves ft_nr_of_leaves, - Tree_level_index mt_max_level_idx, - Tree_degree mt_max_child_idx, - Number_of_leaves mt_nr_of_leaves); - - Type type() const { return _type; } - - bool success() const { return _success; } - - static char const *type_to_string(Type type); - - - /******************** - ** Module_request ** - ********************/ - - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } + void print(Output &out) const override { Genode::print(out, "init"); } }; -class Tresor::Sb_initializer_channel +class Tresor::Sb_initializer_channel : public Module_channel { private: - friend class Sb_initializer; + using Request = Sb_initializer_request; enum State { - INACTIVE, SUBMITTED, PENDING, IN_PROGRESS, SLOT_COMPLETE, COMPLETE, - FT_REQUEST_COMPLETE, - FT_REQUEST_IN_PROGRESS, - FT_REQUEST_PENDING, - MT_REQUEST_COMPLETE, - MT_REQUEST_IN_PROGRESS, - MT_REQUEST_PENDING, - SYNC_REQUEST_COMPLETE, - SYNC_REQUEST_IN_PROGRESS, - SYNC_REQUEST_PENDING, - TA_REQUEST_CREATE_KEY_COMPLETE, - TA_REQUEST_CREATE_KEY_IN_PROGRESS, - TA_REQUEST_CREATE_KEY_PENDING, - TA_REQUEST_ENCRYPT_KEY_COMPLETE, - TA_REQUEST_ENCRYPT_KEY_IN_PROGRESS, - TA_REQUEST_ENCRYPT_KEY_PENDING, - TA_REQUEST_SECURE_SB_COMPLETE, - TA_REQUEST_SECURE_SB_IN_PROGRESS, - TA_REQUEST_SECURE_SB_PENDING, - VBD_REQUEST_COMPLETE, - VBD_REQUEST_IN_PROGRESS, - VBD_REQUEST_PENDING, - WRITE_REQUEST_COMPLETE, - WRITE_REQUEST_IN_PROGRESS, - WRITE_REQUEST_PENDING, - }; + REQ_SUBMITTED, START_NEXT_SB, SB_COMPLETE, REQ_COMPLETE, INIT_FT_SUCCEEDED, INIT_MT_SUCCEEDED, + WRITE_HASH_TO_TA, CREATE_KEY_SUCCEEDED, ENCRYPT_KEY_SUCCEEDED, SECURE_SB_SUCCEEDED, INIT_VBD_SUCCEEDED, + WRITE_BLK_SUCCEEDED, REQ_GENERATED }; - State _state { INACTIVE }; - Sb_initializer_request _request { }; - Superblock_index _sb_slot_index { 0 }; - Superblock _sb { }; - Block _encoded_blk { }; - Key _key_plain { }; - Key _key_cipher { }; - Hash _sb_hash { }; - Type_1_node _vbd_node { }; - Type_1_node _ft_node { }; - Type_1_node _mt_node { }; - bool _generated_req_success { false }; + State _state { REQ_COMPLETE }; + Request *_req_ptr { }; + Superblock_index _sb_idx { 0 }; + Superblock _sb { }; + Block _blk { }; + Hash _hash { }; + Constructible _vbd { }; + Constructible _mt { }; + Constructible _ft { }; + bool _generated_req_success { false }; - void clean_data() + NONCOPYABLE(Sb_initializer_channel); + + void _generated_req_completed(State_uint) override; + + void _request_submitted(Module_request &) override; + + bool _request_complete() override { return _state == REQ_COMPLETE; } + + template + void _generate_req(State_uint state, bool &progress, ARGS &&... args) { - _sb = Superblock { }; - - memset(&_key_plain, 0, sizeof(_key_plain)); - memset(&_key_cipher, 0, sizeof(_key_cipher)); - memset(&_sb_hash, 0, sizeof(_sb_hash)); - - memset(&_vbd_node, 0, sizeof(_vbd_node)); - memset(&_ft_node, 0, sizeof(_ft_node)); - memset(&_mt_node, 0, sizeof(_mt_node)); + _state = REQ_GENERATED; + generate_req(state, progress, args..., _generated_req_success); } + + void _mark_req_successful(bool &); + + public: + + Sb_initializer_channel(Module_channel_id id) : Module_channel { SB_INITIALIZER, id } { } + + void execute(bool &); }; @@ -155,62 +107,17 @@ class Tresor::Sb_initializer : public Module { private: - using Request = Sb_initializer_request; using Channel = Sb_initializer_channel; - enum { NR_OF_CHANNELS = 1 }; - - Channel _channels[NR_OF_CHANNELS] { }; - - void _populate_sb_slot(Channel &channel, - Physical_block_address first, - Number_of_blocks num); - - void _execute(Channel &channel, - bool &progress); - - void _execute_init(Channel &channel, - bool &progress); - - void _mark_req_failed(Channel &channel, - bool &progress, - char const *str); - - void _mark_req_successful(Channel &channel, - bool &progress); - - - /************ - ** Module ** - ************/ - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; - - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_generated_request(Module_request &mod_req) override; - - void generated_request_complete(Module_request &req) override; + Constructible _channels[1] { }; + NONCOPYABLE(Sb_initializer); public: Sb_initializer(); - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &req) override; - void execute(bool &) override; - }; #endif /* _TRESOR__SB_INITIALIZER_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/sha256_4k_hash.h b/repos/gems/src/lib/tresor/include/tresor/sha256_4k_hash.h deleted file mode 100644 index 850b9485dd..0000000000 --- a/repos/gems/src/lib/tresor/include/tresor/sha256_4k_hash.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * \brief Calculate SHA256 hash over data blocks of a size of 4096 bytes - * \author Martin Stein - * \date 2023-02-13 - */ - -/* - * Copyright (C) 2023 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _TRESOR__SHAE256_4K_HASH_H_ -#define _TRESOR__SHAE256_4K_HASH_H_ - -namespace Tresor { - - class Block; - class Hash; - - void calc_sha256_4k_hash(Block const &blk, - Hash &hash); - - - bool check_sha256_4k_hash(Block const &blk, - Hash const &expected_hash); -} - -#endif /* _TRESOR__SHAE256_4K_HASH_ */ 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 48cc1a73f8..09e2127525 100644 --- a/repos/gems/src/lib/tresor/include/tresor/superblock_control.h +++ b/repos/gems/src/lib/tresor/include/tresor/superblock_control.h @@ -1,5 +1,5 @@ /* - * \brief Module for management of the superblocks + * \brief Module for accessing and managing the superblocks * \author Martin Stein * \date 2023-02-13 */ @@ -16,7 +16,9 @@ /* tresor includes */ #include -#include +#include +#include +#include namespace Tresor { @@ -25,378 +27,157 @@ namespace Tresor { class Superblock_control_channel; } -class Tresor::Superblock_control_request : public Module_request +class Tresor::Superblock_control_request : Module_request, Noncopyable { + friend class Superblock_control_channel; + public: enum Type { - INVALID = 0, READ_VBA = 1, WRITE_VBA = 2, SYNC = 3, INITIALIZE = 4, - DEINITIALIZE = 5, - VBD_EXTENSION_STEP = 6, - FT_EXTENSION_STEP = 7, - CREATE_SNAPSHOT = 8, - DISCARD_SNAPSHOT = 9, - INITIALIZE_REKEYING = 10, - REKEY_VBA = 11 - }; + READ_VBA, WRITE_VBA, SYNC, INITIALIZE, DEINITIALIZE, VBD_EXTENSION_STEP, + FT_EXTENSION_STEP, CREATE_SNAPSHOT, DISCARD_SNAPSHOT, INITIALIZE_REKEYING, + REKEY_VBA }; private: - friend class Superblock_control; - friend class Superblock_control_channel; - - Type _type { INVALID }; - uint64_t _client_req_offset { 0 }; - uint64_t _client_req_tag { 0 }; - Virtual_block_address _vba { 0 }; - Superblock::State _sb_state { Superblock::INVALID }; - Number_of_blocks _nr_of_blks { 0 }; - bool _success { false }; - bool _request_finished { false }; - addr_t _generation_ptr { 0 }; + Type const _type; + Request_offset const _client_req_offset; + Request_tag const _client_req_tag; + Number_of_blocks _nr_of_blks; + Virtual_block_address const _vba; + bool &_success; + bool &_client_req_finished; + Superblock::State &_sb_state; + Generation &_gen; public: - Superblock_control_request() { } + Superblock_control_request(Module_id, Module_channel_id, Type, Request_offset, + Request_tag, Number_of_blocks, Virtual_block_address, + bool &, bool &, Superblock::State &, Generation &); - Type type() const { return _type; } + static char const *type_to_string(Type); - Superblock_control_request(Module_id src_module_id, - Module_request_id src_request_id); - - static void create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - uint64_t client_req_offset, - uint64_t client_req_tag, - Number_of_blocks nr_of_blks, - 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; } - - static char const *type_to_string(Type type); - - - /******************** - ** Module_request ** - ********************/ - - void print(Output &out) const override - { - Genode::print(out, type_to_string(_type)); - switch (_type) { - case REKEY_VBA: - case READ_VBA: - case WRITE_VBA: - Genode::print(out, " ", _vba); - break; - default: - break; - } - } + void print(Output &) const override; }; -class Tresor::Superblock_control_channel + +class Tresor::Superblock_control_channel : public Module_channel { private: - friend class Superblock_control; + using Request = Superblock_control_request; - enum State { - SUBMITTED, - READ_VBA_AT_VBD_PENDING, - READ_VBA_AT_VBD_IN_PROGRESS, - READ_VBA_AT_VBD_COMPLETED, - WRITE_VBA_AT_VBD_PENDING, - WRITE_VBA_AT_VBD_IN_PROGRESS, - WRITE_VBA_AT_VBD_COMPLETED, - READ_SB_PENDING, - READ_SB_IN_PROGRESS, - READ_SB_COMPLETED, - READ_CURRENT_SB_PENDING, - READ_CURRENT_SB_IN_PROGRESS, - READ_CURRENT_SB_COMPLETED, - REKEY_VBA_IN_VBD_PENDING, - REKEY_VBA_IN_VBD_IN_PROGRESS, - REKEY_VBA_IN_VBD_COMPLETED, - VBD_EXT_STEP_IN_VBD_PENDING, - VBD_EXT_STEP_IN_VBD_IN_PROGRESS, - FT_EXT_STEP_IN_FT_PENDING, - FT_EXT_STEP_IN_FT_IN_PROGRESS, - TREE_EXT_STEP_IN_TREE_COMPLETED, - CREATE_KEY_PENDING, - CREATE_KEY_IN_PROGRESS, - CREATE_KEY_COMPLETED, - ENCRYPT_CURRENT_KEY_PENDING, - ENCRYPT_CURRENT_KEY_IN_PROGRESS, - ENCRYPT_CURRENT_KEY_COMPLETED, - ENCRYPT_PREVIOUS_KEY_PENDING, - ENCRYPT_PREVIOUS_KEY_IN_PROGRESS, - ENCRYPT_PREVIOUS_KEY_COMPLETED, - DECRYPT_CURRENT_KEY_PENDING, - DECRYPT_CURRENT_KEY_IN_PROGRESS, - DECRYPT_CURRENT_KEY_COMPLETED, - DECRYPT_PREVIOUS_KEY_PENDING, - DECRYPT_PREVIOUS_KEY_IN_PROGRESS, - DECRYPT_PREVIOUS_KEY_COMPLETED, - SYNC_CACHE_PENDING, - SYNC_CACHE_IN_PROGRESS, - SYNC_CACHE_COMPLETED, - ADD_KEY_AT_CRYPTO_MODULE_PENDING, - ADD_KEY_AT_CRYPTO_MODULE_IN_PROGRESS, - ADD_KEY_AT_CRYPTO_MODULE_COMPLETED, - ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING, - ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_IN_PROGRESS, - ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED, - ADD_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING, - ADD_CURRENT_KEY_AT_CRYPTO_MODULE_IN_PROGRESS, - ADD_CURRENT_KEY_AT_CRYPTO_MODULE_COMPLETED, - REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING, - REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_IN_PROGRESS, - REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED, - REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING, - REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_IN_PROGRESS, - REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_COMPLETED, - WRITE_SB_PENDING, - WRITE_SB_IN_PROGRESS, - WRITE_SB_COMPLETED, - SYNC_BLK_IO_PENDING, - SYNC_BLK_IO_IN_PROGRESS, - SYNC_BLK_IO_COMPLETED, - SECURE_SB_PENDING, - SECURE_SB_IN_PROGRESS, - SECURE_SB_COMPLETED, - MAX_SB_HASH_PENDING, - MAX_SB_HASH_IN_PROGRESS, - MAX_SB_HASH_COMPLETED, - COMPLETED - }; + enum State : State_uint { + INACTIVE, REQ_SUBMITTED, ACCESS_VBA_AT_VBD_SUCCEEDED, + REKEY_VBA_AT_VBD_SUCCEEDED, CREATE_KEY_SUCCEEDED, + TREE_EXT_STEP_IN_TREE_SUCCEEDED, DECRYPT_CURR_KEY_SUCCEEDED, + DECRYPT_PREV_KEY_SUCCEEDED, READ_SB_HASH_SUCCEEDED, ADD_PREV_KEY_SUCCEEDED, + ADD_CURR_KEY_SUCCEEDED, REMOVE_PREV_KEY_SUCCEEDED, REMOVE_CURR_KEY_SUCCEEDED, + READ_SB_SUCCEEDED, REQ_COMPLETE, REQ_GENERATED, SECURE_SB, SECURE_SB_SUCCEEDED }; - enum Tag_type { - TAG_SB_CTRL_VBD_VBD_EXT_STEP, - TAG_SB_CTRL_FT_FT_EXT_STEP, - TAG_SB_CTRL_VBD_RKG_REKEY_VBA, - TAG_SB_CTRL_VBD_RKG_READ_VBA, - TAG_SB_CTRL_VBD_RKG_WRITE_VBA, - TAG_SB_CTRL_TA_ENCRYPT_KEY, - TAG_SB_CTRL_CACHE, - TAG_SB_CTRL_BLK_IO_READ_SB, - TAG_SB_CTRL_BLK_IO_WRITE_SB, - TAG_SB_CTRL_BLK_IO_SYNC, - TAG_SB_CTRL_TA_SECURE_SB, - TAG_SB_CTRL_TA_LAST_SB_HASH, - TAG_SB_CTRL_TA_DECRYPT_KEY, - TAG_SB_CTRL_TA_CREATE_KEY, - TAG_SB_CTRL_CRYPTO_ADD_KEY, - TAG_SB_CTRL_CRYPTO_REMOVE_KEY, - }; + enum Secure_sb_state : State_uint { + SECURE_SB_INACTIVE, STARTED, ENCRYPT_CURR_KEY_SUCCEEDED, + SECURE_SB_REQ_GENERATED, ENCRYPT_PREV_KEY_SUCCEEDED, SYNC_CACHE_SUCCEEDED, + WRITE_SB_SUCCEEDED, SYNC_BLK_IO_SUCCEEDED, WRITE_SB_HASH_SUCCEEDED }; - struct Generated_prim + State _state { INACTIVE }; + Constructible _ft { }; + Constructible _mt { }; + Secure_sb_state _secure_sb_state { SECURE_SB_INACTIVE }; + Superblock _sb_ciphertext { }; + Block _blk { }; + Generation _gen { INVALID_GENERATION }; + Hash _hash { }; + Physical_block_address _pba { INVALID_PBA }; + Number_of_blocks _nr_of_leaves { 0 }; + Request *_req_ptr { nullptr }; + bool _gen_req_success { false }; + Superblock &_sb; + Superblock_index &_sb_idx; + Generation &_curr_gen; + + NONCOPYABLE(Superblock_control_channel); + + void _generated_req_completed(State_uint) override; + + void _request_submitted(Module_request &) override; + + bool _request_complete() override { return _state == REQ_COMPLETE; } + + void _mark_req_successful(bool &); + + void _mark_req_failed(bool &, char const *); + + void _access_vba(Virtual_block_device_request::Type, bool &); + + void _generate_vbd_req(Virtual_block_device_request::Type, State_uint, bool &, Key_id, Virtual_block_address); + + template + void _generate_req(State_uint complete_state, bool &progress, ARGS &&... args) { - enum Type { READ, WRITE, SYNC }; + generate_req(complete_state, progress, args..., _gen_req_success); + if (_state == SECURE_SB) + _secure_sb_state = SECURE_SB_REQ_GENERATED; + else + _state = REQ_GENERATED; + } - Type op { READ }; - bool succ { false }; - Tag_type tg { }; - uint64_t blk_nr { 0 }; - uint64_t idx { 0 }; - }; + void _start_secure_sb(bool &); - State _state { SUBMITTED }; - Superblock_control_request _request { }; - Generated_prim _generated_prim { }; - Key _key_plaintext { }; - Superblock _sb_ciphertext { }; - Block _encoded_blk { }; - Superblock_index _sb_idx { 0 }; - bool _sb_found { false }; - Superblock_index _read_sb_idx { 0 }; - Generation _generation { 0 }; - Snapshots _snapshots { }; - Hash _hash { }; - Key _curr_key_plaintext { }; - Key _prev_key_plaintext { }; - Physical_block_address _pba { 0 }; - Number_of_blocks _nr_of_leaves { 0 }; - Type_1_node _ft_root { }; - Tree_level_index _ft_max_lvl { 0 }; - Number_of_leaves _ft_nr_of_leaves { 0 }; + void _secure_sb(bool &); + + void _tree_ext_step(Superblock::State, bool, String<4>, bool &); + + void _rekey_vba(bool &); + + void _init_rekeying(bool &); + + void _discard_snap(bool &); + + void _create_snap(bool &); + + void _sync(bool &); + + void _initialize(bool &); + + void _deinitialize(bool &); public: - Superblock_control_request const &request() const { return _request; } + void execute(bool &); + + Superblock_control_channel(Module_channel_id, Superblock &, Superblock_index &, Generation &); }; class Tresor::Superblock_control : public Module { private: - using Request = Superblock_control_request; using Channel = Superblock_control_channel; - using Generated_prim = Channel::Generated_prim; - using Tag = Channel::Tag_type; - enum { NR_OF_CHANNELS = 1 }; + enum { NUM_CHANNELS = 1 }; - Superblock _sb { }; - Superblock_index _sb_idx { 0 }; - Generation _curr_gen { 0 }; - Channel _channels[NR_OF_CHANNELS] { }; - - void _mark_req_failed(Channel &chan, - bool &progress, - char const *str); - - void _mark_req_successful(Channel &chan, - bool &progress); - - static char const *_state_to_step_label(Channel::State state); - - bool _handle_failed_generated_req(Channel &chan, - bool &progress); - - void _secure_sb_init(Channel &chan, - uint64_t chan_idx, - bool &progress); - - void _secure_sb_encr_curr_key_compl(Channel &chan, - uint64_t chan_idx, - bool &progress); - - void _secure_sb_encr_prev_key_compl(Channel &chan, - uint64_t chan_idx, - bool &progress); - - void _secure_sb_sync_cache_compl(Channel &chan, - uint64_t chan_idx, - bool &progress); - - void _secure_sb_write_sb_compl(Channel &chan, - uint64_t chan_idx, - bool &progress); - - void _secure_sb_sync_blk_io_compl(Channel &chan, - 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); - - 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, - Superblock::State tree_ext_sb_state, - bool tree_ext_verbose, - Tag tree_ext_tag, - Channel::State tree_ext_pending_state, - String<4> tree_name, - bool &progress); - - void _execute_rekey_vba(Channel &chan, - uint64_t chan_idx, - bool &progress); - - void _execute_initialize_rekeying(Channel &chan, - uint64_t chan_idx, - bool &progress); - - void _execute_read_vba(Channel &, uint64_t const job_idx, - Superblock const &, bool &progress); - - void _execute_write_vba(Channel &, uint64_t const job_idx, - Superblock &, Generation const &, bool &progress); - - void _execute_initialize(Channel &, uint64_t const job_idx, - Superblock &, Superblock_index &, - Generation &, bool &progress); - - void _execute_deinitialize(Channel &, uint64_t const job_idx, - Superblock &, Superblock_index &, - Generation &, bool &progress); - - - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &req) override; - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; + Superblock _sb { }; + Superblock_index _sb_idx { INVALID_SB_IDX }; + Generation _curr_gen { INVALID_GENERATION }; + Constructible _channels[NUM_CHANNELS] { }; void execute(bool &) override; - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_generated_request(Module_request &mod_req) override; - - void generated_request_complete(Module_request &req) override; - public: - Virtual_block_address max_vba() const; + Virtual_block_address max_vba() const { return _sb.valid() ? _sb.max_vba() : 0; }; - Virtual_block_address resizing_nr_of_pbas() const; + Virtual_block_address resizing_nr_of_pbas() const { return _sb.resizing_nr_of_pbas; } - Virtual_block_address rekeying_vba() const; + Virtual_block_address rekeying_vba() const { return _sb.rekeying_vba; } - void snapshot_generations(Snapshot_generations &generations) const - { - if (_sb.valid()) { + Snapshots_info snapshots_info() const; - for (Snapshot_index idx { 0 }; - idx < MAX_NR_OF_SNAPSHOTS; - idx++) { + Superblock_info sb_info() const; - Snapshot const &snap { _sb.snapshots.items[idx] }; - if (snap.valid && snap.keep) - generations.items[idx] = snap.gen; - else - generations.items[idx] = INVALID_GENERATION; - } - } else { - - generations = Snapshot_generations { }; - } - } - - Superblock_info sb_info() const - { - if (_sb.valid()) - - return Superblock_info { - true, _sb.state == Superblock::REKEYING, - _sb.state == Superblock::EXTENDING_FT, - _sb.state == Superblock::EXTENDING_VBD }; - - else - - return Superblock_info { }; - } + Superblock_control(); }; #endif /* _TRESOR__SUPERBLOCK_CONTROL_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/trust_anchor.h b/repos/gems/src/lib/tresor/include/tresor/trust_anchor.h index 7c81dcf88d..b9a08d8ed2 100644 --- a/repos/gems/src/lib/tresor/include/tresor/trust_anchor.h +++ b/repos/gems/src/lib/tresor/include/tresor/trust_anchor.h @@ -16,8 +16,7 @@ /* tresor includes */ #include -#include -#include +#include namespace Tresor { @@ -28,73 +27,78 @@ namespace Tresor { class Tresor::Trust_anchor_request : public Module_request { + friend class Trust_anchor_channel; + public: - enum Type { - INVALID = 0, CREATE_KEY = 1, ENCRYPT_KEY = 2, DECRYPT_KEY = 3, - SECURE_SUPERBLOCK = 4, GET_LAST_SB_HASH = 5, INITIALIZE = 6 }; + enum Type { CREATE_KEY, ENCRYPT_KEY, DECRYPT_KEY, WRITE_HASH, READ_HASH, INITIALIZE }; private: - friend class Trust_anchor; - friend class Trust_anchor_channel; + Type const _type; + Key_value &_key_plaintext; + Key_value &_key_ciphertext; + Hash &_hash; + Passphrase const _pass; + bool &_success; - Type _type { INVALID }; - uint8_t _key_plaintext[KEY_SIZE] { 0 }; - uint8_t _key_ciphertext[KEY_SIZE] { 0 }; - Hash _hash { }; - addr_t _passphrase_ptr { 0 }; - bool _success { false }; + NONCOPYABLE(Trust_anchor_request); public: - Trust_anchor_request() { } + Trust_anchor_request(Module_id src, Module_channel_id, Type, Key_value &, Key_value &, Hash &, Passphrase, bool &); - Trust_anchor_request(Module_id src_module_id, - Module_request_id src_request_id); - - static void create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - void *key_plaintext_ptr, - void *key_ciphertext_ptr, - char const *passphrase_ptr, - void *hash_ptr); - - void *hash_ptr() { return (void *)&_hash; } - void *key_plaintext_ptr() { return (void *)&_key_plaintext; } - void *key_ciphertext_ptr() { return (void *)&_key_ciphertext; } - - Type type() const { return _type; } - - bool success() const { return _success; } - - static char const *type_to_string(Type type); - - - /******************** - ** Module_request ** - ********************/ + static char const *type_to_string(Type); void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } }; -class Tresor::Trust_anchor_channel +class Tresor::Trust_anchor_channel : public Module_channel { private: - friend class Trust_anchor; + using Request = Trust_anchor_request; - enum State { - INACTIVE, SUBMITTED, WRITE_PENDING, WRITE_IN_PROGRESS, - READ_PENDING, READ_IN_PROGRESS, COMPLETE }; + enum State { REQ_SUBMITTED, REQ_COMPLETE, READ_OK, WRITE_OK, FILE_ERR }; - State _state { INACTIVE }; - Trust_anchor_request _request { }; - Vfs::file_offset _file_offset { 0 }; - size_t _file_size { 0 }; + State _state { REQ_COMPLETE }; + Vfs::Env &_vfs_env; + char _result_buf[3]; + Tresor::Path const _path; + Read_write_file _decrypt_file { _state, _vfs_env, { _path, "/decrypt" } }; + Read_write_file _encrypt_file { _state, _vfs_env, { _path, "/encrypt" } }; + Read_write_file _generate_key_file { _state, _vfs_env, { _path, "/generate_key" } }; + Read_write_file _initialize_file { _state, _vfs_env, { _path, "/initialize" } }; + Read_write_file _hashsum_file { _state, _vfs_env, { _path, "/hashsum" } }; + Trust_anchor_request *_req_ptr { nullptr }; + + NONCOPYABLE(Trust_anchor_channel); + + void _request_submitted(Module_request &) override; + + bool _request_complete() override { return _state == REQ_COMPLETE; } + + void _create_key(bool &); + + void _read_hash(bool &); + + void _initialize(bool &); + + void _write_hash(bool &); + + void _encrypt_key(bool &); + + void _decrypt_key(bool &); + + void _mark_req_failed(bool &, Error_string); + + void _mark_req_successful(bool &); + + public: + + void execute(bool &); + + Trust_anchor_channel(Module_channel_id, Vfs::Env &, Xml_node const &); }; class Tresor::Trust_anchor : public Module @@ -103,71 +107,50 @@ class Tresor::Trust_anchor : public Module using Request = Trust_anchor_request; using Channel = Trust_anchor_channel; - using Read_result = Vfs::File_io_service::Read_result; - using Write_result = Vfs::File_io_service::Write_result; - enum { NR_OF_CHANNELS = 1 }; + Constructible _channels[1] { }; - Vfs::Env &_vfs_env; - char _read_buf[64]; - String<128> const _path; - String<128> const _decrypt_path { _path, "/decrypt" }; - Vfs::Vfs_handle &_decrypt_file { vfs_open_rw(_vfs_env, { _decrypt_path }) }; - String<128> const _encrypt_path { _path, "/encrypt" }; - Vfs::Vfs_handle &_encrypt_file { vfs_open_rw(_vfs_env, { _encrypt_path }) }; - String<128> const _generate_key_path { _path, "/generate_key" }; - Vfs::Vfs_handle &_generate_key_file { vfs_open_rw(_vfs_env, { _generate_key_path }) }; - String<128> const _initialize_path { _path, "/initialize" }; - Vfs::Vfs_handle &_initialize_file { vfs_open_rw(_vfs_env, { _initialize_path }) }; - String<128> const _hashsum_path { _path, "/hashsum" }; - Vfs::Vfs_handle &_hashsum_file { vfs_open_rw(_vfs_env, { _hashsum_path }) }; - Channel _channels[NR_OF_CHANNELS] { }; - - void - _execute_write_read_operation(Vfs::Vfs_handle &file, - String<128> const &file_path, - Channel &channel, - char const *write_buf, - char *read_buf, - size_t read_size, - bool &progress); - - void _execute_write_operation(Vfs::Vfs_handle &file, - String<128> const &file_path, - Channel &channel, - char const *write_buf, - bool &progress, - bool result_via_read); - - void _execute_read_operation(Vfs::Vfs_handle &file, - String<128> const &file_path, - Channel &channel, - char *read_buf, - bool &progress); - - - /************ - ** Module ** - ************/ - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; + NONCOPYABLE(Trust_anchor); public: - Trust_anchor(Vfs::Env &vfs_env, - Xml_node const &xml_node); + struct Create_key : Request + { + Create_key(Module_id m, Module_channel_id c, Key_value &k, bool &s) + : Request(m, c, Request::CREATE_KEY, k, *(Key_value*)0, *(Hash*)0, Passphrase(), s) { } + }; + struct Encrypt_key : Request + { + Encrypt_key(Module_id m, Module_channel_id c, Key_value const &kp, Key_value &kc, bool &s) + : Request(m, c, Request::ENCRYPT_KEY, *const_cast(&kp), kc, *(Hash*)0, Passphrase(), s) { } + }; - /************ - ** Module ** - ************/ + struct Decrypt_key : Request + { + Decrypt_key(Module_id m, Module_channel_id c, Key_value &kp, Key_value const &kc, bool &s) + : Request(m, c, Request::DECRYPT_KEY, kp, *const_cast(&kc), *(Hash*)0, Passphrase(), s) { } + }; - bool ready_to_submit_request() override; + struct Write_hash : Request + { + Write_hash(Module_id m, Module_channel_id c, Hash const &h, bool &s) + : Request(m, c, Request::WRITE_HASH, *(Key_value*)0, *(Key_value*)0, *const_cast(&h), Passphrase(), s) { } + }; - void submit_request(Module_request &req) override; + struct Read_hash : Request + { + Read_hash(Module_id m, Module_channel_id c, Hash &h, bool &s) + : Request(m, c, Request::READ_HASH, *(Key_value*)0, *(Key_value*)0, h, Passphrase(), s) { } + }; + + struct Initialize : Request + { + Initialize(Module_id src_mod, Module_channel_id src_chan, Passphrase pass, bool &succ) + : Request(src_mod, src_chan, Request::INITIALIZE, *(Key_value*)0, *(Key_value*)0, *(Hash*)0, pass, succ) { } + }; + + Trust_anchor(Vfs::Env &, Xml_node const &); void execute(bool &) override; }; diff --git a/repos/gems/src/lib/tresor/include/tresor/types.h b/repos/gems/src/lib/tresor/include/tresor/types.h index ab6dcd101c..9ad7c43a7d 100644 --- a/repos/gems/src/lib/tresor/include/tresor/types.h +++ b/repos/gems/src/lib/tresor/include/tresor/types.h @@ -16,16 +16,14 @@ #define _TRESOR__TYPES_H_ /* base includes */ -#include -#include +#include /* os includes */ #include /* tresor includes */ -#include #include -#include +#include namespace Tresor { @@ -46,9 +44,15 @@ namespace Tresor { using Snapshot_index = uint32_t; using Superblock_index = uint8_t; using On_disc_bool = uint8_t; + using Request_offset = uint64_t; + using Request_tag = uint64_t; + using Passphrase = String<64>; + using Error_string = String<128>; enum { BLOCK_SIZE = 4096 }; enum { INVALID_KEY_ID = 0 }; + enum { INVALID_REQ_TAG = 0xffff'ffff }; + enum { INVALID_SB_IDX = 0xff }; enum { INVALID_GENERATION = 0 }; enum { INITIAL_GENERATION = 0 }; enum { MAX_PBA = 0xffff'ffff'ffff'ffff }; @@ -57,18 +61,12 @@ namespace Tresor { enum { MAX_GENERATION = 0xffff'ffff'ffff'ffff }; enum { MAX_SNAP_ID = 0xffff'ffff }; enum { HASH_SIZE = 32 }; - enum { T1_NODE_STORAGE_SIZE = 64 }; - enum { T2_NODE_STORAGE_SIZE = 64 }; - enum { NR_OF_T2_NODES_PER_BLK = (size_t)BLOCK_SIZE / (size_t)T2_NODE_STORAGE_SIZE }; - enum { NR_OF_T1_NODES_PER_BLK = (size_t)BLOCK_SIZE / (size_t)T1_NODE_STORAGE_SIZE }; + enum { ON_DISC_NODE_SIZE = 64 }; + enum { NUM_NODES_PER_BLK = (size_t)BLOCK_SIZE / (size_t)ON_DISC_NODE_SIZE }; enum { TREE_MAX_DEGREE_LOG_2 = 6 }; enum { TREE_MAX_DEGREE = 1 << TREE_MAX_DEGREE_LOG_2 }; enum { TREE_MAX_LEVEL = 6 }; enum { TREE_MAX_NR_OF_LEVELS = TREE_MAX_LEVEL + 1 }; - enum { T2_NODE_LVL = 1 }; - enum { VBD_LOWEST_T1_LVL = 1 }; - enum { FT_LOWEST_T1_LVL = 2 }; - enum { MT_LOWEST_T1_LVL = 2 }; enum { KEY_SIZE = 32 }; enum { MAX_NR_OF_SNAPSHOTS = 48 }; enum { MAX_SNAP_IDX = MAX_NR_OF_SNAPSHOTS - 1 }; @@ -91,15 +89,19 @@ namespace Tresor { struct Superblock; struct Superblock_info; struct Snapshot; - struct Snapshot_generations; + struct Snapshots_info; struct Snapshots; struct Type_1_node; struct Type_1_node_block; struct Type_1_node_walk; + struct Type_1_node_block_walk; struct Type_2_node; struct Type_2_node_block; struct Tree_walk_pbas; + struct Tree_walk_generations; struct Level_indent; + struct Tree_root; + class Pba_allocator; template class Fixed_length; @@ -114,24 +116,16 @@ namespace Tresor { return to_the_power_of(degree, max_lvl) - 1; } - inline Physical_block_address - alloc_pba_from_resizing_contingent(Physical_block_address &first_pba, - Number_of_blocks &nr_of_pbas) + inline Physical_block_address alloc_pba_from_range(Physical_block_address &first_pba, Number_of_blocks &num_pbas) { - if (nr_of_pbas == 0) { - class Exception_1 { }; - throw Exception_1 { }; - } - Physical_block_address const allocated_pba { first_pba }; - first_pba = first_pba + 1; - nr_of_pbas = nr_of_pbas - 1; - return allocated_pba; + ASSERT(num_pbas); + first_pba++; + num_pbas--; + return first_pba - 1; } inline Tree_node_index - t1_child_idx_for_vba_typed(Virtual_block_address vba, - Tree_level_index lvl, - Tree_degree degr) + t1_node_idx_for_vba_typed(Virtual_block_address vba, Tree_level_index lvl, Tree_degree degr) { uint64_t const degr_log_2 { log2(degr) }; uint64_t const degr_mask { ((uint64_t)1 << degr_log_2) - 1 }; @@ -140,59 +134,89 @@ namespace Tresor { } template - inline Tree_node_index t1_child_idx_for_vba(T1 vba, - T2 lvl, - T3 degr) + inline Tree_node_index t1_node_idx_for_vba(T1 vba, T2 lvl, T3 degr) { - return t1_child_idx_for_vba_typed((Virtual_block_address)vba, - (Tree_level_index)lvl, - (Tree_degree)degr); + return t1_node_idx_for_vba_typed((Virtual_block_address)vba, (Tree_level_index)lvl, (Tree_degree)degr); } - inline Tree_node_index t2_child_idx_for_vba(Virtual_block_address vba, - Tree_degree degr) + inline Tree_node_index t2_node_idx_for_vba(Virtual_block_address vba, Tree_degree degr) { uint64_t const degr_log_2 { log2(degr) }; uint64_t const degr_mask { ((uint64_t)1 << degr_log_2) - 1 }; return (Tree_node_index)((uint64_t)vba & degr_mask); } + + inline Virtual_block_address vbd_node_min_vba(Tree_degree_log_2 vbd_degr_log_2, + Tree_level_index vbd_lvl, + Virtual_block_address vbd_leaf_vba) + { + return vbd_leaf_vba & (~(Physical_block_address)0 << ((Physical_block_address)vbd_degr_log_2 * vbd_lvl)); + } + + inline Number_of_blocks vbd_node_num_vbas(Tree_degree_log_2 vbd_degr_log_2, Tree_level_index vbd_lvl) + { + return (Number_of_blocks)1 << ((Number_of_blocks)vbd_degr_log_2 * vbd_lvl); + } + + inline Virtual_block_address vbd_node_max_vba(Tree_degree_log_2 vbd_degr_log_2, + Tree_level_index vbd_lvl, + Virtual_block_address vbd_leaf_vba) + { + return vbd_node_num_vbas(vbd_degr_log_2, vbd_lvl) - 1 + vbd_node_min_vba(vbd_degr_log_2, vbd_lvl, vbd_leaf_vba); + } } +class Tresor::Pba_allocator +{ + private: + + Physical_block_address const _first_pba; + Number_of_blocks _num_used_pbas { 0 }; + + public: + + Pba_allocator(Physical_block_address const first_pba) : _first_pba { first_pba } { } + + Number_of_blocks num_used_pbas() { return _num_used_pbas; } + + Physical_block_address first_pba() { return _first_pba; } + + bool alloc(Physical_block_address &pba) + { + if (_num_used_pbas > MAX_PBA - _first_pba) + return false; + + pba = _first_pba + _num_used_pbas; + _num_used_pbas++; + return true; + } +}; + + struct Tresor::Byte_range { uint8_t const *ptr; - size_t size; + size_t size; void print(Output &out) const { using Genode::print; - enum { MAX_BYTES_PER_LINE = 64 }; enum { MAX_BYTES_PER_WORD = 4 }; - - if (size > 0xffff) { - class Exception_1 { }; - throw Exception_1 { }; - } + ASSERT(size <= 0xffff); if (size > MAX_BYTES_PER_LINE) { - for (size_t idx { 0 }; idx < size; idx++) { - if (idx % MAX_BYTES_PER_LINE == 0) - print(out, "\n ", - Hex((uint16_t)idx, Hex::PREFIX, Hex::PAD), ": "); + print(out, "\n ", Hex((uint16_t)idx, Hex::PREFIX, Hex::PAD), ": "); else if (idx % MAX_BYTES_PER_WORD == 0) print(out, " "); print(out, Hex(ptr[idx], Hex::OMIT_PREFIX, Hex::PAD)); } - } else { - for (size_t idx { 0 }; idx < size; idx++) { - if (idx % MAX_BYTES_PER_WORD == 0 && idx != 0) print(out, " "); @@ -450,6 +474,11 @@ struct Tresor::Type_1_node hash != node.hash; } + bool is_volatile(Generation curr_gen) const + { + return gen == INITIAL_GENERATION || gen == curr_gen; + } + void print(Output &out) const { Genode::print(out, "pba ", pba, " gen ", gen, " hash ", hash); @@ -457,9 +486,26 @@ struct Tresor::Type_1_node }; +struct Tresor::Tree_root +{ + Physical_block_address &pba; + Generation &gen; + Hash &hash; + Tree_level_index &max_lvl; + Tree_degree °ree; + Number_of_leaves &num_leaves; + + Type_1_node t1_node() const { return { pba, gen, hash }; } + + void t1_node(Type_1_node const &node) { pba = node.pba; gen = node.gen; hash = node.hash; } + + void print(Output &out) const { Genode::print(out, t1_node(), " maxlvl ", max_lvl, " degr ", degree, " leaves ", num_leaves); } +}; + + struct Tresor::Type_1_node_block { - Type_1_node nodes[NR_OF_T1_NODES_PER_BLK] { }; + Type_1_node nodes[NUM_NODES_PER_BLK] { }; void decode_from_blk(Block const &blk) { @@ -477,6 +523,12 @@ struct Tresor::Type_1_node_block }; +struct Tresor::Type_1_node_block_walk +{ + Type_1_node_block items[TREE_MAX_NR_OF_LEVELS] { }; +}; + + struct Tresor::Type_2_node { Physical_block_address pba { 0 }; @@ -531,7 +583,7 @@ struct Tresor::Type_2_node struct Tresor::Type_2_node_block { - Type_2_node nodes[NR_OF_T2_NODES_PER_BLK] { }; + Type_2_node nodes[NUM_NODES_PER_BLK] { }; void decode_from_blk(Block const &blk) { @@ -610,7 +662,7 @@ struct Tresor::Snapshots void print(Output &out) const { - bool first { false }; + bool first { true }; for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { if (!items[idx].valid) @@ -647,31 +699,27 @@ struct Tresor::Snapshots } } - Snapshot_index newest_snapshot_idx() const + Snapshot_index newest_snap_idx() const { Snapshot_index result { INVALID_SNAP_IDX }; for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx ++) { - - Snapshot const &snap { items[idx] }; - if (!snap.valid) + if (!items[idx].valid) continue; - if (result != INVALID_SNAP_IDX && - snap.gen <= items[result].gen) + if (result != INVALID_SNAP_IDX && items[idx].gen <= items[result].gen) continue; result = idx; } - if (result != INVALID_SNAP_IDX) - return result; - - class Exception_1 { }; - throw Exception_1 { }; + ASSERT(result != INVALID_SNAP_IDX); + return result; } - Snapshot_index - idx_of_invalid_or_lowest_gen_evictable_snap(Generation curr_gen, - Generation last_secured_gen) const + /** + * Returns the index of an unused slot or, if all are used, of the slot + * that contains the lowest-generation evictable snapshot (no "keep" flag). + */ + Snapshot_index alloc_idx(Generation curr_gen, Generation last_secured_gen) const { Snapshot_index result { INVALID_SNAP_IDX }; for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx ++) { @@ -691,11 +739,8 @@ struct Tresor::Snapshots result = idx; } - if (result != INVALID_SNAP_IDX) - return result; - - class Exception_1 { }; - throw Exception_1 { }; + ASSERT(result != INVALID_SNAP_IDX); + return result; } }; @@ -714,20 +759,20 @@ struct Tresor::Superblock Key previous_key { }; // offset 25 Key current_key { }; // offset 61 Snapshots snapshots { }; // offset 97 - Generation last_secured_generation { }; // offset 3553 - Snapshot_index curr_snap { }; // offset 3561 + Generation last_secured_generation { 0 }; // offset 3553 + Snapshot_index curr_snap_idx { 0 }; // offset 3561 Tree_degree degree { TREE_MIN_DEGREE }; // offset 3565 Physical_block_address first_pba { 0 }; // offset 3569 Number_of_blocks nr_of_pbas { 0 }; // offset 3577 Generation free_gen { 0 }; // offset 3585 Physical_block_address free_number { 0 }; // offset 3593 - Hash free_hash { 0 }; // offset 3601 + Hash free_hash { }; // offset 3601 Tree_level_index free_max_level { 0 }; // offset 3633 Tree_degree free_degree { TREE_MIN_DEGREE }; // offset 3637 Number_of_leaves free_leaves { 0 }; // offset 3641 Generation meta_gen { 0 }; // offset 3649 Physical_block_address meta_number { 0 }; // offset 3657 - Hash meta_hash { 0 }; // offset 3665 + Hash meta_hash { }; // offset 3665 Tree_level_index meta_max_level { 0 }; // offset 3697 Tree_degree meta_degree { TREE_MIN_DEGREE }; // offset 3701 Number_of_leaves meta_leaves { 0 }; // offset 3705 @@ -770,7 +815,7 @@ struct Tresor::Superblock current_key.decode_from_blk(scanner); snapshots.decode_from_blk(scanner); scanner.fetch(last_secured_generation); - scanner.fetch(curr_snap); + scanner.fetch(curr_snap_idx); scanner.fetch(degree); scanner.fetch(first_pba); scanner.fetch(nr_of_pbas); @@ -800,7 +845,7 @@ struct Tresor::Superblock current_key.encode_to_blk(generator); snapshots.encode_to_blk(generator); generator.append(last_secured_generation); - generator.append(curr_snap); + generator.append(curr_snap_idx); generator.append(degree); generator.append(first_pba); generator.append(nr_of_pbas); @@ -835,7 +880,7 @@ struct Tresor::Superblock { Genode::print( out, "state ", state_to_str(state), " last_secured_gen ", - last_secured_generation, " curr_snap ", curr_snap, " degr ", + last_secured_generation, " curr_snap ", curr_snap_idx, " degr ", degree, " first_pba ", first_pba, " pbas ", nr_of_pbas, " snapshots"); @@ -843,6 +888,43 @@ struct Tresor::Superblock if (snap.valid) Genode::print(out, " ", snap); } + + Snapshot &curr_snap() { return snapshots.items[curr_snap_idx]; } + Snapshot const &curr_snap() const { return snapshots.items[curr_snap_idx]; } + + Virtual_block_address max_vba() const + { + ASSERT(valid()); + return curr_snap().nr_of_leaves - 1; + } + + void copy_all_but_key_values_from(Superblock const &sb) + { + state = sb.state; + rekeying_vba = sb.rekeying_vba; + resizing_nr_of_pbas = sb.resizing_nr_of_pbas; + resizing_nr_of_leaves = sb.resizing_nr_of_leaves; + first_pba = sb.first_pba; + nr_of_pbas = sb.nr_of_pbas; + previous_key.id = sb.previous_key.id; + current_key.id = sb.current_key.id; + snapshots = sb.snapshots; + last_secured_generation = sb.last_secured_generation; + curr_snap_idx = sb.curr_snap_idx; + degree = sb.degree; + free_gen = sb.free_gen; + free_number = sb.free_number; + free_hash = sb.free_hash; + free_max_level = sb.free_max_level; + free_degree = sb.free_degree; + free_leaves = sb.free_leaves; + meta_gen = sb.meta_gen; + meta_number = sb.meta_number; + meta_hash = sb.meta_hash; + meta_max_level = sb.meta_max_level; + meta_degree = sb.meta_degree; + meta_leaves = sb.meta_leaves; + } }; @@ -884,9 +966,21 @@ struct Tresor::Tree_walk_pbas }; -struct Tresor::Snapshot_generations +struct Tresor::Tree_walk_generations { - Generation items[MAX_NR_OF_SNAPSHOTS] { 0 }; + Generation items[TREE_MAX_NR_OF_LEVELS] { }; +}; + + +struct Tresor::Snapshots_info +{ + Generation generations[MAX_NR_OF_SNAPSHOTS] { }; + + Snapshots_info() + { + for (Generation &gen : generations) + gen = INVALID_GENERATION; + } }; diff --git a/repos/gems/src/lib/tresor/include/tresor/vbd_check.h b/repos/gems/src/lib/tresor/include/tresor/vbd_check.h index 224d489a33..5a23231c2c 100644 --- a/repos/gems/src/lib/tresor/include/tresor/vbd_check.h +++ b/repos/gems/src/lib/tresor/include/tresor/vbd_check.h @@ -14,12 +14,8 @@ #ifndef _TRESOR__VBD_CHECK_H_ #define _TRESOR__VBD_CHECK_H_ -/* base includes */ -#include - /* tresor includes */ #include -#include namespace Tresor { @@ -31,94 +27,65 @@ namespace Tresor { class Tresor::Vbd_check_request : public Module_request { - public: - - enum Type { INVALID = 0, CHECK = 1, }; + friend class Vbd_check_channel; private: - friend class Vbd_check; - friend class Vbd_check_channel; + Tree_root const &_vbd; + bool &_success; - Type _type { INVALID }; - Tree_level_index _max_lvl { 0 }; - Tree_node_index _max_child_idx { 0 }; - Number_of_leaves _nr_of_leaves { 0 }; - Type_1_node _root { }; - bool _success { false }; + NONCOPYABLE(Vbd_check_request); public: - Vbd_check_request() { } + Vbd_check_request(Module_id, Module_channel_id, Tree_root const &, bool &); - Vbd_check_request(uint64_t src_module_id, - uint64_t src_request_id, - Type type, - Tree_level_index max_lvl, - Tree_node_index max_child_idx, - Number_of_leaves nr_of_leaves, - Type_1_node root); - - Type type() const { return _type; } - - bool success() const { return _success; } - - static char const *type_to_string(Type type); - - - /******************** - ** Module_request ** - ********************/ - - void print(Output &out) const override - { - Genode::print(out, type_to_string(_type), " root ", _root); - } + void print(Output &out) const override { Genode::print(out, "check ", _vbd); } }; -class Tresor::Vbd_check_channel +class Tresor::Vbd_check_channel : public Module_channel { private: - friend class Vbd_check; - using Request = Vbd_check_request; - enum Child_state { - READ_BLOCK = 0, CHECK_HASH = 1, DONE = 2 }; + enum State : State_uint { REQ_SUBMITTED, REQ_IN_PROGRESS, REQ_COMPLETE, REQ_GENERATED, READ_BLK_SUCCEEDED }; - struct Type_1_level + State _state { REQ_COMPLETE }; + Type_1_node_block_walk _t1_blks { }; + bool _check_node[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { }; + Block _blk { }; + Request *_req_ptr { }; + Number_of_leaves _num_remaining_leaves { 0 }; + bool _generated_req_success { false }; + + NONCOPYABLE(Vbd_check_channel); + + void _generated_req_completed(State_uint) override; + + void _request_submitted(Module_request &) override; + + bool _request_complete() override { return _state == REQ_COMPLETE; } + + void _mark_req_failed(bool &, Error_string); + + void _mark_req_successful(bool &); + + bool _execute_node(Tree_level_index, Tree_node_index, bool &); + + template + void _generate_req(State_uint state, bool &progress, ARGS &&... args) { - Child_state children_state[NR_OF_T1_NODES_PER_BLK] { }; - Type_1_node_block children { }; + _state = REQ_GENERATED; + generate_req(state, progress, args..., _generated_req_success); + } - Type_1_level() - { - for (Child_state &state : children_state) - state = DONE; - } - }; + public: - enum Primitive_tag { INVALID, BLOCK_IO }; + Vbd_check_channel(Module_channel_id id) : Module_channel { VBD_CHECK, id } { } - struct Generated_primitive - { - bool success { false }; - Primitive_tag tag { INVALID }; - Physical_block_address blk_nr { 0 }; - bool dropped { false }; - - bool valid() const { return tag != INVALID; } - }; - - Generated_primitive _gen_prim { }; - Tree_level_index _lvl_to_read { 0 }; - Child_state _root_state { DONE }; - Block _leaf_lvl { }; - Block _encoded_blk { }; - Type_1_level _t1_lvls[TREE_MAX_LEVEL] { }; - Request _request { }; + void execute(bool &); }; @@ -126,72 +93,17 @@ class Tresor::Vbd_check : public Module { private: - using Request = Vbd_check_request; using Channel = Vbd_check_channel; - using Child_state = Vbd_check_channel::Child_state; - using Type_1_level = Vbd_check_channel::Type_1_level; - enum { NR_OF_CHANNELS = 1 }; - - Channel _channels[NR_OF_CHANNELS] { }; - - void _execute_check(Channel &channel, - bool &progress); - - void _mark_req_failed(Channel &channel, - bool &progress, - char const *str); - - void _mark_req_successful(Channel &channel, - bool &progress); - - void _execute_inner_t1_child(Channel &chan, - Type_1_node const &child, - Type_1_level &child_lvl, - Child_state &child_state, - Tree_level_index lvl, - Tree_node_index child_idx, - bool &progress); - - - void _execute_leaf_child(Channel &chan, - Type_1_node const &child, - Block const &child_lvl, - Child_state &child_state, - Tree_level_index lvl, - Tree_node_index child_idx, - bool &progress); - - - /************ - ** Module ** - ************/ - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; - - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_generated_request(Module_request &mod_req) override; - - void generated_request_complete(Module_request &req) override; + Constructible _channels[1] { }; + NONCOPYABLE(Vbd_check); public: - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &req) override; + Vbd_check(); void execute(bool &) override; - }; #endif /* _TRESOR__VBD_CHECK_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/vbd_initializer.h b/repos/gems/src/lib/tresor/include/tresor/vbd_initializer.h index c990627b97..ac8db70ca4 100644 --- a/repos/gems/src/lib/tresor/include/tresor/vbd_initializer.h +++ b/repos/gems/src/lib/tresor/include/tresor/vbd_initializer.h @@ -1,5 +1,6 @@ /* * \brief Module for initializing the VBD + * \author Martin Stein * \author Josef Soentgen * \date 2023-03-03 */ @@ -14,11 +15,8 @@ #ifndef _TRESOR__VBD_INITIALIZER_H_ #define _TRESOR__VBD_INITIALIZER_H_ -/* base includes */ -#include - /* tresor includes */ -#include +#include namespace Tresor { @@ -30,116 +28,63 @@ namespace Tresor { class Tresor::Vbd_initializer_request : public Module_request { - public: - - enum Type { INVALID = 0, INIT = 1, }; + friend class Vbd_initializer_channel; private: - friend class Vbd_initializer; - friend class Vbd_initializer_channel; - - Type _type { INVALID }; - uint8_t _root_node[sizeof(Type_1_node)] { 0 }; - uint64_t _max_level_idx { 0 }; - uint64_t _max_child_idx { 0 }; - uint64_t _nr_of_leaves { 0 }; - bool _success { false }; + Tree_root &_vbd; + Pba_allocator &_pba_alloc; + bool &_success; + NONCOPYABLE(Vbd_initializer_request); public: - Vbd_initializer_request() { } + Vbd_initializer_request(Module_id, Module_channel_id, Tree_root &, Pba_allocator &, bool &); - Vbd_initializer_request(Module_id src_module_id, - Module_request_id src_request_id); - - static void create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - uint64_t max_level_idx, - uint64_t max_child_idx, - uint64_t nr_of_leaves); - - void *root_node() { return _root_node; } - - Type type() const { return _type; } - - bool success() const { return _success; } - - static char const *type_to_string(Type type); - - - /******************** - ** Module_request ** - ********************/ - - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } + void print(Output &out) const override { Genode::print(out, "init"); } }; -class Tresor::Vbd_initializer_channel +class Tresor::Vbd_initializer_channel : public Module_channel { private: - friend class Vbd_initializer; + using Request = Vbd_initializer_request; - enum State { - INACTIVE, SUBMITTED, PENDING, IN_PROGRESS, COMPLETE, - BLOCK_ALLOC_PENDING, - BLOCK_ALLOC_IN_PROGRESS, - BLOCK_ALLOC_COMPLETE, - BLOCK_IO_PENDING, - BLOCK_IO_IN_PROGRESS, - BLOCK_IO_COMPLETE, - }; + enum State { REQ_GENERATED, SUBMITTED, COMPLETE, EXECUTE_NODES }; - enum Child_state { DONE, INIT_BLOCK, INIT_NODE, WRITE_BLOCK, }; + enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITE_BLOCK }; - struct Type_1_level - { - Type_1_node_block children { }; - Child_state children_state[NR_OF_T1_NODES_PER_BLK] { DONE }; - }; + State _state { COMPLETE }; + Vbd_initializer_request *_req_ptr { }; + Type_1_node_block_walk _t1_blks { }; + Node_state _node_states[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { DONE }; + bool _generated_req_success { false }; + Block _blk { }; + Number_of_leaves _num_remaining_leaves { }; - struct Root_node - { - Type_1_node node { }; - Child_state state { DONE }; - }; + NONCOPYABLE(Vbd_initializer_channel); - State _state { INACTIVE }; - Vbd_initializer_request _request { }; - Root_node _root_node { }; - Type_1_level _t1_levels[TREE_MAX_LEVEL] { }; - uint64_t _level_to_write { 0 }; - uint64_t _blk_nr { 0 }; - uint64_t _child_pba { 0 }; - bool _generated_req_success { false }; - Block _encoded_blk { }; + void _generated_req_completed(State_uint) override; - static void reset_node(Type_1_node &node) - { - memset(&node, 0, sizeof(Type_1_node)); - } + bool _request_complete() override { return _state == COMPLETE; } - static void reset_level(Type_1_level &level, - Child_state state) - { - for (unsigned int i = 0; i < NR_OF_T1_NODES_PER_BLK; i++) { - reset_node(level.children.nodes[i]); - level.children_state[i] = state; - } - } + void _request_submitted(Module_request &) override; - static void dump(Type_1_node_block const &node_block) - { - for (auto v : node_block.nodes) { - log(v); - } - } + void _reset_level(Tree_level_index, Node_state); + + bool _execute_node(Tree_level_index, Tree_node_index, bool &); + + void _mark_req_failed(bool &, char const *); + + void _mark_req_successful(bool &); + + public: + + Vbd_initializer_channel(Module_channel_id id) : Module_channel { VBD_INITIALIZER, id } { } + + void execute(bool &); }; @@ -147,76 +92,17 @@ class Tresor::Vbd_initializer : public Module { private: - using Request = Vbd_initializer_request; using Channel = Vbd_initializer_channel; - enum { NR_OF_CHANNELS = 1 }; - - Channel _channels[NR_OF_CHANNELS] { }; - - void _execute_leaf_child(Channel &channel, - bool &progress, - uint64_t &nr_of_leaves, - Type_1_node &child, - Vbd_initializer_channel::Child_state &child_state, - uint64_t level_index, - uint64_t child_index); - - void _execute_inner_t1_child(Channel &channel, - bool &progress, - uint64_t nr_of_leaves, - uint64_t &level_to_write, - Type_1_node &child, - Vbd_initializer_channel::Type_1_level &child_level, - Vbd_initializer_channel::Child_state &child_state, - uint64_t level_index, - uint64_t child_index); - - void _execute(Channel &channel, - bool &progress); - - void _execute_init(Channel &channel, - bool &progress); - - void _mark_req_failed(Channel &channel, - bool &progress, - char const *str); - - void _mark_req_successful(Channel &channel, - bool &progress); - - - /************ - ** Module ** - ************/ - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; - - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_generated_request(Module_request &mod_req) override; - - void generated_request_complete(Module_request &req) override; + Constructible _channels[1] { }; + NONCOPYABLE(Vbd_initializer); public: Vbd_initializer(); - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &req) override; - void execute(bool &) override; - }; #endif /* _TRESOR__VBD_INITIALIZER_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/verbosity.h b/repos/gems/src/lib/tresor/include/tresor/verbosity.h index 394776b4c2..a9f32f1287 100644 --- a/repos/gems/src/lib/tresor/include/tresor/verbosity.h +++ b/repos/gems/src/lib/tresor/include/tresor/verbosity.h @@ -19,6 +19,8 @@ namespace Tresor { enum { VERBOSE_MODULE_COMMUNICATION = 0 }; enum { VERBOSE_VBD_EXTENSION = 0 }; enum { VERBOSE_FT_EXTENSION = 0 }; + enum { VERBOSE_VBD_INIT = 0 }; + enum { VERBOSE_FT_INIT = 0 }; enum { VERBOSE_REKEYING = 0 }; enum { VERBOSE_READ_VBA = 0 }; enum { VERBOSE_WRITE_VBA = 0 }; diff --git a/repos/gems/src/lib/tresor/include/tresor/vfs_utilities.h b/repos/gems/src/lib/tresor/include/tresor/vfs_utilities.h deleted file mode 100644 index bce620c001..0000000000 --- a/repos/gems/src/lib/tresor/include/tresor/vfs_utilities.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * \brief Utilities for a more convenient use of the VFS - * \author Martin Stein - * \date 2020-10-29 - */ - -/* - * Copyright (C) 2023 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _TRESOR__VFS_UTILITIES_H_ -#define _TRESOR__VFS_UTILITIES_H_ - -/* base includes */ -#include -#include - - -Vfs::Vfs_handle &vfs_open(Vfs::Env &vfs_env, - Genode::String<128> path, - Vfs::Directory_service::Open_mode mode); - - -Vfs::Vfs_handle &vfs_open_wo(Vfs::Env &vfs_env, - Genode::String<128> path); - - -Vfs::Vfs_handle &vfs_open_rw(Vfs::Env &vfs_env, - Genode::String<128> path); - - -#endif /* _TRESOR__VFS_UTILITIES_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/virtual_block_device.h b/repos/gems/src/lib/tresor/include/tresor/virtual_block_device.h index 856c75a167..0d58513a9a 100644 --- a/repos/gems/src/lib/tresor/include/tresor/virtual_block_device.h +++ b/repos/gems/src/lib/tresor/include/tresor/virtual_block_device.h @@ -15,9 +15,8 @@ #define _TRESOR__VIRTUAL_BLOCK_DEVICE_H_ /* tresor includes */ -#include #include -#include +#include namespace Tresor { @@ -28,230 +27,139 @@ namespace Tresor { class Tresor::Virtual_block_device_request : public Module_request { + friend class Virtual_block_device_channel; + public: - enum Type { - INVALID = 0, REKEY_VBA = 3, READ_VBA = 1, WRITE_VBA = 2, VBD_EXTENSION_STEP = 4 }; + enum Type { REKEY_VBA, READ_VBA, WRITE_VBA, EXTENSION_STEP }; private: - friend class Virtual_block_device; - friend class Virtual_block_device_channel; + Type const _type; + Virtual_block_address const _vba; + Snapshots &_snapshots; + Snapshot_index const _curr_snap_idx; + Tree_degree const _snap_degr; + Generation const _curr_gen; + Key_id const _curr_key_id; + Key_id const _prev_key_id; + Tree_root &_ft; + Tree_root &_mt; + Tree_degree const _vbd_degree; + Virtual_block_address const _vbd_highest_vba; + bool const _rekeying; + Request_offset const _client_req_offset; + Request_tag const _client_req_tag; + Generation const _last_secured_gen; + Physical_block_address &_pba; + Number_of_blocks &_num_pbas; + Number_of_leaves &_num_leaves; + bool &_success; - Type _type { INVALID }; - Virtual_block_address _vba { 0 }; - Snapshots _snapshots { }; - Snapshot_index _curr_snap_idx { 0 }; - Tree_degree _snapshots_degree { 0 }; - Generation _curr_gen { INVALID_GENERATION }; - Key_id _new_key_id { 0 }; - Key_id _old_key_id { 0 }; - addr_t _ft_root_pba_ptr { 0 }; - addr_t _ft_root_gen_ptr { 0 }; - addr_t _ft_root_hash_ptr { 0 }; - uint64_t _ft_max_level { 0 }; - uint64_t _ft_degree { 0 }; - uint64_t _ft_leaves { 0 }; - addr_t _mt_root_pba_ptr { 0 }; - addr_t _mt_root_gen_ptr { 0 }; - addr_t _mt_root_hash_ptr { 0 }; - uint64_t _mt_max_level { 0 }; - uint64_t _mt_degree { 0 }; - uint64_t _mt_leaves { 0 }; - uint64_t _vbd_degree { 0 }; - uint64_t _vbd_highest_vba { 0 }; - bool _rekeying { 0 }; - uint64_t _client_req_offset { 0 }; - uint64_t _client_req_tag { 0 }; - Generation _last_secured_generation { INVALID_GENERATION }; - Physical_block_address _pba { 0 }; - Number_of_blocks _nr_of_pbas { 0 }; - Number_of_leaves _nr_of_leaves { 0 }; - bool _success { false }; + NONCOPYABLE(Virtual_block_device_request); public: - Virtual_block_device_request() { } + Virtual_block_device_request(Module_id, Module_channel_id, Type, Request_offset, Request_tag, Generation, + Tree_root &, Tree_root &, Tree_degree, Virtual_block_address, bool, + Virtual_block_address, Snapshot_index, Snapshots &, Tree_degree, Key_id, + Key_id, Generation, Physical_block_address &, bool &, Number_of_leaves &, + Number_of_blocks &); - Virtual_block_device_request(Module_id src_module_id, - Module_request_id src_request_id); - - static void create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - uint64_t client_req_offset, - uint64_t client_req_tag, - Generation last_secured_generation, - addr_t ft_root_pba_ptr, - addr_t ft_root_gen_ptr, - addr_t ft_root_hash_ptr, - uint64_t ft_max_level, - uint64_t ft_degree, - uint64_t ft_leaves, - addr_t mt_root_pba_ptr, - addr_t mt_root_gen_ptr, - addr_t mt_root_hash_ptr, - uint64_t mt_max_level, - uint64_t mt_degree, - uint64_t mt_leaves, - uint64_t vbd_degree, - uint64_t vbd_highest_vba, - bool rekeying, - Virtual_block_address vba, - Snapshot_index curr_snap_idx, - Snapshots const *snapshots_ptr, - Tree_degree snapshots_degree, - Key_id old_key_id, - Key_id new_key_id, - Generation current_gen, - Key_id key_id, - Physical_block_address first_pba, - Number_of_blocks nr_of_pbas); - - bool success() const { return _success; } - - Physical_block_address pba() const { return _pba; } - - Number_of_blocks nr_of_pbas() const { return _nr_of_pbas; } - - Number_of_leaves nr_of_leaves() const { return _nr_of_leaves; } - - Snapshot_index curr_snap_idx() const { return _curr_snap_idx; } - - Snapshots *snapshots_ptr() { return &_snapshots; } - - static char const *type_to_string(Type type); - - char const *type_name() const { return type_to_string(_type); } - - - /******************** - ** Module_request ** - ********************/ + static char const *type_to_string(Type); void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } }; -class Tresor::Virtual_block_device_channel +class Tresor::Virtual_block_device_channel : public Module_channel { private: - friend class Virtual_block_device; - using Request = Virtual_block_device_request; enum State { - SUBMITTED, - READ_ROOT_NODE_PENDING, - READ_ROOT_NODE_IN_PROGRESS, - READ_ROOT_NODE_COMPLETED, - READ_INNER_NODE_PENDING, - READ_INNER_NODE_IN_PROGRESS, - READ_INNER_NODE_COMPLETED, - READ_LEAF_NODE_PENDING, - READ_LEAF_NODE_IN_PROGRESS, - READ_LEAF_NODE_COMPLETED, - READ_CLIENT_DATA_FROM_LEAF_NODE_PENDING, - READ_CLIENT_DATA_FROM_LEAF_NODE_IN_PROGRESS, - READ_CLIENT_DATA_FROM_LEAF_NODE_COMPLETED, - WRITE_CLIENT_DATA_TO_LEAF_NODE_PENDING, - WRITE_CLIENT_DATA_TO_LEAF_NODE_IN_PROGRESS, - WRITE_CLIENT_DATA_TO_LEAF_NODE_COMPLETED, - DECRYPT_LEAF_NODE_PENDING, - DECRYPT_LEAF_NODE_IN_PROGRESS, - DECRYPT_LEAF_NODE_COMPLETED, - ALLOC_PBAS_AT_LEAF_LVL_PENDING, - ALLOC_PBAS_AT_LEAF_LVL_IN_PROGRESS, - ALLOC_PBAS_AT_LEAF_LVL_COMPLETED, - ALLOC_PBAS_AT_LOWEST_INNER_LVL_PENDING, - ALLOC_PBAS_AT_LOWEST_INNER_LVL_IN_PROGRESS, - ALLOC_PBAS_AT_LOWEST_INNER_LVL_COMPLETED, - ALLOC_PBAS_AT_HIGHER_INNER_LVL_PENDING, - ALLOC_PBAS_AT_HIGHER_INNER_LVL_IN_PROGRESS, - ALLOC_PBAS_AT_HIGHER_INNER_LVL_COMPLETED, - ENCRYPT_LEAF_NODE_PENDING, - ENCRYPT_LEAF_NODE_IN_PROGRESS, - ENCRYPT_LEAF_NODE_COMPLETED, - WRITE_LEAF_NODE_PENDING, - WRITE_LEAF_NODE_IN_PROGRESS, - WRITE_LEAF_NODE_COMPLETED, - WRITE_INNER_NODE_PENDING, - WRITE_INNER_NODE_IN_PROGRESS, - WRITE_INNER_NODE_COMPLETED, - WRITE_ROOT_NODE_PENDING, - WRITE_ROOT_NODE_IN_PROGRESS, - WRITE_ROOT_NODE_COMPLETED, - COMPLETED - }; + SUBMITTED, REQ_GENERATED, REQ_COMPLETE, READ_BLK_SUCCEEDED, WRITE_BLK_SUCCEEDED, + DECRYPT_LEAF_DATA_SUCCEEDED, ENCRYPT_LEAF_DATA_SUCCEEDED, ALLOC_PBAS_SUCCEEDED }; - struct Type_1_node_blocks + Request *_req_ptr { nullptr }; + State _state { REQ_COMPLETE }; + Snapshot_index _snap_idx { 0 }; + Type_1_node_block_walk _t1_blks { }; + Type_1_node_walk _t1_nodes { }; + Tree_level_index _lvl { 0 }; + Virtual_block_address _vba { 0 }; + Tree_walk_pbas _old_pbas { }; + Tree_walk_pbas _new_pbas { }; + Hash _hash { }; + Number_of_blocks _num_blks { 0 }; + Generation _free_gen { 0 }; + Block _encoded_blk { }; + Block _data_blk { }; + bool _first_snapshot { false }; + bool _gen_req_success { false }; + + NONCOPYABLE(Virtual_block_device_channel); + + template + void _generate_req(State_uint complete_state, bool &progress, ARGS &&... args) { - Type_1_node_block items[TREE_MAX_LEVEL] { }; - }; - - struct Type_1_node_blocks_pbas - { - Physical_block_address items[TREE_MAX_LEVEL] { 0 }; - }; - - enum Tag_type - { - TAG_INVALID, - TAG_VBD_CACHE, - TAG_VBD_BLK_IO_WRITE_CLIENT_DATA, - TAG_VBD_BLK_IO_READ_CLIENT_DATA, - TAG_VBD_BLK_IO, - TAG_VBD_FT_ALLOC_FOR_NON_RKG, - TAG_VBD_FT_ALLOC_FOR_RKG_CURR_GEN_BLKS, - TAG_VBD_FT_ALLOC_FOR_RKG_OLD_GEN_BLKS, - TAG_VBD_CRYPTO_ENCRYPT, - TAG_VBD_CRYPTO_DECRYPT, - }; - - struct Generated_prim - { - enum Type { READ, WRITE }; - - Type op { READ }; - bool succ { false }; - Tag_type tg { TAG_INVALID }; - uint64_t blk_nr { 0 }; - uint64_t idx { 0 }; - }; - - Snapshot &snapshots(Snapshot_index idx) - { - if (idx < MAX_NR_OF_SNAPSHOTS) - return _request._snapshots.items[idx]; - - class Snapshot_idx_too_large { }; - throw Snapshot_idx_too_large { }; + generate_req(complete_state, progress, args..., _gen_req_success); + _state = REQ_GENERATED; } - Snapshot &snap(); + void _request_submitted(Module_request &) override; - void _log_rekeying_pba_alloc() const; + bool _request_complete() override { return _state == REQ_COMPLETE; } - Virtual_block_device_request _request { }; - State _state { SUBMITTED }; - Generated_prim _generated_prim { }; - Snapshot_index _snapshot_idx { 0 }; - Type_1_node_blocks _t1_blks { }; - Type_1_node_blocks_pbas _t1_blks_old_pbas { }; - Tree_level_index _t1_blk_idx { 0 }; - Virtual_block_address _vba { 0 }; - Type_1_node_walk _t1_node_walk { }; - Tree_walk_pbas _new_pbas { }; - Hash _hash { }; - Number_of_blocks _nr_of_blks { 0 }; - Generation _last_secured_gen { 0 }; - Generation _free_gen { 0 }; - Block _encoded_blk { }; - Block _data_blk { }; - Physical_block_address _data_blk_old_pba { 0 }; - bool _first_snapshot { false }; + void _generated_req_completed(State_uint) override; + + void _generate_ft_req(State, bool, Free_tree_request::Type); + + Snapshot &snap() { return _req_ptr->_snapshots.items[_snap_idx]; } + + void _generate_write_blk_req(bool &); + + bool _find_next_snap_to_rekey_vba_at(Snapshot_index &) const; + + void _read_vba(bool &); + + bool _check_and_decode_read_blk(bool &, bool); + + Tree_node_index _node_idx(Tree_level_index, Virtual_block_address) const; + + Type_1_node &_node(Tree_level_index, Virtual_block_address); + + void _mark_req_successful(bool &); + + void _mark_req_failed(bool &, char const *); + + void _set_new_pbas_and_num_blks_for_alloc(); + + void _generate_ft_alloc_req_for_write_vba(bool &); + + void _write_vba(bool &); + + void _update_nodes_of_branch_of_written_vba(); + + void _rekey_vba(bool &); + + void _generate_ft_alloc_req_for_rekeying(Tree_level_index, bool &); + + void _add_new_root_lvl_to_snap(); + + void _add_new_branch_to_snap(Tree_level_index, Tree_node_index); + + void _set_new_pbas_identical_to_curr_pbas(); + + void _generate_ft_alloc_req_for_resizing(Tree_level_index, bool &); + + void _extension_step(bool &); + + public: + + Virtual_block_device_channel(Module_channel_id id) : Module_channel { VIRTUAL_BLOCK_DEVICE, id } { } + + void execute(bool &); }; class Tresor::Virtual_block_device : public Module @@ -259,149 +167,16 @@ class Tresor::Virtual_block_device : public Module private: using Channel = Virtual_block_device_channel; - using Request = Virtual_block_device_request; - using Generated_prim = Channel::Generated_prim; - using Type_1_node_blocks = Channel::Type_1_node_blocks; - enum { NR_OF_CHANNELS = 1 }; - enum { FIRST_T1_NODE_BLKS_IDX = 1 }; - enum { MAX_T1_NODE_BLKS_IDX = 6 }; + Constructible _channels[1] { }; - Channel _channels[NR_OF_CHANNELS] { }; - - static char const *_state_to_step_label(Channel::State state); - - bool _handle_failed_generated_req(Channel &chan, - bool &progress); - - bool _find_next_snap_to_rekey_vba_at(Channel const &chan, - Snapshot_index &next_snap_idx); - - void _execute_read_vba (Channel &, uint64_t, bool &); - void _execute_write_vba (Channel &, uint64_t, bool &); - void _execute_rekey_vba (Channel &, uint64_t, bool &); - void _execute_vbd_extension_step (Channel &, uint64_t, bool &); - - void _mark_req_failed(Channel &chan, - bool &progress, - char const *str); - - void _mark_req_successful(Channel &chan, - bool &progress); - - void _check_that_primitive_was_successful(Channel::Generated_prim const &); - - void _execute_read_vba_read_inner_node_completed(Channel &channel, - uint64_t const job_idx, - bool &progress); - - Virtual_block_address _tree_max_max_vba(Tree_degree snap_degree, - Snapshot const &snap); - - void _update_nodes_of_branch_of_written_vba(Snapshot &snapshot, - uint64_t const snapshot_degree, - uint64_t const vba, - Tree_walk_pbas const &new_pbas, - Hash const & leaf_hash, - uint64_t curr_gen, - Channel::Type_1_node_blocks &t1_blks); - - void - _alloc_pba_from_resizing_contingent(Physical_block_address &first_pba, - Number_of_blocks &nr_of_pbas, - Physical_block_address &allocated_pba); - - void _set_args_in_order_to_write_client_data_to_leaf_node(Tree_walk_pbas const &, - uint64_t const job_idx, - Channel::State &, - Channel::Generated_prim &, - bool &progress); - - void _set_new_pbas_identical_to_current_pbas(Channel &chan); - - void - _add_new_branch_to_snap_using_pba_contingent(Channel &chan, - Tree_level_index mount_at_lvl, - Tree_node_index mount_at_child_idx); - - void - _set_args_for_alloc_of_new_pbas_for_resizing(Channel &chan, - uint64_t chan_idx, - Tree_level_index min_lvl, - bool &progress); - - void _add_new_root_lvl_to_snap_using_pba_contingent(Channel &chan); - - void _check_hash_of_read_type_1_node(Channel &chan, - Snapshot const &snapshot, - uint64_t const snapshots_degree, - uint64_t const t1_blk_idx, - Channel::Type_1_node_blocks const &t1_blks, - uint64_t const vba); - - void _initialize_new_pbas_and_determine_nr_of_pbas_to_allocate(uint64_t const curr_gen, - Snapshot const &snapshot, - uint64_t const snapshots_degree, - uint64_t const vba, - Channel::Type_1_node_blocks const &t1_blks, - Tree_walk_pbas &new_pbas, - uint64_t &nr_of_blks); - - void _set_args_for_alloc_of_new_pbas_for_branch_of_written_vba(uint64_t curr_gen, - Snapshot const &snapshot, - uint64_t const snapshots_degree, - uint64_t const vba, - Channel::Type_1_node_blocks const &t1_blks, - uint64_t const prim_idx, - uint64_t &free_gen, - Type_1_node_walk &t1_walk, - Channel::State &state, - Channel::Generated_prim &prim, - bool &progress); - - void _set_args_for_alloc_of_new_pbas_for_rekeying(Channel &chan, - uint64_t chan_idx, - Tree_level_index min_lvl); - - void _set_args_in_order_to_read_type_1_node(Snapshot const &snapshot, - uint64_t const snapshots_degree, - uint64_t const t1_blk_idx, - Channel::Type_1_node_blocks const &t1_blks, - uint64_t const vba, - uint64_t const job_idx, - Channel::State &state, - Channel::Generated_prim &prim, - bool &progress); - - void _set_args_for_write_back_of_t1_lvl(Tree_level_index const max_lvl_idx, - uint64_t const t1_lvl_idx, - uint64_t const pba, - uint64_t const prim_idx, - Channel::State &state, - bool &progress, - Channel::Generated_prim &prim); - - /************ - ** Module ** - ************/ - - bool ready_to_submit_request() override; - - void submit_request(Module_request &mod_req) override; - - bool _peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) override; - - void _drop_completed_request(Module_request &req) override; + NONCOPYABLE(Virtual_block_device); void execute(bool &) override; - bool _peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) override; + public: - void _drop_generated_request(Module_request &mod_req) override; - - void generated_request_complete(Module_request &req) override; + Virtual_block_device(); }; #endif /* _TRESOR__VIRTUAL_BLOCK_DEVICE_H_ */ diff --git a/repos/gems/src/lib/tresor/meta_tree.cc b/repos/gems/src/lib/tresor/meta_tree.cc index 8ea2b212b8..1bbe5512bf 100644 --- a/repos/gems/src/lib/tresor/meta_tree.cc +++ b/repos/gems/src/lib/tresor/meta_tree.cc @@ -1,5 +1,5 @@ /* - * \brief Module for doing free tree COW allocations on the meta tree + * \brief Module for doing VBD COW allocations on the meta tree * \author Martin Stein * \date 2023-02-13 */ @@ -14,670 +14,209 @@ /* tresor includes */ #include #include -#include +#include using namespace Tresor; - -/*************** - ** Utilities ** - ***************/ - -static bool check_level_0_usable(Generation gen, - Type_2_node &node) -{ - return node.alloc_gen != gen; -} - - -/*********************** - ** Meta_tree_request ** - ***********************/ - -void Meta_tree_request::create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - void *mt_root_pba_ptr, - void *mt_root_gen_ptr, - void *mt_root_hash_ptr, - uint64_t mt_max_lvl, - uint64_t mt_edges, - uint64_t mt_leaves, - uint64_t curr_gen, - uint64_t old_pba) -{ - Meta_tree_request req { src_module_id, src_request_id }; - req._type = (Type)req_type; - req._mt_root_pba_ptr = (addr_t)mt_root_pba_ptr; - req._mt_root_gen_ptr = (addr_t)mt_root_gen_ptr; - req._mt_root_hash_ptr = (addr_t)mt_root_hash_ptr; - req._mt_max_lvl = mt_max_lvl; - req._mt_edges = mt_edges; - req._mt_leaves = mt_leaves; - req._current_gen = curr_gen; - req._old_pba = old_pba; - if (sizeof(req) > buf_size) { - class Exception_2 { }; - throw Exception_2 { }; - } - memcpy(buf_ptr, &req, sizeof(req)); -} - - -Meta_tree_request::Meta_tree_request(Module_id src_module_id, - Module_request_id src_request_id) -: - Module_request { src_module_id, src_request_id, META_TREE } -{ } - - char const *Meta_tree_request::type_to_string(Type type) { switch (type) { - case INVALID: return "invalid"; - case UPDATE: return "update"; + case ALLOC_PBA: return "alloc pba"; } - return "?"; + ASSERT_NEVER_REACHED; } -/*************** - ** Meta_tree ** - ***************/ - -bool Meta_tree::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (uint32_t id { 0 }; id < NR_OF_CHANNELS; id++) { - - Channel &channel { _channels[id] }; - Local_cache_request const &local_req { channel._cache_request }; - if (local_req.state == Local_cache_request::PENDING) { - - Block_io_request::Type blk_io_req_type { - local_req.op == Local_cache_request::READ ? - Block_io_request::READ : - Local_cache_request::WRITE ? - Block_io_request::WRITE : - Block_io_request::INVALID }; - - if (blk_io_req_type == Block_io_request::INVALID) { - class Exception_1 { }; - throw Exception_1 { }; - } - construct_in_buf( - buf_ptr, buf_size, META_TREE, id, blk_io_req_type, - 0, 0, 0, local_req.pba, 0, 1, - (void *)&channel._cache_request.block_data, nullptr); - - return true; - } - } - return false; -} - - -void Meta_tree::_drop_generated_request(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Local_cache_request &local_req { _channels[id]._cache_request }; - if (local_req.state != Local_cache_request::PENDING) { - class Exception_2 { }; - throw Exception_2 { }; - } - local_req.state = Local_cache_request::IN_PROGRESS; -} - - -void Meta_tree::generated_request_complete(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Local_cache_request &local_req { _channels[id]._cache_request }; - if (local_req.state != Local_cache_request::IN_PROGRESS) { - class Exception_2 { }; - throw Exception_2 { }; - } - if (mod_req.dst_module_id() != BLOCK_IO) { - class Exception_3 { }; - throw Exception_3 { }; - } - Block_io_request &blk_io_req { *static_cast(&mod_req) }; - Channel &channel { _channels[id] }; - if (!blk_io_req.success()) { - - channel._request._success = false; - channel._request._new_pba = INVALID_PBA; - channel._state = Channel::COMPLETE; - return; - - } - Type_1_info &t1_info { channel._level_n_nodes[local_req.level] }; - Type_2_info &t2_info { channel._level_1_node }; - - switch (local_req.op) { - case Local_cache_request::SYNC: - - class Exception_3 { }; - throw Exception_3 { }; - - case Local_cache_request::READ: - - if (local_req.level > T2_NODE_LVL) { - - if (!check_sha256_4k_hash(channel._cache_request.block_data, t1_info.node.hash)) { - - channel._state = Channel::TREE_HASH_MISMATCH; - - } else { - - t1_info.entries.decode_from_blk(channel._cache_request.block_data); - t1_info.index = 0; - t1_info.state = Type_1_info::READ_COMPLETE; - } - } else if (local_req.level == T2_NODE_LVL) { - - if (!check_sha256_4k_hash(channel._cache_request.block_data, t2_info.node.hash)) { - - channel._state = Channel::TREE_HASH_MISMATCH; - - } else { - - t2_info.entries.decode_from_blk(channel._cache_request.block_data); - t2_info.index = 0; - t2_info.state = Type_2_info::READ_COMPLETE; - } - } else { - class Exception_4 { }; - throw Exception_4 { }; - } - break; - - case Local_cache_request::WRITE: - - if (local_req.level > T2_NODE_LVL) { - - t1_info.state = Type_1_info::WRITE_COMPLETE; - - } else if (local_req.level == T2_NODE_LVL) { - - t2_info.state = Type_2_info::WRITE_COMPLETE; - - } else { - - class Exception_5 { }; - throw Exception_5 { }; - } - break; - } - local_req = Local_cache_request { - Local_cache_request::INVALID, Local_cache_request::READ, - false, 0, 0, nullptr }; -} - - -void Meta_tree::_mark_req_failed(Channel &chan, - bool &progress, - char const *str) -{ - error(chan._request.type_name(), " request failed, reason: \"", str, "\""); - chan._request._success = false; - chan._state = Channel::COMPLETE; - progress = true; -} - - -void Meta_tree::_mark_req_successful(Channel &channel, - bool &progress) -{ - channel._request._success = true; - channel._state = Channel::COMPLETE; - progress = true; -} - - -void Meta_tree::_update_parent(Type_1_node &node, - Block const &blk, - uint64_t gen, - uint64_t pba) -{ - calc_sha256_4k_hash(blk, node.hash); - node.gen = gen; - node.pba = pba; -} - - -void Meta_tree::_exchange_nv_inner_nodes(Channel &channel, - Type_2_node &t2_entry, - bool &exchanged) -{ - Request &req { channel._request }; - uint64_t pba; - exchanged = false; - - // loop non-volatile inner nodes - for (uint64_t lvl { MT_LOWEST_T1_LVL }; lvl <= TREE_MAX_LEVEL; lvl++) { - - Type_1_info &t1_info { channel._level_n_nodes[lvl] }; - if (t1_info.node.valid() && !t1_info.volatil) { - - pba = t1_info.node.pba; - t1_info.node.pba = t2_entry.pba; - t1_info.node.gen = req._current_gen; - t1_info.volatil = true; - t2_entry.pba = pba; - t2_entry.alloc_gen = req._current_gen; - t2_entry.free_gen = req._current_gen; - t2_entry.reserved = false; - - exchanged = true; - break; - } - } -} - - -void Meta_tree::_exchange_nv_level_1_node(Channel &channel, - Type_2_node &t2_entry, - bool &exchanged) -{ - Request &req { channel._request }; - uint64_t pba { channel._level_1_node.node.pba }; - exchanged = false; - - if (!channel._level_1_node.volatil) { - - channel._level_1_node.node.pba = t2_entry.pba; - channel._level_1_node.volatil = true; - - t2_entry.pba = pba; - t2_entry.alloc_gen = req._current_gen; - t2_entry.free_gen = req._current_gen; - t2_entry.reserved = false; - - exchanged = true; - } -} - - -void Meta_tree::_exchange_request_pba(Channel &channel, - Type_2_node &t2_entry) -{ - Request &req { channel._request }; - req._success = true; - req._new_pba = t2_entry.pba; - channel._finished = true; - - t2_entry.pba = req._old_pba; - t2_entry.alloc_gen = req._current_gen; - t2_entry.free_gen = req._current_gen; - t2_entry.reserved = false; -} - - -void Meta_tree::_handle_level_0_nodes(Channel &channel, - bool &handled) -{ - Request &req { channel._request }; - Type_2_node tmp_t2_entry; - handled = false; - - for(unsigned i = 0; i <= req._mt_edges - 1; i++) { - - tmp_t2_entry = channel._level_1_node.entries.nodes[i]; - - if (tmp_t2_entry.valid() && - check_level_0_usable(req._current_gen, tmp_t2_entry)) - { - bool exchanged_level_1; - bool exchanged_level_n { false }; - bool exchanged_request_pba { false }; - - // first try to exchange the level 1 node ... - _exchange_nv_level_1_node( - channel, tmp_t2_entry, exchanged_level_1); - - // ... next the inner level n nodes ... - if (!exchanged_level_1) - _exchange_nv_inner_nodes( - channel, tmp_t2_entry, exchanged_level_n); - - // ... and than satisfy the original mt request - if (!exchanged_level_1 && !exchanged_level_n) { - _exchange_request_pba(channel, tmp_t2_entry); - exchanged_request_pba = true; - } - channel._level_1_node.entries.nodes[i] = tmp_t2_entry; - handled = true; - - if (exchanged_request_pba) - return; - } - } -} - - -void Meta_tree::_handle_level_1_node(Channel &channel, - bool &handled) -{ - Type_1_info &t1_info { channel._level_n_nodes[MT_LOWEST_T1_LVL] }; - Type_2_info &t2_info { channel._level_1_node }; - Request &req { channel._request }; - - switch (t2_info.state) { - case Type_2_info::INVALID: - - handled = false; - break; - - case Type_2_info::READ: - - channel._cache_request = Local_cache_request { - Local_cache_request::PENDING, Local_cache_request::READ, false, - t2_info.node.pba, 1, nullptr }; - - handled = true; - break; - - case Type_2_info::READ_COMPLETE: - - _handle_level_0_nodes(channel, handled); - if (handled) { - t2_info.state = Type_2_info::WRITE; - } else { - t2_info.state = Type_2_info::COMPLETE; - handled = true; - } - break; - - case Type_2_info::WRITE: - { - Block block_data { }; - t2_info.entries.encode_to_blk(block_data); - - _update_parent( - t1_info.entries.nodes[t1_info.index], block_data, - req._current_gen, t2_info.node.pba); - - channel._cache_request = Local_cache_request { - Local_cache_request::PENDING, Local_cache_request::WRITE, false, - t2_info.node.pba, 1, &block_data }; - - t1_info.dirty = true; - handled = true; - break; - } - case Type_2_info::WRITE_COMPLETE: - - t1_info.index++; - t2_info.state = Type_2_info::INVALID; - handled = true; - break; - - case Type_2_info::COMPLETE: - - t1_info.index++; - t2_info.state = Type_2_info::INVALID; - handled = true; - break; - } -} - - -void Meta_tree::_execute_update(Channel &channel, - bool &progress) -{ - bool handled_level_1_node; - bool handled_level_n_nodes; - _handle_level_1_node(channel, handled_level_1_node); - if (handled_level_1_node) { - progress = true; - return; - } - _handle_level_n_nodes(channel, handled_level_n_nodes); - progress = progress || handled_level_n_nodes; -} +Meta_tree_request::Meta_tree_request(Module_id src_module_id, Module_channel_id src_channel_id, + Type type, Tree_root &mt, Generation curr_gen, + Physical_block_address &pba, bool &success) +: + Module_request { src_module_id, src_channel_id, META_TREE }, _type { type }, _mt { mt }, + _curr_gen { curr_gen }, _pba { pba }, _success { success } +{ } void Meta_tree::execute(bool &progress) { - for (Channel &channel : _channels) { + for_each_channel([&] (Channel &chan) { + chan.execute(progress); }); +} - if (channel._cache_request.state != Local_cache_request::INVALID) - continue; - switch(channel._state) { - case Channel::INVALID: - break; - case Channel::UPDATE: - _execute_update(channel, progress); - break; - case Channel::COMPLETE: - break; - case Channel::TREE_HASH_MISMATCH: - _mark_req_failed(channel, progress, "node hash mismatch"); - break; +bool Meta_tree_channel::_can_alloc_pba_of(Type_2_node &node) +{ + return node.valid() && node.alloc_gen != _req_ptr->_curr_gen; +} + + +void Meta_tree_channel::_generated_req_completed(State_uint state_uint) +{ + if (!_generated_req_success) { + error("meta tree: request (", *_req_ptr, ") failed because generated request failed)"); + _req_ptr->_success = false; + _state = COMPLETE; + _req_ptr = nullptr; + return; + } + _state = (State)state_uint; +} + + +void Meta_tree_channel::_alloc_pba_of(Type_2_node &t2_node, Physical_block_address &pba) +{ + Request &req { *_req_ptr }; + Physical_block_address old_pba { pba }; + pba = t2_node.pba; + t2_node.pba = old_pba; + t2_node.alloc_gen = req._curr_gen; + t2_node.free_gen = req._curr_gen; + t2_node.reserved = false; +} + + +void Meta_tree_channel::_mark_req_failed(bool &progress, char const *str) +{ + error(Request::type_to_string(_req_ptr->_type), " request failed, reason: \"", str, "\""); + _req_ptr->_success = false; + _state = COMPLETE; + _req_ptr = nullptr; + progress = true; +} + + +void Meta_tree_channel::_mark_req_successful(bool &progress) +{ + _req_ptr->_success = true; + _state = COMPLETE; + _req_ptr = nullptr; + progress = true; +} + + +void Meta_tree_channel::_start_tree_traversal(bool &progress) +{ + Request &req { *_req_ptr }; + _lvl = req._mt.max_lvl; + _node_idx[_lvl] = 0; + _t1_blks[_lvl].nodes[_node_idx[_lvl]] = req._mt.t1_node(); + _generate_req(SEEK_DOWN, progress, req._mt.pba, _blk); +} + + +void Meta_tree_channel::_traverse_curr_node(bool &progress) +{ + Request &req { *_req_ptr }; + if (_lvl) { + Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] }; + if (t1_node.pba) + _generate_req(SEEK_DOWN, progress, t1_node.pba, _blk); + else { + _state = SEEK_LEFT_OR_UP; + progress = true; } - } -} - - -Meta_tree::Meta_tree() { } - - -bool Meta_tree::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (Channel &channel : _channels) { - if (channel._state == Channel::COMPLETE) { - if (sizeof(channel._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &channel._request, sizeof(channel._request)); - return true; - } - } - return false; -} - - -void Meta_tree::_drop_completed_request(Module_request &req) -{ - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (_channels[id]._state != Channel::COMPLETE) { - class Exception_2 { }; - throw Exception_2 { }; - } - _channels[id]._state = Channel::INVALID; -} - - -bool Meta_tree::ready_to_submit_request() -{ - for (Channel &channel : _channels) { - if (channel._state == Channel::INVALID) - return true; - } - return false; -} - - -bool Meta_tree::_node_volatile(Type_1_node const &node, - uint64_t gen) -{ - return node.gen == 0 || node.gen != gen; -} - - -void Meta_tree::submit_request(Module_request &mod_req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - Channel &chan { _channels[id] }; - if (chan._state == Channel::INVALID) { - - mod_req.dst_request_id(id); - - chan._request = *static_cast(&mod_req); - chan._finished = false; - chan._state = Channel::UPDATE; - for (Type_1_info &t1_info : chan._level_n_nodes) { - t1_info = Type_1_info { }; - } - chan._level_1_node = Type_2_info { }; - - Request &req { chan._request }; - Type_1_node root_node { }; - root_node.pba = *(uint64_t *)req._mt_root_pba_ptr; - root_node.gen = *(uint64_t *)req._mt_root_gen_ptr; - memcpy(&root_node.hash, (uint8_t *)req._mt_root_hash_ptr, - HASH_SIZE); - - chan._level_n_nodes[req._mt_max_lvl].node = root_node; - chan._level_n_nodes[req._mt_max_lvl].state = Type_1_info::READ; - chan._level_n_nodes[req._mt_max_lvl].volatil = - _node_volatile(root_node, req._current_gen); - - return; - } - } - class Invalid_call { }; - throw Invalid_call { }; -} - - -void Meta_tree::_handle_level_n_nodes(Channel &channel, - bool &handled) -{ - Request &req { channel._request }; - handled = false; - - for (uint64_t lvl { MT_LOWEST_T1_LVL }; lvl <= TREE_MAX_LEVEL; lvl++) { - - Type_1_info &t1_info { channel._level_n_nodes[lvl] }; - - switch (t1_info.state) { - case Type_1_info::INVALID: - - break; - - case Type_1_info::READ: - - channel._cache_request = Local_cache_request { - Local_cache_request::PENDING, Local_cache_request::READ, false, - t1_info.node.pba, lvl, nullptr }; - - handled = true; - return; - - case Type_1_info::READ_COMPLETE: - - if (t1_info.index < req._mt_edges && - t1_info.entries.nodes[t1_info.index].valid() && - !channel._finished) { - - if (lvl != MT_LOWEST_T1_LVL) { - channel._level_n_nodes[lvl - 1] = { - Type_1_info::READ, t1_info.entries.nodes[t1_info.index], - { }, 0, false, - _node_volatile(t1_info.node, req._current_gen) }; - - } else { - channel._level_1_node = { - Type_2_info::READ, t1_info.entries.nodes[t1_info.index], - { }, 0, - _node_volatile(t1_info.node, req._current_gen) }; + } else { + Type_2_node &t2_node { _t2_blk.nodes[_node_idx[_lvl]] }; + if (_can_alloc_pba_of(t2_node)) { + _alloc_pba_of(t2_node, _req_ptr->_pba); + for (Tree_level_index lvl { 1 }; lvl <= req._mt.max_lvl; lvl++) { + Type_1_node &t1_node { _t1_blks[lvl].nodes[_node_idx[lvl]] }; + if (!t1_node.is_volatile(req._curr_gen)) { + bool pba_allocated { false }; + for (Type_2_node &t2_node : _t2_blk.nodes) { + if (_can_alloc_pba_of(t2_node)) { + _alloc_pba_of(t2_node, t1_node.pba); + pba_allocated = true; + break; + } + } + ASSERT(pba_allocated); } - - } else { - - if (t1_info.dirty) - t1_info.state = Type_1_info::WRITE; - else - t1_info.state = Type_1_info::COMPLETE; } - handled = true; - return; - - case Type_1_info::WRITE: - { - Block block_data; - t1_info.entries.encode_to_blk(block_data); - - if (lvl == req._mt_max_lvl) { - - Type_1_node root_node { }; - root_node.pba = *(uint64_t *)req._mt_root_pba_ptr; - root_node.gen = *(uint64_t *)req._mt_root_gen_ptr; - memcpy(&root_node.hash, (uint8_t *)req._mt_root_hash_ptr, - HASH_SIZE); - - _update_parent( - root_node, block_data, req._current_gen, - t1_info.node.pba); - - *(uint64_t *)req._mt_root_pba_ptr = root_node.pba; - *(uint64_t *)req._mt_root_gen_ptr = root_node.gen; - memcpy((uint8_t *)req._mt_root_hash_ptr, &root_node.hash, - HASH_SIZE); - - channel._root_dirty = true; - - } else { - - Type_1_info &parent { channel._level_n_nodes[lvl + 1] }; - _update_parent( - parent.entries.nodes[parent.index], block_data, - req._current_gen, t1_info.node.pba); - - parent.dirty = true; - } - channel._cache_request = Local_cache_request { - Local_cache_request::PENDING, Local_cache_request::WRITE, - false, t1_info.node.pba, lvl, &block_data }; - - handled = true; - return; - } - case Type_1_info::WRITE_COMPLETE: - - if (lvl == req._mt_max_lvl) - channel._state = Channel::COMPLETE; - else - channel._level_n_nodes[lvl + 1].index++; - - channel._cache_request = Local_cache_request { - Local_cache_request::INVALID, Local_cache_request::READ, - false, 0, 0, nullptr }; - - t1_info.state = Type_1_info::INVALID; - handled = true; - return; - - case Type_1_info::COMPLETE: - - if (lvl == req._mt_max_lvl) - channel._state = Channel::COMPLETE; - else - channel._level_n_nodes[lvl + 1].index++; - - t1_info.state = Type_1_info::INVALID; - handled = true; - return; - } + _state = WRITE_BLK; + } else + _state = SEEK_LEFT_OR_UP; + progress = true; + } +} + + +void Meta_tree_channel::execute(bool &progress) +{ + if (!_req_ptr) + return; + + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: + + _start_tree_traversal(progress); + break; + + case SEEK_DOWN: + + if (!check_hash(_blk, _t1_blks[_lvl].nodes[_node_idx[_lvl]].hash)) { + _mark_req_failed(progress, "hash mismatch"); + break; + } + _lvl--; + _node_idx[_lvl] = 0; + if (_lvl) + _t1_blks[_lvl].decode_from_blk(_blk); + else + _t2_blk.decode_from_blk(_blk); + _traverse_curr_node(progress); + break; + + case SEEK_LEFT_OR_UP: + + if (_lvl < req._mt.max_lvl) { + if (_node_idx[_lvl] < req._mt.degree - 1) { + _node_idx[_lvl]++; + _traverse_curr_node(progress); + } else { + _lvl++; + _state = SEEK_LEFT_OR_UP; + progress = true; + } + } else + _mark_req_failed(progress, "not enough free pbas"); + break; + + case WRITE_BLK: + + if (_lvl < req._mt.max_lvl) { + if (_lvl) + _t1_blks[_lvl].encode_to_blk(_blk); + else + _t2_blk.encode_to_blk(_blk); + _lvl++; + Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] }; + t1_node.gen = req._curr_gen; + calc_hash(_blk, t1_node.hash); + _generate_req(WRITE_BLK, progress, t1_node.pba, _blk); + } else { + req._mt.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]); + _mark_req_successful(progress); + } + break; + + default: break; + } +} + + +void Meta_tree_channel::_request_submitted(Module_request &mod_req) +{ + _req_ptr = static_cast(&mod_req); + _state = REQ_SUBMITTED; +} + + +Meta_tree::Meta_tree() +{ + Module_channel_id id { 0 }; + for (Constructible &chan : _channels) { + chan.construct(id++); + add_channel(*chan); } } diff --git a/repos/gems/src/lib/tresor/module.cc b/repos/gems/src/lib/tresor/module.cc index d4285b6bbf..17bab9a658 100644 --- a/repos/gems/src/lib/tresor/module.cc +++ b/repos/gems/src/lib/tresor/module.cc @@ -18,40 +18,12 @@ using namespace Tresor; -/******************** - ** Module_request ** - ********************/ - -Module_request::Module_request(Module_id src_module_id, - Module_request_id src_request_id, - Module_id dst_module_id) +Module_request::Module_request(Module_id src_module_id, Module_channel_id src_chan_id, Module_id dst_module_id) : - _src_module_id { src_module_id }, - _src_request_id { src_request_id }, - _dst_module_id { dst_module_id } + _src_module_id { src_module_id }, _src_chan_id { src_chan_id }, _dst_module_id { dst_module_id } { } -String<32> Module_request::src_request_id_str() const -{ - return - _src_request_id == INVALID_MODULE_REQUEST_ID ? - String<32> { "?" } : String<32> { _src_request_id }; -} - - -String<32> Module_request::dst_request_id_str() const -{ - return - _dst_request_id == INVALID_MODULE_REQUEST_ID ? - String<32> { "?" } : String<32> { _dst_request_id }; -} - - -/********************** - ** Global functions ** - **********************/ - char const *Tresor::module_name(Module_id id) { switch (id) { @@ -65,16 +37,109 @@ char const *Tresor::module_name(Module_id id) case CLIENT_DATA: return "client_data"; case TRUST_ANCHOR: return "trust_anchor"; case COMMAND_POOL: return "command_pool"; - case BLOCK_ALLOCATOR: return "block_allocator"; case VBD_INITIALIZER: return "vbd_initializer"; case FT_INITIALIZER: return "ft_initializer"; case SB_INITIALIZER: return "sb_initializer"; case SB_CHECK: return "sb_check"; case VBD_CHECK: return "vbd_check"; case FT_CHECK: return "ft_check"; - case FT_RESIZING: return "ft_resizing"; + case SPLITTER: return "splitter"; case REQUEST_POOL: return "request_pool"; default: break; } - return "?"; + ASSERT_NEVER_REACHED; +} + + +void Module_channel::generated_req_completed() +{ + ASSERT(_gen_req_state == IN_PROGRESS); + _gen_req_state = NONE; + _generated_req_completed(_gen_req_complete_state); +} + + +bool Module_channel::try_submit_request(Module_request &req) +{ + if (_req_ptr) + return false; + + req.dst_chan_id(_id); + _req_ptr = &req; + _request_submitted(req); + return true; +} + + +bool Module::try_submit_request(Module_request &req) +{ + bool success { false }; + for_each_channel([&] (Module_channel &chan) { + if (success) + return; + + success = chan.try_submit_request(req); + }); + return success; +} + + +void Module_composition::execute_modules() +{ + bool progress { true }; + while (progress) { + + progress = false; + for (Module_id id { 0 }; id <= MAX_MODULE_ID; id++) { + if (!_module_ptrs[id]) + continue; + + Module &mod { *_module_ptrs[id] }; + mod.execute(progress); + mod.for_each_generated_request([&] (Module_request &req) { + ASSERT(req.dst_module_id() <= MAX_MODULE_ID); + ASSERT(_module_ptrs[req.dst_module_id()]); + Module &dst_module { *_module_ptrs[req.dst_module_id()] }; + if (dst_module.try_submit_request(req)) { + if (VERBOSE_MODULE_COMMUNICATION) + log(module_name(id), " ", req.src_chan_id(), " --", req, "--> ", + module_name(req.dst_module_id()), " ", req.dst_chan_id()); + + progress = true; + return true; + } + if (VERBOSE_MODULE_COMMUNICATION) + log(module_name(id), " ", req.src_chan_id(), " --", req, "-| ", module_name(req.dst_module_id())); + + return false; + }); + mod.for_each_completed_request([&] (Module_request &req) { + ASSERT(req.src_module_id() <= MAX_MODULE_ID); + if (VERBOSE_MODULE_COMMUNICATION) + log(module_name(req.src_module_id()), " ", req.src_chan_id(), " <--", req, + "-- ", module_name(id), " ", req.dst_chan_id()); + + Module &src_module { *_module_ptrs[req.src_module_id()] }; + src_module.with_channel(req.src_chan_id(), [&] (Module_channel &chan) { + chan.generated_req_completed(); }); + progress = true; + }); + } + }; +} + + +void Module_composition::add_module(Module_id module_id, Module &mod) +{ + ASSERT(module_id <= MAX_MODULE_ID); + ASSERT(!_module_ptrs[module_id]); + _module_ptrs[module_id] = &mod; +} + + +void Module_composition::remove_module(Module_id module_id) +{ + ASSERT(module_id <= MAX_MODULE_ID); + ASSERT(_module_ptrs[module_id]); + _module_ptrs[module_id] = nullptr; } diff --git a/repos/gems/src/lib/tresor/request_pool.cc b/repos/gems/src/lib/tresor/request_pool.cc index e70049423a..aefba814c2 100644 --- a/repos/gems/src/lib/tresor/request_pool.cc +++ b/repos/gems/src/lib/tresor/request_pool.cc @@ -13,868 +13,369 @@ /* tresor includes */ #include -#include using namespace Tresor; - -char const *Request::op_to_string(Operation op) { return to_string(op); } +Request::Request(Module_id src_module_id, Module_channel_id src_chan_id, Operation op, Virtual_block_address vba, + Request_offset offset, Number_of_blocks count, Key_id key_id, Request_tag tag, Generation &gen, bool &success) +: + Module_request { src_module_id, src_chan_id, REQUEST_POOL }, _op { op }, _vba { vba }, _offset { offset }, + _count { count }, _key_id { key_id }, _tag { tag }, _gen { gen }, _success { success } +{ } -void Request_pool::_execute_read(Channel &channel, Index_queue &indices, - Slots_index const idx, bool &progress) +void Request::print(Output &out) const { - switch (channel._state) { - case Channel::State::SUBMITTED: - channel._nr_of_blks = 0; - - channel._prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_READ_VBA, - .pl_idx = idx, - .blk_nr = channel._request.block_number() + channel._nr_of_blks, - .idx = 0 - }; - - channel._state = Channel::State::READ_VBA_AT_SB_CTRL_PENDING; - progress = true; - + Genode::print(out, op_to_string(_op)); + switch (_op) { + case READ: + case WRITE: + case SYNC: + if (_count > 1) + Genode::print(out, " vbas ", _vba, "..", _vba + _count - 1); + else + Genode::print(out, " vba ", _vba); break; - case Channel::State::READ_VBA_AT_SB_CTRL_COMPLETE: - if (channel._prim.succ) { - - channel._nr_of_blks += 1; - - if (channel._nr_of_blks < channel._request.count()) { - - channel._prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_READ_VBA, - .pl_idx = idx, - .blk_nr = channel._request.block_number() + channel._nr_of_blks, - .idx = 0 - }; - - channel._state = Channel::State::READ_VBA_AT_SB_CTRL_PENDING; - progress = true; - } else { - channel._request.success(true); - channel._state = Channel::State::COMPLETE; - indices.dequeue(idx); - progress = true; - } - } else { - channel._request.success(false); - channel._state = Channel::State::COMPLETE; - indices.dequeue(idx); - progress = true; - } - break; - default: - break; - } -} - - -void Request_pool::_execute_write(Channel &channel, Index_queue &indices, - Slots_index const idx, bool &progress) -{ - switch (channel._state) { - case Channel::State::SUBMITTED: - - channel._nr_of_blks = 0; - - channel._prim = { - .op = Channel::Generated_prim::Type::WRITE, - .succ = false, - .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_WRITE_VBA, - .pl_idx = idx, - .blk_nr = channel._request.block_number() + channel._nr_of_blks, - .idx = 0 - }; - channel._state = Channel::State::WRITE_VBA_AT_SB_CTRL_PENDING; - progress = true; - break; - - case Channel::State::WRITE_VBA_AT_SB_CTRL_COMPLETE: - - if (channel._prim.succ) { - channel._nr_of_blks += 1; - - if (channel._nr_of_blks < channel._request.count()) { - - channel._prim = { - .op = Channel::Generated_prim::Type::WRITE, - .succ = false, - .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_WRITE_VBA, - .pl_idx = idx, - .blk_nr = channel._request.block_number() + channel._nr_of_blks, - .idx = 0 - }; - - channel._state = Channel::State::WRITE_VBA_AT_SB_CTRL_PENDING; - progress = true; - - } else { - - channel._request.success(true); - channel._state = Channel::State::COMPLETE; - indices.dequeue(idx); - progress = true; - - } - } else { - - channel._request.success(false); - channel._state = Channel::State::COMPLETE; - indices.dequeue(idx); - progress = true; - - } - - break; - default: - break; - } -} - - -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) -{ - 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_SYNC, - .pl_idx = idx, - .blk_nr = 0, - .idx = 0 - }; - - channel._state = Channel::State::SYNC_AT_SB_CTRL_PENDING; - progress = true; - - break; - case Channel::State::SYNC_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; - } -} - - -char const *Request_pool::_state_to_step_label(Channel::State state) -{ - switch (state) { - case Channel::State::TREE_EXTENSION_STEP_COMPLETE: return "tree ext step"; default: break; } - return "?"; } -void Request_pool::_mark_req_failed(Channel &chan, - bool &progress, - char const *str) +char const *Request::op_to_string(Operation op) { - error("request_pool: request (", chan._request, - ") failed at step \"", str, "\""); + switch (op) { + case Request::READ: return "read"; + case Request::WRITE: return "write"; + case Request::SYNC: return "sync"; + case Request::CREATE_SNAPSHOT: return "create_snapshot"; + case Request::DISCARD_SNAPSHOT: return "discard_snapshot"; + case Request::REKEY: return "rekey"; + case Request::EXTEND_VBD: return "extend_vbd"; + case Request::EXTEND_FT: return "extend_ft"; + case Request::RESUME_REKEYING: return "resume_rekeying"; + case Request::DEINITIALIZE: return "deinitialize"; + case Request::INITIALIZE: return "initialize"; + } + ASSERT_NEVER_REACHED; +} - chan._request.success(false); - chan._state = Channel::COMPLETE; + +void Request_pool_channel::_gen_sb_control_req(bool &progress, Superblock_control_request::Type type, + State complete_state, Virtual_block_address vba = 0) +{ + _state = REQ_GENERATED; + generate_req( + complete_state, progress, type, _req_ptr->_offset, _req_ptr->_tag, _req_ptr->_count, vba, _generated_req_success, + _request_finished, _sb_state, _req_ptr->_gen); +} + + +void Request_pool_channel::_access_vbas(bool &progress, Superblock_control_request::Type type) +{ + switch (_state) { + case REQ_SUBMITTED: + _gen_sb_control_req(progress, type, ACCESS_VBA_AT_SB_CTRL_SUCCEEDED, _req_ptr->_vba + _num_blks); + break; + case ACCESS_VBA_AT_SB_CTRL_SUCCEEDED: + if (++_num_blks < _req_ptr->_count) + _gen_sb_control_req(progress, type, ACCESS_VBA_AT_SB_CTRL_SUCCEEDED, _req_ptr->_vba + _num_blks); + else + _mark_req_successful(progress); + break; + default: break; + } +} + + +void Request_pool_channel::_mark_req_successful(bool &progress) +{ + _req_ptr->_success = true; + _state = REQ_COMPLETE; + _chan_queue.dequeue(*this); + _req_ptr = nullptr; progress = true; } -bool Request_pool::_handle_failed_generated_req(Channel &chan, - bool &progress) +void Request_pool_channel::_try_prepone_requests(bool &progress) { - if (chan._prim.succ) - return false; + enum { MAX_NUM_REQUESTS_PREPONED = 8 }; + bool requests_preponed { false }; + bool at_req_that_cannot_be_preponed { false }; + _num_requests_preponed = 0; - _mark_req_failed(chan, progress, _state_to_step_label(chan._state)); - return true; + while (_num_requests_preponed < MAX_NUM_REQUESTS_PREPONED && + !at_req_that_cannot_be_preponed && + !_chan_queue.is_tail(*this)) { + + switch (_chan_queue.next(*this)._req_ptr->_op) { + case Request::READ: + case Request::WRITE: + case Request::SYNC: + case Request::DISCARD_SNAPSHOT: + + _chan_queue.move_one_slot_towards_tail(*this); + _num_requests_preponed++; + requests_preponed = true; + progress = true; + break; + + default: + + at_req_that_cannot_be_preponed = true; + break; + } + } + if (!requests_preponed) { + _state = PREPONED_REQUESTS_COMPLETE; + progress = true; + } } -void Request_pool::_mark_req_successful(Channel &chan, - Slots_index idx, - bool &progress) +void Request_pool_channel::_extend_tree(Superblock_control_request::Type type, bool &progress) { - chan._request.success(true); - chan._state = Channel::COMPLETE; - _indices.dequeue(idx); + switch (_state) { + case REQ_SUBMITTED: + + _gen_sb_control_req(progress, type, TREE_EXTENSION_STEP_SUCCEEDED); + break; + + case TREE_EXTENSION_STEP_SUCCEEDED: + + if (_request_finished) + _mark_req_successful(progress); + else + _try_prepone_requests(progress); + break; + + case PREPONED_REQUESTS_COMPLETE: + + _gen_sb_control_req(progress, type, TREE_EXTENSION_STEP_SUCCEEDED); + break; + + default: break; + } +} + + +void Request_pool_channel::_rekey(bool &progress) +{ + switch (_state) { + case REQ_SUBMITTED: + + _gen_sb_control_req(progress, Superblock_control_request::INITIALIZE_REKEYING, REKEY_INIT_SUCCEEDED); + break; + + case REQ_RESUMED: + case REKEY_INIT_SUCCEEDED: _try_prepone_requests(progress); break; + case REKEY_VBA_SUCCEEDED: + + if (_request_finished) + _mark_req_successful(progress); + else + _try_prepone_requests(progress); + break; + + case PREPONED_REQUESTS_COMPLETE: + + _gen_sb_control_req(progress, Superblock_control_request::REKEY_VBA, REKEY_VBA_SUCCEEDED); + break; + + default: break; + } +} + + +void Request_pool_channel::_resume_request(bool &progress, Request::Operation op) +{ + _state = REQ_RESUMED; + _req_ptr->_op = op; progress = true; } -void Request_pool::_execute_extend_tree(Channel &chan, - Slots_index idx, - Channel::State tree_ext_step_pending, - bool &progress) +void Request_pool_channel::_initialize(bool &progress) { - switch (chan._state) { - case Channel::SUBMITTED: + switch (_state) { + case REQ_SUBMITTED: - chan._prim = { - .op = Generated_prim::Type::READ, - .succ = false, - .tg = Channel::TAG_POOL_SB_CTRL_TREE_EXT_STEP, - .pl_idx = idx, - .blk_nr = 0, - .idx = 0 - }; - chan._state = tree_ext_step_pending; - progress = true; + _gen_sb_control_req(progress, Superblock_control_request::INITIALIZE, INITIALIZE_SB_CTRL_SUCCEEDED); break; - case Channel::TREE_EXTENSION_STEP_COMPLETE: + case INITIALIZE_SB_CTRL_SUCCEEDED: - if (_handle_failed_generated_req(chan, progress)) - break; - - if (chan._request_finished) { - - _mark_req_successful(chan, idx, progress); - - } else { - - chan._nr_of_requests_preponed = 0; - chan._state = Channel::PREPONE_REQUESTS_PENDING; - progress = true; - } - break; - - case Channel::PREPONE_REQUESTS_PENDING: - { - bool requests_preponed { false }; - bool at_req_that_cannot_be_preponed { false }; - - while (chan._nr_of_requests_preponed < MAX_NR_OF_REQUESTS_PREPONED_AT_A_TIME && - !at_req_that_cannot_be_preponed && - !_indices.item_is_tail(idx)) - { - Pool_index const next_idx { _indices.next_item(idx) }; - switch (_channels[next_idx]._request.operation()) { - case Request::READ: - case Request::WRITE: - case Request::SYNC: - case Request::DISCARD_SNAPSHOT: - - _indices.move_one_item_towards_tail(idx); - chan._nr_of_requests_preponed++; - requests_preponed = true; - progress = true; - break; - - default: - - at_req_that_cannot_be_preponed = true; - break; - } - } - if (!requests_preponed) { - - chan._state = Channel::PREPONE_REQUESTS_COMPLETE; - progress = true; - } - break; - } - case Channel::PREPONE_REQUESTS_COMPLETE: - - chan._prim = { - .op = Generated_prim::Type::READ, - .succ = false, - .tg = Channel::TAG_POOL_SB_CTRL_TREE_EXT_STEP, - .pl_idx = idx, - .blk_nr = 0, - .idx = 0 - }; - chan._state = tree_ext_step_pending; - progress = true; - break; - - default: - - break; - } -} - - -void Request_pool::_execute_rekey(Channel &chan, - Index_queue &indices, - Slots_index idx, - bool &progress) -{ - Request &req { chan._request }; - - switch (chan._state) { - case Channel::State::SUBMITTED: - - chan._prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_INIT_REKEY, - .pl_idx = idx, - .blk_nr = 0, - .idx = 0 - }; - chan._state = Channel::State::REKEY_INIT_PENDING; - progress = true; - break; - - case Channel::State::SUBMITTED_RESUME_REKEYING: - - chan._prim = { }; - chan._nr_of_requests_preponed = 0; - chan._state = Channel::State::PREPONE_REQUESTS_PENDING; - progress = true; - break; - - case Channel::State::REKEY_INIT_COMPLETE: - - if (!chan._prim.succ) { - class Exception_1 { }; - throw Exception_1 { }; - } - chan._nr_of_requests_preponed = 0; - chan._state = Channel::State::PREPONE_REQUESTS_PENDING; - progress = true; - break; - - case Channel::State::REKEY_VBA_COMPLETE: - - if (!chan._prim.succ) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (chan._request_finished) { - - req.success(true); - chan._state = Channel::State::COMPLETE; - _indices.dequeue(idx); - progress = true; - break; - - } else { - - chan._nr_of_requests_preponed = 0; - chan._state = Channel::State::PREPONE_REQUESTS_PENDING; - progress = true; - break; - } - - case Channel::State::PREPONE_REQUESTS_PENDING: - { - bool requests_preponed { false }; - while (true) { - - bool exit_loop { false }; - - if (chan._nr_of_requests_preponed >= MAX_NR_OF_REQUESTS_PREPONED_AT_A_TIME || - indices.item_is_tail(idx)) - break; - - Pool_index const next_idx { indices.next_item(idx) }; - switch (_channels[next_idx]._request.operation()) { - case Request::READ: - case Request::WRITE: - case Request::SYNC: - case Request::DISCARD_SNAPSHOT: - - indices.move_one_item_towards_tail(idx); - chan._nr_of_requests_preponed++; - requests_preponed = true; - progress = true; - break; - - default: - - exit_loop = true; - break; - } - if (exit_loop) - break; - } - if (!requests_preponed) { - chan._state = Channel::State::PREPONE_REQUESTS_COMPLETE; - progress = true; - } - break; - } - case Channel::State::PREPONE_REQUESTS_COMPLETE: - - chan._prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_REKEY_VBA, - .pl_idx = idx, - .blk_nr = 0, - .idx = 0 - }; - chan._state = Channel::State::REKEY_VBA_PENDING; - progress = true; - break; - - default: - - break; - } -} - - -void Request_pool::_execute_initialize(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_INITIALIZE, - .pl_idx = idx, - .blk_nr = 0, - .idx = 0 - }; - - channel._state = Channel::State::INITIALIZE_SB_CTRL_PENDING; - progress = true; - - break; - - case Channel::State::INITIALIZE_SB_CTRL_COMPLETE: - - if (not channel._prim.succ) { - class Initialize_primitive_not_successfull { }; - throw Initialize_primitive_not_successfull { }; - } - - switch (channel._sb_state) { - case Superblock::INVALID: - class Initialize_sb_ctrl_invalid { }; - throw Initialize_sb_ctrl_invalid { }; - - break; + switch (_sb_state) { + case Superblock::INVALID: ASSERT_NEVER_REACHED; case Superblock::NORMAL: - indices.dequeue(idx); - channel.invalidate(); + _chan_queue.dequeue(*this); + _reset(); progress = true; - break; - case Superblock::REKEYING: - - class Exception_rekeying { }; - throw Exception_rekeying { }; - channel._request = Tresor::Request(Request::Operation::REKEY, - false, 0, 0, 0, 0, 0, 0, - INVALID_MODULE_ID, - INVALID_MODULE_REQUEST_ID); - indices.enqueue(idx); - progress = true; - - break; - case Superblock::EXTENDING_VBD: - - class Exception_ext_vbd { }; - throw Exception_ext_vbd { }; - channel._state = Channel::State::SUBMITTED; - - channel._request = Tresor::Request(Request::Operation::EXTEND_VBD, - false, 0, 0, 0, 0, 0, 0, - INVALID_MODULE_ID, - INVALID_MODULE_REQUEST_ID); - - indices.enqueue(idx); - - progress = true; - - break; - case Superblock::EXTENDING_FT: - - class Exception_ext_ft { }; - throw Exception_ext_ft { }; - channel._state = Channel::State::SUBMITTED; - - channel._request = Tresor::Request(Request::Operation::EXTEND_FT, - false, 0, 0, 0, 0, 0, 0, - INVALID_MODULE_ID, - INVALID_MODULE_REQUEST_ID); - - indices.enqueue(idx); - - progress = true; - - break; + case Superblock::REKEYING: _resume_request(progress, Request::REKEY); break; + case Superblock::EXTENDING_VBD: _resume_request(progress, Request::EXTEND_VBD); break; + case Superblock::EXTENDING_FT: _resume_request(progress, Request::EXTEND_FT); break; } + break; - break; - default: - break; + default: break; } } -void Request_pool::_execute_deinitialize(Channel &channel, Index_queue &indices, - Slots_index const idx, bool &progress) +void Request_pool_channel::_forward_to_sb_ctrl(bool &progress, Superblock_control_request::Type type) { - 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_DEINITIALIZE, - .pl_idx = idx, - .blk_nr = 0, - .idx = 0 - }; - - channel._state = Channel::State::DEINITIALIZE_SB_CTRL_PENDING; - progress = true; - - break; - - case Channel::State::DEINITIALIZE_SB_CTRL_COMPLETE: - - if (not channel._prim.succ) { - class Deinitialize_primitive_not_successfull { }; - throw Deinitialize_primitive_not_successfull { }; - } - - channel._request.success(true); - channel._state = Channel::State::COMPLETE; - indices.dequeue(idx); - progress = true; - - break; - default: - break; + switch (_state) { + case REQ_SUBMITTED: _gen_sb_control_req(progress, type, FORWARD_TO_SB_CTRL_SUCCEEDED); break; + case FORWARD_TO_SB_CTRL_SUCCEEDED: _mark_req_successful(progress); break; + default: break; } } void Request_pool::execute(bool &progress) { - if (_indices.empty()) - return; - - class Not_implemented { }; - - auto const idx = _indices.head(); - - if (idx >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &channel = _channels[idx]; - Request &request = { channel._request }; - - switch (request.operation()) { - case Tresor::Request::Operation::READ: _execute_read(channel, _indices, idx, progress); break; - case Tresor::Request::Operation::WRITE: _execute_write(channel, _indices, idx, progress); break; - case Tresor::Request::Operation::SYNC: _execute_sync(channel, _indices, idx, progress); break; - case Tresor::Request::Operation::REKEY: _execute_rekey(channel, _indices, idx, progress); break; - case Tresor::Request::Operation::EXTEND_VBD: _execute_extend_tree(channel, idx, Channel::VBD_EXTENSION_STEP_PENDING, progress); break; - 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: _execute_create_snap(channel, _indices, idx, progress); break; - case Tresor::Request::Operation::DISCARD_SNAPSHOT: _execute_discard_snap(channel, _indices, idx, progress); break; - default: break; - } + if (!_chan_queue.empty()) + _chan_queue.head().execute(progress); } -void Request_pool::submit_request(Module_request &mod_req) +void Request_pool_channel::execute(bool &progress) { - for (Module_request_id idx { 0 }; idx < NR_OF_CHANNELS; idx++) { - if (_channels[idx]._state == Channel::INVALID) { - Request &req { *static_cast(&mod_req) }; - switch (req.operation()) { - case Request::INITIALIZE: - - class Exception_1 { }; - throw Exception_1 { }; - - case Request::SYNC: - case Request::READ: - case Request::WRITE: - case Request::DEINITIALIZE: - 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; - _channels[idx]._request = req; - _indices.enqueue((Slots_index)idx); - return; - - default: - - class Exception_2 { }; - throw Exception_2 { }; - } - } - } - class Exception_3 { }; - throw Exception_3 { }; -} - - -bool Request_pool::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) -{ - if (_indices.empty()) - return false; - - Slots_index const idx { _indices.head() }; - 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::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::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; - 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._gen); - - return true; -} - - -void Request_pool::_drop_generated_request(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - switch (chan._state) { - case Channel::READ_VBA_AT_SB_CTRL_PENDING: chan._state = Channel::READ_VBA_AT_SB_CTRL_IN_PROGRESS; break; - case Channel::WRITE_VBA_AT_SB_CTRL_PENDING: chan._state = Channel::WRITE_VBA_AT_SB_CTRL_IN_PROGRESS; break; - case Channel::SYNC_AT_SB_CTRL_PENDING: chan._state = Channel::SYNC_AT_SB_CTRL_IN_PROGRESS; break; - case Channel::REKEY_INIT_PENDING: chan._state = Channel::REKEY_INIT_IN_PROGRESS; break; - case Channel::REKEY_VBA_PENDING: chan._state = Channel::REKEY_VBA_IN_PROGRESS; break; - case Channel::VBD_EXTENSION_STEP_PENDING: chan._state = Channel::TREE_EXTENSION_STEP_IN_PROGRESS; break; - case Channel::FT_EXTENSION_STEP_PENDING: chan._state = Channel::TREE_EXTENSION_STEP_IN_PROGRESS; break; - case Channel::CREATE_SNAP_AT_SB_CTRL_PENDING: chan._state = Channel::CREATE_SNAP_AT_SB_CTRL_IN_PROGRESS; break; - case Channel::DISCARD_SNAP_AT_SB_CTRL_PENDING: chan._state = Channel::DISCARD_SNAP_AT_SB_CTRL_IN_PROGRESS; break; - case Channel::INITIALIZE_SB_CTRL_PENDING: chan._state = Channel::INITIALIZE_SB_CTRL_IN_PROGRESS; break; - case Channel::DEINITIALIZE_SB_CTRL_PENDING: chan._state = Channel::DEINITIALIZE_SB_CTRL_IN_PROGRESS; break; - default: - class Exception_2 { }; - throw Exception_2 { }; - } -} - - -void Request_pool::generated_request_complete(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - switch (mod_req.dst_module_id()) { - case SUPERBLOCK_CONTROL: - { - Superblock_control_request &gen_req { *static_cast(&mod_req) }; - chan._prim.succ = gen_req.success(); - switch (chan._state) { - case Channel::READ_VBA_AT_SB_CTRL_IN_PROGRESS: chan._state = Channel::READ_VBA_AT_SB_CTRL_COMPLETE; break; - case Channel::WRITE_VBA_AT_SB_CTRL_IN_PROGRESS: chan._state = Channel::WRITE_VBA_AT_SB_CTRL_COMPLETE; break; - case Channel::SYNC_AT_SB_CTRL_IN_PROGRESS: chan._state = Channel::SYNC_AT_SB_CTRL_COMPLETE; break; - case Channel::TREE_EXTENSION_STEP_IN_PROGRESS: - chan._state = Channel::TREE_EXTENSION_STEP_COMPLETE; - chan._request_finished = gen_req.request_finished(); - break; - case Channel::CREATE_SNAP_AT_SB_CTRL_IN_PROGRESS: - chan._state = Channel::CREATE_SNAP_AT_SB_CTRL_COMPLETE; - break; - case Channel::DISCARD_SNAP_AT_SB_CTRL_IN_PROGRESS: - chan._state = Channel::DISCARD_SNAP_AT_SB_CTRL_COMPLETE; - break; - case Channel::INITIALIZE_SB_CTRL_IN_PROGRESS: - chan._sb_state = gen_req.sb_state(); - chan._state = Channel::INITIALIZE_SB_CTRL_COMPLETE; - break; - case Channel::DEINITIALIZE_SB_CTRL_IN_PROGRESS: chan._state = Channel::DEINITIALIZE_SB_CTRL_COMPLETE; break; - case Channel::REKEY_INIT_IN_PROGRESS: chan._state = Channel::REKEY_INIT_COMPLETE; break; - case Channel::REKEY_VBA_IN_PROGRESS: - chan._request_finished = gen_req.request_finished(); - chan._state = Channel::REKEY_VBA_COMPLETE; - break; - default: - class Exception_2 { }; - throw Exception_2 { }; - } - break; - } - default: - class Exception_5 { }; - throw Exception_5 { }; + switch (_req_ptr->_op) { + case Request::READ: _access_vbas(progress, Superblock_control_request::READ_VBA); break; + case Request::WRITE: _access_vbas(progress, Superblock_control_request::WRITE_VBA); break; + case Request::SYNC: _forward_to_sb_ctrl(progress, Superblock_control_request::SYNC); break; + case Request::REKEY: _rekey(progress); break; + case Request::EXTEND_VBD: _extend_tree(Superblock_control_request::VBD_EXTENSION_STEP, progress); break; + case Request::EXTEND_FT: _extend_tree(Superblock_control_request::FT_EXTENSION_STEP, progress); break; + case Request::INITIALIZE: _initialize(progress); break; + case Request::DEINITIALIZE: _forward_to_sb_ctrl(progress, Superblock_control_request::DEINITIALIZE); break; + case Request::CREATE_SNAPSHOT: _forward_to_sb_ctrl(progress, Superblock_control_request::CREATE_SNAPSHOT); break; + case Request::DISCARD_SNAPSHOT: _forward_to_sb_ctrl(progress, Superblock_control_request::DISCARD_SNAPSHOT); break; + default: break; } } Request_pool::Request_pool() { - Slots_index const idx { 0 }; - _channels[idx]._state = Channel::SUBMITTED; - _channels[idx]._request = Request { - Request::INITIALIZE, false, 0, 0, 0, 0, 0, 0, - INVALID_MODULE_ID, INVALID_MODULE_REQUEST_ID }; - - _indices.enqueue(idx); + for (Module_channel_id id { 0 }; id < NUM_CHANNELS; id++) { + _channels[id].construct(id, _chan_queue); + add_channel(*_channels[id]); + } + ASSERT(try_submit_request(_init_req)); } -bool Request_pool::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) +void Request_pool_channel::_generated_req_completed(State_uint state_uint) { - for (Channel &channel : _channels) { - if (channel._request.operation() != Request::INVALID && - channel._state == Channel::COMPLETE) { + if (!_generated_req_success) { + error("request_pool: request (", *_req_ptr, ") failed because generated request failed)"); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _chan_queue.dequeue(*this); + _req_ptr = nullptr; + } else + _state = (State)state_uint; +} - if (sizeof(channel._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &channel._request, sizeof(channel._request)); - return true; + +void Request_pool_channel::_reset() +{ + _state = INVALID; + _sb_state = Superblock::INVALID; + _num_blks = _num_requests_preponed = 0; + _request_finished = false; +} + + +Request_pool_channel &Request_pool_channel_queue::head() const +{ + ASSERT(!empty()); + return *_slots[_head]; +} + + +void Request_pool_channel_queue::enqueue(Channel &chan) +{ + ASSERT(!full()); + _slots[_tail] = &chan; + _tail = (_tail + 1) % NUM_SLOTS; + _num_used_slots++; +} + + +void Request_pool_channel_queue::move_one_slot_towards_tail(Channel const &chan) +{ + Slot_index slot_idx { _head }; + Slot_index next_slot_idx; + ASSERT(!empty()); + while (1) { + if (slot_idx < NUM_SLOTS - 1) + next_slot_idx = slot_idx + 1; + else + next_slot_idx = 0; + + ASSERT(next_slot_idx != _tail); + if (_slots[slot_idx] == &chan) { + Channel *chan_ptr = _slots[next_slot_idx]; + _slots[next_slot_idx] = _slots[slot_idx]; + _slots[slot_idx] = chan_ptr; + return; } + slot_idx = next_slot_idx; } - return false; } -void Request_pool::_drop_completed_request(Module_request &req) +bool Request_pool_channel_queue::is_tail(Channel const &chan) const { - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - if (chan._request.operation() == Request::INVALID || - chan._state != Channel::COMPLETE) { + Slot_index slot_idx; + ASSERT(!empty()); + if (_tail) + slot_idx = _tail - 1; + else + slot_idx = NUM_SLOTS - 1; - class Exception_2 { }; - throw Exception_2 { }; - } - chan = Channel { }; + return _slots[slot_idx] == &chan; +} + + +Request_pool_channel &Request_pool_channel_queue::next(Channel const &chan) const +{ + Slot_index slot_idx { _head }; + Slot_index next_slot_idx; + ASSERT(!empty()); + while (1) { + if (slot_idx < NUM_SLOTS - 1) + next_slot_idx = slot_idx + 1; + else + next_slot_idx = 0; + + ASSERT(next_slot_idx != _tail); + if (_slots[slot_idx] == &chan) + return *_slots[next_slot_idx]; + else + slot_idx = next_slot_idx; + } +} + + +void Request_pool_channel_queue::dequeue(Channel const &chan) +{ + ASSERT(!empty() && &head() == &chan); + _head = (_head + 1) % NUM_SLOTS; + _num_used_slots--; +} + + +void Request_pool_channel::_request_submitted(Module_request &req) +{ + _reset(); + _req_ptr = static_cast(&req); + _state = REQ_SUBMITTED; + _chan_queue.enqueue(*this); } diff --git a/repos/gems/src/lib/tresor/sb_check.cc b/repos/gems/src/lib/tresor/sb_check.cc index aba72805bc..74a4d09725 100644 --- a/repos/gems/src/lib/tresor/sb_check.cc +++ b/repos/gems/src/lib/tresor/sb_check.cc @@ -11,9 +11,6 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base includes */ -#include - /* tresor includes */ #include #include @@ -22,487 +19,149 @@ using namespace Tresor; - -/********************** - ** Sb_check_request ** - **********************/ - -Sb_check_request::Sb_check_request(Module_id src_module_id, - Module_request_id src_request_id) +Sb_check_request::Sb_check_request(Module_id src_mod, Module_channel_id src_chan, bool &success) : - Module_request { src_module_id, src_request_id, SB_CHECK } + Module_request { src_mod, src_chan, SB_CHECK }, _success { success } { } -void Sb_check_request::create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type) +void Sb_check_channel::_generated_req_completed(State_uint state_uint) { - Sb_check_request req { src_module_id, src_request_id }; - req._type = (Type)req_type; - - if (sizeof(req) > buf_size) { - class Bad_size_0 { }; - throw Bad_size_0 { }; + if (!_generated_req_success) { + error("sb check: request (", *_req_ptr, ") failed because generated request failed)"); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; + return; } - memcpy(buf_ptr, &req, sizeof(req)); + _state = (State)state_uint; } -char const *Sb_check_request::type_to_string(Type type) +void Sb_check_channel::execute(bool &progress) { - switch (type) { - case INVALID: return "invalid"; - case CHECK: return "check"; - } - return "?"; -} + if (!_req_ptr) + return; + switch (_state) { + case REQ_SUBMITTED: -/************** - ** Sb_check ** - **************/ + _highest_gen = 0; + _highest_gen_sb_idx = 0; + _snap_idx = 0; + _sb_idx = 0; + _scan_for_highest_gen_sb_done = false; + _generate_req(READ_BLK_SUCCESSFUL, progress, _sb_idx, _blk); + break; -char const *Sb_check::_state_to_step_label(Channel::Sb_slot_state state) -{ - switch (state) { - case Channel::READ_DONE: return "read"; - case Channel::VBD_CHECK_DONE: return "vbd check"; - case Channel::FT_CHECK_DONE: return "ft check"; - case Channel::MT_CHECK_DONE: return "mt check"; + case READ_BLK_SUCCESSFUL: + + _sb.decode_from_blk(_blk); + if (_scan_for_highest_gen_sb_done) { + if (!_sb.valid()) { + _mark_req_failed(progress, "no valid superblock");; + break; + } + Snapshot &snap { _sb.snapshots.items[_snap_idx] }; + if (snap.valid) { + Snapshot &snap { _sb.snapshots.items[_snap_idx] }; + _tree_root.construct(snap.pba, snap.gen, snap.hash, snap.max_level, _sb.degree, snap.nr_of_leaves); + _generate_req(CHECK_VBD_SUCCESSFUL, progress, *_tree_root); + if (VERBOSE_CHECK) + log(" check snap ", _snap_idx, " (", snap, ")"); + } else { + _state = CHECK_VBD_SUCCESSFUL; + progress = true; + if (VERBOSE_CHECK) + log(" skip snap ", _snap_idx, " as it is unused"); + } + } else { + Snapshot &snap { _sb.curr_snap() }; + if (_sb.valid() && snap.gen > _highest_gen) { + _highest_gen = snap.gen; + _highest_gen_sb_idx = _sb_idx; + } + if (_sb_idx < MAX_SUPERBLOCK_INDEX) { + _sb_idx++; + _generate_req(READ_BLK_SUCCESSFUL, progress, _sb_idx, _blk); + progress = true; + } else { + _scan_for_highest_gen_sb_done = true; + _generate_req(READ_BLK_SUCCESSFUL, progress, _highest_gen_sb_idx, _blk); + if (VERBOSE_CHECK) + log("check superblock ", _highest_gen_sb_idx, "\n read superblock"); + } + } + break; + + case CHECK_VBD_SUCCESSFUL: + + if (_snap_idx < MAX_SNAP_IDX) { + _snap_idx++; + _state = READ_BLK_SUCCESSFUL; + progress = true; + } else { + _snap_idx = 0; + _tree_root.construct(_sb.free_number, _sb.free_gen, _sb.free_hash, _sb.free_max_level, _sb.free_degree, _sb.free_leaves); + _generate_req(CHECK_FT_SUCCESSFUL, progress, *_tree_root); + if (VERBOSE_CHECK) + log(" check free tree"); + } + break; + + case CHECK_FT_SUCCESSFUL: + + _tree_root.construct(_sb.meta_number, _sb.meta_gen, _sb.meta_hash, _sb.meta_max_level, _sb.meta_degree, _sb.meta_leaves); + _generate_req(CHECK_MT_SUCCESSFUL, progress, *_tree_root); + if (VERBOSE_CHECK) + log(" check meta tree"); + break; + + case CHECK_MT_SUCCESSFUL: _mark_req_successful(progress); break; default: break; } - return "?"; } -bool Sb_check::_handle_failed_generated_req(Channel &chan, - bool &progress) +void Sb_check_channel::_mark_req_failed(bool &progress, char const *str) { - if (chan._gen_prim_success) - return false; - - _mark_req_failed( - chan, progress, _state_to_step_label(chan._sb_slot_state)); - - return true; -} - -void Sb_check::_execute_check(Channel &chan, - bool &progress) -{ - switch (chan._state) { - case Channel::INSPECT_SBS: - - switch (chan._sb_slot_state) { - case Channel::INIT: - - chan._sb_slot_state = Channel::READ_STARTED; - chan._gen_prim_blk_nr = chan._sb_slot_idx; - progress = true; - break; - - case Channel::READ_DONE: - { - if (_handle_failed_generated_req(chan, progress)) - break; - - Snapshot &snap { - chan._sb_slot.snapshots.items[chan._sb_slot.curr_snap] }; - - if (chan._sb_slot.valid() && - snap.gen > chan._highest_gen) { - - chan._highest_gen = snap.gen; - chan._last_sb_slot_idx = chan._sb_slot_idx; - } - if (chan._sb_slot_idx < MAX_SUPERBLOCK_INDEX) { - - chan._sb_slot_idx++; - chan._sb_slot_state = Channel::INIT; - progress = true; - - } else { - - chan._state = Channel::CHECK_SB; - chan._sb_slot_idx = chan._last_sb_slot_idx; - chan._sb_slot_state = Channel::INIT; - progress = true; - - if (VERBOSE_CHECK) - log("check superblock ", chan._sb_slot_idx); - } - break; - } - default: - - break; - } - break; - - case Channel::CHECK_SB: - - switch (chan._sb_slot_state) { - case Channel::INIT: - - chan._sb_slot_state = Channel::READ_STARTED; - chan._gen_prim_blk_nr = chan._sb_slot_idx; - progress = true; - - if (VERBOSE_CHECK) - log(" read superblock"); - - break; - - case Channel::READ_DONE: - - if (_handle_failed_generated_req(chan, progress)) - break; - - if (chan._sb_slot.valid()) { - - Snapshot &snap { - chan._sb_slot.snapshots.items[chan._snap_idx] }; - - if (snap.valid) { - - chan._sb_slot_state = Channel::VBD_CHECK_STARTED; - chan._gen_prim_blk_nr = snap.pba; - progress = true; - - if (VERBOSE_CHECK) - log(" check snap ", chan._snap_idx, " (", snap, ")"); - - } else { - - chan._sb_slot_state = Channel::VBD_CHECK_DONE; - progress = true; - - if (VERBOSE_CHECK) - log(" skip snap ", chan._snap_idx, - " as it is unused"); - } - } else { - - chan._sb_slot_state = Channel::DONE; - progress = true; - - if (VERBOSE_CHECK) - log(" skip superblock as it is unused"); - } - break; - - case Channel::VBD_CHECK_DONE: - - if (_handle_failed_generated_req(chan, progress)) - break; - - if (chan._snap_idx < MAX_SNAP_IDX) { - - chan._snap_idx++; - chan._sb_slot_state = Channel::READ_DONE; - progress = true; - - } else { - - chan._snap_idx = 0; - chan._gen_prim_blk_nr = chan._sb_slot.free_number; - chan._sb_slot_state = Channel::FT_CHECK_STARTED; - progress = true; - - if (VERBOSE_CHECK) - log(" check free tree"); - } - break; - - case Channel::FT_CHECK_DONE: - - if (_handle_failed_generated_req(chan, progress)) - break; - - chan._sb_slot_state = Channel::MT_CHECK_STARTED; - progress = true; - - if (VERBOSE_CHECK) - log(" check meta tree"); - - break; - - case Channel::MT_CHECK_DONE: - - if (_handle_failed_generated_req(chan, progress)) - break; - - _mark_req_successful(chan, progress); - break; - - case Channel::DONE: - - break; - - default: - - break; - } - break; - - default: - - break; - } -} - - -void Sb_check::_mark_req_failed(Channel &chan, - bool &progress, - char const *str) -{ - error("sb check: request (", chan._request, ") failed at step \"", str, "\""); - chan._request._success = false; - chan._sb_slot_state = Channel::DONE; + error("sb check: request (", *_req_ptr, ") failed at step \"", str, "\""); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; } -void Sb_check::_mark_req_successful(Channel &chan, - bool &progress) +void Sb_check_channel::_mark_req_successful(bool &progress) { - Request &req { chan._request }; + Request &req { *_req_ptr }; req._success = true; - chan._sb_slot_state = Channel::DONE; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; } -bool Sb_check::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) +void Sb_check_channel::_request_submitted(Module_request &mod_req) { - for (Channel &channel : _channels) { - if (channel._sb_slot_state == Channel::DONE) { - if (sizeof(channel._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &channel._request, sizeof(channel._request)); - return true; - } - } - return false; + _req_ptr = static_cast(&mod_req); + _state = REQ_SUBMITTED; } -void Sb_check::_drop_completed_request(Module_request &req) +Sb_check::Sb_check() { - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; + Module_channel_id id { 0 }; + for (Constructible &chan : _channels) { + chan.construct(id++); + add_channel(*chan); } - if (_channels[id]._sb_slot_state != Channel::DONE) { - class Exception_2 { }; - throw Exception_2 { }; - } - _channels[id]._sb_slot_state = Channel::INACTIVE; -} - - -bool Sb_check::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - - Channel &chan { _channels[id] }; - - if (chan._sb_slot_state == Channel::INACTIVE) - continue; - - switch (chan._sb_slot_state) { - case Channel::READ_STARTED: - - construct_in_buf( - buf_ptr, buf_size, SB_CHECK, id, - Block_io_request::READ, 0, 0, 0, - chan._gen_prim_blk_nr, 0, 1, &chan._encoded_blk, - nullptr); - - return true; - - case Channel::VBD_CHECK_STARTED: - { - Snapshot const &snap { - chan._sb_slot.snapshots.items[chan._snap_idx] }; - - construct_in_buf( - buf_ptr, buf_size, SB_CHECK, id, - Vbd_check_request::CHECK, snap.max_level, - chan._sb_slot.degree - 1, - snap.nr_of_leaves, - Type_1_node { snap.pba, snap.gen, snap.hash }); - - return true; - } - case Channel::FT_CHECK_STARTED: - - construct_in_buf( - buf_ptr, buf_size, SB_CHECK, id, - Ft_check_request::CHECK, - (Tree_level_index)chan._sb_slot.free_max_level, - (Tree_degree)chan._sb_slot.free_degree - 1, - (Number_of_leaves)chan._sb_slot.free_leaves, - Type_1_node { - chan._sb_slot.free_number, - chan._sb_slot.free_gen, - chan._sb_slot.free_hash }); - - return true; - - case Channel::MT_CHECK_STARTED: - - construct_in_buf( - buf_ptr, buf_size, SB_CHECK, id, - Ft_check_request::CHECK, - (Tree_level_index)chan._sb_slot.meta_max_level, - (Tree_degree)chan._sb_slot.meta_degree - 1, - (Number_of_leaves)chan._sb_slot.meta_leaves, - Type_1_node { - chan._sb_slot.meta_number, - chan._sb_slot.meta_gen, - chan._sb_slot.meta_hash }); - - return true; - - default: - break; - } - } - return false; -} - - -void Sb_check::_drop_generated_request(Module_request &req) -{ - Module_request_id const id { req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_0 { }; - throw Exception_0 { }; - } - Channel &chan { _channels[id] }; - switch (chan._sb_slot_state) { - case Channel::READ_STARTED: chan._sb_slot_state = Channel::READ_DROPPED; break; - case Channel::VBD_CHECK_STARTED: chan._sb_slot_state = Channel::VBD_CHECK_DROPPED; break; - case Channel::FT_CHECK_STARTED: chan._sb_slot_state = Channel::FT_CHECK_DROPPED; break; - case Channel::MT_CHECK_STARTED: chan._sb_slot_state = Channel::MT_CHECK_DROPPED; break; - default: - class Exception_4 { }; - throw Exception_4 { }; - } -} - - -void Sb_check::generated_request_complete(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - switch (mod_req.dst_module_id()) { - case BLOCK_IO: - { - Block_io_request &gen_req { *static_cast(&mod_req) }; - chan._gen_prim_success = gen_req.success(); - switch (chan._sb_slot_state) { - case Channel::READ_DROPPED: - chan._sb_slot.decode_from_blk(chan._encoded_blk); - chan._sb_slot_state = Channel::READ_DONE; - break; - default: - class Exception_2 { }; - throw Exception_2 { }; - } - break; - } - case VBD_CHECK: - { - Vbd_check_request &gen_req { *static_cast(&mod_req) }; - chan._gen_prim_success = gen_req.success(); - switch (chan._sb_slot_state) { - case Channel::VBD_CHECK_DROPPED: chan._sb_slot_state = Channel::VBD_CHECK_DONE; break; - default: - class Exception_3 { }; - throw Exception_3 { }; - } - break; - } - case FT_CHECK: - { - Ft_check_request &gen_req { *static_cast(&mod_req) }; - chan._gen_prim_success = gen_req.success(); - switch (chan._sb_slot_state) { - case Channel::FT_CHECK_DROPPED: chan._sb_slot_state = Channel::FT_CHECK_DONE; break; - case Channel::MT_CHECK_DROPPED: chan._sb_slot_state = Channel::MT_CHECK_DONE; break; - default: - class Exception_3 { }; - throw Exception_3 { }; - } - break; - } - default: - class Exception_8 { }; - throw Exception_8 { }; - } -} - - -bool Sb_check::ready_to_submit_request() -{ - for (Channel &chan : _channels) { - if (chan._sb_slot_state == Channel::INACTIVE) - return true; - } - return false; -} - - -void Sb_check::submit_request(Module_request &req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - Channel &chan { _channels[id] }; - if (chan._sb_slot_state == Channel::INACTIVE) { - req.dst_request_id(id); - chan = Channel { }; - chan._request = *static_cast(&req); - chan._sb_slot_state = Channel::INIT; - return; - } - } - class Exception_1 { }; - throw Exception_1 { }; } void Sb_check::execute(bool &progress) { - for (Channel &chan : _channels) { - - if (chan._sb_slot_state == Channel::INACTIVE) - continue; - - Request &req { chan._request }; - switch (req._type) { - case Request::CHECK: - - _execute_check(chan, progress); - break; - - default: - - class Exception_1 { }; - throw Exception_1 { }; - } - } + for_each_channel([&] (Channel &chan) { + chan.execute(progress); }); } diff --git a/repos/gems/src/lib/tresor/sb_initializer.cc b/repos/gems/src/lib/tresor/sb_initializer.cc index c4ffbd7da4..5c7cfe1324 100644 --- a/repos/gems/src/lib/tresor/sb_initializer.cc +++ b/repos/gems/src/lib/tresor/sb_initializer.cc @@ -1,5 +1,6 @@ /* * \brief Module for initializing the superblocks of a new Tresor + * \author Martin Stein * \author Josef Soentgen * \date 2023-03-14 */ @@ -11,12 +12,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base includes */ -#include - /* tresor includes */ -#include -#include +#include #include #include #include @@ -25,701 +22,150 @@ using namespace Tresor; - -Sb_initializer_request::Sb_initializer_request(Module_id src_module_id, - Module_request_id src_request_id) +Sb_initializer_request:: +Sb_initializer_request(Module_id src_mod, Module_channel_id src_chan, Tree_level_index vbd_max_lvl, + Tree_degree vbd_degree, Number_of_leaves vbd_num_leaves, Tree_level_index ft_max_lvl, + Tree_degree ft_degree, Number_of_leaves ft_num_leaves, Tree_level_index mt_max_lvl, + Tree_degree mt_degree, Number_of_leaves mt_num_leaves, Pba_allocator &pba_alloc, bool &success) : - Module_request { src_module_id, src_request_id, SB_INITIALIZER } + Module_request { src_mod, src_chan, SB_INITIALIZER }, _vbd_max_lvl { vbd_max_lvl }, + _vbd_degree { vbd_degree }, _vbd_num_leaves { vbd_num_leaves }, _ft_max_lvl { ft_max_lvl }, + _ft_degree { ft_degree }, _ft_num_leaves { ft_num_leaves }, _mt_max_lvl { mt_max_lvl }, + _mt_degree { mt_degree }, _mt_num_leaves { mt_num_leaves }, _pba_alloc { pba_alloc }, _success { success } { } -void Sb_initializer_request::create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - Tree_level_index vbd_max_level_idx, - Tree_degree vbd_max_child_idx, - Number_of_leaves vbd_nr_of_leaves, - Tree_level_index ft_max_level_idx, - Tree_degree ft_max_child_idx, - Number_of_leaves ft_nr_of_leaves, - Tree_level_index mt_max_level_idx, - Tree_degree mt_max_child_idx, - Number_of_leaves mt_nr_of_leaves) +void Sb_initializer_channel::_generated_req_completed(State_uint state_uint) { - Sb_initializer_request req { src_module_id, src_request_id }; - - req._type = (Type)req_type; - req._vbd_max_level_idx = vbd_max_level_idx; - req._vbd_max_child_idx = vbd_max_child_idx; - req._vbd_nr_of_leaves = vbd_nr_of_leaves; - req._ft_max_level_idx = ft_max_level_idx; - req._ft_max_child_idx = ft_max_child_idx; - req._ft_nr_of_leaves = ft_nr_of_leaves; - req._mt_max_level_idx = mt_max_level_idx; - req._mt_max_child_idx = mt_max_child_idx; - req._mt_nr_of_leaves = mt_nr_of_leaves; - - if (sizeof(req) > buf_size) { - class Bad_size_0 { }; - throw Bad_size_0 { }; - } - memcpy(buf_ptr, &req, sizeof(req)); -} - - -char const *Sb_initializer_request::type_to_string(Type type) -{ - switch (type) { - case INVALID: return "invalid"; - case INIT: return "init"; - } - return "?"; -} - - -void Sb_initializer::_populate_sb_slot(Channel &channel, - Physical_block_address first, - Number_of_blocks num) -{ - Superblock &sb = channel._sb; - - Request const &req = channel._request; - Type_1_node const &vbd_node = channel._vbd_node; - Type_1_node const &ft_node = channel._ft_node; - Type_1_node const &mt_node = channel._mt_node; - - sb.state = Superblock::NORMAL; - sb.snapshots.items[0] = Snapshot { - .hash = vbd_node.hash, - .pba = vbd_node.pba, - .gen = 0, - .nr_of_leaves = req._vbd_nr_of_leaves, - .max_level = req._vbd_max_level_idx, - .valid = true, - .id = 0, - .keep = false - }; - - sb.rekeying_vba = 0; - sb.resizing_nr_of_pbas = 0; - sb.resizing_nr_of_leaves = 0; - memset(&sb.previous_key, 0, sizeof(sb.previous_key)); - sb.current_key = channel._key_cipher; - sb.curr_snap = 0; - sb.degree = req._vbd_max_child_idx; - sb.first_pba = first; - sb.nr_of_pbas = num; - sb.last_secured_generation = 0; - sb.free_gen = 0; - sb.free_number = ft_node.pba; - sb.free_hash = ft_node.hash; - sb.free_max_level = req._ft_max_level_idx; - sb.free_degree = req._ft_max_child_idx; - sb.free_leaves = req._ft_nr_of_leaves; - sb.meta_gen = 0; - sb.meta_number = mt_node.pba; - sb.meta_hash = mt_node.hash; - sb.meta_max_level = req._mt_max_level_idx; - sb.meta_degree = req._mt_max_child_idx; - sb.meta_leaves = req._mt_nr_of_leaves; -} - - -extern uint64_t block_allocator_first_block(); -extern uint64_t block_allocator_nr_of_blks(); - - -void Sb_initializer::_execute(Channel &channel, - bool &progress) -{ - - using CS = Channel::State; - - switch (channel._state) { - case CS::IN_PROGRESS: - - if (channel._sb_slot_index == 0) { - channel._state = CS::VBD_REQUEST_PENDING; - } else { - channel._sb.encode_to_blk(channel._encoded_blk); - channel._state = CS::WRITE_REQUEST_PENDING; - } - progress = true; - break; - - case CS::VBD_REQUEST_COMPLETE: - - channel._state = CS::FT_REQUEST_PENDING; - progress = true; - break; - - case CS::FT_REQUEST_COMPLETE: - - channel._state = CS::MT_REQUEST_PENDING; - progress = true; - break; - - case CS::MT_REQUEST_COMPLETE: - - channel._state = CS::TA_REQUEST_CREATE_KEY_PENDING; - progress = true; - break; - - case CS::TA_REQUEST_CREATE_KEY_COMPLETE: - - channel._state = CS::TA_REQUEST_ENCRYPT_KEY_PENDING; - progress = true; - break; - - case CS::TA_REQUEST_ENCRYPT_KEY_COMPLETE: - - _populate_sb_slot(channel, - Physical_block_address { block_allocator_first_block() } - NR_OF_SUPERBLOCK_SLOTS, - Number_of_blocks { (uint32_t)block_allocator_nr_of_blks() + NR_OF_SUPERBLOCK_SLOTS }); - - channel._sb.encode_to_blk(channel._encoded_blk); - calc_sha256_4k_hash(channel._encoded_blk, channel._sb_hash); - - channel._state = CS::WRITE_REQUEST_PENDING; - progress = true; - break; - - case CS::WRITE_REQUEST_COMPLETE: - - channel._state = CS::SYNC_REQUEST_PENDING; - progress = true; - break; - - case CS::SYNC_REQUEST_COMPLETE: - - if (channel._sb_slot_index == 0) { - channel._state = CS::TA_REQUEST_SECURE_SB_PENDING; - } else { - channel._state = CS::SLOT_COMPLETE; - } - progress = true; - break; - - case CS::TA_REQUEST_SECURE_SB_COMPLETE: - - channel._state = CS::SLOT_COMPLETE; - progress = true; - break; - default: - break; - } - - /* finished */ - if (channel._sb_slot_index == NR_OF_SUPERBLOCK_SLOTS) - _mark_req_successful(channel, progress); -} - - -void Sb_initializer::_execute_init(Channel &channel, - bool &progress) -{ - using CS = Channel::State; - - switch (channel._state) { - case CS::SUBMITTED: - - /* - * Reset the index on every new job as it is - * indicator for a finished job. - */ - channel._sb_slot_index = 0; - - channel._state = Channel::PENDING; - progress = true; - return; - - case CS::PENDING: - - /* - * Remove residual data here as we will end up - * here for every SB slot. - */ - channel.clean_data(); - - channel._state = Channel::IN_PROGRESS; - progress = true; - return; - - case CS::IN_PROGRESS: - - _execute(channel, progress); - return; - - case CS::SLOT_COMPLETE: - - if (channel._sb_slot_index < NR_OF_SUPERBLOCK_SLOTS) { - ++channel._sb_slot_index; - channel._state = Channel::PENDING; - progress = true; - } - return; - - case CS::FT_REQUEST_COMPLETE: - - _execute(channel, progress); - return; - - case CS::MT_REQUEST_COMPLETE: - - _execute(channel, progress); - return; - - case CS::VBD_REQUEST_COMPLETE: - - _execute(channel, progress); - return; - - case CS::SYNC_REQUEST_COMPLETE: - - _execute(channel, progress); - return; - - case CS::TA_REQUEST_CREATE_KEY_COMPLETE: - - _execute(channel, progress); - return; - - case CS::TA_REQUEST_ENCRYPT_KEY_COMPLETE: - - _execute(channel, progress); - return; - - case CS::TA_REQUEST_SECURE_SB_COMPLETE: - - _execute(channel, progress); - return; - - case CS::WRITE_REQUEST_COMPLETE: - - _execute(channel, progress); - return; - - default: - /* - * Omit other states related to FT/MT/VBD as - * those are handled via Module API. - */ + if (!_generated_req_success) { + error("sb initializer: request (", *_req_ptr, ") failed because generated request failed)"); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; return; } + _state = (State)state_uint; } -void Sb_initializer::_mark_req_failed(Channel &channel, - bool &progress, - char const *str) +void Sb_initializer_channel::_request_submitted(Module_request &mod_req) { - error("request failed: failed to ", str); - channel._request._success = false; - channel._state = Channel::COMPLETE; + _req_ptr = static_cast(&mod_req); + _state = REQ_SUBMITTED; +} + + +void Sb_initializer_channel::_mark_req_successful(bool &progress) +{ + _req_ptr->_success = true; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; } -void Sb_initializer::_mark_req_successful(Channel &channel, - bool &progress) +void Sb_initializer_channel::execute(bool &progress) { - Request &req { channel._request }; + if (!_req_ptr) + return; - req._success = true; - - channel._state = Channel::COMPLETE; - progress = true; -} - - -bool Sb_initializer::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (Channel &channel : _channels) { - if (channel._state == Channel::COMPLETE) { - if (sizeof(channel._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &channel._request, sizeof(channel._request)); - return true; - } - } - return false; -} - - -void Sb_initializer::_drop_completed_request(Module_request &req) -{ - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (_channels[id]._state != Channel::COMPLETE) { - class Exception_2 { }; - throw Exception_2 { }; - } - _channels[id]._state = Channel::INACTIVE; -} - - -bool Sb_initializer::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) -{ - using CS = Channel::State; - - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - - Channel const &channel { _channels[id] }; - - if (channel._state == CS::INACTIVE) - continue; - - switch (channel._state) { - case CS::VBD_REQUEST_PENDING: - { - Vbd_initializer_request::Type const vbd_initializer_req_type { - Vbd_initializer_request::INIT }; - - Vbd_initializer_request::create( - buf_ptr, buf_size, SB_INITIALIZER, id, - vbd_initializer_req_type, - channel._request._vbd_max_level_idx, - channel._request._vbd_max_child_idx - 1, - channel._request._vbd_nr_of_leaves); - - return true; - } - case CS::FT_REQUEST_PENDING: - { - Ft_initializer_request::Type const ft_initializer_req_type { - Ft_initializer_request::INIT }; - - Ft_initializer_request::create( - buf_ptr, buf_size, SB_INITIALIZER, id, - ft_initializer_req_type, - channel._request._ft_max_level_idx, - channel._request._ft_max_child_idx - 1, - channel._request._ft_nr_of_leaves); - - return true; - } - case CS::MT_REQUEST_PENDING: - { - Ft_initializer_request::Type const ft_initializer_req_type { - Ft_initializer_request::INIT }; - - Ft_initializer_request::create( - buf_ptr, buf_size, SB_INITIALIZER, id, - ft_initializer_req_type, - channel._request._ft_max_level_idx, - channel._request._ft_max_child_idx - 1, - channel._request._ft_nr_of_leaves); - - return true; - } - case CS::WRITE_REQUEST_PENDING: - { - Block_io_request::Type const block_io_req_type { - Block_io_request::WRITE }; - - construct_in_buf( - buf_ptr, buf_size, SB_INITIALIZER, id, block_io_req_type, 0, 0, - 0, channel._sb_slot_index, 0, 1, (void *)&channel._encoded_blk, - nullptr); - - return true; - } - case CS::SYNC_REQUEST_PENDING: - { - Block_io_request::Type const block_io_req_type { - Block_io_request::SYNC }; - - construct_in_buf( - buf_ptr, buf_size, SB_INITIALIZER, id, - block_io_req_type, 0, 0, 0, - channel._sb_slot_index, 0, - 0, nullptr, nullptr); - - return true; - } - case CS::TA_REQUEST_CREATE_KEY_PENDING: - { - Trust_anchor_request::Type const trust_anchor_req_type { - Trust_anchor_request::CREATE_KEY }; - - Trust_anchor_request::create( - buf_ptr, buf_size, SB_INITIALIZER, id, - trust_anchor_req_type, - nullptr, nullptr, nullptr, nullptr); - - return true; - } - case CS::TA_REQUEST_ENCRYPT_KEY_PENDING: - { - Trust_anchor_request::Type const trust_anchor_req_type { - Trust_anchor_request::ENCRYPT_KEY }; - - Trust_anchor_request::create( - buf_ptr, buf_size, SB_INITIALIZER, id, - trust_anchor_req_type, - (void*)&channel._key_plain.value, - nullptr, nullptr, nullptr); - - return true; - } - case CS::TA_REQUEST_SECURE_SB_PENDING: - { - Trust_anchor_request::Type const trust_anchor_req_type { - Trust_anchor_request::SECURE_SUPERBLOCK }; - - Trust_anchor_request::create( - buf_ptr, buf_size, SB_INITIALIZER, id, - trust_anchor_req_type, - nullptr, nullptr, nullptr, - (void*)&channel._sb_hash); - - return true; - } - default: - break; - } - } - return false; -} - - -void Sb_initializer::_drop_generated_request(Module_request &req) -{ - Module_request_id const id { req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Bad_id { }; - throw Bad_id { }; - } - switch (_channels[id]._state) { - case Channel::VBD_REQUEST_PENDING: - _channels[id]._state = Channel::VBD_REQUEST_IN_PROGRESS; - break; - case Channel::FT_REQUEST_PENDING: - _channels[id]._state = Channel::FT_REQUEST_IN_PROGRESS; - break; - case Channel::MT_REQUEST_PENDING: - _channels[id]._state = Channel::MT_REQUEST_IN_PROGRESS; - break; - case Channel::WRITE_REQUEST_PENDING: - _channels[id]._state = Channel::WRITE_REQUEST_IN_PROGRESS; - break; - case Channel::SYNC_REQUEST_PENDING: - _channels[id]._state = Channel::SYNC_REQUEST_IN_PROGRESS; - break; - case Channel::TA_REQUEST_CREATE_KEY_PENDING: - _channels[id]._state = Channel::TA_REQUEST_CREATE_KEY_IN_PROGRESS; - break; - case Channel::TA_REQUEST_ENCRYPT_KEY_PENDING: - _channels[id]._state = Channel::TA_REQUEST_ENCRYPT_KEY_IN_PROGRESS; - break; - case Channel::TA_REQUEST_SECURE_SB_PENDING: - _channels[id]._state = Channel::TA_REQUEST_SECURE_SB_IN_PROGRESS; - break; - default: - class Exception_1 { }; - throw Exception_1 { }; - } -} - - -void Sb_initializer::generated_request_complete(Module_request &req) -{ - Module_request_id const id { req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &channel = _channels[id]; - - switch (channel._state) { - case Channel::VBD_REQUEST_IN_PROGRESS: + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: { - if (req.dst_module_id() != VBD_INITIALIZER) { - class Exception_3 { }; - throw Exception_3 { }; - } - Vbd_initializer_request const *vbd_initializer_req = static_cast(&req); - channel._state = Channel::VBD_REQUEST_COMPLETE; - channel._generated_req_success = vbd_initializer_req->success(); - memcpy(&channel._vbd_node, - const_cast(vbd_initializer_req)->root_node(), - sizeof(Type_1_node)); - + _sb_idx = 0; + _sb = { }; + Snapshot &snap = _sb.snapshots.items[0]; + _vbd.construct(snap.pba, snap.gen, snap.hash, req._vbd_max_lvl, req._vbd_degree, req._vbd_num_leaves); + _generate_req(INIT_VBD_SUCCEEDED, progress, *_vbd, req._pba_alloc); + progress = true; break; } - case Channel::FT_REQUEST_IN_PROGRESS: + case INIT_VBD_SUCCEEDED: + + _ft.construct(_sb.free_number, _sb.free_gen, _sb.free_hash, req._ft_max_lvl, req._ft_degree, req._ft_num_leaves); + _generate_req(INIT_FT_SUCCEEDED, progress, *_ft, req._pba_alloc); + break; + + case INIT_FT_SUCCEEDED: + + _mt.construct(_sb.meta_number, _sb.meta_gen, _sb.meta_hash, req._ft_max_lvl, req._ft_degree, req._ft_num_leaves); + _generate_req(INIT_MT_SUCCEEDED, progress, *_mt, req._pba_alloc); + break; + + case INIT_MT_SUCCEEDED: + + _generate_req(CREATE_KEY_SUCCEEDED, progress, _sb.current_key.value); + break; + + case CREATE_KEY_SUCCEEDED: + + _generate_req(ENCRYPT_KEY_SUCCEEDED, progress, _sb.current_key.value, _sb.current_key.value); + break; + + case ENCRYPT_KEY_SUCCEEDED: { - if (req.dst_module_id() != FT_INITIALIZER) { - class Exception_4 { }; - throw Exception_4 { }; - } - Ft_initializer_request const *ft_initializer_req = static_cast(&req); - channel._state = Channel::FT_REQUEST_COMPLETE; - channel._generated_req_success = ft_initializer_req->success(); - memcpy(&channel._ft_node, - const_cast(ft_initializer_req)->root_node(), - sizeof(Type_1_node)); - + Snapshot &snap = _sb.snapshots.items[0]; + snap.gen = 0; + snap.nr_of_leaves = req._vbd_num_leaves; + snap.max_level = req._vbd_max_lvl; + snap.valid = true; + snap.id = 0; + _sb.current_key.id = 1; + _sb.state = Superblock::NORMAL; + _sb.degree = req._vbd_degree; + _sb.first_pba = req._pba_alloc.first_pba() - NR_OF_SUPERBLOCK_SLOTS; + _sb.nr_of_pbas = req._pba_alloc.num_used_pbas() + NR_OF_SUPERBLOCK_SLOTS; + _sb.free_max_level = _ft->max_lvl; + _sb.free_degree = _ft->degree; + _sb.free_leaves = _ft->num_leaves; + _sb.meta_max_level = _mt->max_lvl; + _sb.meta_degree = _mt->degree; + _sb.meta_leaves = _mt->num_leaves; + _sb.encode_to_blk(_blk); + _generate_req(WRITE_BLK_SUCCEEDED, progress, _sb_idx, _blk); break; } - case Channel::MT_REQUEST_IN_PROGRESS: - { - if (req.dst_module_id() != FT_INITIALIZER) { - class Exception_5 { }; - throw Exception_5 { }; - } - channel._state = Channel::MT_REQUEST_COMPLETE; - Ft_initializer_request const *ft_initializer_req = static_cast(&req); + case WRITE_BLK_SUCCEEDED: - memcpy(&channel._mt_node, - const_cast(ft_initializer_req)->root_node(), - sizeof(Type_1_node)); - - channel._generated_req_success = - ft_initializer_req->success(); + _generate_req(_sb_idx ? SB_COMPLETE : WRITE_HASH_TO_TA, progress); + progress = true; break; - } - case Channel::TA_REQUEST_CREATE_KEY_IN_PROGRESS: - { - if (req.dst_module_id() != TRUST_ANCHOR) { - class Exception_6 { }; - throw Exception_6 { }; - } - Trust_anchor_request const *trust_anchor_req = static_cast(&req); - channel._state = Channel::TA_REQUEST_CREATE_KEY_COMPLETE; - channel._generated_req_success = trust_anchor_req->success(); - memcpy(&channel._key_plain.value, - const_cast(trust_anchor_req)->key_plaintext_ptr(), - sizeof(channel._key_plain.value)); + case WRITE_HASH_TO_TA: + + calc_hash(_blk, _hash); + _generate_req(SB_COMPLETE, progress, _hash); break; - } - case Channel::TA_REQUEST_ENCRYPT_KEY_IN_PROGRESS: - { - if (req.dst_module_id() != TRUST_ANCHOR) { - class Exception_7 { }; - throw Exception_7 { }; - } - channel._state = Channel::TA_REQUEST_ENCRYPT_KEY_COMPLETE; - Trust_anchor_request const *trust_anchor_req = - static_cast(&req); - /* store and set ID to copy later on */ - memcpy(&channel._key_cipher.value, - const_cast(trust_anchor_req)->key_ciphertext_ptr(), - sizeof(channel._key_cipher.value)); - channel._key_cipher.id = 1; + case SB_COMPLETE: - channel._generated_req_success = - trust_anchor_req->success(); + if (_sb_idx < NR_OF_SUPERBLOCK_SLOTS - 1) { + _sb_idx++; + _sb = { }; + _sb.encode_to_blk(_blk); + _generate_req(WRITE_BLK_SUCCEEDED, progress, _sb_idx, _blk); + } else + _mark_req_successful(progress); break; - } - case Channel::TA_REQUEST_SECURE_SB_IN_PROGRESS: - { - if (req.dst_module_id() != TRUST_ANCHOR) { - class Exception_8 { }; - throw Exception_8 { }; - } - channel._state = Channel::TA_REQUEST_SECURE_SB_COMPLETE; - Trust_anchor_request const *trust_anchor_req = - static_cast(&req); - channel._generated_req_success = - trust_anchor_req->success(); - break; - } - case Channel::WRITE_REQUEST_IN_PROGRESS: - { - if (req.dst_module_id() != BLOCK_IO) { - class Exception_9 { }; - throw Exception_9 { }; - } - channel._state = Channel::WRITE_REQUEST_COMPLETE; - Block_io_request const *block_io_req = - static_cast(&req); - - channel._generated_req_success = - block_io_req->success(); - break; - } - case Channel::SYNC_REQUEST_IN_PROGRESS: - { - if (req.dst_module_id() != BLOCK_IO) { - class Exception_10 { }; - throw Exception_10 { }; - } - channel._state = Channel::SYNC_REQUEST_COMPLETE; - Block_io_request const *block_io_req = - static_cast(&req); - - channel._generated_req_success = - block_io_req->success(); - break; - } - default: - class Exception_2 { }; - throw Exception_2 { }; + default: break; } } Sb_initializer::Sb_initializer() -{ } - - -bool Sb_initializer::ready_to_submit_request() { - for (Channel &channel : _channels) { - if (channel._state == Channel::INACTIVE) - return true; + Module_channel_id id { 0 }; + for (Constructible &chan : _channels) { + chan.construct(id++); + add_channel(*chan); } - return false; -} - - -void Sb_initializer::submit_request(Module_request &req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - if (_channels[id]._state == Channel::INACTIVE) { - req.dst_request_id(id); - _channels[id]._request = *static_cast(&req); - _channels[id]._state = Channel::SUBMITTED; - return; - } - } - class Invalid_call { }; - throw Invalid_call { }; } void Sb_initializer::execute(bool &progress) { - for (Channel &channel : _channels) { - - if (channel._state == Channel::INACTIVE) - continue; - - Request &req { channel._request }; - switch (req._type) { - case Request::INIT: - - _execute_init(channel, progress); - - break; - default: - - class Exception_1 { }; - throw Exception_1 { }; - } - } + for_each_channel([&] (Channel &chan) { + chan.execute(progress); }); } diff --git a/repos/gems/src/lib/tresor/sha256_4k_hash.cc b/repos/gems/src/lib/tresor/sha256_4k_hash.cc deleted file mode 100644 index 8a3ed0f99b..0000000000 --- a/repos/gems/src/lib/tresor/sha256_4k_hash.cc +++ /dev/null @@ -1,50 +0,0 @@ -/* - * \brief Calculate SHA256 hash over data blocks of a size of 4096 bytes - * \author Martin Stein - * \date 2023-02-13 - */ - -/* - * Copyright (C) 2023 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* tresor includes */ -#include -#include - -/* base includes */ -#include - -/* libcrypto */ -#include - - -bool Tresor::check_sha256_4k_hash(Block const &blk, - Hash const &expected_hash) -{ - Hash got_hash; - calc_sha256_4k_hash(blk, got_hash); - return got_hash == expected_hash; -} - - -void Tresor::calc_sha256_4k_hash(Block const &blk, - Hash &hash) -{ - SHA256_CTX context { }; - if (!SHA256_Init(&context)) { - class Calc_sha256_4k_hash_init_error { }; - throw Calc_sha256_4k_hash_init_error { }; - } - if (!SHA256_Update(&context, &blk, BLOCK_SIZE)) { - class Calc_sha256_4k_hash_update_error { }; - throw Calc_sha256_4k_hash_update_error { }; - } - if (!SHA256_Final((unsigned char *)(&hash), &context)) { - class Calc_sha256_4k_hash_final_error { }; - throw Calc_sha256_4k_hash_final_error { }; - } -} diff --git a/repos/gems/src/lib/tresor/superblock_control.cc b/repos/gems/src/lib/tresor/superblock_control.cc index 0f3c1dc12b..e5a4eeb19f 100644 --- a/repos/gems/src/lib/tresor/superblock_control.cc +++ b/repos/gems/src/lib/tresor/superblock_control.cc @@ -11,65 +11,32 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base includes */ -#include - /* tresor includes */ #include #include -#include -#include -#include -#include -#include +#include +#include using namespace Tresor; - -/******************************** - ** Superblock_control_request ** - ********************************/ - -void Superblock_control_request::create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - uint64_t client_req_offset, - uint64_t client_req_tag, - Number_of_blocks nr_of_blks, - uint64_t vba, - Generation &gen) -{ - Superblock_control_request req { src_module_id, src_request_id }; - - req._type = (Type)req_type; - req._client_req_offset = client_req_offset; - 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 { }; - throw Bad_size_0 { }; - } - memcpy(buf_ptr, &req, sizeof(req)); -} - - Superblock_control_request:: -Superblock_control_request(Module_id src_module_id, - Module_request_id src_request_id) +Superblock_control_request(Module_id src_module_id, Module_channel_id src_channel_id, + Type type, Request_offset client_req_offset, + Request_tag client_req_tag, Number_of_blocks nr_of_blks, + Virtual_block_address vba, bool &success, + bool &client_req_finished, Superblock::State &sb_state, + Generation &gen) : - Module_request { src_module_id, src_request_id, SUPERBLOCK_CONTROL } + Module_request { src_module_id, src_channel_id, SUPERBLOCK_CONTROL }, _type { type }, + _client_req_offset { client_req_offset }, _client_req_tag { client_req_tag }, + _nr_of_blks { nr_of_blks }, _vba { vba }, _success { success }, + _client_req_finished { client_req_finished }, _sb_state { sb_state }, _gen { gen } { } char const *Superblock_control_request::type_to_string(Type type) { switch (type) { - case INVALID: return "invalid"; case READ_VBA: return "read_vba"; case WRITE_VBA: return "write_vba"; case SYNC: return "sync"; @@ -82,785 +49,371 @@ char const *Superblock_control_request::type_to_string(Type type) case INITIALIZE_REKEYING: return "init_rekeying"; case REKEY_VBA: return "rekey_vba"; } - return "?"; + ASSERT_NEVER_REACHED; } -/************************ - ** Superblock_control ** - ************************/ - -void Superblock_control::_mark_req_failed(Channel &chan, - bool &progress, - char const *str) +void Superblock_control_channel::_mark_req_failed(bool &progress, char const *str) { - error("sb control: request (", chan._request, ") failed at step \"", str, "\""); - chan._request._success = false; - chan._state = Channel::COMPLETED; + error("sb control: request (", *_req_ptr, ") failed at step \"", str, "\""); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; } -void Superblock_control::_mark_req_successful(Channel &chan, - bool &progress) +void Superblock_control_channel::_mark_req_successful(bool &progress) { - chan._request._success = true; - chan._state = Channel::COMPLETED; + _req_ptr->_success = true; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; } -Virtual_block_address Superblock_control::max_vba() const +void Superblock_control_channel::_generated_req_completed(State_uint state_uint) { - if (_sb.valid()) - return _sb.snapshots.items[_sb.curr_snap].nr_of_leaves - 1; + if (!_gen_req_success) { + error("superblock control: request (", *_req_ptr, ") failed because generated request failed)"); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; + return; + } + if (_state == SECURE_SB) + _secure_sb_state = (Secure_sb_state)state_uint; else - return 0; + _state = (State)state_uint; } -Virtual_block_address Superblock_control::rekeying_vba() const +void Superblock_control_channel:: +_generate_vbd_req(Virtual_block_device_request::Type type, State_uint complete_state, bool + &progress, Key_id key_id, Virtual_block_address vba = INVALID_VBA) { - return _sb.rekeying_vba; + if (_state == SECURE_SB) + _secure_sb_state = SECURE_SB_REQ_GENERATED; + else + _state = REQ_GENERATED; + + _state = REQ_GENERATED; + _pba = _sb.first_pba + _sb.nr_of_pbas; + _ft.construct(_sb.free_number, _sb.free_gen, _sb.free_hash, _sb.free_max_level, _sb.free_degree, _sb.free_leaves); + _mt.construct(_sb.meta_number, _sb.meta_gen, _sb.meta_hash, _sb.meta_max_level, _sb.meta_degree, _sb.meta_leaves); + generate_req( + complete_state, progress, type, _req_ptr->_client_req_offset, _req_ptr->_client_req_tag, + _sb.last_secured_generation, *_ft, *_mt, _sb.degree, _sb.max_vba(), _sb.state == Superblock::REKEYING, + vba, _sb.curr_snap_idx, _sb.snapshots, _sb.degree, _sb.previous_key.id, key_id, + _curr_gen, _pba, _gen_req_success, _nr_of_leaves, _req_ptr->_nr_of_blks); } -Virtual_block_address Superblock_control::resizing_nr_of_pbas() const +void Superblock_control_channel::_access_vba(Virtual_block_device_request::Type type, bool &progress) { - return _sb.resizing_nr_of_pbas; -} - - -void Superblock_control::_execute_read_vba(Channel &channel, - uint64_t const job_idx, - Superblock const &sb, - bool &progress) -{ - switch (channel._state) { - case Channel::State::SUBMITTED: - - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - switch (sb.state) { - case Superblock::REKEYING: { - Virtual_block_address const vba = channel._request._vba; - - if (vba < sb.rekeying_vba) - channel._curr_key_plaintext.id = sb.current_key.id; - else - channel._curr_key_plaintext.id = sb.previous_key.id; - - break; - } - case Superblock::NORMAL: - { - Virtual_block_address const vba = channel._request._vba; - if (vba > max_vba()) { - channel._request._success = false; - channel._state = Channel::State::COMPLETED; - progress = true; - return; - } - channel._curr_key_plaintext.id = sb.current_key.id; - break; - } - case Superblock::EXTENDING_FT: - case Superblock::EXTENDING_VBD: - channel._curr_key_plaintext.id = sb.current_key.id; - break; - case Superblock::INVALID: - class Superblock_not_valid { }; - throw Superblock_not_valid { }; - - break; - } - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_VBD_RKG_READ_VBA, - .blk_nr = channel._request._vba, - .idx = job_idx - }; - - channel._state = Channel::State::READ_VBA_AT_VBD_PENDING; - progress = true; - - if (VERBOSE_READ_VBA) - log("read vba ", channel._request._vba, - ": snap ", (Snapshot_index)_sb.curr_snap, - " key ", (Key_id)channel._curr_key_plaintext.id); - - break; - case Channel::State::READ_VBA_AT_VBD_COMPLETED: - channel._request._success = channel._generated_prim.succ; - channel._state = Channel::State::COMPLETED; - progress = true; - - break; - default: - break; - } -} - - -void Superblock_control::_execute_write_vba(Channel &channel, - uint64_t const job_idx, - Superblock &sb, - Generation const &curr_gen, - bool &progress) -{ - switch (channel._state) { - case Channel::State::SUBMITTED: - - sb.snapshots.discard_disposable_snapshots(sb.last_secured_generation, curr_gen); - switch (sb.state) { - case Superblock::REKEYING: { - Virtual_block_address const vba = channel._request._vba; - - if (vba < sb.rekeying_vba) - channel._curr_key_plaintext.id = sb.current_key.id; - else - channel._curr_key_plaintext.id = sb.previous_key.id; - - break; - } - case Superblock::NORMAL: - { - Virtual_block_address const vba = channel._request._vba; - if (vba > max_vba()) { - channel._request._success = false; - channel._state = Channel::State::COMPLETED; - progress = true; - return; - } - channel._curr_key_plaintext.id = sb.current_key.id; - break; - } - case Superblock::EXTENDING_FT: - case Superblock::EXTENDING_VBD: - channel._curr_key_plaintext.id = sb.current_key.id; - - break; - case Superblock::INVALID: - class Superblock_not_valid_write { }; - throw Superblock_not_valid_write { }; - - break; - } - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::WRITE, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_VBD_RKG_WRITE_VBA, - .blk_nr = channel._request._vba, - .idx = job_idx - }; - - channel._state = Channel::State::WRITE_VBA_AT_VBD_PENDING; - progress = true; - - if (VERBOSE_WRITE_VBA) - log("write vba ", channel._request._vba, - ": snap ", (Snapshot_index)_sb.curr_snap, - " key ", (Key_id)channel._curr_key_plaintext.id, - " gen ", curr_gen); - - break; - case Channel::State::WRITE_VBA_AT_VBD_COMPLETED: - if (sb.snapshots.items[sb.curr_snap].gen < curr_gen) { - - sb.curr_snap = - sb.snapshots.idx_of_invalid_or_lowest_gen_evictable_snap( - curr_gen, sb.last_secured_generation); - - sb.snapshots.items[sb.curr_snap] = channel._snapshots.items[0]; - sb.snapshots.items[sb.curr_snap].keep = false; - } else if (sb.snapshots.items[sb.curr_snap].gen == curr_gen) { - sb.snapshots.items[sb.curr_snap] = channel._snapshots.items[0]; - } else { - class Superblock_write_vba_at_vbd { }; - throw Superblock_write_vba_at_vbd { }; - } - - channel._request._success = channel._generated_prim.succ; - channel._state = Channel::State::COMPLETED; - progress = true; - - break; - default: - break; - } -} - - -void Superblock_control::_init_sb_without_key_values(Superblock const &sb_in, - Superblock &sb_out) -{ - sb_out.state = sb_in.state; - sb_out.rekeying_vba = sb_in.rekeying_vba; - sb_out.resizing_nr_of_pbas = sb_in.resizing_nr_of_pbas; - sb_out.resizing_nr_of_leaves = sb_in.resizing_nr_of_leaves; - sb_out.first_pba = sb_in.first_pba; - sb_out.nr_of_pbas = sb_in.nr_of_pbas; - memset(&sb_out.previous_key.value, 0, sizeof(sb_out.previous_key.value)); - sb_out.previous_key.id = sb_in.previous_key.id; - memset(&sb_out.current_key.value, 0, sizeof(sb_out.current_key.value)); - sb_out.current_key.id = sb_in.current_key.id; - sb_out.snapshots = sb_in.snapshots; - sb_out.last_secured_generation = sb_in.last_secured_generation; - sb_out.curr_snap = sb_in.curr_snap; - sb_out.degree = sb_in.degree; - sb_out.free_gen = sb_in.free_gen; - sb_out.free_number = sb_in.free_number; - sb_out.free_hash = sb_in.free_hash; - sb_out.free_max_level = sb_in.free_max_level; - sb_out.free_degree = sb_in.free_degree; - sb_out.free_leaves = sb_in.free_leaves; - sb_out.meta_gen = sb_in.meta_gen; - sb_out.meta_number = sb_in.meta_number; - sb_out.meta_hash = sb_in.meta_hash; - sb_out.meta_max_level = sb_in.meta_max_level; - sb_out.meta_degree = sb_in.meta_degree; - sb_out.meta_leaves = sb_in.meta_leaves; -} - - -char const *Superblock_control::_state_to_step_label(Channel::State state) -{ - switch (state) { - case Channel::TREE_EXT_STEP_IN_TREE_COMPLETED: return "tree ext step in tree"; - case Channel::SECURE_SB_COMPLETED: return "secure sb"; - default: break; - } - return "?"; -} - - -bool Superblock_control::_handle_failed_generated_req(Channel &chan, - bool &progress) -{ - if (chan._generated_prim.succ) - return false; - - _mark_req_failed(chan, progress, _state_to_step_label(chan._state)); - return true; -} - - -void Superblock_control::_execute_tree_ext_step(Channel &chan, - uint64_t chan_idx, - Superblock::State tree_ext_sb_state, - bool tree_ext_verbose, - Tag tree_ext_tag, - Channel::State tree_ext_pending_state, - String<4> tree_name, - bool &progress) -{ - Request &req { chan._request }; - switch (chan._state) { - case Channel::SUBMITTED: + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: { _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - Physical_block_address const last_used_pba { _sb.first_pba + (_sb.nr_of_pbas - 1) }; - Number_of_blocks const nr_of_unused_pbas { MAX_PBA - last_used_pba }; + if (req._vba > _sb.max_vba()) { + _mark_req_failed(progress, "VBA greater than max VBA"); + break; + } + if (type == Virtual_block_device_request::WRITE_VBA && _sb.curr_snap().gen != _curr_gen) { + Snapshot &snap { _sb.curr_snap() }; + _sb.curr_snap_idx = _sb.snapshots.alloc_idx(_curr_gen, _sb.last_secured_generation); + _sb.curr_snap() = snap; + _sb.curr_snap().keep = false; + } + Key_id key_id { _sb.state == Superblock::REKEYING && req._vba >= _sb.rekeying_vba ? + _sb.previous_key.id : _sb.current_key.id }; + + _generate_vbd_req(type, ACCESS_VBA_AT_VBD_SUCCEEDED, progress, key_id, req._vba); + if (VERBOSE_READ_VBA) + log("read vba ", req._vba, ": snap ", _sb.curr_snap_idx, " key ", key_id, " gen ", _curr_gen); + + break; + } + case ACCESS_VBA_AT_VBD_SUCCEEDED: _mark_req_successful(progress); break; + default: break; + } +} + + +void Superblock_control_channel::_tree_ext_step(Superblock::State sb_state, bool verbose, String<4> tree_name, bool &progress) +{ + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: + { + _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); + Physical_block_address const last_used_pba { _sb.first_pba + (_sb.nr_of_pbas - 1) }; + Number_of_blocks const nr_of_unused_pbas { MAX_PBA - last_used_pba }; if (req._nr_of_blks > nr_of_unused_pbas) { - _mark_req_failed(chan, progress, "check number of unused blocks"); + _mark_req_failed(progress, "check number of unused blocks"); break; } if (_sb.state == Superblock::NORMAL) { - req._request_finished = false; - _sb.state = tree_ext_sb_state; + req._client_req_finished = false; + _sb.state = sb_state; _sb.resizing_nr_of_pbas = req._nr_of_blks; _sb.resizing_nr_of_leaves = 0; - chan._pba = last_used_pba + 1; - - if (tree_ext_verbose) - log(tree_name, " ext init: pbas ", chan._pba, "..", - chan._pba + (Number_of_blocks)_sb.resizing_nr_of_pbas - 1, + _pba = last_used_pba + 1; + if (verbose) + log(tree_name, " ext init: pbas ", _pba, "..", + _pba + (Number_of_blocks)_sb.resizing_nr_of_pbas - 1, " leaves ", (Number_of_blocks)_sb.resizing_nr_of_leaves); - _secure_sb_init(chan, chan_idx, progress); + _start_secure_sb(progress); break; - } else if (_sb.state == tree_ext_sb_state) { + } else if (_sb.state == sb_state) { - chan._pba = last_used_pba + 1; + _pba = last_used_pba + 1; req._nr_of_blks = _sb.resizing_nr_of_pbas; - if (tree_ext_verbose) - log(tree_name, " ext step: pbas ", chan._pba, "..", - chan._pba + (Number_of_blocks)_sb.resizing_nr_of_pbas - 1, + if (verbose) + log(tree_name, " ext step: pbas ", _pba, "..", + _pba + (Number_of_blocks)_sb.resizing_nr_of_pbas - 1, " leaves ", (Number_of_blocks)_sb.resizing_nr_of_leaves); - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = tree_ext_tag, - .blk_nr = 0, - .idx = chan_idx - }; - chan._state = tree_ext_pending_state; - progress = true; - break; + req._nr_of_blks = _sb.resizing_nr_of_pbas; + _pba = _sb.first_pba + _sb.nr_of_pbas; + if (tree_name == "vbd") { - } else { + _generate_vbd_req( + Virtual_block_device_request::EXTENSION_STEP, + TREE_EXT_STEP_IN_TREE_SUCCEEDED, progress, _sb.current_key.id); + + } else if (tree_name == "ft") { + + _mt.construct( + _sb.free_number, _sb.free_gen, _sb.free_hash, _sb.free_max_level, _sb.free_degree, + _sb.free_leaves); + + _mt.construct( + _sb.meta_number, _sb.meta_gen, _sb.meta_hash, _sb.meta_max_level, _sb.meta_degree, + _sb.meta_leaves); + + _generate_req( + TREE_EXT_STEP_IN_TREE_SUCCEEDED, progress, _curr_gen, *_ft, *_mt, _pba, req._nr_of_blks); + } + } else + _mark_req_failed(progress, "check superblock state"); - _mark_req_failed(chan, progress, "check superblock state"); - break; - } break; } - case Channel::TREE_EXT_STEP_IN_TREE_COMPLETED: + case TREE_EXT_STEP_IN_TREE_SUCCEEDED: { - if (_handle_failed_generated_req(chan, progress)) - break; - if (req._nr_of_blks >= _sb.resizing_nr_of_pbas) { - _mark_req_failed(chan, progress, "check number of pbas"); + _mark_req_failed(progress, "check number of pbas"); break; } - Number_of_blocks const nr_of_added_pbas { _sb.resizing_nr_of_pbas - req._nr_of_blks }; + Number_of_blocks const nr_of_added_pbas { _sb.resizing_nr_of_pbas - req._nr_of_blks }; Physical_block_address const new_first_unused_pba { _sb.first_pba + (_sb.nr_of_pbas + nr_of_added_pbas) }; - - if (chan._pba != new_first_unused_pba) { - _mark_req_failed(chan, progress, "check new first unused pba"); + if (_pba != new_first_unused_pba) { + _mark_req_failed(progress, "check new first unused pba"); break; } _sb.nr_of_pbas = _sb.nr_of_pbas + nr_of_added_pbas; _sb.resizing_nr_of_pbas = req._nr_of_blks; - _sb.resizing_nr_of_leaves += chan._nr_of_leaves; + _sb.resizing_nr_of_leaves += _nr_of_leaves; - if (tree_name == "vbd") { - - _sb.snapshots = chan._snapshots; - _sb.curr_snap = chan._snapshots.newest_snapshot_idx(); - - } else if (tree_name == "ft") { - - _sb.free_gen = chan._ft_root.gen; - _sb.free_number = chan._ft_root.pba; - _sb.free_hash = chan._ft_root.hash; - _sb.free_max_level = chan._ft_max_lvl; - _sb.free_leaves = chan._ft_nr_of_leaves; - - } else { - - class Exception_1 { }; - throw Exception_1 { }; - } - if (req._nr_of_blks == 0) { + if (tree_name == "vbd") + _sb.curr_snap_idx = _sb.snapshots.newest_snap_idx(); + if (!req._nr_of_blks) { _sb.state = Superblock::NORMAL; - req._request_finished = true; + req._client_req_finished = true; } - _secure_sb_init(chan, chan_idx, progress); + _start_secure_sb(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; - - _mark_req_successful(chan, progress); - break; - - default: - break; + case SECURE_SB: _secure_sb(progress); break; + case SECURE_SB_SUCCEEDED: _mark_req_successful(progress); break; + default: break; } } - -void Superblock_control::_execute_rekey_vba(Channel &chan, - uint64_t chan_idx, - bool &progress) +void Superblock_control_channel::_rekey_vba(bool &progress) { - Request &req { chan._request }; - - switch (chan._state) { - case Channel::SUBMITTED: + switch (_state) { + case REQ_SUBMITTED: _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); if (_sb.state != Superblock::REKEYING) { - _mark_req_failed(chan, progress, "check superblock state"); + _mark_req_failed(progress, "check superblock state"); break; } - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_SB_CTRL_VBD_RKG_REKEY_VBA, - .blk_nr = _sb.rekeying_vba, - .idx = chan_idx - }; - chan._state = Channel::REKEY_VBA_IN_VBD_PENDING; - progress = true; + _generate_vbd_req( + Virtual_block_device_request::REKEY_VBA, REKEY_VBA_AT_VBD_SUCCEEDED, + progress, _sb.current_key.id, _sb.rekeying_vba); + _state = REQ_GENERATED; if (VERBOSE_REKEYING) { - log("rekey vba ", (Virtual_block_address)_sb.rekeying_vba, ":"); - log(" update vbd: keys ", (Key_id)_sb.previous_key.id, - ",", (Key_id)_sb.current_key.id, - " generations ", (Generation)_sb.last_secured_generation, - ",", _curr_gen); + log("rekey vba ", _sb.rekeying_vba, ":"); + log(" update vbd: keys ", _sb.previous_key.id, ",", _sb.current_key.id, " generations ", _sb.last_secured_generation, ",", _curr_gen); } break; - case Channel::REKEY_VBA_IN_VBD_COMPLETED: + case REKEY_VBA_AT_VBD_SUCCEEDED: { - if (!chan._generated_prim.succ) { - _mark_req_failed(chan, progress, "rekey vba at vbd"); - break; - } - _sb.snapshots = chan._snapshots; Number_of_leaves max_nr_of_leaves { 0 }; - for (Snapshot const &snap : _sb.snapshots.items) { if (snap.valid && max_nr_of_leaves < snap.nr_of_leaves) max_nr_of_leaves = snap.nr_of_leaves; } if (_sb.rekeying_vba < max_nr_of_leaves - 1) { - _sb.rekeying_vba++; - req._request_finished = false; - _secure_sb_init(chan, chan_idx, progress); - + _req_ptr->_client_req_finished = false; + _start_secure_sb(progress); if (VERBOSE_REKEYING) log(" secure sb: gen ", _curr_gen); - } else { - - chan._prev_key_plaintext.id = _sb.previous_key.id; - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_SB_CTRL_CRYPTO_REMOVE_KEY, - .blk_nr = 0, - .idx = chan_idx - }; - chan._state = Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING; - progress = true; - + _generate_req(REMOVE_PREV_KEY_SUCCEEDED, progress, _sb.previous_key.id); if (VERBOSE_REKEYING) - log(" remove key ", (Key_id)chan._key_plaintext.id); + log(" remove key ", _sb.previous_key.id); } break; } - case Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED: + case REMOVE_PREV_KEY_SUCCEEDED: - if (!chan._generated_prim.succ) { - _mark_req_failed(chan, progress, "remove key at crypto"); - break; - } _sb.previous_key = { }; _sb.state = Superblock::NORMAL; - req._request_finished = true; - _secure_sb_init(chan, chan_idx, progress); - + _req_ptr->_client_req_finished = true; + _start_secure_sb(progress); if (VERBOSE_REKEYING) log(" secure sb: gen ", _curr_gen); - 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; - - _mark_req_successful(chan, progress); - break; - - default: - - break; + case SECURE_SB: _secure_sb(progress); break; + case SECURE_SB_SUCCEEDED: _mark_req_successful(progress); break; + default: break; } } -void Superblock_control::_secure_sb_init(Channel &chan, - uint64_t chan_idx, - bool &progress) +void Superblock_control_channel::_start_secure_sb(bool &progress) { - _sb.snapshots.items[_sb.curr_snap].gen = _curr_gen; - _init_sb_without_key_values(_sb, chan._sb_ciphertext); - chan._key_plaintext = _sb.current_key; - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_SB_CTRL_TA_ENCRYPT_KEY, - .blk_nr = 0, - .idx = chan_idx - }; - chan._state = Channel::ENCRYPT_CURRENT_KEY_PENDING; + _state = SECURE_SB; + _secure_sb_state = STARTED; progress = true; } -void Superblock_control::_secure_sb_encr_curr_key_compl(Channel &chan, - uint64_t chan_idx, - bool &progress) +void Superblock_control_channel::_secure_sb(bool &progress) { - if (!chan._generated_prim.succ) { - _mark_req_failed(chan, progress, "encrypt current key"); - return; - } - switch (_sb.state) { - case Superblock::REKEYING: + switch (_secure_sb_state) { + case STARTED: - chan._key_plaintext = _sb.previous_key; - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_SB_CTRL_TA_ENCRYPT_KEY, - .blk_nr = 0, - .idx = chan_idx - }; - chan._state = Channel::ENCRYPT_PREVIOUS_KEY_PENDING; - progress = true; + _sb.curr_snap().gen = _curr_gen; + _sb_ciphertext.copy_all_but_key_values_from(_sb); + _generate_req( + ENCRYPT_CURR_KEY_SUCCEEDED, progress, _sb.current_key.value, _sb_ciphertext.current_key.value); break; - default: + case ENCRYPT_CURR_KEY_SUCCEEDED: - chan._generated_prim = { - .op = Generated_prim::SYNC, - .succ = false, - .tg = Channel::TAG_SB_CTRL_CACHE, - .blk_nr = 0, - .idx = chan_idx - }; - chan._state = Channel::SYNC_CACHE_PENDING; - progress = true; + if (_sb.state == Superblock::REKEYING) + _generate_req( + ENCRYPT_PREV_KEY_SUCCEEDED, progress, _sb.previous_key.value, _sb_ciphertext.previous_key.value); + else + _generate_req(SYNC_CACHE_SUCCEEDED, progress); break; - } -} + case ENCRYPT_PREV_KEY_SUCCEEDED: _generate_req(SYNC_CACHE_SUCCEEDED, progress); break; + case SYNC_CACHE_SUCCEEDED: -void Superblock_control::_secure_sb_encr_prev_key_compl(Channel &chan, - uint64_t chan_idx, - bool &progress) -{ - if (!chan._generated_prim.succ) { - _mark_req_failed(chan, progress, "encrypt previous key"); - return; - } - chan._generated_prim = { - .op = Generated_prim::SYNC, - .succ = false, - .tg = Channel::TAG_SB_CTRL_CACHE, - .blk_nr = 0, - .idx = chan_idx - }; - chan._state = Channel::SYNC_CACHE_PENDING; - progress = true; -} + _sb_ciphertext.encode_to_blk(_blk); + _generate_req(WRITE_SB_SUCCEEDED, progress, _sb_idx, _blk); + break; - -void Superblock_control::_secure_sb_sync_cache_compl(Channel &chan, - uint64_t chan_idx, - bool &progress) -{ - if (!chan._generated_prim.succ) { - _mark_req_failed(chan, progress, "sync cache"); - return; - } - chan._generated_prim = { - .op = Generated_prim::WRITE, - .succ = false, - .tg = Channel::TAG_SB_CTRL_BLK_IO_WRITE_SB, - .blk_nr = _sb_idx, - .idx = chan_idx - }; - chan._state = Channel::WRITE_SB_PENDING; - progress = true; -} - - -void Superblock_control::_secure_sb_sync_blk_io_compl(Channel &chan, - uint64_t chan_idx, - bool &progress) -{ - if (!chan._generated_prim.succ) { - _mark_req_failed(chan, progress, "sync block io"); - return; - } - Block blk { }; - chan._sb_ciphertext.encode_to_blk(blk); - calc_sha256_4k_hash(blk, chan._hash); - - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_SB_CTRL_TA_SECURE_SB, - .blk_nr = 0, - .idx = chan_idx - }; - chan._state = Channel::SECURE_SB_PENDING; + case WRITE_SB_SUCCEEDED: _generate_req(SYNC_BLK_IO_SUCCEEDED, progress); break; + case SYNC_BLK_IO_SUCCEEDED: + { + _sb_ciphertext.encode_to_blk(_blk); + calc_hash(_blk, _hash); + _generate_req(WRITE_SB_HASH_SUCCEEDED, progress, _hash); if (_sb_idx < MAX_SUPERBLOCK_INDEX) _sb_idx++; else _sb_idx = 0; - chan._generation = _curr_gen; + _gen = _curr_gen; _curr_gen++; - progress = true; -} - - -void Superblock_control::_secure_sb_write_sb_compl(Channel &chan, - uint64_t chan_idx, - bool &progress) -{ - if (!chan._generated_prim.succ) { - _mark_req_failed(chan, progress, "write superblock"); - return; + break; } - chan._generated_prim = { - .op = Generated_prim::SYNC, - .succ = false, - .tg = Channel::TAG_SB_CTRL_BLK_IO_SYNC, - .blk_nr = _sb_idx, - .idx = chan_idx - }; - chan._state = Channel::SYNC_BLK_IO_PENDING; - progress = true; -} + case WRITE_SB_HASH_SUCCEEDED: - -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, - bool &progress) -{ - switch (chan._state) { - case Channel::SUBMITTED: - - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_SB_CTRL_TA_CREATE_KEY, - .blk_nr = 0, - .idx = chan_idx - }; - chan._state = Channel::CREATE_KEY_PENDING; - progress = true; + _sb.last_secured_generation = _gen; + _state = SECURE_SB_SUCCEEDED; break; - case Channel::CREATE_KEY_COMPLETED: + default: break; + } +} - if (!chan._generated_prim.succ) { - _mark_req_failed(chan, progress, "create key"); - break; - } + +void Superblock_control_channel::_init_rekeying(bool &progress) +{ + switch (_state) { + case REQ_SUBMITTED: + + _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); if (_sb.state != Superblock::NORMAL) { - _mark_req_failed(chan, progress, "check superblock state"); + _mark_req_failed(progress, "check superblock state"); break; } _sb.state = Superblock::REKEYING; _sb.rekeying_vba = 0; _sb.previous_key = _sb.current_key; - _sb.current_key = { - .value = chan._key_plaintext.value, - .id = _sb.previous_key.id + 1 - }; - chan._key_plaintext = _sb.current_key; - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_SB_CTRL_CRYPTO_ADD_KEY, - .blk_nr = 0, - .idx = chan_idx - }; - chan._state = Channel::ADD_KEY_AT_CRYPTO_MODULE_PENDING; - progress = true; - - if (VERBOSE_REKEYING) { - log("start rekeying:"); - log(" update sb: keys ", (Key_id)_sb.previous_key.id, - ",", (Key_id)chan._key_plaintext.id); - } + _sb.current_key.id++; + _generate_req(CREATE_KEY_SUCCEEDED, progress, _sb.current_key.value); break; - case Channel::ADD_KEY_AT_CRYPTO_MODULE_COMPLETED: + case CREATE_KEY_SUCCEEDED: - if (!chan._generated_prim.succ) { - _mark_req_failed(chan, progress, "add key at crypto"); - break; - } - _secure_sb_init(chan, chan_idx, progress); + _generate_req(ADD_CURR_KEY_SUCCEEDED, progress, _sb.current_key); + if (VERBOSE_REKEYING) + log("start rekeying:\n update sb: keys ", _sb.previous_key.id, ",", _sb.current_key.id); + break; + + case ADD_CURR_KEY_SUCCEEDED: if (VERBOSE_REKEYING) log(" secure sb: gen ", _curr_gen); - + _start_secure_sb(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; - - _mark_req_successful(chan, progress); - break; - - default: - - break; + case SECURE_SB: _secure_sb(progress); break; + case SECURE_SB_SUCCEEDED: _mark_req_successful(progress); break; + default: break; } } -void Superblock_control::_execute_discard_snap(Channel &chan, uint64_t chan_idx, bool &progress) +void Superblock_control_channel::_discard_snap(bool &progress) { - Request &req { chan._request }; - switch (chan._state) { - case Channel::State::SUBMITTED: - { + switch (_state) { + case REQ_SUBMITTED: + for (Snapshot &snap : _sb.snapshots.items) - if (snap.valid && snap.gen == req.gen() && snap.keep) + if (snap.valid && snap.gen == _req_ptr->_gen && snap.keep) snap.keep = false; _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - _secure_sb_init(chan, chan_idx, progress); + _start_secure_sb(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; + case SECURE_SB: _secure_sb(progress); break; + case SECURE_SB_SUCCEEDED: - req.gen(chan._generation); - _mark_req_successful(chan, progress); + _req_ptr->_gen = _gen; + _mark_req_successful(progress); break; default: break; @@ -868,1249 +421,229 @@ void Superblock_control::_execute_discard_snap(Channel &chan, uint64_t chan_idx, } -void Superblock_control::_execute_create_snap(Channel &chan, uint64_t chan_idx, bool &progress) +void Superblock_control_channel::_create_snap(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, - Superblock_index &sb_idx, - Generation &curr_gen, - bool &progress) -{ - switch (channel._state) { - case Channel::State::SUBMITTED: - - sb.snapshots.discard_disposable_snapshots(sb.last_secured_generation, curr_gen); - sb.last_secured_generation = curr_gen; - sb.snapshots.items[sb.curr_snap].gen = curr_gen; - _init_sb_without_key_values(sb, channel._sb_ciphertext); - - channel._key_plaintext = sb.current_key; - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_TA_ENCRYPT_KEY, - .blk_nr = 0, - .idx = job_idx - }; - channel._state = Channel::State::ENCRYPT_CURRENT_KEY_PENDING; - progress = true; - break; - - case Channel::State::ENCRYPT_CURRENT_KEY_COMPLETED: - - if (!channel._generated_prim.succ) { - class Encrypt_current_key_error { }; - throw Encrypt_current_key_error { }; - } - switch (sb.state) { - case Superblock::REKEYING: - - channel._key_plaintext = sb.previous_key; - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_TA_ENCRYPT_KEY, - .blk_nr = 0, - .idx = job_idx - }; - channel._state = Channel::State::ENCRYPT_PREVIOUS_KEY_PENDING; - progress = true; - break; - - default: - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::SYNC, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_CACHE, - .blk_nr = 0, - .idx = job_idx - }; - channel._state = Channel::State::SYNC_CACHE_PENDING; - progress = true; - break; - } - break; - - case Channel::State::ENCRYPT_PREVIOUS_KEY_COMPLETED: - - if (!channel._generated_prim.succ) { - class Encrypt_previous_key_error { }; - throw Encrypt_previous_key_error { }; - } - channel._generated_prim = { - .op = Channel::Generated_prim::Type::SYNC, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_CACHE, - .blk_nr = 0, - .idx = job_idx - }; - channel._state = Channel::State::SYNC_CACHE_PENDING; - progress = true; - break; - - case Channel::State::SYNC_CACHE_COMPLETED: - - if (!channel._generated_prim.succ) { - class Sync_cache_error { }; - throw Sync_cache_error { }; - } - channel._generated_prim = { - .op = Channel::Generated_prim::Type::WRITE, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_WRITE_SB, - .blk_nr = sb_idx, - .idx = job_idx - }; - channel._state = Channel::State::WRITE_SB_PENDING; - progress = true; - break; - - case Channel::State::WRITE_SB_COMPLETED: - - if (!channel._generated_prim.succ) { - class Write_sb_completed_error { }; - throw Write_sb_completed_error { }; - } - channel._generated_prim = { - .op = Channel::Generated_prim::Type::SYNC, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_SYNC, - .blk_nr = sb_idx, - .idx = job_idx - }; - channel._state = Channel::State::SYNC_BLK_IO_PENDING; - progress = true; - break; - - case Channel::State::SYNC_BLK_IO_COMPLETED: - { - if (!channel._generated_prim.succ) { - class Sync_blk_io_completed_error { }; - throw Sync_blk_io_completed_error { }; - } - Block blk { }; - channel._sb_ciphertext.encode_to_blk(blk); - calc_sha256_4k_hash(blk, channel._hash); - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_TA_SECURE_SB, - .blk_nr = 0, - .idx = job_idx - }; - channel._state = Channel::State::SECURE_SB_PENDING; - - if (sb_idx < MAX_SUPERBLOCK_INDEX) - sb_idx = sb_idx + 1; - else - sb_idx = 0; - - channel._generation = curr_gen; - curr_gen = curr_gen + 1; - progress = true; - break; - } - case Channel::State::SECURE_SB_COMPLETED: - - if (!_secure_sb_finish(channel, progress)) - break; - - channel._request._success = true; - channel._state = Channel::State::COMPLETED; - progress = true; - break; - - default: - - break; - } -} - - -void Superblock_control::_execute_initialize(Channel &channel, - uint64_t const job_idx, - Superblock &sb, - Superblock_index &sb_idx, - Generation &curr_gen, - bool &progress) -{ - switch (channel._state) { - case Channel::State::SUBMITTED: - - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - channel._sb_found = false; - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_TA_LAST_SB_HASH, - .blk_nr = 0, - .idx = job_idx - }; - channel._state = Channel::State::MAX_SB_HASH_PENDING; - progress = true; - break; - - case Channel::State::MAX_SB_HASH_COMPLETED: - - channel._read_sb_idx = 0; - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_READ_SB, - .blk_nr = channel._read_sb_idx, - .idx = job_idx - }; - channel._state = Channel::State::READ_SB_PENDING; - progress = true; - break; - - case Channel::State::READ_SB_COMPLETED: - - if (!channel._generated_prim.succ) { - class Execute_initialize_error { }; - throw Execute_initialize_error { }; - } - if (channel._sb_ciphertext.state != Superblock::INVALID) { - - Superblock const &cipher { channel._sb_ciphertext }; - Snapshot_index const snap_index { cipher.snapshots.newest_snapshot_idx() }; - Generation const sb_generation { cipher.snapshots.items[snap_index].gen }; - - if (check_sha256_4k_hash(channel._encoded_blk, channel._hash)) { - channel._generation = sb_generation; - channel._sb_idx = channel._read_sb_idx; - channel._sb_found = true; - } - } - if (channel._read_sb_idx < MAX_SUPERBLOCK_INDEX) { - - channel._read_sb_idx = channel._read_sb_idx + 1; - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_READ_SB, - .blk_nr = channel._read_sb_idx, - .idx = job_idx - }; - channel._state = Channel::State::READ_SB_PENDING; - progress = true; + switch (_state) { + case REQ_SUBMITTED: + if (_sb.curr_snap().keep) { + _req_ptr->_gen = _sb.curr_snap().gen; + _mark_req_successful(progress); } else { - - if (!channel._sb_found) { - class Execute_initialize_sb_found_error { }; - throw Execute_initialize_sb_found_error { }; - } - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_READ_SB, - .blk_nr = channel._sb_idx, - .idx = job_idx - }; - - channel._state = Channel::State::READ_CURRENT_SB_PENDING; - progress = true; + _sb.curr_snap().keep = true; + _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); + _start_secure_sb(progress); } break; - case Channel::State::READ_CURRENT_SB_COMPLETED: - - if (!channel._generated_prim.succ) { - class Execute_initialize_read_current_sb_error { }; - throw Execute_initialize_read_current_sb_error { }; - } - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_TA_DECRYPT_KEY, - .blk_nr = 0, - .idx = job_idx - }; - - channel._state = Channel::State::DECRYPT_CURRENT_KEY_PENDING; - progress = true; + case SECURE_SB: _secure_sb(progress); break; + case SECURE_SB_SUCCEEDED: + _req_ptr->_gen = _gen; + _mark_req_successful(progress); break; - case Channel::State::DECRYPT_CURRENT_KEY_COMPLETED: - if (!channel._generated_prim.succ) { - class Execute_initialize_decrypt_current_key_error { }; - throw Execute_initialize_decrypt_current_key_error { }; - } - channel._curr_key_plaintext.id = channel._sb_ciphertext.current_key.id; - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_CRYPTO_ADD_KEY, - .blk_nr = 0, - .idx = job_idx - }; - - channel._state = Channel::State::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING; - progress = true; - - break; - case Channel::State::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_COMPLETED: - if (!channel._generated_prim.succ) { - class Execute_add_current_key_at_crypto_error { }; - throw Execute_add_current_key_at_crypto_error { }; - } - - switch (channel._sb_ciphertext.state) { - case Superblock::INVALID: - class Execute_add_current_key_at_crypto_invalid_error { }; - throw Execute_add_current_key_at_crypto_invalid_error { }; - - break; - case Superblock::REKEYING: - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_TA_DECRYPT_KEY, - .blk_nr = 0, - .idx = job_idx - }; - - channel._state = Channel::State::DECRYPT_PREVIOUS_KEY_PENDING; - progress = true; - - break; - case Superblock::NORMAL: - case Superblock::EXTENDING_VBD: - case Superblock::EXTENDING_FT: - - _init_sb_without_key_values(channel._sb_ciphertext, sb); - - sb.current_key.value = channel._curr_key_plaintext.value; - sb_idx = channel._sb_idx; - curr_gen = channel._generation + 1; - - sb_idx = channel._sb_idx; - curr_gen = channel._generation + 1; - - if (sb.free_max_level < FREE_TREE_MIN_MAX_LEVEL) { - class Execute_add_current_key_at_crypto_max_level_error { }; - throw Execute_add_current_key_at_crypto_max_level_error { }; - } - - channel._request._sb_state = _sb.state; - channel._request._success = true; - - channel._state = Channel::State::COMPLETED; - progress = true; - - break; - } - - break; - case Channel::State::DECRYPT_PREVIOUS_KEY_COMPLETED: - if (!channel._generated_prim.succ) { - class Decrypt_previous_key_error { }; - throw Decrypt_previous_key_error { }; - } - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_CRYPTO_ADD_KEY, - .blk_nr = 0, - .idx = job_idx - }; - - channel._state = Channel::State::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING; - progress = true; - - break; - case Channel::State::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED: - if (!channel._generated_prim.succ) { - class Add_previous_key_at_crypto_module_error { }; - throw Add_previous_key_at_crypto_module_error { }; - } - - _init_sb_without_key_values(channel._sb_ciphertext, sb); - - sb.current_key.value = channel._curr_key_plaintext.value; - sb.previous_key.value = channel._prev_key_plaintext.value; - - sb_idx = channel._sb_idx; - curr_gen = channel._generation + 1; - - channel._request._sb_state = _sb.state; - channel._request._success = true; - - channel._state = Channel::State::COMPLETED; - progress = true; - - break; - default: - break; + default: break; } } -void Superblock_control::_execute_deinitialize(Channel &channel, - uint64_t const job_idx, - Superblock &sb, - Superblock_index &sb_idx, - Generation &curr_gen, - bool &progress) +void Superblock_control_channel::_sync(bool &progress) { - switch (channel._state) { - case Channel::State::SUBMITTED: - - sb.snapshots.discard_disposable_snapshots(sb.last_secured_generation, curr_gen); - sb.last_secured_generation = curr_gen; - sb.snapshots.items[sb.curr_snap].gen = curr_gen; - - _init_sb_without_key_values(sb, channel._sb_ciphertext); - channel._key_plaintext = sb.current_key; - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_TA_ENCRYPT_KEY, - .blk_nr = 0, - .idx = job_idx - }; - - channel._state = Channel::State::ENCRYPT_CURRENT_KEY_PENDING; - progress = true; + switch (_state) { + case REQ_SUBMITTED: + _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); + _sb.last_secured_generation = _curr_gen; + _start_secure_sb(progress); break; - case Channel::State::ENCRYPT_CURRENT_KEY_COMPLETED: - if (!channel._generated_prim.succ) { - class Deinitialize_encrypt_current_key_error { }; - throw Deinitialize_encrypt_current_key_error { }; - } - switch (sb.state) { - case Superblock::REKEYING: - channel._key_plaintext = sb.previous_key; + case SECURE_SB: _secure_sb(progress); break; + case SECURE_SB_SUCCEEDED: _mark_req_successful(progress); break; + default: break; + } +} - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_TA_ENCRYPT_KEY, - .blk_nr = 0, - .idx = job_idx - }; - channel._state = Channel::State::ENCRYPT_PREVIOUS_KEY_PENDING; - progress = true; +void Superblock_control_request::print(Output &out) const +{ + Genode::print(out, type_to_string(_type)); + switch (_type) { + case REKEY_VBA: + case READ_VBA: + case WRITE_VBA: Genode::print(out, " ", _vba); break; + default: break; + } +} - break; - default: - channel._generated_prim = { - .op = Channel::Generated_prim::Type::SYNC, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_CACHE, - .blk_nr = 0, - .idx = job_idx - }; - - channel._state = Channel::State::SYNC_CACHE_PENDING; - progress = true; - - break; - } +void Superblock_control_channel::_initialize(bool &progress) +{ + switch (_state) { + case REQ_SUBMITTED: + _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); + _generate_req(READ_SB_HASH_SUCCEEDED, progress, _hash); break; - case Channel::State::ENCRYPT_PREVIOUS_KEY_COMPLETED: - if (!channel._generated_prim.succ) { - class Deinitialize_encrypt_previous_key_error { }; - throw Deinitialize_encrypt_previous_key_error { }; - } - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::SYNC, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_CACHE, - .blk_nr = 0, - .idx = job_idx - }; - - channel._state = Channel::State::SYNC_CACHE_PENDING; - progress = true; + case READ_SB_HASH_SUCCEEDED: + _sb_idx = 0; + _generate_req(READ_SB_SUCCEEDED, progress, _sb_idx, _blk); break; - case Channel::State::SYNC_CACHE_COMPLETED: - if (!channel._generated_prim.succ) { - class Deinitialize_sync_cache_error { }; - throw Deinitialize_sync_cache_error { }; - } - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::WRITE, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_WRITE_SB, - .blk_nr = sb_idx, - .idx = job_idx - }; - - channel._state = Channel::State::WRITE_SB_PENDING; - progress = true; + case READ_SB_SUCCEEDED: + _sb_ciphertext.decode_from_blk(_blk); + if (check_hash(_blk, _hash)) { + _gen = _sb_ciphertext.snapshots.items[_sb_ciphertext.snapshots.newest_snap_idx()].gen; + _sb.copy_all_but_key_values_from(_sb_ciphertext); + _generate_req( + DECRYPT_CURR_KEY_SUCCEEDED, progress, _sb.current_key.value, _sb_ciphertext.current_key.value); + } else + if (_sb_idx < MAX_SUPERBLOCK_INDEX) { + _sb_idx++; + _generate_req(READ_SB_SUCCEEDED, progress, _sb_idx, _blk); + } else + _mark_req_failed(progress, "superblock not found"); break; - case Channel::State::WRITE_SB_COMPLETED: - if (!channel._generated_prim.succ) { - class Deinitialize_write_sb_error { }; - throw Deinitialize_write_sb_error { }; - } - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::SYNC, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_SYNC, - .blk_nr = sb_idx, - .idx = job_idx - }; - - channel._state = Channel::State::SYNC_BLK_IO_PENDING; - progress = true; + case DECRYPT_CURR_KEY_SUCCEEDED: + _generate_req(ADD_CURR_KEY_SUCCEEDED, progress, _sb.current_key); break; - case Channel::State::SYNC_BLK_IO_COMPLETED: - { - if (!channel._generated_prim.succ) { - class Deinitialize_sync_blk_io_error { }; - throw Deinitialize_sync_blk_io_error { }; + + case ADD_CURR_KEY_SUCCEEDED: + + if (_sb_ciphertext.state == Superblock::REKEYING) + _generate_req( + DECRYPT_PREV_KEY_SUCCEEDED, progress, _sb.previous_key.value, _sb_ciphertext.previous_key.value); + else { + _curr_gen = _gen + 1; + _req_ptr->_sb_state = _sb.state; + _mark_req_successful(progress); } - Block blk { }; - channel._sb_ciphertext.encode_to_blk(blk); - calc_sha256_4k_hash(blk, channel._hash); + break; - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_TA_SECURE_SB, - .blk_nr = 0, - .idx = job_idx - }; + case DECRYPT_PREV_KEY_SUCCEEDED: - channel._state = Channel::State::SECURE_SB_PENDING; + _generate_req(ADD_PREV_KEY_SUCCEEDED, progress, _sb.previous_key); + break; - if (sb_idx < MAX_SUPERBLOCK_INDEX) - sb_idx = sb_idx + 1; + case ADD_PREV_KEY_SUCCEEDED: + + _curr_gen = _gen + 1; + _req_ptr->_sb_state = _sb.state; + _mark_req_successful(progress); + break; + + default: break; + } +} + + +void Superblock_control_channel::_deinitialize(bool &progress) +{ + switch (_state) { + case REQ_SUBMITTED: + + _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); + _sb.last_secured_generation = _curr_gen; + _start_secure_sb(progress); + break; + + case SECURE_SB: _secure_sb(progress); break; + case SECURE_SB_SUCCEEDED: _generate_req(REMOVE_CURR_KEY_SUCCEEDED, progress, _sb.current_key.id); break; + case REMOVE_CURR_KEY_SUCCEEDED: + + if (_sb.state == Superblock::REKEYING) + _generate_req(REMOVE_CURR_KEY_SUCCEEDED, progress, _sb.previous_key.id); else - sb_idx = 0; - - channel._generation = curr_gen; - curr_gen = curr_gen + 1; - - progress = true; - + _mark_req_successful(progress); break; - } - case Channel::State::SECURE_SB_COMPLETED: - if (!_secure_sb_finish(channel, progress)) - break; - - channel._request._success = true; - - channel._curr_key_plaintext.id = sb.current_key.id; - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_CRYPTO_REMOVE_KEY, - .blk_nr = 0, - .idx = job_idx - }; - - channel._state = Channel::State::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING; - progress = true; + case REMOVE_PREV_KEY_SUCCEEDED: + _sb.state = Superblock::INVALID; + _mark_req_successful(progress); break; - case Channel::State::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_COMPLETED: - if (!channel._generated_prim.succ) { - class Deinitialize_remove_current_key_error { }; - throw Deinitialize_remove_current_key_error { }; - } - - switch (sb.state) { - default: - class Deinitialize_remove_current_key_invalid_error { }; - throw Deinitialize_remove_current_key_invalid_error { }; - break; - case Superblock::REKEYING: - - channel._prev_key_plaintext.id = sb.previous_key.id; - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_SB_CTRL_CRYPTO_REMOVE_KEY, - .blk_nr = 0, - .idx = job_idx - }; - - channel._state = Channel::State::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING; - progress = true; - - break; - case Superblock::NORMAL: - case Superblock::EXTENDING_VBD: - case Superblock::EXTENDING_FT: - - channel._request._success = true; - - channel._state = Channel::State::COMPLETED; - progress = true; - - break; - } - - break; - case Channel::State::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED: - - if (!channel._generated_prim.succ) { - class Deinitialize_remove_previous_key_error { }; - throw Deinitialize_remove_previous_key_error { }; - } - - sb.state = Superblock::INVALID; - - channel._request._success = true; - - channel._state = Channel::State::COMPLETED; - progress = true; - - break; - default: - break; + default: break; } } -bool Superblock_control::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) +void Superblock_control_channel::execute(bool &progress) { - for (unsigned id = 0; id < NR_OF_CHANNELS; id++) { + if (!_req_ptr) + return; - Channel &chan { _channels[id] }; - Request &req { chan._request }; - if (req._type == Request::INVALID) - continue; - - switch (chan._state) { - case Channel::CREATE_KEY_PENDING: - - Trust_anchor_request::create( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Trust_anchor_request::CREATE_KEY, nullptr, - nullptr, nullptr, nullptr); - - return 1; - - case Channel::ENCRYPT_CURRENT_KEY_PENDING: - case Channel::ENCRYPT_PREVIOUS_KEY_PENDING: - - Trust_anchor_request::create( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Trust_anchor_request::ENCRYPT_KEY, - &chan._key_plaintext.value, nullptr, nullptr, nullptr); - - return 1; - - case Channel::DECRYPT_CURRENT_KEY_PENDING: - - Trust_anchor_request::create( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Trust_anchor_request::DECRYPT_KEY, - nullptr, &chan._sb_ciphertext.current_key.value, - nullptr, nullptr); - - return 1; - - case Channel::DECRYPT_PREVIOUS_KEY_PENDING: - - Trust_anchor_request::create( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Trust_anchor_request::DECRYPT_KEY, - nullptr, &chan._sb_ciphertext.previous_key.value, - nullptr, nullptr); - - return 1; - - case Channel::SECURE_SB_PENDING: - - Trust_anchor_request::create( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Trust_anchor_request::SECURE_SUPERBLOCK, - nullptr, nullptr, nullptr, &chan._hash); - - return 1; - - case Channel::MAX_SB_HASH_PENDING: - - Trust_anchor_request::create( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Trust_anchor_request::GET_LAST_SB_HASH, - nullptr, nullptr, nullptr, nullptr); - - return 1; - - case Channel::ADD_KEY_AT_CRYPTO_MODULE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Crypto_request::ADD_KEY, 0, 0, (Key_id)chan._key_plaintext.id, - &chan._key_plaintext.value, 0, 0, nullptr, nullptr); - - return 1; - - case Channel::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Crypto_request::ADD_KEY, 0, 0, (Key_id)chan._curr_key_plaintext.id, - &chan._curr_key_plaintext.value, 0, 0, nullptr, nullptr); - - return 1; - - case Channel::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Crypto_request::ADD_KEY, 0, 0, - (Key_id)chan._prev_key_plaintext.id, &chan._prev_key_plaintext.value, - 0, 0, nullptr, nullptr); - - return 1; - - case Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Crypto_request::REMOVE_KEY, 0, 0, - (Key_id)chan._prev_key_plaintext.id, nullptr, - 0, 0, nullptr, nullptr); - - return 1; - - case Channel::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Crypto_request::REMOVE_KEY, 0, 0, - (Key_id)chan._curr_key_plaintext.id, nullptr, - 0, 0, nullptr, nullptr); - - return 1; - - case Channel::READ_VBA_AT_VBD_PENDING: - - Virtual_block_device_request::create( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Virtual_block_device_request::READ_VBA, - req._client_req_offset, req._client_req_tag, - _sb.last_secured_generation, - (addr_t)&_sb.free_number, - (addr_t)&_sb.free_gen, - (addr_t)&_sb.free_hash, - _sb.free_max_level, - _sb.free_degree, - _sb.free_leaves, - (addr_t)&_sb.meta_number, - (addr_t)&_sb.meta_gen, - (addr_t)&_sb.meta_hash, - _sb.meta_max_level, - _sb.meta_degree, - _sb.meta_leaves, - _sb.degree, - max_vba(), - _sb.state == Superblock::REKEYING ? 1 : 0, - req._vba, - _sb.curr_snap, - &_sb.snapshots, - _sb.degree, 0, 0, - _curr_gen, - chan._curr_key_plaintext.id, 0, 0); - - return 1; - - case Channel::WRITE_VBA_AT_VBD_PENDING: - - Virtual_block_device_request::create( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Virtual_block_device_request::WRITE_VBA, - req._client_req_offset, req._client_req_tag, - _sb.last_secured_generation, - (addr_t)&_sb.free_number, - (addr_t)&_sb.free_gen, - (addr_t)&_sb.free_hash, - _sb.free_max_level, - _sb.free_degree, - _sb.free_leaves, - (addr_t)&_sb.meta_number, - (addr_t)&_sb.meta_gen, - (addr_t)&_sb.meta_hash, - _sb.meta_max_level, - _sb.meta_degree, - _sb.meta_leaves, - _sb.degree, - max_vba(), - _sb.state == Superblock::REKEYING ? 1 : 0, - req._vba, - _sb.curr_snap, - &_sb.snapshots, - _sb.degree, 0, 0, - _curr_gen, - chan._curr_key_plaintext.id, 0, 0); - - return 1; - - case Channel::READ_SB_PENDING: - case Channel::READ_CURRENT_SB_PENDING: - - construct_in_buf( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Block_io_request::READ, 0, 0, 0, - chan._generated_prim.blk_nr, 0, 1, &chan._encoded_blk, - nullptr); - - return true; - - case Channel::SYNC_BLK_IO_PENDING: - case Channel::SYNC_CACHE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Block_io_request::SYNC, 0, 0, 0, - chan._generated_prim.blk_nr, 0, 1, nullptr, nullptr); - - return true; - - case Channel::WRITE_SB_PENDING: - - chan._sb_ciphertext.encode_to_blk(chan._encoded_blk); - construct_in_buf( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Block_io_request::WRITE, 0, 0, 0, - chan._generated_prim.blk_nr, 0, 1, &chan._encoded_blk, - nullptr); - - return true; - - case Channel::REKEY_VBA_IN_VBD_PENDING: - - Virtual_block_device_request::create( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Virtual_block_device_request::REKEY_VBA, - req._client_req_offset, req._client_req_tag, - _sb.last_secured_generation, - (addr_t)&_sb.free_number, - (addr_t)&_sb.free_gen, - (addr_t)&_sb.free_hash, - _sb.free_max_level, - _sb.free_degree, - _sb.free_leaves, - (addr_t)&_sb.meta_number, - (addr_t)&_sb.meta_gen, - (addr_t)&_sb.meta_hash, - _sb.meta_max_level, - _sb.meta_degree, - _sb.meta_leaves, - _sb.degree, - max_vba(), - _sb.state == Superblock::REKEYING ? 1 : 0, - _sb.rekeying_vba, - _sb.curr_snap, - &_sb.snapshots, - _sb.degree, - _sb.previous_key.id, - _sb.current_key.id, - _curr_gen, - chan._curr_key_plaintext.id, 0, 0); - - return 1; - - case Channel::VBD_EXT_STEP_IN_VBD_PENDING: - - Virtual_block_device_request::create( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Virtual_block_device_request::VBD_EXTENSION_STEP, - req._client_req_offset, req._client_req_tag, - _sb.last_secured_generation, - (addr_t)&_sb.free_number, - (addr_t)&_sb.free_gen, - (addr_t)&_sb.free_hash, - _sb.free_max_level, - _sb.free_degree, - _sb.free_leaves, - (addr_t)&_sb.meta_number, - (addr_t)&_sb.meta_gen, - (addr_t)&_sb.meta_hash, - _sb.meta_max_level, - _sb.meta_degree, - _sb.meta_leaves, - _sb.degree, - max_vba(), - _sb.state == Superblock::REKEYING ? 1 : 0, - 0, - _sb.curr_snap, - &_sb.snapshots, - _sb.degree, - 0, - 0, - _curr_gen, - 0, - _sb.first_pba + _sb.nr_of_pbas, - _sb.resizing_nr_of_pbas); - - return 1; - - case Channel::FT_EXT_STEP_IN_FT_PENDING: - - construct_in_buf( - buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, - Ft_resizing_request::FT_EXTENSION_STEP, _curr_gen, - Type_1_node { _sb.free_number, _sb.free_gen, _sb.free_hash }, - (Tree_level_index)_sb.free_max_level, - (Number_of_leaves)_sb.free_leaves, - (Tree_degree)_sb.free_degree, - (addr_t)&_sb.meta_number, - (addr_t)&_sb.meta_gen, - (addr_t)&_sb.meta_hash, - (Tree_level_index)_sb.meta_max_level, - (Tree_degree)_sb.meta_degree, - (Number_of_leaves)_sb.meta_leaves, - _sb.first_pba + _sb.nr_of_pbas, - (Number_of_blocks)_sb.resizing_nr_of_pbas); - - return 1; - - default: break; - } - } - return false; -} - - -void Superblock_control::_drop_generated_request(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_3 { }; - throw Exception_3 { }; - } - Channel &chan { _channels[id] }; - Request &req { chan._request }; - if (req._type == Request::INVALID) { - class Exception_2 { }; - throw Exception_2 { }; - } - switch (chan._state) { - case Channel::CREATE_KEY_PENDING: chan._state = Channel::CREATE_KEY_IN_PROGRESS; break; - case Channel::ENCRYPT_CURRENT_KEY_PENDING: chan._state = Channel::ENCRYPT_CURRENT_KEY_IN_PROGRESS; break; - case Channel::ENCRYPT_PREVIOUS_KEY_PENDING: chan._state = Channel::ENCRYPT_PREVIOUS_KEY_IN_PROGRESS; break; - case Channel::DECRYPT_CURRENT_KEY_PENDING: chan._state = Channel::DECRYPT_CURRENT_KEY_IN_PROGRESS; break; - case Channel::DECRYPT_PREVIOUS_KEY_PENDING: chan._state = Channel::DECRYPT_PREVIOUS_KEY_IN_PROGRESS; break; - case Channel::SECURE_SB_PENDING: chan._state = Channel::SECURE_SB_IN_PROGRESS; break; - case Channel::MAX_SB_HASH_PENDING: chan._state = Channel::MAX_SB_HASH_IN_PROGRESS; break; - case Channel::ADD_KEY_AT_CRYPTO_MODULE_PENDING: chan._state = Channel::ADD_KEY_AT_CRYPTO_MODULE_IN_PROGRESS; break; - case Channel::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING: chan._state = Channel::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_IN_PROGRESS; break; - case Channel::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING: chan._state = Channel::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_IN_PROGRESS; break; - case Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING: chan._state = Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_IN_PROGRESS; break; - case Channel::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING: chan._state = Channel::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_IN_PROGRESS; break; - case Channel::READ_VBA_AT_VBD_PENDING: chan._state = Channel::READ_VBA_AT_VBD_IN_PROGRESS; break; - case Channel::WRITE_VBA_AT_VBD_PENDING: chan._state = Channel::WRITE_VBA_AT_VBD_IN_PROGRESS; break; - case Channel::READ_SB_PENDING: chan._state = Channel::READ_SB_IN_PROGRESS; break; - case Channel::READ_CURRENT_SB_PENDING: chan._state = Channel::READ_CURRENT_SB_IN_PROGRESS; break; - case Channel::SYNC_BLK_IO_PENDING: chan._state = Channel::SYNC_BLK_IO_IN_PROGRESS; break; - case Channel::SYNC_CACHE_PENDING: chan._state = Channel::SYNC_CACHE_IN_PROGRESS; break; - case Channel::WRITE_SB_PENDING: chan._state = Channel::WRITE_SB_IN_PROGRESS; break; - case Channel::REKEY_VBA_IN_VBD_PENDING: chan._state = Channel::REKEY_VBA_IN_VBD_IN_PROGRESS; break; - case Channel::VBD_EXT_STEP_IN_VBD_PENDING: chan._state = Channel::VBD_EXT_STEP_IN_VBD_IN_PROGRESS; break; - case Channel::FT_EXT_STEP_IN_FT_PENDING: chan._state = Channel::FT_EXT_STEP_IN_FT_IN_PROGRESS; break; - default: - class Exception_1 { }; - throw Exception_1 { }; + switch (_req_ptr->_type) { + case Request::READ_VBA: _access_vba(Virtual_block_device_request::READ_VBA, progress); break; + case Request::WRITE_VBA: _access_vba(Virtual_block_device_request::WRITE_VBA, progress); break; + case Request::SYNC: _sync(progress); break; + case Request::INITIALIZE_REKEYING: _init_rekeying(progress); break; + case Request::REKEY_VBA: _rekey_vba(progress); break; + case Request::VBD_EXTENSION_STEP: _tree_ext_step(Superblock::EXTENDING_VBD, VERBOSE_VBD_EXTENSION, "vbd", progress); break; + case Request::FT_EXTENSION_STEP: _tree_ext_step(Superblock::EXTENDING_FT, VERBOSE_FT_EXTENSION, "ft", progress); break; + case Request::CREATE_SNAPSHOT: _create_snap(progress); break; + case Request::DISCARD_SNAPSHOT: _discard_snap(progress); break; + case Request::INITIALIZE: _initialize(progress); break; + case Request::DEINITIALIZE: _deinitialize (progress); break; } } void Superblock_control::execute(bool &progress) { - for (unsigned idx = 0; idx < NR_OF_CHANNELS; idx++) { - - Channel &channel = _channels[idx]; - Request &request { channel._request }; - - switch (request._type) { - case Request::READ_VBA: - _execute_read_vba(channel, idx, _sb, progress); - - break; - case Request::WRITE_VBA: - _execute_write_vba(channel, idx, _sb, _curr_gen, progress); - - break; - case Request::SYNC: - _execute_sync(channel, idx, _sb, _sb_idx, _curr_gen, progress); - - break; - case Request::INITIALIZE_REKEYING: _execute_initialize_rekeying(channel, idx, progress); break; - 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: _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); - - break; - case Request::DEINITIALIZE: - _execute_deinitialize (channel, idx, _sb, _sb_idx, - _curr_gen, progress); - - break; - case Request::INVALID: - break; - } - } + for_each_channel([&] (Channel &chan) { + chan.execute(progress); }); } -void Superblock_control::generated_request_complete(Module_request &mod_req) +Snapshots_info Superblock_control::snapshots_info() const { - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - switch (mod_req.dst_module_id()) { - case TRUST_ANCHOR: - { - Trust_anchor_request &gen_req { *static_cast(&mod_req) }; - chan._generated_prim.succ = gen_req.success(); - switch (chan._state) { - case Channel::CREATE_KEY_IN_PROGRESS: - chan._state = Channel::CREATE_KEY_COMPLETED; - memcpy(&chan._key_plaintext.value, gen_req.key_plaintext_ptr(), KEY_SIZE); - break; - case Channel::ENCRYPT_CURRENT_KEY_IN_PROGRESS: - chan._state = Channel::ENCRYPT_CURRENT_KEY_COMPLETED; - memcpy(&chan._sb_ciphertext.current_key.value, gen_req.key_ciphertext_ptr(), KEY_SIZE); - break; - case Channel::ENCRYPT_PREVIOUS_KEY_IN_PROGRESS: - chan._state = Channel::ENCRYPT_PREVIOUS_KEY_COMPLETED; - memcpy(&chan._sb_ciphertext.previous_key.value, gen_req.key_ciphertext_ptr(), KEY_SIZE); - break; - case Channel::DECRYPT_CURRENT_KEY_IN_PROGRESS: - chan._state = Channel::DECRYPT_CURRENT_KEY_COMPLETED; - memcpy(&chan._curr_key_plaintext.value, gen_req.key_plaintext_ptr(), KEY_SIZE); - break; - case Channel::DECRYPT_PREVIOUS_KEY_IN_PROGRESS: - chan._state = Channel::DECRYPT_PREVIOUS_KEY_COMPLETED; - memcpy(&chan._prev_key_plaintext.value, gen_req.key_plaintext_ptr(), KEY_SIZE); - break; - case Channel::SECURE_SB_IN_PROGRESS: chan._state = Channel::SECURE_SB_COMPLETED; break; - case Channel::MAX_SB_HASH_IN_PROGRESS: - chan._state = Channel::MAX_SB_HASH_COMPLETED; - memcpy(&chan._hash, gen_req.hash_ptr(), HASH_SIZE); - break; - default: - class Exception_4 { }; - throw Exception_4 { }; + Snapshots_info info { }; + if (_sb.valid()) { + for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { + Snapshot const &snap { _sb.snapshots.items[idx] }; + if (snap.valid && snap.keep) + info.generations[idx] = snap.gen; } - break; - } - case CRYPTO: - { - Crypto_request &gen_req { *static_cast(&mod_req) }; - chan._generated_prim.succ = gen_req.success(); - switch (chan._state) { - case Channel::ADD_KEY_AT_CRYPTO_MODULE_IN_PROGRESS: chan._state = Channel::ADD_KEY_AT_CRYPTO_MODULE_COMPLETED; break; - case Channel::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_IN_PROGRESS: chan._state = Channel::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_COMPLETED; break; - case Channel::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_IN_PROGRESS: chan._state = Channel::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED; break; - case Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_IN_PROGRESS: chan._state = Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED; break; - case Channel::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_IN_PROGRESS: chan._state = Channel::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_COMPLETED; break; - default: - class Exception_5 { }; - throw Exception_5 { }; - } - break; - } - case VIRTUAL_BLOCK_DEVICE: - { - Virtual_block_device_request &gen_req { *static_cast(&mod_req) }; - chan._generated_prim.succ = gen_req.success(); - switch (chan._state) { - case Channel::READ_VBA_AT_VBD_IN_PROGRESS: chan._state = Channel::READ_VBA_AT_VBD_COMPLETED; break; - case Channel::WRITE_VBA_AT_VBD_IN_PROGRESS: - chan._state = Channel::WRITE_VBA_AT_VBD_COMPLETED; - chan._snapshots.items[0] = gen_req.snapshots_ptr()->items[gen_req.curr_snap_idx()]; - break; - case Channel::REKEY_VBA_IN_VBD_IN_PROGRESS: - chan._state = Channel::REKEY_VBA_IN_VBD_COMPLETED; - chan._snapshots = *(gen_req.snapshots_ptr()); - break; - case Channel::VBD_EXT_STEP_IN_VBD_IN_PROGRESS: - chan._state = Channel::TREE_EXT_STEP_IN_TREE_COMPLETED; - chan._snapshots = *(gen_req.snapshots_ptr()); - chan._pba = gen_req.pba(); - chan._request._nr_of_blks = gen_req.nr_of_pbas(); - chan._nr_of_leaves = gen_req.nr_of_leaves(); - break; - default: - class Exception_6 { }; - throw Exception_6 { }; - } - break; - } - case FT_RESIZING: - { - Ft_resizing_request &gen_req { *static_cast(&mod_req) }; - chan._generated_prim.succ = gen_req.success(); - switch (chan._state) { - case Channel::FT_EXT_STEP_IN_FT_IN_PROGRESS: - chan._state = Channel::TREE_EXT_STEP_IN_TREE_COMPLETED; - chan._ft_root = gen_req.ft_root(); - chan._ft_max_lvl = gen_req.ft_max_lvl(); - chan._ft_nr_of_leaves = gen_req.ft_nr_of_leaves(); - chan._pba = gen_req.pba(); - chan._request._nr_of_blks = gen_req.nr_of_pbas(); - chan._nr_of_leaves = gen_req.nr_of_leaves(); - break; - default: - class Exception_16 { }; - throw Exception_16 { }; - } - break; - } - case BLOCK_IO: - { - Block_io_request &gen_req { *static_cast(&mod_req) }; - chan._generated_prim.succ = gen_req.success(); - switch (chan._state) { - case Channel::READ_SB_IN_PROGRESS: - chan._sb_ciphertext.decode_from_blk(chan._encoded_blk); - chan._state = Channel::READ_SB_COMPLETED; - break; - case Channel::READ_CURRENT_SB_IN_PROGRESS: - chan._sb_ciphertext.decode_from_blk(chan._encoded_blk); - chan._state = Channel::READ_CURRENT_SB_COMPLETED; - break; - case Channel::SYNC_BLK_IO_IN_PROGRESS: chan._state = Channel::SYNC_BLK_IO_COMPLETED; break; - case Channel::SYNC_CACHE_IN_PROGRESS: chan._state = Channel::SYNC_CACHE_COMPLETED; break; - case Channel::WRITE_SB_IN_PROGRESS: chan._state = Channel::WRITE_SB_COMPLETED; break; - default: - class Exception_7 { }; - throw Exception_7 { }; - } - break; - } - default: - class Exception_8 { }; - throw Exception_8 { }; } + return info; } -bool Superblock_control::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) +Superblock_info Superblock_control::sb_info() const { - for (Channel &channel : _channels) { - if (channel._request._type != Request::INVALID && - channel._state == Channel::COMPLETED) { + if (!_sb.valid()) + return Superblock_info { }; - if (sizeof(channel._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &channel._request, sizeof(channel._request)); - return true; - } - } - return false; + return Superblock_info { + true, _sb.state == Superblock::REKEYING, _sb.state == Superblock::EXTENDING_FT, + _sb.state == Superblock::EXTENDING_VBD }; } -void Superblock_control::_drop_completed_request(Module_request &req) +void Superblock_control_channel::_request_submitted(Module_request &req) { - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (_channels[id]._request._type == Request::INVALID) { - class Exception_2 { }; - throw Exception_2 { }; - } - if (_channels[id]._state != Channel::COMPLETED) { - class Exception_3 { }; - throw Exception_3 { }; - } - _channels[id]._request._type = Request::INVALID; + _req_ptr = static_cast(&req); + _state = REQ_SUBMITTED; } -bool Superblock_control::ready_to_submit_request() +Superblock_control::Superblock_control() { - for (Channel const &channel : _channels) { - if (channel._request._type == Request::INVALID) - return true; + for (Module_channel_id id { 0 }; id < NUM_CHANNELS; id++) { + _channels[id].construct(id, _sb, _sb_idx, _curr_gen); + add_channel(*_channels[id]); } - return false; } -void Superblock_control::submit_request(Module_request &req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - if (_channels[id]._request._type == Request::INVALID) { - req.dst_request_id(id); - _channels[id]._request = *static_cast(&req); - _channels[id]._state = Channel::SUBMITTED; - return; - } - } - class Invalid_call { }; - throw Invalid_call { }; -} +Superblock_control_channel:: +Superblock_control_channel(Module_channel_id id, Superblock &sb, Superblock_index &sb_idx, Generation &curr_gen) +: + Module_channel { SUPERBLOCK_CONTROL, id }, _sb { sb }, _sb_idx { sb_idx }, _curr_gen { curr_gen } +{ } diff --git a/repos/gems/src/lib/tresor/trust_anchor.cc b/repos/gems/src/lib/tresor/trust_anchor.cc index c21729223b..d3a8cb17c2 100644 --- a/repos/gems/src/lib/tresor/trust_anchor.cc +++ b/repos/gems/src/lib/tresor/trust_anchor.cc @@ -11,546 +11,179 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base includes */ -#include - /* tresor includes */ #include using namespace Tresor; - -/************************** - ** Trust_anchor_request ** - **************************/ - -void Trust_anchor_request::create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - void *key_plaintext_ptr, - void *key_ciphertext_ptr, - char const *passphrase_ptr, - void *hash_ptr) -{ - Trust_anchor_request req { src_module_id, src_request_id }; - req._type = (Type)req_type; - req._passphrase_ptr = (addr_t)passphrase_ptr; - if (key_plaintext_ptr != nullptr) - memcpy( - &req._key_plaintext, key_plaintext_ptr, - sizeof(req._key_plaintext)); - - if (key_ciphertext_ptr != nullptr) - memcpy( - &req._key_ciphertext, key_ciphertext_ptr, - sizeof(req._key_ciphertext)); - - if (hash_ptr != nullptr) - memcpy(&req._hash, hash_ptr, sizeof(req._hash)); - - if (sizeof(req) > buf_size) { - class Exception_2 { }; - throw Exception_2 { }; - } - memcpy(buf_ptr, &req, sizeof(req)); -} - - -Trust_anchor_request::Trust_anchor_request(Module_id src_module_id, - Module_request_id src_request_id) +Trust_anchor_request::Trust_anchor_request(Module_id src_module_id, Module_channel_id src_chan_id, + Type type, Key_value &key_plaintext, Key_value &key_ciphertext, + Hash &hash, Passphrase passphrase, bool &success) : - Module_request { src_module_id, src_request_id, TRUST_ANCHOR } + Module_request { src_module_id, src_chan_id, TRUST_ANCHOR }, _type { type }, _key_plaintext { key_plaintext }, + _key_ciphertext { key_ciphertext }, _hash { hash }, _pass { passphrase }, _success { success } { } char const *Trust_anchor_request::type_to_string(Type type) { switch (type) { - case INVALID: return "invalid"; case CREATE_KEY: return "create_key"; case ENCRYPT_KEY: return "encrypt_key"; case DECRYPT_KEY: return "decrypt_key"; - case SECURE_SUPERBLOCK: return "secure_superblock"; - case GET_LAST_SB_HASH: return "get_last_sb_hash"; + case WRITE_HASH: return "write_hash"; + case READ_HASH: return "read_hash"; case INITIALIZE: return "initialize"; } - return "?"; + ASSERT_NEVER_REACHED; } -/****************** - ** Trust_anchor ** - ******************/ - -void Trust_anchor::_execute_write_read_operation(Vfs::Vfs_handle &file, - String<128> const &file_path, - Channel &channel, - char const *write_buf, - char *read_buf, - size_t read_size, - bool &progress) +void Trust_anchor_channel::_mark_req_failed(bool &progress, Error_string str) { - Request &req { channel._request }; - switch (channel._state) { - case Channel::WRITE_PENDING: + error("trust_anchor: request (", *_req_ptr, ") failed: ", str); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; + progress = true; +} - file.seek(channel._file_offset); - channel._state = Channel::WRITE_IN_PROGRESS; - progress = true; - return; - case Channel::WRITE_IN_PROGRESS: - { - size_t nr_of_written_bytes { 0 }; +void Trust_anchor_channel::_mark_req_successful(bool &progress) +{ + Request &req { *_req_ptr }; + req._success = true; + _state = REQ_COMPLETE; + _req_ptr = nullptr; + progress = true; +} - Const_byte_range_ptr src { - write_buf + channel._file_offset, channel._file_size }; - Write_result const result = - file.fs().write(&file, src, nr_of_written_bytes); - - switch (result) { - - case Write_result::WRITE_ERR_WOULD_BLOCK: - return; - - case Write_result::WRITE_OK: - - channel._file_offset += nr_of_written_bytes; - channel._file_size -= nr_of_written_bytes; - - if (channel._file_size > 0) { - - channel._state = Channel::WRITE_PENDING; - progress = true; - return; - } - channel._state = Channel::READ_PENDING; - channel._file_offset = 0; - channel._file_size = read_size; - progress = true; - return; - - default: - - req._success = false; - error("failed to write file ", file_path); - channel._state = Channel::COMPLETE; - progress = true; - return; - } - } - case Channel::READ_PENDING: - - file.seek(channel._file_offset); - - if (!file.fs().queue_read(&file, channel._file_size)) { - return; - } - channel._state = Channel::READ_IN_PROGRESS; - progress = true; - return; - - case Channel::READ_IN_PROGRESS: - { - size_t nr_of_read_bytes { 0 }; - - Byte_range_ptr dst { - read_buf + channel._file_offset, channel._file_size }; - - Read_result const result { - file.fs().complete_read( &file, dst, nr_of_read_bytes) }; - - switch (result) { - case Read_result::READ_QUEUED: - case Read_result::READ_ERR_WOULD_BLOCK: - - return; - - case Read_result::READ_OK: - - channel._file_offset += nr_of_read_bytes; - channel._file_size -= nr_of_read_bytes; - req._success = true; - - if (channel._file_size > 0) { - - channel._state = Channel::READ_PENDING; - progress = true; - return; - } - channel._state = Channel::COMPLETE; - progress = true; - return; - - default: - - req._success = false; - error("failed to read file ", file_path); - channel._state = Channel::COMPLETE; - return; - } - } - default: - - return; +void Trust_anchor_channel::_read_hash(bool &progress) +{ + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: _hashsum_file.read(READ_OK, FILE_ERR, 0, { (char *)&req._hash, HASH_SIZE }, progress); break; + case READ_OK: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: break; } } -void Trust_anchor::_execute_write_operation(Vfs::Vfs_handle &file, - String<128> const &file_path, - Channel &channel, - char const *write_buf, - bool &progress, - bool result_via_read) +void Trust_anchor_channel::_create_key(bool &progress) { - Request &req { channel._request }; - switch (channel._state) { - case Channel::WRITE_PENDING: - - file.seek(channel._file_offset); - channel._state = Channel::WRITE_IN_PROGRESS; - progress = true; - return; - - case Channel::WRITE_IN_PROGRESS: - { - size_t nr_of_written_bytes { 0 }; - - Const_byte_range_ptr src { - write_buf + channel._file_offset, channel._file_size }; - - Write_result const result = - file.fs().write(&file, src, nr_of_written_bytes); - - switch (result) { - - case Write_result::WRITE_ERR_WOULD_BLOCK: - return; - - case Write_result::WRITE_OK: - - channel._file_offset += nr_of_written_bytes; - channel._file_size -= nr_of_written_bytes; - - if (channel._file_size > 0) { - - channel._state = Channel::WRITE_PENDING; - progress = true; - return; - } - channel._state = Channel::READ_PENDING; - channel._file_offset = 0; - - if (result_via_read) - channel._file_size = sizeof(_read_buf); - else - channel._file_size = 0; - - progress = true; - return; - - default: - - req._success = false; - error("failed to write file ", file_path); - channel._state = Channel::COMPLETE; - progress = true; - return; - } - } - case Channel::READ_PENDING: - - file.seek(channel._file_offset); - - if (!file.fs().queue_read(&file, channel._file_size)) { - return; - } - channel._state = Channel::READ_IN_PROGRESS; - progress = true; - return; - - case Channel::READ_IN_PROGRESS: - { - size_t nr_of_read_bytes { 0 }; - Byte_range_ptr dst { - _read_buf + channel._file_offset, channel._file_size }; - - Read_result const result { - file.fs().complete_read(&file, dst, nr_of_read_bytes) }; - - switch (result) { - case Read_result::READ_QUEUED: - case Read_result::READ_ERR_WOULD_BLOCK: - - return; - - case Read_result::READ_OK: - - channel._file_offset += nr_of_read_bytes; - channel._file_size -= nr_of_read_bytes; - - if (channel._file_size > 0) { - - channel._state = Channel::READ_PENDING; - progress = true; - return; - } - if (result_via_read) { - req._success = !strcmp(_read_buf, "ok", 3); - } else - req._success = true; - - channel._state = Channel::COMPLETE; - progress = true; - return; - - default: - - req._success = false; - error("failed to read file ", file_path); - channel._state = Channel::COMPLETE; - return; - } - } - default: - - return; + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: _generate_key_file.read(READ_OK, FILE_ERR, 0, { (char *)&req._key_plaintext, KEY_SIZE }, progress); break; + case READ_OK: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: break; } } -void Trust_anchor::_execute_read_operation(Vfs::Vfs_handle &file, - String<128> const &file_path, - Channel &channel, - char *read_buf, - bool &progress) +void Trust_anchor_channel::_initialize(bool &progress) { - Request &req { channel._request }; - switch (channel._state) { - case Channel::READ_PENDING: + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: _initialize_file.write(WRITE_OK, FILE_ERR, 0, { req._pass.string(), req._pass.length() - 1 }, progress); break; + case WRITE_OK: _initialize_file.read(READ_OK, FILE_ERR, 0, { _result_buf, sizeof(_result_buf) }, progress); break; + case READ_OK: - file.seek(channel._file_offset); + if (strcmp(_result_buf, "ok", sizeof(_result_buf))) + _mark_req_failed(progress, { "trust anchor did not return \"ok\""}); + else + _mark_req_successful(progress); + break; - if (!file.fs().queue_read(&file, channel._file_size)) { - return; - } - channel._state = Channel::READ_IN_PROGRESS; - progress = true; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: break; + } +} + + +void Trust_anchor_channel::_write_hash(bool &progress) +{ + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: _hashsum_file.write(WRITE_OK, FILE_ERR, 0, { (char *)&req._hash, HASH_SIZE }, progress); break; + case WRITE_OK: _hashsum_file.read(READ_OK, FILE_ERR, 0, { _result_buf, 0 }, progress); break; + case READ_OK: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: break; + } +} + + +void Trust_anchor_channel::_encrypt_key(bool &progress) +{ + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: _encrypt_file.write(WRITE_OK, FILE_ERR, 0, { (char *)&req._key_plaintext, KEY_SIZE }, progress); break; + case WRITE_OK: _encrypt_file.read(READ_OK, FILE_ERR, 0, { (char *)&req._key_ciphertext, KEY_SIZE }, progress); break; + case READ_OK: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: break; + } +} + + +void Trust_anchor_channel::_decrypt_key(bool &progress) +{ + Request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: _decrypt_file.write(WRITE_OK, FILE_ERR, 0, { (char *)&req._key_ciphertext, KEY_SIZE }, progress); break; + case WRITE_OK: _decrypt_file.read(READ_OK, FILE_ERR, 0, { (char *)&req._key_plaintext, KEY_SIZE }, progress); break; + case READ_OK: _mark_req_successful(progress); break; + case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + default: break; + } +} + + +void Trust_anchor_channel::execute(bool &progress) +{ + if (!_req_ptr) return; - case Channel::READ_IN_PROGRESS: - { - size_t nr_of_read_bytes { 0 }; - Byte_range_ptr dst { - read_buf + channel._file_offset, channel._file_size }; - - Read_result const result { - file.fs().complete_read(&file, dst, nr_of_read_bytes) }; - - switch (result) { - case Read_result::READ_QUEUED: - case Read_result::READ_ERR_WOULD_BLOCK: - - return; - - case Read_result::READ_OK: - - channel._file_offset += nr_of_read_bytes; - channel._file_size -= nr_of_read_bytes; - req._success = true; - - if (channel._file_size > 0) { - - channel._state = Channel::READ_PENDING; - progress = true; - return; - } - channel._state = Channel::COMPLETE; - progress = true; - return; - - default: - - req._success = false; - error("failed to read file ", file_path); - channel._state = Channel::COMPLETE; - return; - } + Request &req { *_req_ptr }; + switch (req._type) { + case Request::INITIALIZE: _initialize(progress); break; + case Request::WRITE_HASH: _write_hash(progress); break; + case Request::READ_HASH: _read_hash(progress); break; + case Request::CREATE_KEY: _create_key(progress); break; + case Request::ENCRYPT_KEY: _encrypt_key(progress); break; + case Request::DECRYPT_KEY: _decrypt_key(progress); break; } - default: +} - return; + +Trust_anchor_channel::Trust_anchor_channel(Module_channel_id id, Vfs::Env &vfs_env, Xml_node const &xml_node) +: + Module_channel { TRUST_ANCHOR, id }, _vfs_env { vfs_env }, _path { xml_node.attribute_value("path", Tresor::Path()) } +{ } + + +Trust_anchor::Trust_anchor(Vfs::Env &vfs_env, Xml_node const &xml_node) +{ + Module_channel_id id { 0 }; + for (Constructible &chan : _channels) { + chan.construct(id++, vfs_env, xml_node); + add_channel(*chan); } } +void Trust_anchor_channel::_request_submitted(Module_request &mod_req) +{ + _req_ptr = static_cast(&mod_req); + _state = REQ_SUBMITTED; +} + + void Trust_anchor::execute(bool &progress) { - for (Channel &channel : _channels) { - - if (channel._state == Channel::INACTIVE) - continue; - - Request &req { channel._request }; - switch (req._type) { - case Request::INITIALIZE: - - if (channel._state == Channel::SUBMITTED) { - channel._state = Channel::WRITE_PENDING; - channel._file_offset = 0; - channel._file_size = - strlen((char const *)req._passphrase_ptr); - } - _execute_write_operation( - _initialize_file, _initialize_path, channel, - (char const *)req._passphrase_ptr, progress, true); - - break; - - case Request::SECURE_SUPERBLOCK: - - if (channel._state == Channel::SUBMITTED) { - channel._state = Channel::WRITE_PENDING; - channel._file_offset = 0; - channel._file_size = sizeof(req._hash); - } - _execute_write_operation( - _hashsum_file, _hashsum_path, channel, - (char const *)&req._hash, progress, false); - - break; - - case Request::GET_LAST_SB_HASH: - - if (channel._state == Channel::SUBMITTED) { - channel._state = Channel::READ_PENDING; - channel._file_offset = 0; - channel._file_size = sizeof(req._hash); - } - _execute_read_operation( - _hashsum_file, _hashsum_path, channel, - (char *)&req._hash, progress); - - break; - - case Request::CREATE_KEY: - - if (channel._state == Channel::SUBMITTED) { - channel._state = Channel::READ_PENDING; - channel._file_offset = 0; - channel._file_size = sizeof(req._key_plaintext); - } - _execute_read_operation( - _generate_key_file, _generate_key_path, channel, - (char *)req._key_plaintext, progress); - - break; - - case Request::ENCRYPT_KEY: - - if (channel._state == Channel::SUBMITTED) { - channel._state = Channel::WRITE_PENDING; - channel._file_offset = 0; - channel._file_size = sizeof(req._key_plaintext); - } - _execute_write_read_operation( - _encrypt_file, _encrypt_path, channel, - (char const *)req._key_plaintext, - (char *)req._key_ciphertext, - sizeof(req._key_ciphertext), - progress); - - break; - - case Request::DECRYPT_KEY: - - if (channel._state == Channel::SUBMITTED) { - channel._state = Channel::WRITE_PENDING; - channel._file_offset = 0; - channel._file_size = sizeof(req._key_ciphertext); - } - _execute_write_read_operation( - _decrypt_file, _decrypt_path, channel, - (char const *)req._key_ciphertext, - (char *)req._key_plaintext, - sizeof(req._key_plaintext), - progress); - - break; - - default: - - class Exception_1 { }; - throw Exception_1 { }; - } - } -} - - -Trust_anchor::Trust_anchor(Vfs::Env &vfs_env, - Xml_node const &xml_node) -: - _vfs_env { vfs_env }, - _path { xml_node.attribute_value("path", String<128>()) } -{ } - - -bool Trust_anchor::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (Channel &channel : _channels) { - if (channel._state == Channel::COMPLETE) { - if (sizeof(channel._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &channel._request, sizeof(channel._request)); - return true; - } - } - return false; -} - - -void Trust_anchor::_drop_completed_request(Module_request &req) -{ - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (_channels[id]._state != Channel::COMPLETE) { - class Exception_2 { }; - throw Exception_2 { }; - } - _channels[id]._state = Channel::INACTIVE; -} - - -bool Trust_anchor::ready_to_submit_request() -{ - for (Channel &channel : _channels) { - if (channel._state == Channel::INACTIVE) - return true; - } - return false; -} - -void Trust_anchor::submit_request(Module_request &req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - if (_channels[id]._state == Channel::INACTIVE) { - req.dst_request_id(id); - _channels[id]._request = *static_cast(&req); - _channels[id]._state = Channel::SUBMITTED; - return; - } - } - class Invalid_call { }; - throw Invalid_call { }; + for_each_channel([&] (Channel &chan) { + chan.execute(progress); }); } diff --git a/repos/gems/src/lib/tresor/vbd_check.cc b/repos/gems/src/lib/tresor/vbd_check.cc index 2f20e08e58..2a7f539477 100644 --- a/repos/gems/src/lib/tresor/vbd_check.cc +++ b/repos/gems/src/lib/tresor/vbd_check.cc @@ -11,453 +11,173 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base includes */ -#include - /* tresor includes */ #include #include -#include +#include using namespace Tresor; - -/*********************** - ** Vbd_check_request ** - ***********************/ - -Vbd_check_request::Vbd_check_request(uint64_t src_module_id, - uint64_t src_request_id, - Type type, - Tree_level_index max_lvl, - Tree_node_index max_child_idx, - Number_of_leaves nr_of_leaves, - Type_1_node root) +Vbd_check_request::Vbd_check_request(Module_id src_mod, Module_channel_id src_chan, Tree_root const &vbd, bool &success) : - Module_request { src_module_id, src_request_id, VBD_CHECK }, - _type { type }, - _max_lvl { max_lvl }, - _max_child_idx { max_child_idx }, - _nr_of_leaves { nr_of_leaves }, - _root { root } + Module_request { src_mod, src_chan, VBD_CHECK }, _vbd { vbd }, _success { success } { } -char const *Vbd_check_request::type_to_string(Type type) +void Vbd_check_channel::_generated_req_completed(State_uint state_uint) { - switch (type) { - case INVALID: return "invalid"; - case CHECK: return "check"; - } - return "?"; -} - - -/*************** - ** Vbd_check ** - ***************/ - -void Vbd_check::_execute_inner_t1_child(Channel &chan, - Type_1_node const &child, - Type_1_level &child_lvl, - Child_state &child_state, - Tree_level_index lvl, - Tree_node_index child_idx, - bool &progress) -{ - Request &req { chan._request }; - if (child_state == Channel::READ_BLOCK) { - - if (!child.valid()) { - - if (req._nr_of_leaves == 0) { - - child_state = Channel::DONE; - progress = true; - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, - ": expectedly invalid"); - - } else { - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " (", child,"): unexpectedly invalid"); - - _mark_req_failed(chan, progress, "check for valid child"); - } - - } else if (!chan._gen_prim.valid()) { - - chan._gen_prim = { - .success = false, - .tag = Channel::BLOCK_IO, - .blk_nr = child.pba, - .dropped = false }; - - chan._lvl_to_read = lvl - 1; - progress = true; - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " (", child, "): load to lvl ", lvl - 1); - - } else if (chan._gen_prim.tag != Channel::BLOCK_IO || - chan._gen_prim.blk_nr != child.pba) { - - class Exception_1 { }; - throw Exception_1 { }; - - } else if (!chan._gen_prim.success) { - - } else { - - for (Child_state &state : child_lvl.children_state) { - state = Channel::READ_BLOCK; - } - chan._gen_prim = { }; - child_state = Channel::CHECK_HASH; - progress = true; - } - - } else if (child_state == Channel::CHECK_HASH) { - - Block blk { }; - child_lvl.children.encode_to_blk(blk); - - if (child.gen == INITIAL_GENERATION || - check_sha256_4k_hash(blk, child.hash)) { - - child_state = Channel::DONE; - if (&child_state == &chan._root_state) { - chan._request._success = true; - } - progress = true; - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, ": good hash"); - - } else { - - if (VERBOSE_CHECK) { - - Hash hash; - calc_sha256_4k_hash(blk, hash); - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " (", child, "): bad hash ", hash); - } - - _mark_req_failed(chan, progress, "check inner hash"); - } - } -} - - -void Vbd_check::_execute_leaf_child(Channel &chan, - Type_1_node const &child, - Block const &child_lvl, - Child_state &child_state, - Tree_level_index lvl, - Tree_node_index child_idx, - bool &progress) -{ - Request &req { chan._request }; - if (child_state == Channel::READ_BLOCK) { - - if (req._nr_of_leaves == 0) { - - if (child.valid()) { - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " (", child, "): unexpectedly valid"); - - _mark_req_failed(chan, progress, "check for unused child"); - - } else { - - child_state = Channel::DONE; - progress = true; - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, ": expectedly invalid"); - } - - } else if (child.gen == INITIAL_GENERATION) { - - req._nr_of_leaves--; - child_state = Channel::DONE; - progress = true; - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, ": uninitialized"); - - } else if (!chan._gen_prim.valid()) { - - chan._gen_prim = { - .success = false, - .tag = Channel::BLOCK_IO, - .blk_nr = child.pba, - .dropped = false }; - - chan._lvl_to_read = lvl - 1; - progress = true; - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " (", child, "): load to lvl ", lvl - 1); - - } else if (chan._gen_prim.tag != Channel::BLOCK_IO || - chan._gen_prim.blk_nr != child.pba) { - - class Exception_1 { }; - throw Exception_1 { }; - - } else if (!chan._gen_prim.success) { - - } else { - - chan._gen_prim = { }; - child_state = Channel::CHECK_HASH; - progress = true; - } - - } else if (child_state == Channel::CHECK_HASH) { - - if (check_sha256_4k_hash(child_lvl, child.hash)) { - - req._nr_of_leaves--; - child_state = Channel::DONE; - progress = true; - - if (VERBOSE_CHECK) - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, ": good hash"); - - } else { - - if (VERBOSE_CHECK) { - - Hash hash; - calc_sha256_4k_hash(child_lvl, hash); - log(Level_indent { lvl, req._max_lvl }, - " lvl ", lvl, " child ", child_idx, " (", child, "): bad hash ", hash); - } - - _mark_req_failed(chan, progress, "check leaf hash"); - } - } -} - - -void Vbd_check::_execute_check(Channel &chan, - bool &progress) -{ - Request &req { chan._request }; - for (Tree_level_index lvl { VBD_LOWEST_T1_LVL }; lvl <= req._max_lvl; lvl++) { - for (Tree_node_index child_idx { 0 }; - child_idx <= req._max_child_idx; - child_idx++) { - - Type_1_level &t1_lvl { chan._t1_lvls[lvl] }; - if (t1_lvl.children_state[child_idx] != Channel::DONE) { - - if (lvl == VBD_LOWEST_T1_LVL) - _execute_leaf_child( - chan, - chan._t1_lvls[lvl].children.nodes[child_idx], - chan._leaf_lvl, - chan._t1_lvls[lvl].children_state[child_idx], - lvl, child_idx, progress); - else - _execute_inner_t1_child( - chan, - chan._t1_lvls[lvl].children.nodes[child_idx], - chan._t1_lvls[lvl - 1], - chan._t1_lvls[lvl].children_state[child_idx], - lvl, child_idx, progress); - - return; - } - } - } - if (chan._root_state != Channel::DONE) { - - _execute_inner_t1_child( - chan, req._root, chan._t1_lvls[req._max_lvl], chan._root_state, - req._max_lvl + 1, 0, progress); - + if (!_generated_req_success) { + error("vbd check: request (", *_req_ptr, ") failed because generated request failed)"); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; return; } + _state = (State)state_uint; } -void Vbd_check::_mark_req_failed(Channel &chan, - bool &progress, - char const *str) +bool Vbd_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) { - error("vbd check: request (", chan._request, ") failed at step \"", str, "\""); - chan._request._success = false; - chan._root_state = Channel::DONE; + bool &check_node = _check_node[lvl][node_idx]; + if (!check_node) + return false; + + Request &req { *_req_ptr }; + Type_1_node const &node = _t1_blks.items[lvl].nodes[node_idx]; + switch (_state) { + case REQ_IN_PROGRESS: + + if (lvl == 1) { + if (!_num_remaining_leaves) { + if (node.valid()) { + _mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, + ") valid but no leaves remaining" }); + break; + } + check_node = false; + progress = true; + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": expectedly invalid"); + break; + } + if (node.gen == INITIAL_GENERATION) { + _num_remaining_leaves--; + check_node = false; + progress = true; + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": uninitialized"); + break; + } + } else { + if (!node.valid()) { + if (_num_remaining_leaves) { + _mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " invalid but ", + _num_remaining_leaves, " leaves remaining" }); + break; + } + check_node = false; + progress = true; + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": expectedly invalid"); + break; + } + } + _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _blk); + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, " (", node, + "): load to lvl ", lvl - 1); + break; + + case READ_BLK_SUCCEEDED: + + if (!(lvl > 1 && node.gen == INITIAL_GENERATION) && !check_hash(_blk, node.hash)) { + _mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, ") has bad hash" }); + break; + } + if (lvl == 1) + _num_remaining_leaves--; + else { + _t1_blks.items[lvl - 1].decode_from_blk(_blk); + for (bool &cn : _check_node[lvl - 1]) + cn = true; + } + check_node = false; + _state = REQ_IN_PROGRESS; + progress = true; + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": good hash"); + break; + + default: break; + } + return true; +} + + +void Vbd_check_channel::execute(bool &progress) +{ + if (!_req_ptr) + return; + + Request &req { *_req_ptr }; + if (_state == REQ_SUBMITTED) { + for (Tree_level_index lvl { 1 }; lvl <= req._vbd.max_lvl + 1; lvl++) + for (Tree_node_index node_idx { 0 }; node_idx < req._vbd.degree; node_idx++) + _check_node[lvl][node_idx] = false; + + _num_remaining_leaves = req._vbd.num_leaves; + _t1_blks.items[req._vbd.max_lvl + 1].nodes[0] = req._vbd.t1_node(); + _check_node[req._vbd.max_lvl + 1][0] = true; + _state = REQ_IN_PROGRESS; + } + for (Tree_level_index lvl { 1 }; lvl <= req._vbd.max_lvl + 1; lvl++) + for (Tree_node_index node_idx { 0 }; node_idx < req._vbd.degree; node_idx++) + if (_execute_node(lvl, node_idx, progress)) + return; + + _mark_req_successful(progress); +} + + +void Vbd_check_channel::_mark_req_failed(bool &progress, Error_string str) +{ + error("vbd check request (", *_req_ptr, ") failed: ", str); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; } -bool Vbd_check::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) +void Vbd_check_channel::_mark_req_successful(bool &progress) { - for (Channel &chan : _channels) { - - if (chan._request._type != Request::INVALID && - chan._root_state == Channel::DONE) { - - if (sizeof(chan._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &chan._request, sizeof(chan._request)); - return true; - } - } - return false; + _req_ptr->_success = true; + _state = REQ_COMPLETE; + _req_ptr = nullptr; + progress = true; } -void Vbd_check::_drop_completed_request(Module_request &req) +void Vbd_check_channel::_request_submitted(Module_request &mod_req) { - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - if (chan._request._type == Request::INVALID && - chan._root_state != Channel::DONE) { - - class Exception_2 { }; - throw Exception_2 { }; - } - chan = Channel { }; + _req_ptr = static_cast(&mod_req); + _state = REQ_SUBMITTED; } -bool Vbd_check::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) +Vbd_check::Vbd_check() { - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - - Channel &chan { _channels[id] }; - - if (!chan._gen_prim.valid() || chan._gen_prim.dropped) - continue; - - switch (chan._gen_prim.tag) { - case Channel::BLOCK_IO: - - construct_in_buf( - buf_ptr, buf_size, VBD_CHECK, id, - Block_io_request::READ, 0, 0, 0, - chan._gen_prim.blk_nr, 0, 1, - chan._lvl_to_read == 0 ? - (void *)&chan._leaf_lvl : - (void *)&chan._encoded_blk, - nullptr); - - return true; - - default: - - class Exception_1 { }; - throw Exception_1 { }; - } + Module_channel_id id { 0 }; + for (Constructible &chan : _channels) { + chan.construct(id++); + add_channel(*chan); } - return false; -} - - -void Vbd_check::_drop_generated_request(Module_request &req) -{ - Module_request_id const id { req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_0 { }; - throw Exception_0 { }; - } - Channel &chan { _channels[id] }; - chan._gen_prim.dropped = true; -} - - -void Vbd_check::generated_request_complete(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - switch (mod_req.dst_module_id()) { - case BLOCK_IO: - { - Block_io_request &gen_req { *static_cast(&mod_req) }; - chan._gen_prim.success = gen_req.success(); - if (chan._lvl_to_read > 0) - chan._t1_lvls[chan._lvl_to_read].children.decode_from_blk(chan._encoded_blk); - break; - } - default: - class Exception_8 { }; - throw Exception_8 { }; - } -} - - -bool Vbd_check::ready_to_submit_request() -{ - for (Channel &chan : _channels) { - if (chan._request._type == Request::INVALID) - return true; - } - return false; -} - - -void Vbd_check::submit_request(Module_request &req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - Channel &chan { _channels[id] }; - if (chan._request._type == Request::INVALID) { - req.dst_request_id(id); - chan._request = *static_cast(&req); - chan._root_state = Channel::READ_BLOCK; - return; - } - } - class Exception_1 { }; - throw Exception_1 { }; } void Vbd_check::execute(bool &progress) { - for (Channel &chan : _channels) { - - Request &req { chan._request }; - switch (req._type) { - case Request::CHECK: - - _execute_check(chan, progress); - break; - - default: - - break; - } - } + for_each_channel([&] (Channel &chan) { + chan.execute(progress); }); } diff --git a/repos/gems/src/lib/tresor/vbd_initializer.cc b/repos/gems/src/lib/tresor/vbd_initializer.cc index cc21f8f764..192036fcdf 100644 --- a/repos/gems/src/lib/tresor/vbd_initializer.cc +++ b/repos/gems/src/lib/tresor/vbd_initializer.cc @@ -1,5 +1,6 @@ /* * \brief Module for initializing the VBD + * \author Martin Stein * \author Josef Soentgen * \date 2023-03-03 */ @@ -11,596 +12,194 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base includes */ -#include - /* tresor includes */ -#include #include -#include +#include #include using namespace Tresor; -static constexpr bool DEBUG = false; - - -Vbd_initializer_request::Vbd_initializer_request(Module_id src_module_id, - Module_request_id src_request_id) +Vbd_initializer_request::Vbd_initializer_request(Module_id src_mod, Module_channel_id src_chan, Tree_root &vbd, + Pba_allocator &pba_alloc, bool &success) : - Module_request { src_module_id, src_request_id, VBD_INITIALIZER } + Module_request { src_mod, src_chan, VBD_INITIALIZER }, _vbd { vbd }, _pba_alloc { pba_alloc }, _success { success } { } -void Vbd_initializer_request::create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - uint64_t max_level_idx, - uint64_t max_child_idx, - uint64_t nr_of_leaves) +bool Vbd_initializer_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) { - Vbd_initializer_request req { src_module_id, src_request_id }; - req._type = (Type)req_type; + Type_1_node &node = _t1_blks.items[lvl].nodes[node_idx]; + Node_state &node_state = _node_states[lvl][node_idx]; + switch (node_state) { + case DONE: return false; + case INIT_BLOCK: - req._max_level_idx = max_level_idx; - req._max_child_idx = max_child_idx; - req._nr_of_leaves = nr_of_leaves; - - if (sizeof(req) > buf_size) { - class Bad_size_0 { }; - throw Bad_size_0 { }; - } - memcpy(buf_ptr, &req, sizeof(req)); -} - - -char const *Vbd_initializer_request::type_to_string(Type type) -{ - switch (type) { - case INVALID: return "invalid"; - case INIT: return "init"; - } - return "?"; -} - - -void Vbd_initializer::_execute_leaf_child(Channel &channel, - bool &progress, - uint64_t &nr_of_leaves, - Type_1_node &child, - Vbd_initializer_channel::Child_state &child_state, - uint64_t level_index, - uint64_t child_index) -{ - using CS = Vbd_initializer_channel::Child_state; - - switch (child_state) { - case CS::INIT_BLOCK: - child_state = CS::INIT_NODE; - progress = true; - return; - - case CS::INIT_NODE: - if (nr_of_leaves == 0) { - - if (DEBUG) - log("[vbd_init] node: ", level_index, " ", child_index, - " assign pba 0, leaf unused"); - - Vbd_initializer_channel::reset_node(child); - child_state = CS::DONE; + if (lvl == 1) { + node_state = INIT_NODE; progress = true; - } else { - - switch (channel._state) { - case Channel::IN_PROGRESS: - channel._state = Channel::BLOCK_ALLOC_PENDING; + } else + if (_num_remaining_leaves) { + _reset_level(lvl - 1, INIT_BLOCK); + node_state = INIT_NODE; progress = true; - break; + if (VERBOSE_VBD_INIT) + log("[vbd_init] node: ", lvl, " ", node_idx, " reset level: ", lvl - 1); + } else { + node = { }; + node_state = DONE; + progress = true; + if (VERBOSE_VBD_INIT) + log("[vbd_init] node: ", lvl, " ", node_idx, " assign pba 0, inner node unused"); + } + break; - case Channel::BLOCK_ALLOC_PENDING: - break; + case INIT_NODE: - case Channel::BLOCK_ALLOC_IN_PROGRESS: - break; - - case Channel::BLOCK_ALLOC_COMPLETE: - /* bail early in case the allocator failed */ - if (!channel._generated_req_success) { - _mark_req_failed(channel, progress, - "allocate block for VBD initialization"); + if (lvl == 1) + if (_num_remaining_leaves) { + node = { }; + if (!_req_ptr->_pba_alloc.alloc(node.pba)) { + _mark_req_failed(progress, "allocate pba"); break; } - channel._state = Channel::IN_PROGRESS; - - Vbd_initializer_channel::reset_node(child); - - child.pba = channel._blk_nr; - child_state = CS::DONE; - --nr_of_leaves; + node_state = DONE; + _num_remaining_leaves--; progress = true; - - if (DEBUG) - log("[vbd_init] node: ", level_index, " ", child_index, - " assign pba: ", channel._blk_nr, " leaves left: ", - nr_of_leaves); - break; - - default: + if (VERBOSE_VBD_INIT) + log("[vbd_init] node: ", lvl, " ", node_idx, " assign pba: ", node.pba, " leaves left: ", _num_remaining_leaves); + } else { + node = { }; + node_state = DONE; + progress = true; + if (VERBOSE_VBD_INIT) + log("[vbd_init] node: ", lvl, " ", node_idx, " assign pba 0, leaf unused"); + } + else { + node = { }; + if (!_req_ptr->_pba_alloc.alloc(node.pba)) { + _mark_req_failed(progress, "allocate pba"); break; } - } - default: - break; - } -} - - -void Vbd_initializer::_execute_inner_t1_child(Channel &channel, - bool &progress, - uint64_t nr_of_leaves, - uint64_t &level_to_write, - Type_1_node &child, - Vbd_initializer_channel::Type_1_level &child_level, - Vbd_initializer_channel::Child_state &child_state, - uint64_t level_index, - uint64_t child_index) - -{ - using CS = Vbd_initializer_channel::Child_state; - - switch (child_state) { - case CS::INIT_BLOCK: - - if (nr_of_leaves == 0) { - - if (DEBUG) - log("[vbd_init] node: ", level_index, " ", child_index, - " assign pba 0, inner node unused"); - - Vbd_initializer_channel::reset_node(child); - child_state = CS::DONE; - progress = true; - return; - } else { - - if (DEBUG) - log("[vbd_init] node: ", level_index, " ", child_index, - " reset level: ", level_index - 1); - - Vbd_initializer_channel::reset_level(child_level, CS::INIT_BLOCK); - child_state = CS::INIT_NODE; - progress = true; - return; + _t1_blks.items[lvl - 1].encode_to_blk(_blk); + calc_hash(_blk, node.hash); + node_state = WRITE_BLOCK; + generate_req(EXECUTE_NODES, progress, node.pba, _blk, _generated_req_success); + _state = REQ_GENERATED; + if (VERBOSE_VBD_INIT) + log("[vbd_init] node: ", lvl, " ", node_idx, " assign pba: ", node.pba); } break; - case CS::INIT_NODE: + case WRITE_BLOCK: - switch (channel._state) { - case Channel::IN_PROGRESS: - channel._state = Channel::BLOCK_ALLOC_PENDING; - progress = true; - break; - - case Channel::BLOCK_ALLOC_PENDING: - break; - - case Channel::BLOCK_ALLOC_IN_PROGRESS: - break; - - case Channel::BLOCK_ALLOC_COMPLETE: - { - /* bail early in case the allocator failed */ - if (!channel._generated_req_success) { - _mark_req_failed(channel, progress, - "allocate block for VBD initialization"); - break; - } - channel._state = Channel::IN_PROGRESS; - - Vbd_initializer_channel::reset_node(child); - child.pba = channel._blk_nr; - - Block blk { }; - child_level.children.encode_to_blk(blk); - calc_sha256_4k_hash(blk, child.hash); - - child_state = CS::WRITE_BLOCK; - progress = true; - - if (DEBUG) - log("[vbd_init] node: ", level_index, " ", child_index, - " assign pba: ", channel._blk_nr); - break; - } - default: - break; - } - break; - - case CS::WRITE_BLOCK: - - switch (channel._state) { - case Channel::IN_PROGRESS: - { - channel._state = Channel::BLOCK_IO_PENDING; - channel._child_pba = child.pba; - level_to_write = level_index - 1; - progress = true; - break; - } - - case Channel::BLOCK_IO_PENDING: - break; - - case Channel::BLOCK_IO_IN_PROGRESS: - break; - - case Channel::BLOCK_IO_COMPLETE: - /* bail early in case the allocator failed */ - if (!channel._generated_req_success) { - _mark_req_failed(channel, progress, - "write block for VBD initialization"); - break; - } - channel._state = Channel::IN_PROGRESS; - - child_state = CS::DONE; - progress = true; - - if (DEBUG) - log("[vbd_init] node: ", level_index, " ", child_index, - " write pba: ", channel._child_pba, " level: ", - level_index -1, " (child: ", child, ")"); - break; - default: - break; - } - - break; - - default: - break; - } -} - - -void Vbd_initializer::_execute(Channel &channel, - bool &progress) -{ - Request &req { channel._request }; - - /* - * First handle all child nodes (leaves and inner nodes) that starts after - * triggering the root node below. - */ - for (uint64_t level_idx = 0; level_idx <= req._max_level_idx; level_idx++) { - - for (uint64_t child_idx = 0; child_idx <= req._max_child_idx; child_idx++) { - - Vbd_initializer_channel::Child_state &state = - channel._t1_levels[level_idx].children_state[child_idx]; - - if (state != Vbd_initializer_channel::Child_state::DONE) { - - Type_1_node &child = - channel._t1_levels[level_idx].children.nodes[child_idx]; - - if (level_idx == 1) { - _execute_leaf_child(channel, progress, req._nr_of_leaves, - child, state, level_idx, child_idx); - } else { - - Vbd_initializer_channel::Type_1_level &t1_level = - channel._t1_levels[level_idx - 1]; - - _execute_inner_t1_child(channel, progress, - req._nr_of_leaves, - channel._level_to_write, - child, t1_level, state, - level_idx, child_idx); - } - return; - } - } - } - - /* - * Checking the root node will trigger the initialization process as - * well as will finish it. - */ - if (channel._root_node.state != Vbd_initializer_channel::Child_state::DONE) { - - Vbd_initializer_channel::Type_1_level &t1_level = - channel._t1_levels[req._max_level_idx]; - - _execute_inner_t1_child(channel, progress, - req._nr_of_leaves, - channel._level_to_write, - channel._root_node.node, t1_level, channel._root_node.state, - req._max_level_idx + 1, 0); - return; - } - - /* - * We will end up here when the root state is 'DONE'. - */ - if (req._nr_of_leaves == 0) - _mark_req_successful(channel, progress); - else - _mark_req_failed(channel, progress, "initialize VBD"); -} - - -void Vbd_initializer::_execute_init(Channel &channel, - bool &progress) -{ - switch (channel._state) { - case Channel::SUBMITTED: - - /* clean residual state */ - for (unsigned int i = 0; i < TREE_MAX_LEVEL; i++) { - Vbd_initializer_channel::reset_level(channel._t1_levels[i], - Vbd_initializer_channel::Child_state::DONE); - } - channel._level_to_write = 0; - - channel._state = Channel::PENDING; - channel._root_node.state = Vbd_initializer_channel::Child_state::INIT_BLOCK; + ASSERT(lvl > 1); + node_state = DONE; progress = true; - - return; - - case Channel::PENDING: - - channel._state = Channel::IN_PROGRESS; - progress = true; - return; - - case Channel::IN_PROGRESS: - - _execute(channel, progress); - return; - - case Channel::BLOCK_ALLOC_COMPLETE: - - _execute(channel, progress); - return; - - case Channel::BLOCK_IO_COMPLETE: - - _execute(channel, progress); - return; - - default: - /* - * Omit other states related to ALLOC and IO as those - * are handled via Module API. - */ - return; + if (VERBOSE_VBD_INIT) + log("[vbd_init] node: ", lvl, " ", node_idx, " write pba: ", node.pba, " level: ", lvl - 1, " (node: ", node, ")"); + break; } + return true; } -void Vbd_initializer::_mark_req_failed(Channel &channel, - bool &progress, - char const *str) +void Vbd_initializer_channel::_generated_req_completed(State_uint state_uint) { - error("request failed: failed to ", str); - channel._request._success = false; - channel._state = Channel::COMPLETE; + if (!_generated_req_success) { + error("vbd initializer: request (", *_req_ptr, ") failed because generated request failed)"); + _req_ptr->_success = false; + _state = COMPLETE; + _req_ptr = nullptr; + return; + } + _state = (State)state_uint; +} + + +void Vbd_initializer_channel::_mark_req_failed(bool &progress, char const *str) +{ + error("vbd_initializer request (", *_req_ptr, ") failed because: ", str); + _req_ptr->_success = false; + _state = COMPLETE; + _req_ptr = nullptr; progress = true; } -void Vbd_initializer::_mark_req_successful(Channel &channel, - bool &progress) +void Vbd_initializer_channel::_mark_req_successful(bool &progress) { - Request &req { channel._request }; - - memcpy(req._root_node, &channel._root_node.node, sizeof (req._root_node)); - req._success = true; - - channel._state = Channel::COMPLETE; + _req_ptr->_vbd.t1_node(_t1_blks.items[_req_ptr->_vbd.max_lvl + 1].nodes[0]); + _req_ptr->_success = true; + _state = COMPLETE; + _req_ptr = nullptr; progress = true; } -bool Vbd_initializer::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) +void Vbd_initializer_channel::_request_submitted(Module_request &mod_req) { - for (Channel &channel : _channels) { - if (channel._state == Channel::COMPLETE) { - if (sizeof(channel._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &channel._request, sizeof(channel._request)); - return true; - } - } - return false; + _req_ptr = static_cast(&mod_req); + _state = SUBMITTED; } -void Vbd_initializer::_drop_completed_request(Module_request &req) +void Vbd_initializer_channel::execute(bool &progress) { - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - if (_channels[id]._state != Channel::COMPLETE) { - class Exception_2 { }; - throw Exception_2 { }; - } - _channels[id]._state = Channel::INACTIVE; -} + if (!_req_ptr) + return; + Request &req { *_req_ptr }; + switch (_state) { + case SUBMITTED: -bool Vbd_initializer::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + _num_remaining_leaves = req._vbd.num_leaves; + for (Tree_level_index lvl = 0; lvl < TREE_MAX_LEVEL; lvl++) + _reset_level(lvl, Vbd_initializer_channel::DONE); - Channel &channel { _channels[id] }; + _node_states[req._vbd.max_lvl + 1][0] = Vbd_initializer_channel::INIT_BLOCK; + _state = EXECUTE_NODES; + progress = true; + return; - if (channel._state != Vbd_initializer_channel::State::INACTIVE) + case EXECUTE_NODES: - switch (channel._state) { - case Vbd_initializer_channel::State::BLOCK_ALLOC_PENDING: - { - Block_allocator_request::Type const block_allocator_req_type { - Block_allocator_request::GET }; + for (Tree_level_index lvl = 0; lvl <= req._vbd.max_lvl + 1; lvl++) + for (Tree_node_index node_idx = 0; node_idx < req._vbd.degree; node_idx++) + if (_execute_node(lvl, node_idx, progress)) + return; - Block_allocator_request::create( - buf_ptr, buf_size, VBD_INITIALIZER, id, - block_allocator_req_type); + if (_num_remaining_leaves) + _mark_req_failed(progress, "leaves remaining"); + else + _mark_req_successful(progress); + return; - return true; - } - case Vbd_initializer_channel::State::BLOCK_IO_PENDING: - { - Block_io_request::Type const block_io_req_type { - Block_io_request::WRITE }; - - channel._t1_levels[channel._level_to_write].children.encode_to_blk(channel._encoded_blk); - construct_in_buf( - buf_ptr, buf_size, VBD_INITIALIZER, id, - block_io_req_type, 0, 0, 0, - channel._child_pba, 0, 1, &channel._encoded_blk, nullptr); - - if (DEBUG) { - log("BLOCK_IO_PENDING write ", channel._child_pba); - Vbd_initializer_channel::dump(channel._t1_levels[channel._level_to_write].children); - } - - return true; - } - default: - break; - } - } - return false; -} - - -void Vbd_initializer::_drop_generated_request(Module_request &req) -{ - Module_request_id const id { req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Bad_id { }; - throw Bad_id { }; - } - switch (_channels[id]._state) { - case Vbd_initializer_channel::State::BLOCK_ALLOC_PENDING: - _channels[id]._state = Vbd_initializer_channel::State::BLOCK_ALLOC_IN_PROGRESS; - break; - case Vbd_initializer_channel::State::BLOCK_IO_PENDING: - _channels[id]._state = Vbd_initializer_channel::State::BLOCK_IO_IN_PROGRESS; - break; - default: - class Exception_1 { }; - throw Exception_1 { }; + default: return; } } -void Vbd_initializer::generated_request_complete(Module_request &mod_req) +void Vbd_initializer_channel::_reset_level(Tree_level_index lvl, Node_state state) { - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - switch (mod_req.dst_module_id()) { - case BLOCK_ALLOCATOR: - { - Block_allocator_request const &gen_req { *static_cast(&mod_req) }; - switch (_channels[id]._state) { - case Channel::BLOCK_ALLOC_IN_PROGRESS: - _channels[id]._state = Channel::BLOCK_ALLOC_COMPLETE; - _channels[id]._blk_nr = gen_req.blk_nr(); - _channels[id]._generated_req_success = gen_req.success(); - break; - default: - class Exception_2 { }; - throw Exception_2 { }; - } - break; - } - case BLOCK_IO: - { - Block_io_request const &gen_req { *static_cast(&mod_req) }; - switch (_channels[id]._state) { - case Channel::BLOCK_IO_IN_PROGRESS: - _channels[id]._state = Channel::BLOCK_IO_COMPLETE; - _channels[id]._generated_req_success = gen_req.success(); - break; - default: - class Exception_2 { }; - throw Exception_2 { }; - } - break; - } - default: - class Exception_2 { }; - throw Exception_2 { }; + for (unsigned int idx = 0; idx < NUM_NODES_PER_BLK; idx++) { + _t1_blks.items[lvl].nodes[idx] = { }; + _node_states[lvl][idx] = state; } } Vbd_initializer::Vbd_initializer() -{ } - - -bool Vbd_initializer::ready_to_submit_request() { - for (Channel &channel : _channels) { - if (channel._state == Channel::INACTIVE) - return true; + Module_channel_id id { 0 }; + for (Constructible &chan : _channels) { + chan.construct(id++); + add_channel(*chan); } - return false; -} - - -void Vbd_initializer::submit_request(Module_request &req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - if (_channels[id]._state == Channel::INACTIVE) { - req.dst_request_id(id); - _channels[id]._request = *static_cast(&req); - _channels[id]._state = Channel::SUBMITTED; - return; - } - } - class Invalid_call { }; - throw Invalid_call { }; } void Vbd_initializer::execute(bool &progress) { - for (Channel &channel : _channels) { - - if (channel._state == Channel::INACTIVE) - continue; - - Request &req { channel._request }; - switch (req._type) { - case Request::INIT: - - _execute_init(channel, progress); - - break; - default: - - class Exception_1 { }; - throw Exception_1 { }; - } - } + for_each_channel([&] (Channel &chan) { + chan.execute(progress); }); } diff --git a/repos/gems/src/lib/tresor/vfs_utilities.cc b/repos/gems/src/lib/tresor/vfs_utilities.cc deleted file mode 100644 index c22c73cf84..0000000000 --- a/repos/gems/src/lib/tresor/vfs_utilities.cc +++ /dev/null @@ -1,55 +0,0 @@ -/* - * \brief Utilities for a more convenient use of the VFS - * \author Martin Stein - * \date 2020-10-29 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* tresor includes */ -#include - -using namespace Genode; -using namespace Vfs; - - -/********************** - ** Global functions ** - **********************/ - -Vfs::Vfs_handle &vfs_open(Vfs::Env &vfs_env, - String<128> path, - Vfs::Directory_service::Open_mode mode) -{ - Vfs_handle *handle { nullptr }; - Directory_service::Open_result const result { - vfs_env.root_dir().open( - path.string(), mode, &handle, vfs_env.alloc()) }; - - if (result != Directory_service::Open_result::OPEN_OK) { - - error("failed to open file ", path.string()); - class Failed { }; - throw Failed { }; - } - return *handle; -} - - -Vfs_handle &vfs_open_wo(Vfs::Env &vfs_env, - String<128> path) -{ - return vfs_open(vfs_env, path, Directory_service::OPEN_MODE_WRONLY); -} - - -Vfs::Vfs_handle &vfs_open_rw(Vfs::Env &vfs_env, - String<128> path) -{ - return vfs_open(vfs_env, path, Directory_service::OPEN_MODE_RDWR); -} diff --git a/repos/gems/src/lib/tresor/virtual_block_device.cc b/repos/gems/src/lib/tresor/virtual_block_device.cc index 9ffffbe0e4..50e61f6293 100644 --- a/repos/gems/src/lib/tresor/virtual_block_device.cc +++ b/repos/gems/src/lib/tresor/virtual_block_device.cc @@ -11,2062 +11,752 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* base includes */ -#include -#include - /* tresor includes */ #include -#include +#include #include #include -#include +#include using namespace Tresor; +Virtual_block_device_request:: +Virtual_block_device_request(Module_id src_module_id, Module_channel_id src_chan_id, Type type, + Request_offset client_req_offset, Request_tag client_req_tag, + Generation last_secured_gen, Tree_root &ft, Tree_root &mt, + Tree_degree vbd_degree, Virtual_block_address vbd_highest_vba, bool rekeying, + Virtual_block_address vba, Snapshot_index curr_snap_idx, Snapshots &snapshots, + Tree_degree snap_degr, Key_id prev_key_id, Key_id curr_key_id, + Generation curr_gen, Physical_block_address &pba, bool &success, + Number_of_leaves &num_leaves, Number_of_blocks &num_pbas) +: + Module_request { src_module_id, src_chan_id, VIRTUAL_BLOCK_DEVICE }, _type { type }, _vba { vba }, + _snapshots { snapshots }, _curr_snap_idx { curr_snap_idx }, _snap_degr { snap_degr }, _curr_gen { curr_gen }, + _curr_key_id { curr_key_id }, _prev_key_id { prev_key_id }, _ft { ft }, _mt { mt }, _vbd_degree { vbd_degree }, + _vbd_highest_vba { vbd_highest_vba }, _rekeying { rekeying }, _client_req_offset { client_req_offset }, + _client_req_tag { client_req_tag }, _last_secured_gen { last_secured_gen }, _pba { pba }, + _num_pbas { num_pbas }, _num_leaves { num_leaves }, _success { success } +{ } -/********************************** - ** Virtual_block_device_request ** - **********************************/ char const *Virtual_block_device_request::type_to_string(Type op) { switch (op) { - case INVALID: return "invalid"; case READ_VBA: return "read_vba"; case WRITE_VBA: return "write_vba"; case REKEY_VBA: return "rekey_vba"; - case VBD_EXTENSION_STEP: return "vbd_extension_step"; + case EXTENSION_STEP: return "extension_step"; } - return "?"; -} - -void Virtual_block_device_request::create(void *buf_ptr, - size_t buf_size, - uint64_t src_module_id, - uint64_t src_request_id, - size_t req_type, - uint64_t client_req_offset, - uint64_t client_req_tag, - Generation last_secured_generation, - addr_t ft_root_pba_ptr, - addr_t ft_root_gen_ptr, - addr_t ft_root_hash_ptr, - uint64_t ft_max_level, - uint64_t ft_degree, - uint64_t ft_leaves, - addr_t mt_root_pba_ptr, - addr_t mt_root_gen_ptr, - addr_t mt_root_hash_ptr, - uint64_t mt_max_level, - uint64_t mt_degree, - uint64_t mt_leaves, - uint64_t vbd_degree, - uint64_t vbd_highest_vba, - bool rekeying, - Virtual_block_address vba, - Snapshot_index curr_snap_idx, - Snapshots const *snapshots_ptr, - Tree_degree snapshots_degree, - Key_id old_key_id, - Key_id new_key_id, - Generation current_gen, - Key_id key_id, - Physical_block_address first_pba, - Number_of_blocks nr_of_pbas) -{ - Virtual_block_device_request req { src_module_id, src_request_id }; - - req._type = (Type)req_type; - req._last_secured_generation = last_secured_generation; - req._ft_root_pba_ptr = (addr_t)ft_root_pba_ptr; - req._ft_root_gen_ptr = (addr_t)ft_root_gen_ptr; - req._ft_root_hash_ptr = (addr_t)ft_root_hash_ptr; - req._ft_max_level = ft_max_level; - req._ft_degree = ft_degree; - req._ft_leaves = ft_leaves; - req._mt_root_pba_ptr = (addr_t)mt_root_pba_ptr; - req._mt_root_gen_ptr = (addr_t)mt_root_gen_ptr; - req._mt_root_hash_ptr = (addr_t)mt_root_hash_ptr; - req._mt_max_level = mt_max_level; - req._mt_degree = mt_degree; - req._mt_leaves = mt_leaves; - req._vbd_degree = vbd_degree; - req._vbd_highest_vba = vbd_highest_vba; - req._rekeying = rekeying; - req._vba = vba; - req._curr_snap_idx = curr_snap_idx; - req._snapshots = *snapshots_ptr; - - switch (req_type) { - case READ_VBA: - case WRITE_VBA: - req._new_key_id = key_id; - break; - case REKEY_VBA: - req._old_key_id = old_key_id; - req._new_key_id = new_key_id; - break; - case VBD_EXTENSION_STEP: - req._pba = first_pba; - req._nr_of_pbas = nr_of_pbas; - break; - default: - class Exception_3 { }; - throw Exception_3 { }; - } - req._snapshots_degree = snapshots_degree; - req._client_req_offset = client_req_offset; - req._client_req_tag = client_req_tag; - req._curr_gen = current_gen; - - if (sizeof(req) > buf_size) { - class Exception_2 { }; - throw Exception_2 { }; - } - memcpy(buf_ptr, &req, sizeof(req)); + ASSERT_NEVER_REACHED; } -Virtual_block_device_request::Virtual_block_device_request(Module_id src_module_id, - Module_request_id src_request_id) -: - Module_request { src_module_id, src_request_id, VIRTUAL_BLOCK_DEVICE } -{ } - - -/********************************** - ** Virtual_block_device_channel ** - **********************************/ - -Snapshot &Virtual_block_device_channel::snap() +void Virtual_block_device_channel::_generated_req_completed(State_uint state_uint) { - return _request._snapshots.items[_snapshot_idx]; -} - - -/************************** - ** Virtual_block_device ** - **************************/ - -void Virtual_block_device::_set_args_for_write_back_of_t1_lvl(Tree_level_index const max_lvl, - uint64_t const t1_lvl, - uint64_t const pba, - uint64_t const prim_idx, - Channel::State &state, - bool &progress, - Channel::Generated_prim &prim) -{ - prim = { - .op = Channel::Generated_prim::Type::WRITE, - .succ = false, - .tg = Channel::Tag_type::TAG_VBD_CACHE, - .blk_nr = pba, - .idx = prim_idx - }; - - if (t1_lvl < max_lvl) { - state = Channel::State::WRITE_INNER_NODE_PENDING; - progress = true; - } else { - state = Channel::State::WRITE_ROOT_NODE_PENDING; - progress = true; - } -} - - -bool Virtual_block_device::ready_to_submit_request() -{ - for (Channel &channel : _channels) { - if (channel._request._type == Request::INVALID) - return true; - } - return false; -} - - -void Virtual_block_device::submit_request(Module_request &mod_req) -{ - for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { - Channel &chan { _channels[id] }; - if (chan._request._type == Request::INVALID) { - mod_req.dst_request_id(id); - chan._request = *static_cast(&mod_req); - chan._vba = chan._request._vba; - chan._state = Channel::SUBMITTED; - return; - } - } - class Invalid_call { }; - throw Invalid_call { }; -} - - -void Virtual_block_device::_execute_read_vba_read_inner_node_completed (Channel &channel, - uint64_t const job_idx, - bool &progress) -{ - _check_that_primitive_was_successful(channel._generated_prim); - - auto &snapshot = channel.snapshots(channel._snapshot_idx); - - _check_hash_of_read_type_1_node(channel, snapshot, - channel._request._snapshots_degree, - channel._t1_blk_idx, channel._t1_blks, - channel._vba); - - if (channel._t1_blk_idx > 1) { - - auto const parent_lvl = channel._t1_blk_idx; - auto const child_lvl = channel._t1_blk_idx - 1; - - auto const child_idx = t1_child_idx_for_vba(channel._request._vba, parent_lvl, channel._request._snapshots_degree); - auto const &child = channel._t1_blks.items[parent_lvl].nodes[child_idx]; - - channel._t1_blk_idx = child_lvl; - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_VBD_CACHE, - .blk_nr = child.pba, - .idx = job_idx - }; - if (VERBOSE_READ_VBA) - log(" ", Branch_lvl_prefix("lvl ", parent_lvl, " node ", child_idx, ": "), child); - - channel._state = Channel::State::READ_INNER_NODE_PENDING; - progress = true; - - } else { - - Tree_level_index const parent_lvl { channel._t1_blk_idx }; - Tree_node_index const child_idx { - t1_child_idx_for_vba( - channel._request._vba, parent_lvl, - channel._request._snapshots_degree) }; - - Type_1_node const &child { - channel._t1_blks.items[parent_lvl].nodes[child_idx] }; - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_VBD_BLK_IO_READ_CLIENT_DATA, - .blk_nr = child.pba, - .idx = job_idx - }; - if (VERBOSE_READ_VBA) - log(" ", Branch_lvl_prefix("lvl ", parent_lvl, " node ", child_idx, ": "), child); - - channel._state = Channel::State::READ_CLIENT_DATA_FROM_LEAF_NODE_PENDING; - progress = true; - } -} - - -void Virtual_block_device::_execute_read_vba(Channel &channel, - uint64_t const idx, - bool &progress) -{ - switch (channel._state) { - case Channel::State::SUBMITTED: - { - Request &request = channel._request; - - channel._snapshot_idx = request._curr_snap_idx; - channel._vba = request._vba; - - Snapshot &snapshot = channel.snapshots(channel._snapshot_idx); - channel._t1_blk_idx = snapshot.max_level; - - channel._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_VBD_CACHE, - .blk_nr = snapshot.pba, - .idx = idx - }; - if (VERBOSE_READ_VBA) { - log(" load branch:"); - log(" ", Branch_lvl_prefix("root: "), snapshot); - } - channel._state = Channel::State::READ_ROOT_NODE_PENDING; - progress = true; - break; - } - case Channel::State::READ_ROOT_NODE_COMPLETED: - - _execute_read_vba_read_inner_node_completed (channel, idx, progress); - break; - - case Channel::State::READ_INNER_NODE_COMPLETED: - - _execute_read_vba_read_inner_node_completed (channel, idx, progress); - break; - - case Channel::State::READ_CLIENT_DATA_FROM_LEAF_NODE_COMPLETED: - - _check_that_primitive_was_successful(channel._generated_prim); - channel._request._success = channel._generated_prim.succ; - channel._state = Channel::State::COMPLETED; - progress = true; - break; - default: - break; - } -} - - -void Virtual_block_device::_update_nodes_of_branch_of_written_vba(Snapshot &snapshot, - uint64_t const snapshot_degree, - uint64_t const vba, - Tree_walk_pbas const &new_pbas, - Hash const & leaf_hash, - uint64_t curr_gen, - Channel::Type_1_node_blocks &t1_blks) -{ - for (Tree_level_index lvl = 0; lvl <= snapshot.max_level; lvl++) { - - if (lvl == 0) { - - auto const child_idx = t1_child_idx_for_vba(vba, lvl + 1, snapshot_degree); - auto &node = t1_blks.items[lvl + 1].nodes[child_idx]; - - node.pba = new_pbas.pbas[lvl]; - node.gen = curr_gen; - node.hash = leaf_hash; - - if (VERBOSE_WRITE_VBA) - log(" ", Branch_lvl_prefix("lvl ", lvl + 1, " node ", child_idx, ": "), node); - - } else if (lvl < snapshot.max_level) { - - auto const child_idx = t1_child_idx_for_vba(vba, lvl + 1, snapshot_degree); - auto &node = t1_blks.items[lvl + 1].nodes[child_idx]; - - node.pba = new_pbas.pbas[lvl]; - node.gen = curr_gen; - - Block blk { }; - t1_blks.items[lvl].encode_to_blk(blk); - calc_sha256_4k_hash(blk, node.hash); - - if (VERBOSE_WRITE_VBA) - log(" ", Branch_lvl_prefix("lvl ", lvl + 1, " node ", child_idx, ": "), node); - - } else { - - snapshot.pba = new_pbas.pbas[lvl]; - snapshot.gen = curr_gen; - - Block blk { }; - t1_blks.items[lvl].encode_to_blk(blk); - calc_sha256_4k_hash(blk, snapshot.hash); - - if (VERBOSE_WRITE_VBA) - log(" ", Branch_lvl_prefix("root: "), snapshot); - } - } -} - - -void Virtual_block_device:: -_set_args_in_order_to_write_client_data_to_leaf_node(Tree_walk_pbas const &new_pbas, - uint64_t const job_idx, - Channel::State &state, - Channel::Generated_prim &prim, - bool &progress) -{ - prim = { - .op = Channel::Generated_prim::Type::WRITE, - .succ = false, - .tg = Channel::Tag_type::TAG_VBD_BLK_IO_WRITE_CLIENT_DATA, - .blk_nr = new_pbas.pbas[0], - .idx = job_idx - }; - - state = Channel::State::WRITE_CLIENT_DATA_TO_LEAF_NODE_PENDING; - progress = true; -} - - -void Virtual_block_device:: -_check_that_primitive_was_successful(Channel::Generated_prim const &prim) -{ - if (prim.succ) + if (!_gen_req_success) { + error("virtual block device: request (", *_req_ptr, ") failed because generated request failed)"); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; return; - - class Primitive_not_successfull { }; - throw Primitive_not_successfull { }; -} - - -void Virtual_block_device::_check_hash_of_read_type_1_node(Channel &chan, - Snapshot const &snapshot, - uint64_t const snapshots_degree, - uint64_t const t1_blk_idx, - Channel::Type_1_node_blocks const &t1_blks, - uint64_t const vba) -{ - if (t1_blk_idx == snapshot.max_level) { - if (!check_sha256_4k_hash(chan._encoded_blk, snapshot.hash)) { - class Program_error_hash_of_read_type_1 { }; - throw Program_error_hash_of_read_type_1 { }; - } - } else { - uint64_t const child_idx = t1_child_idx_for_vba(vba, t1_blk_idx + 1, snapshots_degree); - Type_1_node const &child = t1_blks.items[t1_blk_idx + 1].nodes[child_idx]; - if (!check_sha256_4k_hash(chan._encoded_blk, child.hash)) { - class Program_error_hash_of_read_type_1_B { }; - throw Program_error_hash_of_read_type_1_B { }; - } } + _state = (State)state_uint; } -void Virtual_block_device::_set_args_in_order_to_read_type_1_node(Snapshot const &snapshot, - uint64_t const snapshots_degree, - uint64_t const t1_blk_idx, - Channel::Type_1_node_blocks const &t1_blks, - uint64_t const vba, - uint64_t const job_idx, - Channel::State &state, - Channel::Generated_prim &prim, - bool &progress) +void Virtual_block_device_channel::_generate_write_blk_req(bool &progress) { - if (t1_blk_idx == snapshot.max_level) { - prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_VBD_CACHE, - .blk_nr = snapshot.pba, - .idx = job_idx - }; - } else { - auto const child_idx = t1_child_idx_for_vba(vba, t1_blk_idx + 1, snapshots_degree); - auto const &child = t1_blks.items[t1_blk_idx + 1].nodes[child_idx]; - - prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_VBD_CACHE, - .blk_nr = child.pba, - .idx = job_idx - }; - } - - state = Channel::State::READ_INNER_NODE_PENDING; - progress = true; + if (_lvl) { + _t1_blks.items[_lvl].encode_to_blk(_encoded_blk); + _generate_req(WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _encoded_blk); + } else + _generate_req(WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _data_blk); } -void Virtual_block_device:: -_initialize_new_pbas_and_determine_nr_of_pbas_to_allocate(uint64_t const curr_gen, - Snapshot const &snapshot, - uint64_t const snapshots_degree, - uint64_t const vba, - Channel::Type_1_node_blocks const &t1_blks, - Tree_walk_pbas &new_pbas, - uint64_t &nr_of_blks) +void Virtual_block_device_channel::_read_vba(bool &progress) { - nr_of_blks = 0; - for (Tree_level_index lvl = 0; lvl <= TREE_MAX_LEVEL; lvl++) { + Request &req { *_req_ptr }; + switch (_state) { + case SUBMITTED: - if (lvl > snapshot.max_level) { + _snap_idx = req._curr_snap_idx; + _vba = req._vba; + _lvl = snap().max_level; + _generate_req(READ_BLK_SUCCEEDED, progress, snap().pba, _encoded_blk); + if (VERBOSE_READ_VBA) + log(" load branch:\n ", Branch_lvl_prefix("root: "), snap()); + break; - new_pbas.pbas[lvl] = 0; + case READ_BLK_SUCCEEDED: + { + if (!_check_and_decode_read_blk(progress, false)) + break; - } else if (lvl == snapshot.max_level) { - - if (snapshot.gen < curr_gen) { - - nr_of_blks++; - new_pbas.pbas[lvl] = 0; - - } else if (snapshot.gen == curr_gen) { - - new_pbas.pbas[lvl] = snapshot.pba; - - } else { - - class Exception_1 { }; - throw Exception_1 { }; - } - } else { - - Tree_node_index const child_idx { - t1_child_idx_for_vba(vba, lvl + 1, snapshots_degree) }; - - Type_1_node const &child { - t1_blks.items[lvl + 1].nodes[child_idx] }; - - if (child.gen < curr_gen) { - - if (lvl == 0 && child.gen == INVALID_GENERATION) { - - new_pbas.pbas[lvl] = child.pba; - - } else { - - nr_of_blks++; - new_pbas.pbas[lvl] = 0; - } - } else if (child.gen == curr_gen) { - - new_pbas.pbas[lvl] = child.pba; - - } else { - - class Exception_2 { }; - throw Exception_2 { }; - } + if (!_lvl) { + _mark_req_successful(progress); + break; } - } -} - - -void Virtual_block_device:: -_set_args_for_alloc_of_new_pbas_for_branch_of_written_vba(uint64_t curr_gen, - Snapshot const &snapshot, - uint64_t const snapshots_degree, - uint64_t const vba, - Channel::Type_1_node_blocks const &t1_blks, - uint64_t const prim_idx, - uint64_t &free_gen, - Type_1_node_walk &t1_walk, - Channel::State &state, - Channel::Generated_prim &prim, - bool &progress) -{ - for (Tree_level_index lvl = 0; lvl <= TREE_MAX_LEVEL; lvl++) { - if (lvl > snapshot.max_level) { - t1_walk.nodes[lvl] = Type_1_node { }; /* invalid */ - } else if (lvl == snapshot.max_level) { - auto &node = t1_walk.nodes[lvl]; - - node.pba = snapshot.pba; - node.gen = snapshot.gen; - node.hash = snapshot.hash; - } else { - auto const child_idx = t1_child_idx_for_vba(vba, lvl + 1, snapshots_degree); - t1_walk.nodes[lvl] = t1_blks.items[lvl + 1].nodes[child_idx]; - } - } - - free_gen = curr_gen; - - prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_VBD_FT_ALLOC_FOR_NON_RKG, - .blk_nr = 0, - .idx = prim_idx - }; - - state = Channel::State::ALLOC_PBAS_AT_LEAF_LVL_PENDING; - progress = true; -} - - -void Virtual_block_device::_execute_write_vba(Channel &chan, - uint64_t const job_idx, - bool &progress) -{ - Request &req { chan._request }; - switch (chan._state) { - case Channel::State::SUBMITTED: { - Request &request { chan._request }; - - chan._snapshot_idx = request._curr_snap_idx; - chan._vba = request._vba; - chan._t1_blk_idx = chan.snapshots(chan._snapshot_idx).max_level; - - if (VERBOSE_WRITE_VBA) { - log(" load branch:"); - log(" ", Branch_lvl_prefix("root: "), chan.snapshots(chan._snapshot_idx)); - } - _set_args_in_order_to_read_type_1_node(chan.snapshots(chan._snapshot_idx), - chan._request._snapshots_degree, - chan._t1_blk_idx, - chan._t1_blks, - chan._vba, - job_idx, - chan._state, - chan._generated_prim, - progress); + Type_1_node &node { _node(_lvl, req._vba) }; + if (VERBOSE_READ_VBA) + log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", _node_idx(_lvl, req._vba), ": "), node); + if (_lvl > 1) + _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _encoded_blk); + else + if (node.gen == INITIAL_GENERATION) { + memset(&_data_blk, 0, BLOCK_SIZE); + _generate_req( + READ_BLK_SUCCEEDED, progress, Client_data_request::SUPPLY_PLAINTEXT_BLK, + req._client_req_offset, req._client_req_tag, node.pba, _vba, _data_blk); + } else + _generate_req( + READ_BLK_SUCCEEDED, progress, node.pba, _vba, req._curr_key_id, + req._client_req_tag, req._client_req_offset, _data_blk); + _lvl--; break; } - case Channel::State::READ_INNER_NODE_COMPLETED: - - _check_that_primitive_was_successful(chan._generated_prim); - _check_hash_of_read_type_1_node(chan, chan.snapshots(chan._snapshot_idx), - chan._request._snapshots_degree, - chan._t1_blk_idx, chan._t1_blks, - chan._vba); - - if (VERBOSE_WRITE_VBA) { - uint64_t const child_idx { t1_child_idx_for_vba(chan._vba, chan._t1_blk_idx, chan._request._snapshots_degree) }; - Type_1_node const &child { chan._t1_blks.items[chan._t1_blk_idx].nodes[child_idx] }; - log(" ", Branch_lvl_prefix("lvl ", chan._t1_blk_idx, " node ", child_idx, ": "), child); - } - if (chan._t1_blk_idx > 1) { - chan._t1_blk_idx = chan._t1_blk_idx - 1; - - _set_args_in_order_to_read_type_1_node(chan.snapshots(chan._snapshot_idx), - chan._request._snapshots_degree, - chan._t1_blk_idx, - chan._t1_blks, - chan._vba, - job_idx, - chan._state, - chan._generated_prim, - progress); - - } else { - _initialize_new_pbas_and_determine_nr_of_pbas_to_allocate(req._curr_gen, - chan.snapshots(chan._snapshot_idx), - chan._request._snapshots_degree, - chan._vba, - chan._t1_blks, - chan._new_pbas, - chan._nr_of_blks); - - if (chan._nr_of_blks > 0) { - _set_args_for_alloc_of_new_pbas_for_branch_of_written_vba(req._curr_gen, - chan.snapshots(chan._snapshot_idx), - chan._request._snapshots_degree, - chan._vba, - chan._t1_blks, - job_idx, - chan._free_gen, - chan._t1_node_walk, - chan._state, - chan._generated_prim, - progress); - - } else { - - _set_args_in_order_to_write_client_data_to_leaf_node(chan._new_pbas, - job_idx, - chan._state, - chan._generated_prim, - progress); - } - } - - break; - case Channel::State::ALLOC_PBAS_AT_LEAF_LVL_COMPLETED: - - _check_that_primitive_was_successful(chan._generated_prim); - - if (VERBOSE_WRITE_VBA) - log(" alloc pba", chan._nr_of_blks > 1 ? "s" : "", ": ", Pba_allocation(chan._t1_node_walk, chan._new_pbas)); - - _set_args_in_order_to_write_client_data_to_leaf_node(chan._new_pbas, - job_idx, - chan._state, - chan._generated_prim, - progress); - - break; - - case Channel::State::WRITE_CLIENT_DATA_TO_LEAF_NODE_COMPLETED: - - _check_that_primitive_was_successful(chan._generated_prim); - _update_nodes_of_branch_of_written_vba( - chan.snapshots(chan._snapshot_idx), - chan._request._snapshots_degree, chan._vba, - chan._new_pbas, chan._hash, req._curr_gen, chan._t1_blks); - - _set_args_for_write_back_of_t1_lvl( - chan.snapshots(chan._snapshot_idx).max_level, chan._t1_blk_idx, - chan._new_pbas.pbas[chan._t1_blk_idx], job_idx, chan._state, - progress, chan._generated_prim); - - break; - - case Channel::State::WRITE_INNER_NODE_COMPLETED: - - _check_that_primitive_was_successful(chan._generated_prim); - chan._t1_blk_idx = chan._t1_blk_idx + 1; - - _set_args_for_write_back_of_t1_lvl( - chan.snapshots(chan._snapshot_idx).max_level, - chan._t1_blk_idx, chan._new_pbas.pbas[chan._t1_blk_idx], - job_idx, chan._state, progress, chan._generated_prim); - - break; - case Channel::State::WRITE_ROOT_NODE_COMPLETED: - - _check_that_primitive_was_successful(chan._generated_prim); - chan._state = Channel::State::COMPLETED; - chan._request._success = true; - progress = true; - break; - - default: - break; - } -} - - -void Virtual_block_device::_mark_req_failed(Channel &chan, - bool &progress, - char const *str) -{ - error(chan._request.type_name(), " request failed at step \"", str, "\""); - chan._request._success = false; - chan._state = Channel::COMPLETED; - progress = true; -} - - -void Virtual_block_device::_mark_req_successful(Channel &chan, - bool &progress) -{ - chan._request._success = true; - chan._state = Channel::COMPLETED; - progress = true; -} - - -char const *Virtual_block_device::_state_to_step_label(Channel::State state) -{ - switch (state) { - case Channel::READ_ROOT_NODE_COMPLETED: return "read root node"; - case Channel::READ_INNER_NODE_COMPLETED: return "read inner node"; - case Channel::READ_LEAF_NODE_COMPLETED: return "read leaf node"; - case Channel::READ_CLIENT_DATA_FROM_LEAF_NODE_COMPLETED: return "read client data from leaf node"; - case Channel::WRITE_CLIENT_DATA_TO_LEAF_NODE_COMPLETED: return "write client data to leaf node"; - case Channel::DECRYPT_LEAF_NODE_COMPLETED: return "decrypt leaf node"; - case Channel::ALLOC_PBAS_AT_LEAF_LVL_COMPLETED: return "alloc pbas at leaf lvl"; - case Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_COMPLETED: return "alloc pbas at lowest inner lvl"; - case Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_COMPLETED: return "alloc pbas at higher inner lvl"; - case Channel::ENCRYPT_LEAF_NODE_COMPLETED: return "encrypt leaf node"; - case Channel::WRITE_LEAF_NODE_COMPLETED: return "write leaf node"; - case Channel::WRITE_INNER_NODE_COMPLETED: return "write inner node"; - case Channel::WRITE_ROOT_NODE_COMPLETED: return "write root node"; default: break; } - return "?"; } -bool Virtual_block_device::_handle_failed_generated_req(Channel &chan, - bool &progress) +void Virtual_block_device_channel::_update_nodes_of_branch_of_written_vba() { - if (chan._generated_prim.succ) - return false; + Request &req { *_req_ptr }; + Type_1_node &node { _node(1, _vba) }; + node = Type_1_node { _new_pbas.pbas[0], req._curr_gen, _hash }; + if (VERBOSE_WRITE_VBA) + log(" ", Branch_lvl_prefix("lvl 1 node ", _node_idx(1, _vba), ": "), node); + + for (Tree_level_index lvl = 1; lvl < snap().max_level; lvl++) { + Type_1_node &node { _node(lvl + 1, _vba) }; + node.pba = _new_pbas.pbas[lvl]; + node.gen = req._curr_gen; + _t1_blks.items[lvl].encode_to_blk(_encoded_blk); + calc_hash(_encoded_blk, node.hash); + if (VERBOSE_WRITE_VBA) + log(" ", Branch_lvl_prefix("lvl ", lvl + 1, " node ", _node_idx(lvl + 1, _vba), ": "), node); + } + snap().pba = _new_pbas.pbas[snap().max_level]; + snap().gen = req._curr_gen; + _t1_blks.items[snap().max_level].encode_to_blk(_encoded_blk); + calc_hash(_encoded_blk, snap().hash); + if (VERBOSE_WRITE_VBA) + log(" ", Branch_lvl_prefix("root: "), snap()); +} + + +bool Virtual_block_device_channel::_check_and_decode_read_blk(bool &progress, bool check_leaf_data = true) +{ + if (!check_leaf_data && !_lvl) + return true; + + Hash &hash { _lvl < snap().max_level ? _node(_lvl + 1, _vba).hash : snap().hash }; + if (!check_hash(_lvl ? _encoded_blk : _data_blk, hash)) { + _mark_req_failed(progress, "check hash of read block"); + return false; + } + if (_lvl) + _t1_blks.items[_lvl].decode_from_blk(_encoded_blk); - _mark_req_failed(chan, progress, _state_to_step_label(chan._state)); return true; } -bool -Virtual_block_device::_find_next_snap_to_rekey_vba_at(Channel const &chan, - Snapshot_index &next_snap_idx) +Tree_node_index Virtual_block_device_channel::_node_idx(Tree_level_index lvl, Virtual_block_address vba) const { - bool next_snap_idx_valid { false }; - Request const &req { chan._request }; - Snapshot const &old_snap { req._snapshots.items[chan._snapshot_idx] }; + return t1_node_idx_for_vba(vba, lvl, _req_ptr->_snap_degr); +} - for (Snapshot_index snap_idx { 0 }; - snap_idx < MAX_NR_OF_SNAPSHOTS; - snap_idx++) { - Snapshot const &snap { req._snapshots.items[snap_idx] }; - if (snap.valid && snap.contains_vba(req._vba)) { +Type_1_node &Virtual_block_device_channel::_node(Tree_level_index lvl, Virtual_block_address vba) +{ + return _t1_blks.items[lvl].nodes[_node_idx(lvl, vba)]; +} - if (next_snap_idx_valid) { - Snapshot const &next_snap { req._snapshots.items[next_snap_idx] }; - if (snap.gen > next_snap.gen && - snap.gen < old_snap.gen) - next_snap_idx = snap_idx; - - } else { - - if (snap.gen < old_snap.gen) { - - next_snap_idx = snap_idx; - next_snap_idx_valid = true; +void Virtual_block_device_channel::_set_new_pbas_and_num_blks_for_alloc() +{ + Request &req { *_req_ptr }; + _num_blks = 0; + for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) { + if (lvl > snap().max_level) + _new_pbas.pbas[lvl] = 0; + else if (lvl == snap().max_level) { + if (snap().gen < req._curr_gen) { + _num_blks++; + _new_pbas.pbas[lvl] = 0; + } else if (snap().gen == req._curr_gen) + _new_pbas.pbas[lvl] = snap().pba; + else + ASSERT_NEVER_REACHED; + } else { + Type_1_node const &node { _node(lvl + 1, _vba) }; + if (node.gen < req._curr_gen) { + if (lvl == 0 && node.gen == INVALID_GENERATION) + _new_pbas.pbas[lvl] = node.pba; + else { + _num_blks++; + _new_pbas.pbas[lvl] = 0; } - } + } else if (node.gen == req._curr_gen) + _new_pbas.pbas[lvl] = node.pba; + else + ASSERT_NEVER_REACHED; } } - return next_snap_idx_valid; -} - - -void Virtual_block_device:: -_set_args_for_alloc_of_new_pbas_for_rekeying(Channel &chan, - uint64_t chan_idx, - Tree_level_index min_lvl) -{ - bool const for_curr_gen_blks { chan._first_snapshot }; - Generation const curr_gen { chan._request._curr_gen }; - Snapshot const &snap { chan._request._snapshots.items[chan._snapshot_idx] }; - Tree_degree const snap_degree { chan._request._snapshots_degree }; - Virtual_block_address const vba { chan._request._vba }; - Type_1_node_blocks const &t1_blks { chan._t1_blks }; - Type_1_node_walk &t1_walk { chan._t1_node_walk }; - Tree_walk_pbas &new_pbas { chan._new_pbas }; - - if (min_lvl > snap.max_level) { - class Exception_1 { }; - throw Exception_1 { }; - } - chan._nr_of_blks = 0; - - if (for_curr_gen_blks) - chan._free_gen = curr_gen; - else - chan._free_gen = snap.gen + 1; - - for (Tree_level_index lvl = 0; lvl <= TREE_MAX_LEVEL; lvl++) { - - if (lvl > snap.max_level) { - - t1_walk.nodes[lvl] = { }; - new_pbas.pbas[lvl] = 0; - - } else if (lvl == snap.max_level) { - - chan._nr_of_blks++; - new_pbas.pbas[lvl] = 0; - t1_walk.nodes[lvl] = { snap.pba, snap.gen, snap.hash }; - - } else if (lvl >= min_lvl) { - - chan._nr_of_blks++; - new_pbas.pbas[lvl] = 0; - Tree_node_index const child_idx { - t1_child_idx_for_vba(vba, lvl + 1, snap_degree) }; - - t1_walk.nodes[lvl] = t1_blks.items[lvl + 1].nodes[child_idx]; - - } else { - - Tree_node_index const child_idx { - t1_child_idx_for_vba(vba, lvl + 1, snap_degree) }; - - Type_1_node const &child { t1_blks.items[lvl + 1].nodes[child_idx] }; - t1_walk.nodes[lvl] = { new_pbas.pbas[lvl], child.gen, child.hash}; - } - } - if (for_curr_gen_blks) { - - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_VBD_FT_ALLOC_FOR_RKG_CURR_GEN_BLKS, - .blk_nr = 0, - .idx = chan_idx - }; - - } else { - - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_VBD_FT_ALLOC_FOR_RKG_OLD_GEN_BLKS, - .blk_nr = 0, - .idx = chan_idx - }; - } } -void Virtual_block_device_channel::_log_rekeying_pba_alloc() const +void Virtual_block_device_channel::_generate_ft_alloc_req_for_write_vba(bool &progress) { - if (VERBOSE_REKEYING) - log(" alloc pba", _nr_of_blks > 1 ? "s" : "", ": ", Pba_allocation { _t1_node_walk, _new_pbas }); -} - - -void Virtual_block_device::_execute_rekey_vba(Channel &chan, - uint64_t chan_idx, - bool &progress) -{ - Request &req { chan._request }; - switch (chan._state) { - case Channel::State::SUBMITTED: - { - Snapshot_index first_snap_idx { 0 }; - bool first_snap_idx_found { false }; - for (Snapshot_index snap_idx { 0 }; - snap_idx < MAX_NR_OF_SNAPSHOTS; - snap_idx++) { - - Snapshot const &snap { req._snapshots.items[snap_idx] }; - Snapshot const &first_snap { req._snapshots.items[first_snap_idx] }; - if (snap.valid && - (!first_snap_idx_found || snap.gen > first_snap.gen)) { - - first_snap_idx = snap_idx; - first_snap_idx_found = true; - } - } - if (!first_snap_idx_found) { - - class Exception_1 { }; - throw Exception_1 { }; - } - chan._snapshot_idx = first_snap_idx; - chan._first_snapshot = true; - - Snapshot const &snap { req._snapshots.items[chan._snapshot_idx] }; - chan._t1_blk_idx = snap.max_level; - chan._t1_blks_old_pbas.items[chan._t1_blk_idx] = snap.pba; - - if (VERBOSE_REKEYING) { - log(" snapshot ", chan._snapshot_idx, ":"); - log(" load branch:"); - log(" ", Branch_lvl_prefix("root: "), snap); - } - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_VBD_CACHE, - .blk_nr = snap.pba, - .idx = chan_idx - }; - chan._state = Channel::READ_ROOT_NODE_PENDING; - progress = true; - - break; - } - case Channel::READ_ROOT_NODE_COMPLETED: - case Channel::READ_INNER_NODE_COMPLETED: - { - if (_handle_failed_generated_req(chan, progress)) - break; - - Snapshot const &snap { req._snapshots.items[chan._snapshot_idx] }; - if (chan._t1_blk_idx == snap.max_level) { - - if (!check_sha256_4k_hash(chan._encoded_blk, snap.hash)) { - - _mark_req_failed(chan, progress, "check root node hash"); - break; - } - - } else { - - Tree_level_index const parent_lvl { chan._t1_blk_idx + 1 }; - Tree_node_index const child_idx { - t1_child_idx_for_vba(req._vba, parent_lvl, req._snapshots_degree) }; - - if (!check_sha256_4k_hash(chan._encoded_blk, - chan._t1_blks.items[parent_lvl].nodes[child_idx].hash)) { - - _mark_req_failed(chan, progress, "check inner node hash"); - break; - } - } - if (chan._t1_blk_idx > 1) { - - Tree_level_index const parent_lvl { chan._t1_blk_idx }; - Tree_level_index const child_lvl { parent_lvl - 1 }; - Tree_node_index const child_idx { - t1_child_idx_for_vba(req._vba, parent_lvl, req._snapshots_degree) }; - - Type_1_node const &child { chan._t1_blks.items[parent_lvl].nodes[child_idx] }; - - if (VERBOSE_REKEYING) - log(" ", Branch_lvl_prefix("lvl ", parent_lvl, " node ", child_idx, ": "), child); - - if (!chan._first_snapshot && - chan._t1_blks_old_pbas.items[child_lvl] == child.pba) { - - /* - * The rest of this branch has already been rekeyed while - * rekeying the vba at another snapshot and can therefore be - * skipped. - */ - chan._t1_blk_idx = child_lvl; - _set_args_for_alloc_of_new_pbas_for_rekeying(chan, chan_idx, parent_lvl); - chan._state = Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_PENDING; - - if (VERBOSE_REKEYING) - log(" [child already rekeyed at pba ", chan._new_pbas.pbas[child_lvl], "]"); - - progress = true; - - } else { - - chan._t1_blk_idx = child_lvl; - chan._t1_blks_old_pbas.items[child_lvl] = child.pba; - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_VBD_CACHE, - .blk_nr = child.pba, - .idx = chan_idx - }; - chan._state = Channel::READ_INNER_NODE_PENDING; - progress = true; - } - - } else { - - Tree_level_index const parent_lvl { chan._t1_blk_idx }; - Tree_node_index const child_idx { - t1_child_idx_for_vba(req._vba, parent_lvl, req._snapshots_degree) }; - - Type_1_node const &child { chan._t1_blks.items[parent_lvl].nodes[child_idx] }; - - if (VERBOSE_REKEYING) - log(" ", Branch_lvl_prefix("lvl ", parent_lvl, " node ", child_idx, ": "), child); - - if (!chan._first_snapshot - && chan._data_blk_old_pba == child.pba) { - - /* - * The leaf node of this branch has already been rekeyed while - * rekeying the vba at another snapshot and can therefore be - * skipped. - */ - _set_args_for_alloc_of_new_pbas_for_rekeying( - chan, chan_idx, parent_lvl); - - if (VERBOSE_REKEYING) - log(" [child already rekeyed at pba ", chan._new_pbas.pbas[0], "]"); - - chan._state = Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_PENDING; - progress = true; - - } else if (child.gen == INITIAL_GENERATION) { - - /* - * The leaf node of this branch is still unused and can - * therefore be skipped because the driver will yield all - * zeroes for it regardless of the used key. - */ - _set_args_for_alloc_of_new_pbas_for_rekeying(chan, chan_idx, 0); - - if (VERBOSE_REKEYING) - log(" [child needs no rekeying]"); - - chan._state = Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_PENDING; - progress = true; - - } else { - - chan._data_blk_old_pba = child.pba; - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_VBD_BLK_IO, - .blk_nr = child.pba, - .idx = chan_idx - }; - chan._state = Channel::READ_LEAF_NODE_PENDING; - progress = true; - } - } - break; - } - case Channel::READ_LEAF_NODE_COMPLETED: - { - if (_handle_failed_generated_req(chan, progress)) - break; - - Tree_level_index const parent_lvl { FIRST_T1_NODE_BLKS_IDX }; - Tree_node_index const child_idx { - t1_child_idx_for_vba(req._vba, parent_lvl, req._snapshots_degree) }; - - Type_1_node &node { - chan._t1_blks.items[parent_lvl].nodes[child_idx] }; - - if (!check_sha256_4k_hash(chan._data_blk, node.hash)) { - - _mark_req_failed(chan, progress, "check leaf node hash"); - break; - } - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_VBD_CRYPTO_DECRYPT, - .blk_nr = chan._data_blk_old_pba, - .idx = chan_idx - }; - chan._state = Channel::DECRYPT_LEAF_NODE_PENDING; - progress = true; - - if (VERBOSE_REKEYING) - log(" ", Branch_lvl_prefix("leaf data: "), chan._data_blk); - - break; - } - case Channel::DECRYPT_LEAF_NODE_COMPLETED: - - if (_handle_failed_generated_req(chan, progress)) - break; - - _set_args_for_alloc_of_new_pbas_for_rekeying(chan, chan_idx, 0); - chan._state = Channel::ALLOC_PBAS_AT_LEAF_LVL_PENDING; - - if (VERBOSE_REKEYING) { - Hash hash { }; - calc_sha256_4k_hash(chan._data_blk, hash); - log(" re-encrypt leaf data: plaintext ", chan._data_blk, " hash ", hash); - } - progress = true; - break; - - case Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_COMPLETED: - - if (_handle_failed_generated_req(chan, progress)) - break; - - chan._log_rekeying_pba_alloc(); - - if (VERBOSE_REKEYING) - log(" update branch:"); - - chan._state = Channel::WRITE_LEAF_NODE_COMPLETED; - progress = true; - break; - - case Channel::ALLOC_PBAS_AT_LEAF_LVL_COMPLETED: - - if (_handle_failed_generated_req(chan, progress)) - break; - - chan._log_rekeying_pba_alloc(); - chan._generated_prim = { - .op = Generated_prim::WRITE, - .succ = false, - .tg = Channel::TAG_VBD_CRYPTO_ENCRYPT, - .blk_nr = chan._new_pbas.pbas[0], - .idx = chan_idx - }; - chan._state = Channel::ENCRYPT_LEAF_NODE_PENDING; - progress = true; - break; - - case Channel::ENCRYPT_LEAF_NODE_COMPLETED: - { - if (_handle_failed_generated_req(chan, progress)) - break; - - Tree_level_index const child_lvl { 0 }; - Physical_block_address const child_pba { - chan._new_pbas.pbas[child_lvl] }; - - chan._generated_prim = { - .op = Generated_prim::WRITE, - .succ = false, - .tg = Channel::TAG_VBD_BLK_IO, - .blk_nr = child_pba, - .idx = chan_idx - }; - chan._state = Channel::WRITE_LEAF_NODE_PENDING; - progress = true; - - if (VERBOSE_REKEYING) { - log(" update branch:"); - log(" ", Branch_lvl_prefix("leaf data: "), chan._data_blk); - } - break; - } - case Channel::WRITE_LEAF_NODE_COMPLETED: - { - if (_handle_failed_generated_req(chan, progress)) - break; - - Tree_level_index const parent_lvl { 1 }; - Tree_level_index const child_lvl { 0 }; - Physical_block_address const child_pba { chan._new_pbas.pbas[child_lvl] }; - Physical_block_address const parent_pba { chan._new_pbas.pbas[parent_lvl] }; - Tree_node_index const child_idx { - t1_child_idx_for_vba(req._vba, parent_lvl, req._snapshots_degree) }; - - Type_1_node &node { chan._t1_blks.items[parent_lvl].nodes[child_idx] }; - node.pba = child_pba; - calc_sha256_4k_hash(chan._data_blk, node.hash); - - if (VERBOSE_REKEYING) - log(" ", Branch_lvl_prefix("lvl ", parent_lvl, " node ", child_idx, ": "), node); - - chan._generated_prim = { - .op = Generated_prim::WRITE, - .succ = false, - .tg = Channel::TAG_VBD_CACHE, - .blk_nr = parent_pba, - .idx = chan_idx - }; - chan._state = Channel::WRITE_INNER_NODE_PENDING; - progress = true; - break; - } - case Channel::WRITE_INNER_NODE_COMPLETED: - { - if (_handle_failed_generated_req(chan, progress)) - break; - - Snapshot const &snap { req._snapshots.items[chan._snapshot_idx] }; - Tree_level_index const parent_lvl { chan._t1_blk_idx + 1 }; - Tree_level_index const child_lvl { chan._t1_blk_idx }; - Physical_block_address const child_pba { chan._new_pbas.pbas[child_lvl] }; - Physical_block_address const parent_pba { chan._new_pbas.pbas[parent_lvl] }; - Tree_node_index const child_idx { - t1_child_idx_for_vba(req._vba, parent_lvl, req._snapshots_degree) };; - - Type_1_node &node { chan._t1_blks.items[parent_lvl].nodes[child_idx] }; - node.pba = child_pba; - calc_sha256_4k_hash(chan._encoded_blk, node.hash); - - if (VERBOSE_REKEYING) - log(" ", Branch_lvl_prefix("lvl ", parent_lvl, " node ", child_idx, ": "), node); - - chan._t1_blk_idx++; - chan._generated_prim = { - .op = Generated_prim::WRITE, - .succ = false, - .tg = Channel::TAG_VBD_CACHE, - .blk_nr = parent_pba, - .idx = chan_idx - }; - if (chan._t1_blk_idx < snap.max_level) - chan._state = Channel::WRITE_INNER_NODE_PENDING; + for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) + if (lvl > snap().max_level) + _t1_nodes.nodes[lvl] = Type_1_node { }; + else if (lvl == snap().max_level) + _t1_nodes.nodes[lvl] = Type_1_node { snap().pba, snap().gen, snap().hash }; else - chan._state = Channel::WRITE_ROOT_NODE_PENDING; + _t1_nodes.nodes[lvl] = _node(lvl + 1, _vba); - progress = true; + _free_gen = _req_ptr->_curr_gen; + _generate_ft_req(ALLOC_PBAS_SUCCEEDED, progress, Free_tree_request::ALLOC_FOR_NON_RKG); +} + + +void Virtual_block_device_channel::_write_vba(bool &progress) +{ + Request &req { *_req_ptr }; + switch (_state) { + case SUBMITTED: + + _snap_idx = req._curr_snap_idx; + _vba = req._vba; + _lvl = snap().max_level; + _generate_req(READ_BLK_SUCCEEDED, progress, snap().pba, _encoded_blk); + if (VERBOSE_WRITE_VBA) + log(" load branch:\n ", Branch_lvl_prefix("root: "), snap()); break; - } - case Channel::WRITE_ROOT_NODE_COMPLETED: - { - if (_handle_failed_generated_req(chan, progress)) + + case READ_BLK_SUCCEEDED: + + if (!_check_and_decode_read_blk(progress)) break; - Snapshot &snap { req._snapshots.items[chan._snapshot_idx] }; - Tree_level_index const child_lvl { chan._t1_blk_idx }; - Physical_block_address const child_pba { chan._new_pbas.pbas[child_lvl] }; + if (VERBOSE_WRITE_VBA) + log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", _node_idx(_lvl, _vba), ": "), _node(_lvl, _vba)); - snap.pba = child_pba; - calc_sha256_4k_hash(chan._encoded_blk, snap.hash); - - if (VERBOSE_REKEYING) - log(" ", Branch_lvl_prefix("root: "), snap); - - Snapshot_index next_snap_idx { 0 }; - if (_find_next_snap_to_rekey_vba_at(chan, next_snap_idx)) { - - chan._snapshot_idx = next_snap_idx; - Snapshot const &snap { req._snapshots.items[chan._snapshot_idx] }; - - chan._first_snapshot = false; - chan._t1_blk_idx = snap.max_level; - if (chan._t1_blks_old_pbas.items[chan._t1_blk_idx] == snap.pba) { - - progress = true; - - } else { - - chan._t1_blks_old_pbas.items[chan._t1_blk_idx] = snap.pba; - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_VBD_CACHE, - .blk_nr = snap.pba, - .idx = chan_idx - }; - chan._state = Channel::READ_ROOT_NODE_PENDING; - progress = true; - - if (VERBOSE_REKEYING) { - log(" snapshot ", chan._snapshot_idx, ":"); - log(" load branch:"); - log(" ", Branch_lvl_prefix("root: "), snap); - } - } - - } else { - - _mark_req_successful(chan, progress); + if (_lvl > 1) + _generate_req(READ_BLK_SUCCEEDED, progress, _node(_lvl, _vba).pba, _encoded_blk); + else { + _set_new_pbas_and_num_blks_for_alloc(); + if (_num_blks) + _generate_ft_alloc_req_for_write_vba(progress); + else + _generate_req( + WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[0], _vba, + req._curr_key_id, req._client_req_tag, req._client_req_offset, _data_blk, _hash); } + _lvl--; break; - } - case Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_COMPLETED: - if (_handle_failed_generated_req(chan, progress)) - break; + case ALLOC_PBAS_SUCCEEDED: - chan._log_rekeying_pba_alloc(); - chan._t1_blks.items[chan._t1_blk_idx].encode_to_blk(chan._encoded_blk); - chan._state = Channel::WRITE_INNER_NODE_COMPLETED; + if (VERBOSE_WRITE_VBA) + log(" alloc pba", _num_blks > 1 ? "s" : "", ": ", Pba_allocation(_t1_nodes, _new_pbas)); - if (VERBOSE_REKEYING) - log(" update branch:"); - - progress = true; - - default: + _generate_req( + WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[0], _vba, req._curr_key_id, + req._client_req_tag, req._client_req_offset, _data_blk, _hash); break; + + case WRITE_BLK_SUCCEEDED: + + if (!_lvl) + _update_nodes_of_branch_of_written_vba(); + + if (_lvl < snap().max_level) { + _lvl++; + _generate_write_blk_req(progress); + } else + _mark_req_successful(progress); + break; + + default: break; } } -void Virtual_block_device:: -_add_new_root_lvl_to_snap_using_pba_contingent(Channel &chan) +void Virtual_block_device_channel::_mark_req_failed(bool &progress, char const *str) { - Request &req { chan._request }; - Snapshot_index const old_idx { chan._snapshot_idx }; - Snapshot_index &idx { chan._snapshot_idx }; - Snapshot *snap { req._snapshots.items }; - Physical_block_address new_pba; - - if (snap[idx].max_level == TREE_MAX_LEVEL) { - class Exception_1 { }; - throw Exception_1 { }; - } - Tree_level_index const new_lvl { snap[old_idx].max_level + 1 }; - chan._t1_blks.items[new_lvl] = { }; - chan._t1_blks.items[new_lvl].nodes[0] = - { snap[idx].pba, snap[idx].gen, snap[idx].hash }; - - if (snap[idx].gen < req._curr_gen) { - - idx = - req._snapshots.idx_of_invalid_or_lowest_gen_evictable_snap( - req._curr_gen, req._last_secured_generation); - - if (VERBOSE_VBD_EXTENSION) - log(" new snap ", idx); - } - - _alloc_pba_from_resizing_contingent( - req._pba, req._nr_of_pbas, new_pba); - - snap[idx] = { - Hash { }, new_pba, req._curr_gen, snap[old_idx].nr_of_leaves, - new_lvl, true, 0, false }; - - if (VERBOSE_VBD_EXTENSION) { - log(" update snap ", idx, " ", snap[idx]); - log(" update lvl ", new_lvl, - " child 0 ", chan._t1_blks.items[new_lvl].nodes[0]); - } -} - - -void Virtual_block_device:: -_alloc_pba_from_resizing_contingent(Physical_block_address &first_pba, - Number_of_blocks &nr_of_pbas, - Physical_block_address &allocated_pba) -{ - if (nr_of_pbas == 0) { - class Exception_1 { }; - throw Exception_1 { }; - } - allocated_pba = first_pba; - first_pba++; - nr_of_pbas--; -} - - -void Virtual_block_device:: -_add_new_branch_to_snap_using_pba_contingent(Channel &chan, - Tree_level_index mount_at_lvl, - Tree_node_index mount_at_child_idx) -{ - Request &req { chan._request }; - req._nr_of_leaves = 0; - chan._t1_blk_idx = mount_at_lvl; - - /* reset all levels below mount point */ - if (mount_at_lvl > 1) { - for (Tree_level_index lvl { 1 }; lvl < mount_at_lvl; lvl++) - chan._t1_blks.items[lvl] = { }; - } - if (!req._nr_of_pbas) - return; - - /* set child PBAs of new branch */ - for (Tree_level_index lvl { mount_at_lvl }; lvl > 0; lvl--) { - - chan._t1_blk_idx = lvl; - Tree_node_index child_idx { - lvl == mount_at_lvl ? mount_at_child_idx : 0 }; - - auto add_child_at_curr_lvl_and_child_idx = [&] () { - - if (!req._nr_of_pbas) - return false; - - Physical_block_address child_pba; - _alloc_pba_from_resizing_contingent( - req._pba, req._nr_of_pbas, child_pba); - - Type_1_node &child { chan._t1_blks.items[lvl].nodes[child_idx] }; - child = { child_pba, INITIAL_GENERATION, Hash { } }; - - if (VERBOSE_VBD_EXTENSION) - log(" update lvl ", lvl, " child ", child_idx, " ", child); - - return true; - }; - if (lvl > 1) { - - if (!add_child_at_curr_lvl_and_child_idx()) - return; - - } else { - - for (; child_idx < req._snapshots_degree; child_idx++) { - - if (!add_child_at_curr_lvl_and_child_idx()) - return; - - req._nr_of_leaves++; - } - } - } -} - - -void -Virtual_block_device::_set_new_pbas_identical_to_current_pbas(Channel &chan) -{ - Request &req { chan._request }; - Snapshot &snap { chan._request._snapshots.items[chan._snapshot_idx] }; - - for (Tree_level_index lvl { 0 }; lvl <= TREE_MAX_LEVEL; lvl++) { - - if (lvl > snap.max_level) { - - chan._new_pbas.pbas[lvl] = 0; - - } else if (lvl == snap.max_level) { - - chan._new_pbas.pbas[lvl] = snap.pba; - - } else { - - Tree_node_index const child_idx { - t1_child_idx_for_vba(chan._vba, lvl + 1, req._snapshots_degree) }; - - Type_1_node const &child { - chan._t1_blks.items[lvl + 1].nodes[child_idx] }; - - chan._new_pbas.pbas[lvl] = child.pba; - } - } -} - - -void Virtual_block_device:: -_set_args_for_alloc_of_new_pbas_for_resizing(Channel &chan, - uint64_t chan_idx, - Tree_level_index min_lvl, - bool &progress) -{ - Request const &req { chan._request }; - Snapshot const &snap { req._snapshots.items[chan._snapshot_idx] }; - - if (min_lvl > snap.max_level) { - - _mark_req_failed(chan, progress, "check parent lvl for alloc"); - return; - } - chan._nr_of_blks = 0; - chan._free_gen = req._curr_gen; - for (Tree_level_index lvl = 0; lvl <= TREE_MAX_LEVEL; lvl++) { - - if (lvl > snap.max_level) { - - chan._new_pbas.pbas[lvl] = 0; - chan._t1_node_walk.nodes[lvl] = { }; - - } else if (lvl == snap.max_level) { - - chan._nr_of_blks++; - chan._new_pbas.pbas[lvl] = 0; - chan._t1_node_walk.nodes[lvl] = { - snap.pba, snap.gen, snap.hash }; - - } else { - - Tree_node_index const child_idx { - t1_child_idx_for_vba( - chan._vba, lvl + 1, req._snapshots_degree) }; - - Type_1_node const &child { - chan._t1_blks.items[lvl + 1].nodes[child_idx] }; - - if (lvl >= min_lvl) { - - chan._nr_of_blks++; - chan._new_pbas.pbas[lvl] = 0; - chan._t1_node_walk.nodes[lvl] = child; - - } else { - - /* - * FIXME - * - * This is done only because the Free Tree module would - * otherwise get stuck. It is normal that the lowest - * levels have PBA 0 when creating the new branch - * stopped at an inner node because of a depleted PBA - * contingent. As soon as the strange behavior in the - * Free Tree module has been fixed, the whole 'if' - * statement can be removed. - */ - if (child.pba == 0) { - - chan._new_pbas.pbas[lvl] = INVALID_PBA; - chan._t1_node_walk.nodes[lvl] = { - INVALID_PBA, child.gen, child.hash }; - - } else { - - chan._new_pbas.pbas[lvl] = child.pba; - chan._t1_node_walk.nodes[lvl] = child; - } - } - } - } - chan._generated_prim = { - .op = Channel::Generated_prim::Type::READ, - .succ = false, - .tg = Channel::Tag_type::TAG_VBD_FT_ALLOC_FOR_NON_RKG, - .blk_nr = 0, - .idx = chan_idx - }; - chan._state = Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_PENDING; + error(Request::type_to_string(_req_ptr->_type), " request failed at step \"", str, "\""); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; progress = true; } - -void Virtual_block_device::_execute_vbd_extension_step(Channel &chan, - uint64_t chan_idx, - bool &progress) +void Virtual_block_device_channel::_mark_req_successful(bool &progress) { - Request &req { chan._request }; + _req_ptr->_success = true; + _state = REQ_COMPLETE; + _req_ptr = nullptr; + progress = true; +} - switch (chan._state) { - case Channel::State::SUBMITTED: - { - req._nr_of_leaves = 0; - chan._snapshot_idx = req._snapshots.newest_snapshot_idx(); - chan._vba = chan.snap().nr_of_leaves; - chan._t1_blk_idx = chan.snap().max_level; - chan._t1_blks_old_pbas.items[chan._t1_blk_idx] = chan.snap().pba; - - if (chan._vba <= tree_max_max_vba(req._snapshots_degree, chan.snap().max_level)) { - - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_VBD_CACHE, - .blk_nr = chan.snap().pba, - .idx = chan_idx - }; - - if (VERBOSE_VBD_EXTENSION) - log(" read lvl ", chan._t1_blk_idx, - " parent snap ", chan._snapshot_idx, - " ", chan.snap()); - - chan._state = Channel::READ_ROOT_NODE_PENDING; - progress = true; - - } else { - - _add_new_root_lvl_to_snap_using_pba_contingent(chan); - _add_new_branch_to_snap_using_pba_contingent(chan, req._snapshots.items[chan._snapshot_idx].max_level, 1); - _set_new_pbas_identical_to_current_pbas(chan); - _set_args_for_write_back_of_t1_lvl( - chan.snap().max_level, chan._t1_blk_idx, - chan._new_pbas.pbas[chan._t1_blk_idx], chan_idx, - chan._state, progress, chan._generated_prim); - - if (VERBOSE_VBD_EXTENSION) - log(" write 1 lvl ", chan._t1_blk_idx, " pba ", - (Physical_block_address)chan._new_pbas.pbas[chan._t1_blk_idx]); +bool Virtual_block_device_channel::_find_next_snap_to_rekey_vba_at(Snapshot_index &result) const +{ + bool result_valid { false }; + Request &req { *_req_ptr }; + Snapshot &curr_snap { req._snapshots.items[_snap_idx] }; + for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { + Snapshot &snap { req._snapshots.items[idx] }; + if (snap.valid && snap.contains_vba(req._vba)) { + if (result_valid) { + if (snap.gen < curr_snap.gen && snap.gen > req._snapshots.items[result].gen) + result = idx; + } else + if (snap.gen < curr_snap.gen) { + result = idx; + result_valid = true; + } } - break; } - case Channel::READ_ROOT_NODE_COMPLETED: - case Channel::READ_INNER_NODE_COMPLETED: - { - if (_handle_failed_generated_req(chan, progress)) + return result_valid; +} + + +void Virtual_block_device_channel::_generate_ft_alloc_req_for_rekeying(Tree_level_index min_lvl, bool &progress) +{ + Request &req { *_req_ptr }; + ASSERT(min_lvl <= snap().max_level); + _num_blks = 0; + if (_first_snapshot) + _free_gen = req._curr_gen; + else + _free_gen = snap().gen + 1; + + for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) + if (lvl > snap().max_level) { + _t1_nodes.nodes[lvl] = { }; + _new_pbas.pbas[lvl] = 0; + } else if (lvl == snap().max_level) { + _num_blks++; + _new_pbas.pbas[lvl] = 0; + _t1_nodes.nodes[lvl] = { snap().pba, snap().gen, snap().hash }; + } else if (lvl >= min_lvl) { + _num_blks++; + _new_pbas.pbas[lvl] = 0; + _t1_nodes.nodes[lvl] = _node(lvl + 1, req._vba); + } else { + Type_1_node &node { _node(lvl + 1, req._vba) }; + _t1_nodes.nodes[lvl] = { _new_pbas.pbas[lvl], node.gen, node.hash}; + } + + _generate_ft_req(ALLOC_PBAS_SUCCEEDED, progress, _first_snapshot ? + Free_tree_request::ALLOC_FOR_RKG_CURR_GEN_BLKS : + Free_tree_request::ALLOC_FOR_RKG_OLD_GEN_BLKS); +} + + +void Virtual_block_device_channel::_rekey_vba(bool &progress) +{ + Request &req { *_req_ptr }; + switch (_state) { + case SUBMITTED: + + _vba = req._vba; + _snap_idx = req._snapshots.newest_snap_idx(); + _first_snapshot = true; + _lvl = snap().max_level; + _old_pbas.pbas[_lvl] = snap().pba; + _generate_req(READ_BLK_SUCCEEDED, progress, snap().pba, _encoded_blk); + if (VERBOSE_REKEYING) + log(" snapshot ", _snap_idx, ":\n load branch:\n ", + Branch_lvl_prefix("root: "), snap()); + break; + + case READ_BLK_SUCCEEDED: + + if (!_check_and_decode_read_blk(progress)) break; - if (chan._t1_blk_idx == chan.snap().max_level) { + if (_lvl) { + Type_1_node &node { _node(_lvl, req._vba) }; + if (VERBOSE_REKEYING) + log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", _node_idx(_lvl, req._vba), ": "), node); - if (!check_sha256_4k_hash(chan._encoded_blk, chan.snap().hash)) { + if (!_first_snapshot && _old_pbas.pbas[_lvl - 1] == node.pba) { - _mark_req_failed(chan, progress, "check root node hash"); - break; - } + /* skip rest of this branch as it was rekeyed while rekeying the vba at another snap */ + _generate_ft_alloc_req_for_rekeying(_lvl, progress); + if (VERBOSE_REKEYING) + log(" [node already rekeyed at pba ", _new_pbas.pbas[_lvl - 1], "]"); - } else { + } else if (_lvl == 1 && node.gen == INITIAL_GENERATION) { - Tree_level_index const parent_lvl { chan._t1_blk_idx + 1 }; - Tree_node_index const child_idx { - t1_child_idx_for_vba(chan._vba, parent_lvl, req._snapshots_degree) }; - - if (!check_sha256_4k_hash(chan._encoded_blk, - chan._t1_blks.items[parent_lvl].nodes[child_idx].hash)) { - - _mark_req_failed(chan, progress, "check inner node hash"); - break; - } - } - if (chan._t1_blk_idx > 1) { - - Tree_level_index const parent_lvl { chan._t1_blk_idx }; - Tree_level_index const child_lvl { parent_lvl - 1 }; - Tree_node_index const child_idx { - t1_child_idx_for_vba(chan._vba, parent_lvl, req._snapshots_degree) }; - - Type_1_node const &child { chan._t1_blks.items[parent_lvl].nodes[child_idx] }; - - if (child.valid()) { - - chan._t1_blk_idx = child_lvl; - chan._t1_blks_old_pbas.items[child_lvl] = child.pba; - chan._generated_prim = { - .op = Generated_prim::READ, - .succ = false, - .tg = Channel::TAG_VBD_CACHE, - .blk_nr = child.pba, - .idx = chan_idx - }; - chan._state = Channel::READ_INNER_NODE_PENDING; - progress = true; - - if (VERBOSE_VBD_EXTENSION) - log(" read lvl ", child_lvl, " parent lvl ", parent_lvl, - " child ", child_idx, " ", child); + /* skip yet unused leaf node because the lib will read its data as 0 regardless of the key */ + _generate_ft_alloc_req_for_rekeying(_lvl - 1, progress); + if (VERBOSE_REKEYING) + log(" [node needs no rekeying]"); } else { - _add_new_branch_to_snap_using_pba_contingent(chan, parent_lvl, child_idx); - _set_args_for_alloc_of_new_pbas_for_resizing(chan, chan_idx, parent_lvl, progress); + _lvl--; + _old_pbas.pbas[_lvl] = node.pba; + _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _lvl ? _encoded_blk : _data_blk); + } + } else { + _generate_req( + DECRYPT_LEAF_DATA_SUCCEEDED, progress, req._prev_key_id, _old_pbas.pbas[_lvl], _data_blk); + if (VERBOSE_REKEYING) + log(" ", Branch_lvl_prefix("leaf data: "), _data_blk); + } + break; + + case DECRYPT_LEAF_DATA_SUCCEEDED: + + _generate_ft_alloc_req_for_rekeying(_lvl, progress); + if (VERBOSE_REKEYING) + log(" re-encrypt leaf data: plaintext ", _data_blk, " hash ", hash(_data_blk)); + break; + + case ALLOC_PBAS_SUCCEEDED: + + if (VERBOSE_REKEYING) + log(" alloc pba", _num_blks > 1 ? "s" : "", ": ", Pba_allocation { _t1_nodes, _new_pbas }); + + if (_lvl) { + if (VERBOSE_REKEYING) + log(" update branch:"); + + _lvl--; + _state = WRITE_BLK_SUCCEEDED; + progress = true; + if (_lvl) + _t1_blks.items[_lvl].encode_to_blk(_encoded_blk); + } else + _generate_req( + ENCRYPT_LEAF_DATA_SUCCEEDED, progress, req._curr_key_id, _new_pbas.pbas[0], _data_blk); + break; + + case ENCRYPT_LEAF_DATA_SUCCEEDED: + + _generate_write_blk_req(progress); + if (VERBOSE_REKEYING) + log(" update branch:\n ", Branch_lvl_prefix("leaf data: "), _data_blk); + break; + + case WRITE_BLK_SUCCEEDED: + + if (_lvl < snap().max_level) { + Type_1_node &node { _node(_lvl + 1, req._vba) }; + node.pba = _new_pbas.pbas[_lvl]; + calc_hash(_lvl ? _encoded_blk : _data_blk, node.hash); + _lvl++; + _generate_write_blk_req(progress); + if (VERBOSE_REKEYING) + log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", _node_idx(_lvl + 1, req._vba), ": "), node); + } else { + snap().pba = _new_pbas.pbas[_lvl]; + calc_hash(_encoded_blk, snap().hash); + if (VERBOSE_REKEYING) + log(" ", Branch_lvl_prefix("root: "), snap()); + + Snapshot_index snap_idx; + if (_find_next_snap_to_rekey_vba_at(snap_idx)) { + _snap_idx = snap_idx; + _first_snapshot = false; + _lvl = snap().max_level; + if (_old_pbas.pbas[_lvl] == snap().pba) + progress = true; + else { + _old_pbas.pbas[_lvl] = snap().pba; + _generate_req(READ_BLK_SUCCEEDED, progress, snap().pba, _encoded_blk); + if (VERBOSE_REKEYING) + log(" snapshot ", _snap_idx, ":\n load branch:\n ", + Branch_lvl_prefix("root: "), snap()); + } + } else + _mark_req_successful(progress); + } + break; + + default: break; + } +} + + +void Virtual_block_device_channel::_add_new_root_lvl_to_snap() +{ + Request &req { *_req_ptr }; + Snapshot_index old_idx { _snap_idx }; + Snapshot_index &idx { _snap_idx }; + Snapshot *snap { req._snapshots.items }; + ASSERT(snap[idx].max_level < TREE_MAX_LEVEL); + Tree_level_index new_lvl { snap[old_idx].max_level + 1 }; + _t1_blks.items[new_lvl] = { }; + _t1_blks.items[new_lvl].nodes[0] = { snap[idx].pba, snap[idx].gen, snap[idx].hash }; + + if (snap[idx].gen < req._curr_gen) { + idx = req._snapshots.alloc_idx(req._curr_gen, req._last_secured_gen); + if (VERBOSE_VBD_EXTENSION) + log(" new snap ", idx); + } + snap[idx] = { + { }, alloc_pba_from_range(req._pba, req._num_pbas), req._curr_gen, snap[old_idx].nr_of_leaves, + new_lvl, true, 0, false }; + + if (VERBOSE_VBD_EXTENSION) + log(" update snap ", idx, " ", snap[idx], "\n update lvl ", new_lvl, " child 0 ", _t1_blks.items[new_lvl].nodes[0]); +} + + +void Virtual_block_device_channel::_add_new_branch_to_snap(Tree_level_index mount_lvl, Tree_node_index mount_node_idx) +{ + Request &req { *_req_ptr }; + req._num_leaves = 0; + _lvl = mount_lvl; + if (mount_lvl > 1) + for (Tree_level_index lvl { 1 }; lvl < mount_lvl; lvl++) + _t1_blks.items[lvl] = { }; + + if (!req._num_pbas) + return; + + for (Tree_level_index lvl { mount_lvl }; lvl > 0; lvl--) { + _lvl = lvl; + Tree_node_index node_idx { lvl == mount_lvl ? mount_node_idx : 0 }; + auto try_add_node_at_lvl_and_node_idx = [&] () { + if (!req._num_pbas) + return false; + + Type_1_node &node { _t1_blks.items[lvl].nodes[node_idx] }; + node = { alloc_pba_from_range(req._pba, req._num_pbas), INITIAL_GENERATION, { } }; + if (VERBOSE_VBD_EXTENSION) + log(" update lvl ", lvl, " node ", node_idx, " ", node); + + return true; + }; + if (lvl > 1) { + if (!try_add_node_at_lvl_and_node_idx()) + return; + } else + for (; node_idx < req._snap_degr; node_idx++) { + if (!try_add_node_at_lvl_and_node_idx()) + return; + + req._num_leaves++; + } + } +} + + +void Virtual_block_device_channel::_set_new_pbas_identical_to_curr_pbas() +{ + for (Tree_level_index lvl { 0 }; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) + if (lvl > snap().max_level) + _new_pbas.pbas[lvl] = 0; + else if (lvl == snap().max_level) + _new_pbas.pbas[lvl] = snap().pba; + else + _new_pbas.pbas[lvl] = _node(lvl + 1, _vba).pba; +} + + +void Virtual_block_device_channel::_generate_ft_alloc_req_for_resizing(Tree_level_index min_lvl, bool &progress) +{ + Request &req { *_req_ptr }; + Snapshot &snap { req._snapshots.items[_snap_idx] }; + if (min_lvl > snap.max_level) { + _mark_req_failed(progress, "check parent lvl for alloc"); + return; + } + _num_blks = 0; + _free_gen = req._curr_gen; + for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) { + + if (lvl > snap.max_level) { + _new_pbas.pbas[lvl] = 0; + _t1_nodes.nodes[lvl] = { }; + } else if (lvl == snap.max_level) { + _num_blks++; + _new_pbas.pbas[lvl] = 0; + _t1_nodes.nodes[lvl] = { snap.pba, snap.gen, snap.hash }; + } else { + Type_1_node &node { _node(lvl + 1, _vba) }; + if (lvl >= min_lvl) { + _num_blks++; + _new_pbas.pbas[lvl] = 0; + _t1_nodes.nodes[lvl] = node; + } else { + /* + * FIXME This is done only because the Free Tree module would otherwise get stuck. It is normal that + * the lowest levels have PBA 0 when creating the new branch stopped at an inner node because of a + * depleted PBA contingent. As soon as the strange behavior in the Free Tree module has been fixed, + * the whole 'if' statement can be removed. + */ + if (!node.pba) { + _new_pbas.pbas[lvl] = INVALID_PBA; + _t1_nodes.nodes[lvl] = { INVALID_PBA, node.gen, node.hash }; + } else { + _new_pbas.pbas[lvl] = node.pba; + _t1_nodes.nodes[lvl] = node; + } + } + } + } + _generate_ft_req(ALLOC_PBAS_SUCCEEDED, progress, Free_tree_request::ALLOC_FOR_NON_RKG); +} + + +void Virtual_block_device_channel::_request_submitted(Module_request &req) +{ + _req_ptr = static_cast(&req); + _state = SUBMITTED; +} + + +void Virtual_block_device_channel::_extension_step(bool &progress) +{ + Request &req { *_req_ptr }; + switch (_state) { + case State::SUBMITTED: + + req._num_leaves = 0; + _snap_idx = req._snapshots.newest_snap_idx(); + _vba = snap().nr_of_leaves; + _lvl = snap().max_level; + _old_pbas.pbas[_lvl] = snap().pba; + if (_vba <= tree_max_max_vba(req._snap_degr, snap().max_level)) { + _generate_req(READ_BLK_SUCCEEDED, progress, snap().pba, _encoded_blk); + if (VERBOSE_VBD_EXTENSION) + log(" read lvl ", _lvl, " parent snap ", _snap_idx, " ", snap()); + } else { + _add_new_root_lvl_to_snap(); + _add_new_branch_to_snap(req._snapshots.items[_snap_idx].max_level, 1); + _set_new_pbas_identical_to_curr_pbas(); + _generate_write_blk_req(progress); + if (VERBOSE_VBD_EXTENSION) + log(" write 1 lvl ", _lvl, " pba ", _new_pbas.pbas[_lvl]); + } + break; + + case READ_BLK_SUCCEEDED: + { + _t1_blks.items[_lvl].decode_from_blk(_encoded_blk); + if (_lvl == snap().max_level) { + if (!check_hash(_encoded_blk, snap().hash)) { + _mark_req_failed(progress, "check root node hash"); break; } - } else { - - Tree_level_index const parent_lvl { chan._t1_blk_idx }; - Tree_node_index const child_idx { - t1_child_idx_for_vba(chan._vba, parent_lvl, req._snapshots_degree) }; - - _add_new_branch_to_snap_using_pba_contingent(chan, parent_lvl, child_idx); - _set_args_for_alloc_of_new_pbas_for_resizing(chan, chan_idx, parent_lvl, progress); - break; - } - break; - } - case Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_COMPLETED: - { - if (_handle_failed_generated_req(chan, progress)) - break; - - Physical_block_address const new_pba { - chan._new_pbas.pbas[chan._t1_blk_idx] }; - - if (VERBOSE_VBD_EXTENSION) { - log(" allocated ", chan._nr_of_blks, " pbas"); - for (Tree_level_index lvl { 0 }; lvl < chan.snap().max_level; lvl++) { - log(" lvl ", lvl, " ", - chan._t1_node_walk.nodes[lvl], " -> pba ", - (Physical_block_address)chan._new_pbas.pbas[lvl]); + if (!check_hash(_encoded_blk, _node(_lvl + 1, _vba).hash)) { + _mark_req_failed(progress, "check inner node hash"); + break; } - log(" write 1 lvl ", chan._t1_blk_idx, " pba ", new_pba); } - chan._generated_prim = { - .op = Generated_prim::WRITE, - .succ = false, - .tg = Channel::TAG_VBD_CACHE, - .blk_nr = new_pba, - .idx = chan_idx - }; - if (chan._t1_blk_idx < chan.snap().max_level) - chan._state = Channel::WRITE_INNER_NODE_PENDING; - else - chan._state = Channel::WRITE_ROOT_NODE_PENDING; - - progress = true; + Tree_node_index node_idx { _node_idx(_lvl, _vba) }; + if (_lvl > 1) { + Type_1_node &node { _node(_lvl, _vba) }; + if (node.valid()) { + _old_pbas.pbas[_lvl - 1] = node.pba; + _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _encoded_blk); + if (VERBOSE_VBD_EXTENSION) + log(" read lvl ", _lvl - 1, " parent lvl ", _lvl, " node ", node_idx, " ", node); + _lvl--; + } else { + _add_new_branch_to_snap(_lvl, node_idx); + _generate_ft_alloc_req_for_resizing(_lvl, progress); + } + } else { + _add_new_branch_to_snap(_lvl, node_idx); + _generate_ft_alloc_req_for_resizing(_lvl, progress); + } break; } - case Channel::WRITE_INNER_NODE_COMPLETED: + case ALLOC_PBAS_SUCCEEDED: { - if (_handle_failed_generated_req(chan, progress)) - break; - - Tree_level_index const parent_lvl { chan._t1_blk_idx + 1 }; - Tree_level_index const child_lvl { chan._t1_blk_idx }; - Tree_node_index const child_idx { t1_child_idx_for_vba(chan._vba, parent_lvl, req._snapshots_degree) }; - Physical_block_address const child_pba { chan._new_pbas.pbas[child_lvl] }; - Physical_block_address const parent_pba { chan._new_pbas.pbas[parent_lvl] }; - Type_1_node &child { chan._t1_blks.items[parent_lvl].nodes[child_idx] }; - - calc_sha256_4k_hash(chan._encoded_blk, child.hash); - child.pba = child_pba; - if (VERBOSE_VBD_EXTENSION) { - log(" update lvl ", parent_lvl, " child ", child_idx, " ", child); - log(" write 2 lvl ", parent_lvl, " pba ", parent_pba); - } - chan._t1_blk_idx++; - chan._generated_prim = { - .op = Generated_prim::WRITE, - .succ = false, - .tg = Channel::TAG_VBD_CACHE, - .blk_nr = parent_pba, - .idx = chan_idx - }; - if (chan._t1_blk_idx < chan.snap().max_level) - chan._state = Channel::WRITE_INNER_NODE_PENDING; - else - chan._state = Channel::WRITE_ROOT_NODE_PENDING; + log(" allocated ", _num_blks, " pbas"); + for (Tree_level_index lvl { 0 }; lvl < snap().max_level; lvl++) + log(" lvl ", lvl, " ", _t1_nodes.nodes[lvl], " -> pba ", _new_pbas.pbas[lvl]); - progress = true; + log(" write 1 lvl ", _lvl, " pba ", _new_pbas.pbas[_lvl]); + } + _generate_write_blk_req(progress); break; } - case Channel::WRITE_ROOT_NODE_COMPLETED: + case WRITE_BLK_SUCCEEDED: { - if (_handle_failed_generated_req(chan, progress)) - break; - - Tree_level_index const child_lvl { chan._t1_blk_idx }; - Physical_block_address const child_pba { chan._new_pbas.pbas[child_lvl] }; - Snapshot const &old_snap { req._snapshots.items[chan._snapshot_idx] }; - - if (old_snap.gen < req._curr_gen) { - - chan._snapshot_idx = - req._snapshots.idx_of_invalid_or_lowest_gen_evictable_snap( - req._curr_gen, req._last_secured_generation); - + if (_lvl < snap().max_level) { + _lvl++; + Type_1_node &node { _node(_lvl, _vba) }; + calc_hash(_encoded_blk, node.hash); + node.pba = _new_pbas.pbas[_lvl - 1]; + _generate_write_blk_req(progress); if (VERBOSE_VBD_EXTENSION) - log(" new snap ", chan._snapshot_idx); + log(" update lvl ", _lvl, " node ", _node_idx(_lvl, _vba), " ", node, "\n write 2 lvl ", _lvl, " pba ", _new_pbas.pbas[_lvl]); + } else { + Snapshot &old_snap { snap() }; + if (snap().gen < req._curr_gen) { + _snap_idx = req._snapshots.alloc_idx(req._curr_gen, req._last_secured_gen); + if (VERBOSE_VBD_EXTENSION) + log(" new snap ", _snap_idx); + } + Number_of_leaves num_leaves { old_snap.nr_of_leaves + req._num_leaves }; + snap() = { { }, _new_pbas.pbas[_lvl], req._curr_gen, num_leaves, old_snap.max_level, true, 0, false }; + calc_hash(_encoded_blk, snap().hash); + _mark_req_successful(progress); + if (VERBOSE_VBD_EXTENSION) + log(" update snap ", _snap_idx, " ", snap()); } - - Snapshot &new_snap { req._snapshots.items[chan._snapshot_idx] }; - new_snap = { - Hash { }, child_pba, req._curr_gen, - old_snap.nr_of_leaves + req._nr_of_leaves, old_snap.max_level, - true, 0, false }; - - calc_sha256_4k_hash(chan._encoded_blk, new_snap.hash); - - if (VERBOSE_VBD_EXTENSION) - log(" update snap ", chan._snapshot_idx, " ", new_snap); - - _mark_req_successful(chan, progress); break; } - default: + default: break; + } +} - break; + +void Virtual_block_device_channel::execute(bool &progress) +{ + if (!_req_ptr) + return; + + switch (_req_ptr->_type) { + case Request::READ_VBA: _read_vba(progress); break; + case Request::WRITE_VBA: _write_vba(progress); break; + case Request::REKEY_VBA: _rekey_vba(progress); break; + case Request::EXTENSION_STEP: _extension_step(progress); break; } } void Virtual_block_device::execute(bool &progress) { - for (unsigned idx = 0; idx < NR_OF_CHANNELS; idx++) { - - Channel &channel = _channels[idx]; - Request &request { channel._request }; - - switch (request._type) { - case Request::INVALID: - break; - case Request::READ_VBA: - _execute_read_vba(channel, idx, progress); - break; - case Request::WRITE_VBA: - _execute_write_vba(channel, idx, progress); - break; - case Request::REKEY_VBA: - _execute_rekey_vba(channel, idx, progress); - break; - case Request::VBD_EXTENSION_STEP: - _execute_vbd_extension_step(channel, idx, progress); - break; - } - } + for_each_channel([&] (Channel &chan) { + chan.execute(progress); }); } -bool Virtual_block_device::_peek_generated_request(uint8_t *buf_ptr, - size_t buf_size) +void Virtual_block_device_channel::_generate_ft_req(State complete_state, bool progress, Free_tree_request::Type type) { - for (uint32_t id { 0 }; id < NR_OF_CHANNELS; id++) { - - Channel &chan { _channels[id] }; - Request &req { chan._request }; - if (req._type == Request::INVALID) - continue; - - switch (chan._state) { - case Channel::WRITE_ROOT_NODE_PENDING: - case Channel::WRITE_INNER_NODE_PENDING: - - chan._t1_blks.items[chan._t1_blk_idx].encode_to_blk(chan._encoded_blk); - construct_in_buf( - buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, - Block_io_request::WRITE, 0, 0, 0, - chan._generated_prim.blk_nr, 0, 1, - &chan._encoded_blk, nullptr); - - return true; - - case Channel::WRITE_LEAF_NODE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, - Block_io_request::WRITE, 0, 0, 0, - chan._generated_prim.blk_nr, 0, 1, - &chan._data_blk, nullptr); - - return true; - - case Channel::WRITE_CLIENT_DATA_TO_LEAF_NODE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, - Block_io_request::WRITE_CLIENT_DATA, req._client_req_offset, - req._client_req_tag, req._new_key_id, - chan._generated_prim.blk_nr, chan._vba, 1, nullptr, - &chan._hash); - - return true; - - case Channel::READ_ROOT_NODE_PENDING: - case Channel::READ_INNER_NODE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, - Block_io_request::READ, 0, 0, 0, - chan._generated_prim.blk_nr, 0, 1, - &chan._encoded_blk, nullptr); - - return true; - - case Channel::READ_LEAF_NODE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, - Block_io_request::READ, 0, 0, 0, - chan._generated_prim.blk_nr, 0, 1, &chan._data_blk, nullptr); - - return true; - - case Channel::READ_CLIENT_DATA_FROM_LEAF_NODE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, - Block_io_request::READ_CLIENT_DATA, req._client_req_offset, - req._client_req_tag, req._new_key_id, - chan._generated_prim.blk_nr, chan._vba, 1, nullptr, nullptr); - - return true; - - case Channel::DECRYPT_LEAF_NODE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, - Crypto_request::DECRYPT, - 0, 0, req._old_key_id, nullptr, - chan._generated_prim.blk_nr, 0, &chan._data_blk, - &chan._data_blk); - - return true; - - case Channel::ENCRYPT_LEAF_NODE_PENDING: - - construct_in_buf( - buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, - Crypto_request::ENCRYPT, - 0, 0, req._new_key_id, nullptr, - chan._generated_prim.blk_nr, 0, &chan._data_blk, - &chan._data_blk); - - return true; - - case Channel::ALLOC_PBAS_AT_LEAF_LVL_PENDING: - case Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_PENDING: - case Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_PENDING: - { - Free_tree_request::Type ftrt { Free_tree_request::INVALID }; - switch (chan._generated_prim.tg) { - case Channel::TAG_VBD_FT_ALLOC_FOR_NON_RKG: ftrt = Free_tree_request::ALLOC_FOR_NON_RKG; break; - case Channel::TAG_VBD_FT_ALLOC_FOR_RKG_CURR_GEN_BLKS: ftrt = Free_tree_request::ALLOC_FOR_RKG_CURR_GEN_BLKS; break; - case Channel::TAG_VBD_FT_ALLOC_FOR_RKG_OLD_GEN_BLKS: ftrt = Free_tree_request::ALLOC_FOR_RKG_OLD_GEN_BLKS; break; - default: break; - } - if (ftrt == Free_tree_request::INVALID) { - class Exception_1 { }; - throw Exception_1 { }; - } - construct_in_buf( - buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, - ftrt, req._ft_root_pba_ptr, - req._ft_root_gen_ptr, req._ft_root_hash_ptr, - req._ft_max_level, req._ft_degree, req._ft_leaves, - req._mt_root_pba_ptr, req._mt_root_gen_ptr, - req._mt_root_hash_ptr, req._mt_max_level, req._mt_degree, - req._mt_leaves, &req._snapshots, req._last_secured_generation, - req._curr_gen, chan._free_gen, chan._nr_of_blks, - (addr_t)&chan._new_pbas, (addr_t)&chan._t1_node_walk, - (uint64_t)req._snapshots.items[chan._snapshot_idx].max_level, - chan._vba, req._vbd_degree, req._vbd_highest_vba, - req._rekeying, req._old_key_id, req._new_key_id, chan._vba); - - return true; - } - default: break; - } - } - return false; + Request &req { *_req_ptr }; + _generate_req( + complete_state, progress, type, req._ft, req._mt, req._snapshots, req._last_secured_gen, req._curr_gen, + _free_gen, _num_blks, _new_pbas, _t1_nodes, req._snapshots.items[_snap_idx].max_level, _vba, req._vbd_degree, + req._vbd_highest_vba, req._rekeying, req._prev_key_id, req._curr_key_id, _vba, *(Physical_block_address*)0, + *(Number_of_blocks*)0); } -void Virtual_block_device::_drop_generated_request(Module_request &mod_req) +Virtual_block_device::Virtual_block_device() { - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - switch (chan._state) { - case Channel::READ_ROOT_NODE_PENDING: chan._state = Channel::READ_ROOT_NODE_IN_PROGRESS; break; - case Channel::READ_INNER_NODE_PENDING: chan._state = Channel::READ_INNER_NODE_IN_PROGRESS; break; - case Channel::WRITE_ROOT_NODE_PENDING: chan._state = Channel::WRITE_ROOT_NODE_IN_PROGRESS; break; - case Channel::WRITE_INNER_NODE_PENDING: chan._state = Channel::WRITE_INNER_NODE_IN_PROGRESS; break; - case Channel::READ_LEAF_NODE_PENDING: chan._state = Channel::READ_LEAF_NODE_IN_PROGRESS; break; - case Channel::READ_CLIENT_DATA_FROM_LEAF_NODE_PENDING: chan._state = Channel::READ_CLIENT_DATA_FROM_LEAF_NODE_IN_PROGRESS; break; - case Channel::WRITE_LEAF_NODE_PENDING: chan._state = Channel::WRITE_LEAF_NODE_IN_PROGRESS; break; - case Channel::WRITE_CLIENT_DATA_TO_LEAF_NODE_PENDING: chan._state = Channel::WRITE_CLIENT_DATA_TO_LEAF_NODE_IN_PROGRESS; break; - case Channel::DECRYPT_LEAF_NODE_PENDING: chan._state = Channel::DECRYPT_LEAF_NODE_IN_PROGRESS; break; - case Channel::ENCRYPT_LEAF_NODE_PENDING: chan._state = Channel::ENCRYPT_LEAF_NODE_IN_PROGRESS; break; - case Channel::ALLOC_PBAS_AT_LEAF_LVL_PENDING: chan._state = Channel::ALLOC_PBAS_AT_LEAF_LVL_IN_PROGRESS; break; - case Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_PENDING: chan._state = Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_IN_PROGRESS; break; - case Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_PENDING: chan._state = Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_IN_PROGRESS; break; - default: - class Exception_2 { }; - throw Exception_2 { }; + Module_channel_id id { 0 }; + for (Constructible &chan : _channels) { + chan.construct(id++); + add_channel(*chan); } } - - -void Virtual_block_device::generated_request_complete(Module_request &mod_req) -{ - Module_request_id const id { mod_req.src_request_id() }; - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - switch (mod_req.dst_module_id()) { - case CRYPTO: - { - Crypto_request &crypto_req { *static_cast(&mod_req) }; - chan._generated_prim.succ = crypto_req.success(); - switch (chan._state) { - case Channel::DECRYPT_LEAF_NODE_IN_PROGRESS: chan._state = Channel::DECRYPT_LEAF_NODE_COMPLETED; break; - case Channel::ENCRYPT_LEAF_NODE_IN_PROGRESS: chan._state = Channel::ENCRYPT_LEAF_NODE_COMPLETED; break; - default: - class Exception_3 { }; - throw Exception_3 { }; - } - break; - } - case BLOCK_IO: - { - Block_io_request &blk_io_req { *static_cast(&mod_req) }; - chan._generated_prim.succ = blk_io_req.success(); - switch (chan._state) { - case Channel::READ_ROOT_NODE_IN_PROGRESS: - chan._t1_blks.items[chan._t1_blk_idx].decode_from_blk(chan._encoded_blk); - chan._state = Channel::READ_ROOT_NODE_COMPLETED; - break; - case Channel::READ_INNER_NODE_IN_PROGRESS: - chan._t1_blks.items[chan._t1_blk_idx].decode_from_blk(chan._encoded_blk); - chan._state = Channel::READ_INNER_NODE_COMPLETED; - break; - case Channel::WRITE_ROOT_NODE_IN_PROGRESS: chan._state = Channel::WRITE_ROOT_NODE_COMPLETED; break; - case Channel::WRITE_INNER_NODE_IN_PROGRESS: chan._state = Channel::WRITE_INNER_NODE_COMPLETED; break; - case Channel::READ_LEAF_NODE_IN_PROGRESS: chan._state = Channel::READ_LEAF_NODE_COMPLETED; break; - case Channel::READ_CLIENT_DATA_FROM_LEAF_NODE_IN_PROGRESS: chan._state = Channel::READ_CLIENT_DATA_FROM_LEAF_NODE_COMPLETED; break; - case Channel::WRITE_LEAF_NODE_IN_PROGRESS: chan._state = Channel::WRITE_LEAF_NODE_COMPLETED; break; - case Channel::WRITE_CLIENT_DATA_TO_LEAF_NODE_IN_PROGRESS: chan._state = Channel::WRITE_CLIENT_DATA_TO_LEAF_NODE_COMPLETED; break; - default: - class Exception_4 { }; - throw Exception_4 { }; - } - break; - } - case FREE_TREE: - { - Free_tree_request &ft_req { *static_cast(&mod_req) }; - chan._generated_prim.succ = ft_req.success(); - switch (chan._state) { - case Channel::ALLOC_PBAS_AT_LEAF_LVL_IN_PROGRESS: chan._state = Channel::ALLOC_PBAS_AT_LEAF_LVL_COMPLETED; break; - case Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_IN_PROGRESS: chan._state = Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_COMPLETED; break; - case Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_IN_PROGRESS: chan._state = Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_COMPLETED; break; - default: - class Exception_2 { }; - throw Exception_2 { }; - } - break; - } - default: - class Exception_5 { }; - throw Exception_5 { }; - } -} - - -bool Virtual_block_device::_peek_completed_request(uint8_t *buf_ptr, - size_t buf_size) -{ - for (Channel &channel : _channels) { - if (channel._request._type != Request::INVALID && - channel._state == Channel::COMPLETED) { - - if (sizeof(channel._request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - memcpy(buf_ptr, &channel._request, sizeof(channel._request)); - return true; - } - } - return false; -} - - -void Virtual_block_device::_drop_completed_request(Module_request &req) -{ - Module_request_id id { 0 }; - id = req.dst_request_id(); - if (id >= NR_OF_CHANNELS) { - class Exception_1 { }; - throw Exception_1 { }; - } - Channel &chan { _channels[id] }; - if (chan._request._type == Request::INVALID || - chan._state != Channel::COMPLETED) { - - class Exception_2 { }; - throw Exception_2 { }; - } - chan._request._type = Request::INVALID; -} diff --git a/repos/gems/src/lib/vfs/tresor/splitter.cc b/repos/gems/src/lib/vfs/tresor/splitter.cc new file mode 100644 index 0000000000..caabf35828 --- /dev/null +++ b/repos/gems/src/lib/vfs/tresor/splitter.cc @@ -0,0 +1,225 @@ +/* + * \brief Module for splitting unaligned/uneven I/O requests + * \author Martin Stein + * \author Josef Soentgen + * \date 2023-09-11 + */ + +/* + * Copyright (C) 2023 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* vfs tresor includes */ +#include + +using namespace Tresor; + +Splitter_request::Splitter_request(Module_id src_mod, Module_channel_id src_chan, Operation op, bool &success, + Request_offset off, Byte_range_ptr const &buf, Key_id key_id, Generation gen) +: + Module_request { src_mod, src_chan, SPLITTER }, _op { op }, _off { off }, _key_id { key_id }, _gen { gen }, + _buf { buf.start, buf.num_bytes }, _success { success } +{ } + + +char const *Splitter_request::op_to_string(Operation op) +{ + switch (op) { + case Operation::READ: return "read"; + case Operation::WRITE: return "write"; + } + ASSERT_NEVER_REACHED; +} + + +void Splitter_channel::_generated_req_completed(State_uint state_uint) +{ + if (!_generated_req_success) { + error("splitter: request (", *_req_ptr, ") failed because generated request failed)"); + _req_ptr->_success = false; + _state = REQ_COMPLETE; + _req_ptr = nullptr; + return; + } + _state = (State)state_uint; +} + + +void Splitter_channel::_mark_req_successful(bool &progress) +{ + Request &req { *_req_ptr }; + req._success = true; + _state = REQ_COMPLETE; + _req_ptr = nullptr; + progress = true; +} + + +void Splitter_channel::_request_submitted(Module_request &req) +{ + _req_ptr = static_cast(&req); + _state = REQ_SUBMITTED; +} + + +void Splitter_channel::_advance_curr_off(addr_t advance, Tresor::Request::Operation op, bool &progress) +{ + Splitter_request &req { *_req_ptr }; + _curr_off += advance; + if (!_num_remaining_bytes()) { + _mark_req_successful(progress); + } else if (_curr_off % BLOCK_SIZE) { + _curr_buf_addr = (addr_t)&_blk; + _generate_req( + PROTRUDING_FIRST_BLK_READ, progress, Tresor::Request::READ, _curr_vba(), 0, 1, req._key_id, id(), _gen); + } else if (_num_remaining_bytes() < BLOCK_SIZE) { + _curr_buf_addr = (addr_t)&_blk; + _generate_req( + PROTRUDING_LAST_BLK_READ, progress, Tresor::Request::READ, _curr_vba(), 0, 1, req._key_id, id(), _gen); + } else { + _curr_buf_addr = (addr_t)req._buf.start + _curr_buf_off(); + _generate_req( + INSIDE_BLKS_ACCESSED, progress, op, _curr_vba(), 0, _num_remaining_bytes() / BLOCK_SIZE, req._key_id, id(), _gen); + } +} + + +void Splitter_channel::_write(bool &progress) +{ + Splitter_request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: + + _curr_off = 0; + _gen = req._gen; + _advance_curr_off(req._off, Tresor::Request::WRITE, progress); + break; + + case PROTRUDING_FIRST_BLK_READ: + { + size_t num_outside_bytes { _curr_off % BLOCK_SIZE }; + size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) }; + memcpy((void *)((addr_t)&_blk + num_outside_bytes), req._buf.start, num_inside_bytes); + _curr_buf_addr = (addr_t)&_blk; + _generate_req( + PROTRUDING_FIRST_BLK_WRITTEN, progress, Tresor::Request::WRITE, _curr_vba(), 0, 1, req._key_id, id(), _gen); + break; + } + case PROTRUDING_FIRST_BLK_WRITTEN: + { + size_t num_outside_bytes { _curr_off % BLOCK_SIZE }; + size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) }; + _advance_curr_off(num_inside_bytes, Tresor::Request::WRITE, progress); + break; + } + case INSIDE_BLKS_ACCESSED: + + _advance_curr_off((_num_remaining_bytes() / BLOCK_SIZE) * BLOCK_SIZE, Tresor::Request::WRITE, progress); + break; + + case PROTRUDING_LAST_BLK_READ: + + memcpy(&_blk, (void *)((addr_t)req._buf.start + _curr_buf_off()), _num_remaining_bytes()); + _curr_buf_addr = (addr_t)&_blk; + _generate_req( + PROTRUDING_LAST_BLK_WRITTEN, progress, Tresor::Request::WRITE, _curr_vba(), 0, 1, req._key_id, id(), _gen); + break; + + case PROTRUDING_LAST_BLK_WRITTEN: _advance_curr_off(_num_remaining_bytes(), Tresor::Request::WRITE, progress); break; + default: break; + } +} + + +void Splitter_channel::_read(bool &progress) +{ + Splitter_request &req { *_req_ptr }; + switch (_state) { + case REQ_SUBMITTED: + + _curr_off = 0; + _gen = req._gen; + _advance_curr_off(req._off, Tresor::Request::READ, progress); + break; + + case PROTRUDING_FIRST_BLK_READ: + { + size_t num_outside_bytes { _curr_off % BLOCK_SIZE }; + size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) }; + memcpy(req._buf.start, (void *)((addr_t)&_blk + num_outside_bytes), num_inside_bytes); + _advance_curr_off(num_inside_bytes, Tresor::Request::READ, progress); + break; + } + case INSIDE_BLKS_ACCESSED: + + _advance_curr_off((_num_remaining_bytes() / BLOCK_SIZE) * BLOCK_SIZE, Tresor::Request::READ, progress); + break; + + case PROTRUDING_LAST_BLK_READ: + + memcpy((void *)((addr_t)req._buf.start + _curr_buf_off()), &_blk, _num_remaining_bytes()); + _advance_curr_off(_num_remaining_bytes(), Tresor::Request::READ, progress); + break; + + default: break; + } +} + + +void Splitter_channel::execute(bool &progress) +{ + if (!_req_ptr) + return; + + switch (_req_ptr->_op) { + case Request::READ: _read(progress); break; + case Request::WRITE: _write(progress); break; + } +} + + +Block &Splitter_channel::_blk_buf_for_vba(Virtual_block_address vba) +{ + ASSERT(_state == REQ_GENERATED); + return *(Block *)(_curr_buf_addr + (vba - _curr_vba()) * BLOCK_SIZE); +} + + +Block const &Splitter::src_for_writing_vba(Request_tag tag, Virtual_block_address vba) +{ + Block const *blk_ptr { }; + with_channel(tag, [&] (Splitter_channel &chan) { + blk_ptr = &chan.src_for_writing_vba(vba); }); + ASSERT(blk_ptr); + return *blk_ptr; +} + + +Block &Splitter::dst_for_reading_vba(Request_tag tag, Virtual_block_address vba) +{ + Block *blk_ptr { }; + with_channel(tag, [&] (Splitter_channel &chan) { + blk_ptr = &chan.dst_for_reading_vba(vba); }); + ASSERT(blk_ptr); + return *blk_ptr; +} + + +Splitter::Splitter() +{ + Module_channel_id id { 0 }; + for (Constructible &chan : _channels) { + chan.construct(id++); + add_channel(*chan); + } +} + + +void Splitter::execute(bool &progress) +{ + for_each_channel([&] (Splitter_channel &chan) { + chan.execute(progress); }); +} diff --git a/repos/gems/src/lib/vfs/tresor/splitter.h b/repos/gems/src/lib/vfs/tresor/splitter.h new file mode 100644 index 0000000000..bf244687b9 --- /dev/null +++ b/repos/gems/src/lib/vfs/tresor/splitter.h @@ -0,0 +1,156 @@ +/* + * \brief Module for splitting unaligned/uneven I/O requests + * \author Martin Stein + * \author Josef Soentgen + * \date 2023-09-11 + */ + +/* + * Copyright (C) 2023 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _TRESOR__IO_SPLITTER_H_ +#define _TRESOR__IO_SPLITTER_H_ + +/* tresor includes */ +#include + +namespace Tresor { + + struct Lookup_buffer : Genode::Interface + { + virtual Block const &src_for_writing_vba(Request_tag, Virtual_block_address) = 0; + virtual Block &dst_for_reading_vba(Request_tag, Virtual_block_address) = 0; + }; + + class Splitter_request; + class Splitter_channel; + class Splitter; +} + + +class Tresor::Splitter_request : public Tresor::Module_request +{ + friend class Splitter_channel; + + public: + + enum Operation { READ, WRITE }; + + private: + + Operation const _op; + Request_offset const _off; + Key_id const _key_id; + Generation const _gen; + Byte_range_ptr const _buf; + bool &_success; + + NONCOPYABLE(Splitter_request); + + public: + + Splitter_request(Module_id, Module_channel_id, Operation, bool &, Request_offset, Byte_range_ptr const &, Key_id, Generation); + + static char const *op_to_string(Operation); + + void print(Genode::Output &out) const override { Genode::print(out, op_to_string(_op), " off ", _off, " size ", _buf.num_bytes); } +}; + + +class Tresor::Splitter_channel : public Tresor::Module_channel +{ + private: + + using Request = Splitter_request; + + + enum State : State_uint { + PROTRUDING_FIRST_BLK_WRITTEN, PROTRUDING_LAST_BLK_WRITTEN, PROTRUDING_FIRST_BLK_READ, PROTRUDING_LAST_BLK_READ, INSIDE_BLKS_ACCESSED, + REQ_SUBMITTED, REQ_GENERATED, REQ_COMPLETE }; + + State _state { }; + Request *_req_ptr { }; + addr_t _curr_off { }; + addr_t _curr_buf_addr { }; + Block _blk { }; + Generation _gen { }; + bool _generated_req_success { }; + + NONCOPYABLE(Splitter_channel); + + void _generated_req_completed(State_uint) override; + + void _request_submitted(Module_request &) override; + + bool _request_complete() override { return _state == REQ_COMPLETE; } + + Virtual_block_address _curr_vba() const { return (Virtual_block_address)(_curr_off / BLOCK_SIZE); } + + addr_t _curr_buf_off() const + { + ASSERT(_curr_off >= _req_ptr->_off && _curr_off <= _req_ptr->_off + _req_ptr->_buf.num_bytes); + return _curr_off - _req_ptr->_off; + } + + addr_t _num_remaining_bytes() const + { + ASSERT(_curr_off >= _req_ptr->_off && _curr_off <= _req_ptr->_off + _req_ptr->_buf.num_bytes); + return _req_ptr->_off + _req_ptr->_buf.num_bytes - _curr_off; + } + + template + void _generate_req(State_uint state, bool &progress, ARGS &&... args) + { + _state = REQ_GENERATED; + generate_req(state, progress, args..., _generated_req_success); + } + + void _mark_req_successful(bool &); + + void _advance_curr_off(addr_t, Tresor::Request::Operation, bool &); + + void _read(bool &progress); + + void _write(bool &progress); + + Block &_blk_buf_for_vba(Virtual_block_address); + + public: + + Splitter_channel(Module_channel_id id) : Module_channel { SPLITTER, id } { } + + void execute(bool &progress); + + Block const &src_for_writing_vba(Virtual_block_address vba) { return _blk_buf_for_vba(vba); } + + Block &dst_for_reading_vba(Virtual_block_address vba) { return _blk_buf_for_vba(vba); } +}; + + +class Tresor::Splitter : public Tresor::Module, public Tresor::Lookup_buffer +{ + private: + + using Channel = Splitter_channel; + + Constructible _channels[1] { }; + + NONCOPYABLE(Splitter); + + public: + + Splitter(); + + void execute(bool &) override; + + Block const &src_for_writing_vba(Request_tag, Virtual_block_address) override; + + Block &dst_for_reading_vba(Request_tag, Virtual_block_address) override; +}; + + +#endif /* _TRESOR__IO_SPLITTER_H_ */ diff --git a/repos/gems/src/lib/vfs/tresor/vfs.cc b/repos/gems/src/lib/vfs/tresor/vfs.cc index 9195163e87..87474c3f49 100644 --- a/repos/gems/src/lib/vfs/tresor/vfs.cc +++ b/repos/gems/src/lib/vfs/tresor/vfs.cc @@ -24,13 +24,13 @@ #include #include #include -#include #include #include #include #include #include +#include "splitter.h" namespace Vfs_tresor { using namespace Vfs; @@ -59,6 +59,7 @@ namespace Vfs_tresor { struct Local_factory; class File_system; + class Client_data; class Wrapper; template @@ -86,7 +87,43 @@ namespace Vfs_tresor { bool valid() const { return _obj != nullptr; } }; -} +} /* namespace Vfs_tresor */ + + +class Vfs_tresor::Client_data : public Tresor::Module, public Tresor::Module_channel +{ + private: + + using Request = Client_data_request; + + Lookup_buffer &_lookup; + + NONCOPYABLE(Client_data); + + void _request_submitted(Module_request &mod_req) override + { + Request &req { *static_cast(&mod_req) }; + switch (req._type) { + case Request::OBTAIN_PLAINTEXT_BLK: + { + req._blk = _lookup.src_for_writing_vba(req._req_tag, req._vba); + req._success = true; + break; + } + case Request::SUPPLY_PLAINTEXT_BLK: + { + _lookup.dst_for_reading_vba(req._req_tag, req._vba) = req._blk; + req._success = true; + break; + } } + } + + bool _request_complete() override { return true; } + + public: + + Client_data(Lookup_buffer &lb) : Module_channel { CLIENT_DATA, 0 }, _lookup { lb } { add_channel(*this);} +}; class Vfs_tresor::Wrapper @@ -96,203 +133,220 @@ class Vfs_tresor::Wrapper { private: + NONCOPYABLE(Wrapper); + Vfs::Env &_vfs_env; - Constructible _request_pool { }; + Constructible _request_pool { }; Constructible _free_tree { }; - Constructible _ft_resizing { }; - Constructible _vbd { }; - Constructible _sb_control { }; + Constructible _vbd { }; + Constructible _sb_control { }; Tresor::Meta_tree _meta_tree { }; Constructible _trust_anchor { }; Constructible _crypto { }; Constructible _block_io { }; - Client_data_request _client_data_request { }; + Constructible _splitter { }; + Constructible _client_data { }; + public: - /******************************** - ** Module API for Client_data ** - ********************************/ + enum class Result { UNKNOWN, OK, ERROR, EOF }; - bool ready_to_submit_request() override + + private: + + class Command : public Module_channel { - return _client_data_request._type == Client_data_request::INVALID; + public: + + using Operation = Tresor::Request::Operation; + + enum State { IDLE, PENDING, IN_PROGRESS, COMPLETED }; + + static char const *op_to_string(Command::Operation op) { + return Tresor::Request::op_to_string(op); } + + private: + + NONCOPYABLE(Command); + + Vfs_tresor::Wrapper &_main; + + State _state { IDLE }; + bool _success { false }; + + void _generated_req_completed(State_uint) override { _main.mark_command_completed(id()); } + + public: + + Result result { Result::UNKNOWN }; + Operation op { Operation::READ }; + Number_of_blocks count { 0 }; + Generation gen { 0 }; + Key_id key_id { 0 }; + + /* for READ/WRITE */ + Genode::uint64_t offset { 0 }; + char *buffer_start { nullptr }; + size_t buffer_num_bytes { 0 }; + + Command(Vfs_tresor::Wrapper &main, Module_channel_id id) + : Module_channel { COMMAND_POOL, id }, _main { main } { } + + void reset() + { + _success = false; + + result = Result::UNKNOWN; + op = Operation::READ; + count = 0; + gen = 0; + key_id = 0; + offset = 0; + buffer_start = nullptr; + buffer_num_bytes = 0; + } + + bool success() const { return _success; } + + bool eof(Virtual_block_address max) const { + return offset / Tresor::BLOCK_SIZE > max; } + + bool synchronize() const { return op == Operation::SYNC; } + + State state() const { return _state; } + + void state(State state) + { + ASSERT(state != _state); + _state = state; + } + + void execute(bool verbose, bool &progress) + { + ASSERT(_state == State::PENDING); + + if (verbose) + log("Execute request ", *this); + + switch (op) { + case Command::Operation::READ: + generate_req(State::COMPLETED, + progress, Splitter_request::Operation::READ, _success, + offset, Byte_range_ptr(buffer_start, buffer_num_bytes), key_id, gen); + break; + case Command::Operation::WRITE: + generate_req(State::COMPLETED, + progress, Splitter_request::Operation::WRITE, _success, + offset, Byte_range_ptr(buffer_start, buffer_num_bytes), key_id, gen); + break; + default: + generate_req(State::COMPLETED, + progress, op, 0, 0, count, key_id, id(), gen, _success); + break; + } + + _main.mark_command_in_progress(id()); + } + + void print(Genode::Output &out) const + { + Genode::print(out, "op: ", op_to_string(op), " " + "count: ", count, " " + "gen: ", gen, " " + "key_id: ", key_id, " " + "offset: ", offset, " " + "buffer_start: ", (void*)buffer_start, " " + "buffer_num_bytes: ", buffer_num_bytes); + } + }; + + template + void _with_first_processable_cmd(FUNC && func) + { + bool first_uncompleted_cmd { true }; + bool done { false }; + for_each_channel([&] (Command &cmd) { + + if (done) + return; + + if (cmd.state() == Command::PENDING) { + done = true; + if (first_uncompleted_cmd || !cmd.synchronize()) + func(cmd); + } + + if (cmd.state() == Command::IN_PROGRESS) { + if (cmd.synchronize()) + done = true; + else + first_uncompleted_cmd = false; + } + }); } - void submit_request(Module_request &req) override + template + bool _with_first_idle_cmd(FUNC && func) { - if (_client_data_request._type != Client_data_request::INVALID) { + bool done { false }; + for_each_channel([&] (Command &cmd) { + if (done) + return; - class Exception_1 { }; - throw Exception_1 { }; - } - req.dst_request_id(0); - _client_data_request = *dynamic_cast(&req); - switch (_client_data_request._type) { - case Client_data_request::OBTAIN_PLAINTEXT_BLK: - { - void const *src = - _lookup_write_buffer(_client_data_request._client_req_tag, - _client_data_request._vba); - if (src == nullptr) { - _client_data_request._success = false; - break; + if (cmd.state() == Command::IDLE) { + done = true; + /* + * Always provide a fresh Command to ease burden on + * the callee and set it PENDING afterwards as + * 'func' may not fail. + */ + cmd.reset(); + func(cmd); + cmd.state(Command::PENDING); } - - (void)memcpy((void*)_client_data_request._plaintext_blk_ptr, - src, sizeof(Tresor::Block)); - - _client_data_request._success = true; - break; - } - case Client_data_request::SUPPLY_PLAINTEXT_BLK: - { - void *dst = - _lookup_read_buffer(_client_data_request._client_req_tag, - _client_data_request._vba); - if (dst == nullptr) { - _client_data_request._success = false; - break; - } - - (void)memcpy(dst, (void const*)_client_data_request._plaintext_blk_ptr, - sizeof(Tresor::Block)); - - _client_data_request._success = true; - break; - } - case Client_data_request::INVALID: - - class Exception_2 { }; - throw Exception_2 { }; - } + }); + return done; } - void execute(bool &progress) override + enum { MAX_NUM_COMMANDS = 16 }; + Constructible _commands[MAX_NUM_COMMANDS] { }; + + bool ready_to_submit_request() { - if (_helper_read_request.pending()) { - if (_request_pool->ready_to_submit_request()) { - _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; - } - } - - if (_helper_write_request.pending()) { - if (_request_pool->ready_to_submit_request()) { - _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; - } - } - - if (_frontend_request.pending()) { - - using ST = Frontend_request::State; - - Tresor::Request &request = _frontend_request.tresor_request; - - if (_request_pool->ready_to_submit_request()) { - _request_pool->submit_request(request); - _frontend_request.state = ST::IN_PROGRESS; - progress = true; - } - } + bool result = false; + for_each_channel([&] (Command const &cmd) { + if (cmd.state() == Command::State::IDLE) + result = true; + }); + return result; } - bool _peek_completed_request(Genode::uint8_t *buf_ptr, - Genode::size_t buf_size) override - { - if (_client_data_request._type != Client_data_request::INVALID) { - if (sizeof(_client_data_request) > buf_size) { - class Exception_1 { }; - throw Exception_1 { }; - } - Genode::memcpy(buf_ptr, &_client_data_request, - sizeof(_client_data_request));; - return true; - } - return false; - } + public: - void _drop_completed_request(Module_request &) override - { - if (_client_data_request._type == Client_data_request::INVALID) { - class Exception_2 { }; - throw Exception_2 { }; - } - _client_data_request._type = Client_data_request::INVALID; - } - - struct Rekeying + struct Control_request { enum State { UNKNOWN, IDLE, IN_PROGRESS, }; enum Result { NONE, SUCCESS, FAILED, }; - State state; - Result last_result; - uint32_t key_id; - Virtual_block_address max_vba; - Virtual_block_address rekeying_vba; - uint64_t percent_done; - - bool idle() const { return state == IDLE; } - bool in_progress() const { return state == IN_PROGRESS; } - - bool success() const { return last_result == SUCCESS; } - - static char const *state_to_cstring(State const s) - { - switch (s) { - case State::UNKNOWN: return "unknown"; - case State::IDLE: return "idle"; - case State::IN_PROGRESS: return "in-progress"; - } - - return "-"; - } - }; - - struct Deinitialize - { - enum State { IDLE, IN_PROGRESS, }; - enum Result { NONE, SUCCESS, FAILED, }; - State state; - Result last_result; - uint32_t key_id; - - static char const *state_to_cstring(State const s) - { - switch (s) { - case State::IDLE: return "idle"; - case State::IN_PROGRESS: return "in-progress"; - } - - return "-"; - } - }; - - struct Extending - { - enum Type { INVALID, VBD, FT }; - enum State { UNKNOWN, IDLE, IN_PROGRESS, }; - enum Result { NONE, SUCCESS, FAILED, }; - Type type; State state; Result last_result; - Virtual_block_address resizing_nr_of_pbas; - uint64_t percent_done; + Control_request() : state { State::UNKNOWN }, last_result { Result::NONE } { } bool idle() const { return state == IDLE; } bool in_progress() const { return state == IN_PROGRESS; } bool success() const { return last_result == SUCCESS; } + void mark_in_progress() + { + state = State::IN_PROGRESS; + last_result = Result::NONE; + } + static char const *state_to_cstring(State const s) { switch (s) { @@ -300,9 +354,56 @@ class Vfs_tresor::Wrapper case State::IDLE: return "idle"; case State::IN_PROGRESS: return "in-progress"; } - return "-"; } + }; + + struct Rekeying : Control_request + { + uint32_t key_id; + Virtual_block_address max_vba; + Virtual_block_address rekeying_vba; + uint64_t percent_done; + + Rekeying() : Control_request { }, key_id { 0 }, max_vba { 0 }, + rekeying_vba { 0 }, percent_done { 0 } { } + + void mark_in_progress(Virtual_block_address max, + Virtual_block_address rekeying) + { + max_vba = max; + rekeying_vba = rekeying; + Control_request::mark_in_progress(); + } + }; + + struct Deinitialize : Control_request + { + uint32_t key_id; + + Deinitialize() : Control_request { }, key_id { 0 } + { + state = State::IDLE; + } + }; + + struct Extending : Control_request + { + enum Type { INVALID, VBD, FT }; + + Type type; + Virtual_block_address resizing_nr_of_pbas; + uint64_t percent_done; + + Extending() : Control_request { }, type { Type::INVALID}, + resizing_nr_of_pbas { 0 }, percent_done { 0 } { } + + void mark_in_progress(Type type, Virtual_block_address resizing_nr_of_pbas) + { + type = type; + resizing_nr_of_pbas = resizing_nr_of_pbas; + Control_request::mark_in_progress(); + } static Type string_to_type(char const *s) { @@ -320,42 +421,80 @@ class Vfs_tresor::Wrapper static char const *type_to_string(Type type) { switch (type) { - case Type::VBD: - return "vbd"; - case Type::FT: - return "ft"; - case Type::INVALID: - return "invalid"; + case Type::VBD: return "vbd"; + case Type::FT: return "ft"; + case Type::INVALID: return "invalid"; } - return nullptr; } }; private: - Rekeying _rekey_obj { - .state = Rekeying::State::UNKNOWN, - .last_result = Rekeying::Result::NONE, - .key_id = 0, - .max_vba = 0, - .rekeying_vba = 0, - .percent_done = 0, }; + /* + * XXX The initial object state of Rekeying and + * Extending relies on 'execute()' querying + * the Superblock_info to switch from UNKNOWN + * to the current state and could therefore + * deny attempts. + */ + Rekeying _rekey_obj { }; + Extending _extend_obj { }; + Deinitialize _deinit_obj { }; - Deinitialize _deinit_obj + Genode::Mutex _io_mutex { }; + Vfs_handle const *_io_handle_ptr { nullptr }; + Command *_io_cmd_ptr { nullptr }; + + bool _active_io_cmd_for_handle(Vfs_handle const &handle) const { + return _io_handle_ptr == &handle; } + + template + bool _setup_io_cmd_for_handle(Vfs_handle const &handle, + SETUP_FN const &setup_fn) { - .state = Deinitialize::State::IDLE, - .last_result = Deinitialize::Result::NONE, - .key_id = 0 - }; + ASSERT(_io_handle_ptr == nullptr); - Extending _extend_obj { - .type = Extending::Type::INVALID, - .state = Extending::State::UNKNOWN, - .last_result = Extending::Result::NONE, - .resizing_nr_of_pbas = 0, - .percent_done = 0, - }; + bool done = _with_first_idle_cmd([&] (Command &cmd) { + setup_fn(cmd); + + _io_cmd_ptr = &cmd; + _io_handle_ptr = &handle; + }); + return done; + } + + template + bool _with_io_active_cmd_for_handle(Vfs_handle const &handle, + PENDING_FN const &pending_fn, + COMPLETE_FN const &complete_fn) + { + bool found = false; + if (_io_handle_ptr && _io_handle_ptr == &handle) { + if (_io_cmd_ptr) { + Command &cmd = *_io_cmd_ptr; + + switch (cmd.state()) { + case Command::State::IDLE: + /* should never happen */ + break; + case Command::State::PENDING: [[fallthrough]]; + case Command::State::IN_PROGRESS: + pending_fn(); + break; + case Command::State::COMPLETED: + complete_fn(*_io_cmd_ptr); + cmd.state(Command::IDLE); + + _io_cmd_ptr = nullptr; + _io_handle_ptr = nullptr; + break; + } + found = true; + } + } + return found; + } Pointer _snapshots_fs { }; Pointer _extend_fs { }; @@ -379,232 +518,452 @@ class Vfs_tresor::Wrapper void _initialize_tresor() { - _ft_resizing.construct(); - add_module(FT_RESIZING, *_ft_resizing); - _free_tree.construct(); - add_module(FREE_TREE, *_free_tree); - _vbd.construct(); - add_module(VIRTUAL_BLOCK_DEVICE, *_vbd); - _sb_control.construct(); - add_module(SUPERBLOCK_CONTROL, *_sb_control); - _request_pool.construct(); + + add_module(FREE_TREE, *_free_tree); + add_module(VIRTUAL_BLOCK_DEVICE, *_vbd); + add_module(SUPERBLOCK_CONTROL, *_sb_control); add_module(REQUEST_POOL, *_request_pool); + + Module_channel_id id = 0; + for (auto & cmd : _commands) { + cmd.construct(*this, id++); + add_channel(*cmd); + } } - /***************************** - ** COMMAND_POOL Module API ** - *****************************/ - - bool _peek_generated_request(Genode::uint8_t * /* buf_ptr */, - Genode::size_t /* buf_size */) override + void _process_completed(Command &cmd) { - return false; + using R = Result; + + bool const success = cmd.success(); + + if (_verbose) + log("Completed request ", cmd, " ", + success ? "successfull" : "failed"); + + switch (cmd.op) { + case Command::Operation::REKEY: + { + _rekey_obj.state = Rekeying::State::IDLE; + _rekey_obj.last_result = success ? Rekeying::Result::SUCCESS + : Rekeying::Result::FAILED; + + _rekey_fs_trigger_watch_response(); + _rekey_progress_fs_trigger_watch_response(); + + cmd.state(Command::IDLE); + break; + } + case Command::Operation::DEINITIALIZE: + { + _deinit_obj.state = Deinitialize::State::IDLE; + _deinit_obj.last_result = success ? Deinitialize::Result::SUCCESS + : Deinitialize::Result::FAILED; + + _deinit_fs_trigger_watch_response(); + + cmd.state(Command::IDLE); + break; + } + case Command::Operation::EXTEND_VBD: + { + _extend_obj.state = Extending::State::IDLE; + _extend_obj.last_result = + success ? Extending::Result::SUCCESS + : Extending::Result::FAILED; + + _extend_fs_trigger_watch_response(); + _extend_progress_fs_trigger_watch_response(); + + cmd.state(Command::IDLE); + break; + } + case Command::Operation::EXTEND_FT: + { + _extend_obj.state = Extending::State::IDLE; + _extend_obj.last_result = + success ? Extending::Result::SUCCESS + : Extending::Result::FAILED; + + _extend_fs_trigger_watch_response(); + + cmd.state(Command::IDLE); + break; + } + case Command::Operation::CREATE_SNAPSHOT: + { + // FIXME more TODO here? + _snapshots_fs_update_snapshot_registry(); + + cmd.state(Command::IDLE); + break; + } + case Command::Operation::DISCARD_SNAPSHOT: + { + // FIXME more TODO here? + _snapshots_fs_update_snapshot_registry(); + + cmd.state(Command::IDLE); + break; + } + case Command::Operation::READ: [[fallthrough]]; + case Command::Operation::WRITE: + { + bool const eof = cmd.eof(_sb_control->max_vba()); + + cmd.result = success ? R::OK + : eof ? R::EOF + : R::ERROR; + break; + } + case Command::Operation::SYNC: + cmd.result = success ? R::OK : R::ERROR; + break; + /* not handled here */ + case Command::Operation::RESUME_REKEYING: + cmd.result = success ? R::OK : R::ERROR; + break; + case Command::Operation::INITIALIZE: + cmd.result = success ? R::OK : R::ERROR; + break; + } /* switch */ } - void _drop_generated_request(Module_request &/* mod_req */) override { } + void _snapshots_fs_update_snapshot_registry(); + + void _extend_fs_trigger_watch_response(); + + void _extend_progress_fs_trigger_watch_response(); + + void _rekey_fs_trigger_watch_response(); + + void _rekey_progress_fs_trigger_watch_response(); + + void _deinit_fs_trigger_watch_response(); + + template + void _with_node(char const *name, char const *path, FN const &fn) + { + char xml_buffer[128] { }; + + Genode::Xml_generator xml { + xml_buffer, sizeof(xml_buffer), name, + [&] { xml.attribute("path", path); } + }; + + Genode::Xml_node node { xml_buffer, sizeof(xml_buffer) }; + fn(node); + } public: - void generated_request_complete(Module_request &mod_req) override + Wrapper(Vfs::Env &vfs_env, Xml_node config) : _vfs_env { vfs_env } { - using ST = Frontend_request::State; + _read_config(config); - switch (mod_req.dst_module_id()) { - case REQUEST_POOL: - { - Request const &tresor_request { - *static_cast(&mod_req)}; + using S = Genode::String<32>; - if (tresor_request.operation() == Tresor::Request::Operation::REKEY) { - bool const req_sucess = tresor_request.success(); - if (_verbose) { - log("Complete request: backend request (", tresor_request, ")"); - } - _rekey_obj.state = Rekeying::State::IDLE; - _rekey_obj.last_result = req_sucess ? Rekeying::Result::SUCCESS - : Rekeying::Result::FAILED; + S const block_path = + config.attribute_value("block", S()); + if (block_path.valid()) + _with_node("block_io", block_path.string(), + [&] (Xml_node const &node) { + _block_io.construct(vfs_env, node); + }); - _rekey_fs_trigger_watch_response(); - _rekey_progress_fs_trigger_watch_response(); - break; + S const trust_anchor_path = + config.attribute_value("trust_anchor", S()); + if (trust_anchor_path.valid()) + _with_node("trust_anchor", trust_anchor_path.string(), + [&] (Xml_node const &node) { + _trust_anchor.construct(vfs_env, node); + }); + + S const crypto_path = + config.attribute_value("crypto", S()); + if (crypto_path.valid()) + _with_node("crypto", crypto_path.string(), + [&] (Xml_node const &node) { + _crypto.construct(vfs_env, node); + }); + + _splitter.construct(); + _client_data.construct(*_splitter); + + add_module(COMMAND_POOL, *this); + add_module(META_TREE, _meta_tree); + add_module(CRYPTO, *_crypto); + add_module(TRUST_ANCHOR, *_trust_anchor); + add_module(CLIENT_DATA, *_client_data); + add_module(BLOCK_IO, *_block_io); + add_module(SPLITTER, *_splitter); + + _initialize_tresor(); + } + + void mark_command_in_progress(Module_channel_id cmd_id) + { + with_channel(cmd_id, [&] (Command &cmd) { + cmd.state(Command::IN_PROGRESS); + }); + } + + void mark_command_completed(Module_channel_id cmd_id) + { + with_channel(cmd_id, [&] (Command &cmd) { + cmd.state(Command::COMPLETED); + _process_completed(cmd); + }); + } + + void execute(bool &progress) override + { + _with_first_processable_cmd([&] (Command &cmd) { + cmd.execute(_verbose, progress); + }); + } + + Genode::uint64_t max_vba() + { + return _sb_control->max_vba(); + } + + /* + * Handle a I/O request + * + * We rely on the 'handle' as well as the memory covered by + * 'data' being valid throughout the processing of the pending + * request. + */ + template + void handle_io_request(Vfs_handle const &handle, + Byte_range_ptr const &data, + Tresor::Request::Operation op, + Generation gen, + PENDING_FN const &pending_fn, + COMPLETE_FN const &complete_fn) + { + + Genode::Mutex::Guard guard { _io_mutex }; + + /* queue new I/O request */ + if (!_active_io_cmd_for_handle(handle)) { + bool const done = + _setup_io_cmd_for_handle(handle, [&] (Command &cmd) { + + cmd.op = op; + cmd.gen = gen; + cmd.offset = handle.seek(); + /* make a copy as the object may be dynamic */ + cmd.buffer_start = data.start; + cmd.buffer_num_bytes = data.num_bytes; + }); + + if (!done) { + pending_fn(); + return; } - - if (tresor_request.operation() == Tresor::Request::Operation::DEINITIALIZE) { - bool const req_sucess = tresor_request.success(); - if (_verbose) { - log("Complete request: backend request (", tresor_request, ")"); - } - _deinit_obj.state = Deinitialize::State::IDLE; - _deinit_obj.last_result = req_sucess ? Deinitialize::Result::SUCCESS - : Deinitialize::Result::FAILED; - - _deinit_fs_trigger_watch_response(); - break; - } - - if (tresor_request.operation() == Tresor::Request::Operation::EXTEND_VBD) { - bool const req_sucess = tresor_request.success(); - if (_verbose) { - log("Complete request: backend request (", tresor_request, ")"); - } - _extend_obj.state = Extending::State::IDLE; - _extend_obj.last_result = - req_sucess ? Extending::Result::SUCCESS - : Extending::Result::FAILED; - - _extend_fs_trigger_watch_response(); - _extend_progress_fs_trigger_watch_response(); - break; - } - - if (tresor_request.operation() == Tresor::Request::Operation::EXTEND_FT) { - bool const req_sucess = tresor_request.success(); - if (_verbose) { - log("Complete request: backend request (", tresor_request, ")"); - } - _extend_obj.state = Extending::State::IDLE; - _extend_obj.last_result = - req_sucess ? Extending::Result::SUCCESS - : Extending::Result::FAILED; - - _extend_fs_trigger_watch_response(); - break; - } - - if (tresor_request.operation() == Tresor::Request::Operation::CREATE_SNAPSHOT) { - if (_verbose) { - log("Complete request: (", tresor_request, ")"); - } - _create_snapshot_request.tresor_request = Tresor::Request(); - _snapshots_fs_update_snapshot_registry(); - break; - } - - if (tresor_request.operation() == Tresor::Request::Operation::DISCARD_SNAPSHOT) { - if (_verbose) { - log("Complete request: (", tresor_request, ")"); - } - _discard_snapshot_request.tresor_request = Tresor::Request(); - _snapshots_fs_update_snapshot_registry(); - break; - } - - if (!tresor_request.success()) { - _helper_read_request.state = Helper_request::State::NONE; - _helper_write_request.state = Helper_request::State::NONE; - - bool const eof = tresor_request.block_number() > _sb_control->max_vba(); - _frontend_request.state = eof ? ST::ERROR_EOF : ST::ERROR; - _frontend_request.tresor_request.success(false); - if (_verbose) { - Genode::log("Request failed: ", - " (frontend request: ", _frontend_request.tresor_request, - " count: ", _frontend_request.count, ")"); - } - break; - } - - if (_helper_read_request.in_progress()) { - _helper_read_request.state = Helper_request::State::COMPLETE; - _helper_read_request.tresor_request.success( - tresor_request.success()); - } else if (_helper_write_request.in_progress()) { - _helper_write_request.state = Helper_request::State::COMPLETE; - _helper_write_request.tresor_request.success( - tresor_request.success()); - } else { - _frontend_request.state = ST::COMPLETE; - _frontend_request.tresor_request.success(tresor_request.success()); - if (_verbose) { - Genode::log("Complete request: ", - " (frontend request: ", _frontend_request.tresor_request, - " count: ", _frontend_request.count, ")"); - } - } - - if (_helper_read_request.complete()) { - if (_frontend_request.tresor_request.read()) { - char * dst = reinterpret_cast - (_frontend_request.tresor_request.offset()); - char const * src = reinterpret_cast - (&_helper_read_request.block_data) + _frontend_request.helper_offset; - - Genode::memcpy(dst, src, _frontend_request.count); - - _helper_read_request.state = Helper_request::State::NONE; - _frontend_request.state = ST::COMPLETE; - _frontend_request.tresor_request.success( - _helper_read_request.tresor_request.success()); - - if (_verbose) { - Genode::log("Complete unaligned READ request: ", - " (frontend request: ", _frontend_request.tresor_request, - " (helper request: ", _helper_read_request.tresor_request, - " offset: ", _frontend_request.helper_offset, - " count: ", _frontend_request.count, ")"); - } - } - - if (_frontend_request.tresor_request.write()) { - /* copy whole block first */ - { - char * dst = reinterpret_cast - (&_helper_write_request.block_data); - char const * src = reinterpret_cast - (&_helper_read_request.block_data); - Genode::memcpy(dst, src, sizeof (Tresor::Block)); - } - - /* and than actual request data */ - { - char * dst = reinterpret_cast - (&_helper_write_request.block_data) + _frontend_request.helper_offset; - char const * src = reinterpret_cast - (_frontend_request.tresor_request.offset()); - Genode::memcpy(dst, src, _frontend_request.count); - } - - /* re-use request */ - _helper_write_request.tresor_request = Tresor::Request( - Tresor::Request::Operation::WRITE, - false, - _helper_read_request.tresor_request.block_number(), - (uint64_t) &_helper_write_request.block_data, - _helper_read_request.tresor_request.count(), - _helper_read_request.tresor_request.key_id(), - _helper_read_request.tresor_request.tag(), - _helper_read_request.tresor_request.gen(), - COMMAND_POOL, 0); - - _helper_write_request.state = Helper_request::State::PENDING; - _helper_read_request.state = Helper_request::State::NONE; - } - } - - if (_helper_write_request.complete()) { - if (_verbose) { - Genode::log("Complete unaligned WRITE request: ", - " (frontend request: ", _frontend_request.tresor_request, - " (helper request: ", _helper_read_request.tresor_request, - " offset: ", _frontend_request.helper_offset, - " count: ", _frontend_request.count, ")"); - } - - _helper_write_request.state = Helper_request::State::NONE; - _frontend_request.state = ST::COMPLETE; - } - break; } - default: - class Exception_2 { }; - throw Exception_2 { }; + + execute(); + + _with_io_active_cmd_for_handle(handle, + [&] { pending_fn(); }, + [&] (Command const &cmd) { + complete_fn(cmd.result, + cmd.buffer_num_bytes); + }); + } + + void execute() + { + execute_modules(); + _vfs_env.io().commit(); + + Tresor::Superblock_info const sb_info { + _sb_control->sb_info() }; + + using ES = Extending::State; + if (_extend_obj.state == ES::UNKNOWN && sb_info.valid) { + if (sb_info.extending_ft) { + + _extend_obj.state = ES::IN_PROGRESS; + _extend_obj.type = Extending::Type::FT; + } else + + if (sb_info.extending_vbd) { + + _extend_obj.state = ES::IN_PROGRESS; + _extend_obj.type = Extending::Type::VBD; + } else { + + _extend_obj.state = ES::IDLE; + } + _extend_fs_trigger_watch_response(); + } + + if (_extend_obj.in_progress()) { + + Virtual_block_address const current_nr_of_pbas = + _sb_control->resizing_nr_of_pbas(); + + /* initial query */ + if (_extend_obj.resizing_nr_of_pbas == 0) + _extend_obj.resizing_nr_of_pbas = current_nr_of_pbas; + + /* update user-facing state */ + uint64_t const last_percent_done = _extend_obj.percent_done; + _extend_obj.percent_done = + (_extend_obj.resizing_nr_of_pbas - current_nr_of_pbas) + * 100 / _extend_obj.resizing_nr_of_pbas; + + if (last_percent_done != _extend_obj.percent_done) + _extend_progress_fs_trigger_watch_response(); + } + + using RS = Rekeying::State; + if (_rekey_obj.state == RS::UNKNOWN && sb_info.valid) { + _rekey_obj.state = + sb_info.rekeying ? RS::IN_PROGRESS : RS::IDLE; + + _rekey_fs_trigger_watch_response(); + } + + if (_rekey_obj.in_progress()) { + _rekey_obj.rekeying_vba = _sb_control->rekeying_vba(); + + /* update user-facing state */ + uint64_t const last_percent_done = _rekey_obj.percent_done; + _rekey_obj.percent_done = + _rekey_obj.rekeying_vba * 100 / _rekey_obj.max_vba; + + if (last_percent_done != _rekey_obj.percent_done) + _rekey_progress_fs_trigger_watch_response(); } } + bool start_rekeying() + { + if (!ready_to_submit_request()) + return false; + + bool result = _with_first_idle_cmd([&] (Command &cmd) { + + cmd.op = Command::Operation::REKEY; + cmd.key_id = _rekey_obj.key_id; + + _rekey_obj.mark_in_progress(_sb_control->max_vba(), + _sb_control->rekeying_vba()); + + _rekey_fs_trigger_watch_response(); + _rekey_progress_fs_trigger_watch_response(); + }); + + execute(); + return result; + } + + Rekeying const rekeying_progress() const { + return _rekey_obj; } + + bool start_deinitialize() + { + if (!ready_to_submit_request()) + return false; + + bool result = _with_first_idle_cmd([&] (Command &cmd) { + + cmd.op = Command::Operation::DEINITIALIZE; + + _deinit_obj.mark_in_progress(); + _deinit_fs_trigger_watch_response(); + }); + + execute(); + return result; + } + + Deinitialize const deinitialize_progress() const { + return _deinit_obj; } + + bool start_extending(Extending::Type type, + Tresor::Number_of_blocks blocks) + { + if (!ready_to_submit_request() || type == Extending::Type::INVALID) + return false; + + Command::Operation op = Command::Operation::EXTEND_VBD; + + switch (type) { + case Extending::Type::VBD: + op = Command::Operation::EXTEND_VBD; + break; + case Extending::Type::FT: + op = Command::Operation::EXTEND_FT; + break; + case Extending::Type::INVALID: + /* never reached */ + return false; + } + + bool result = _with_first_idle_cmd([&] (Command &cmd) { + + cmd.op = op; + cmd.count = blocks; + + _extend_obj.mark_in_progress(type, 0); + + _extend_fs_trigger_watch_response(); + _extend_progress_fs_trigger_watch_response(); + }); + + execute(); + return result; + } + + Extending const extending_progress() const { + return _extend_obj; } + + void snapshots_info(Tresor::Snapshots_info &info) + { + info = _sb_control->snapshots_info(); + execute(); + } + + bool create_snapshot() + { + if (!ready_to_submit_request()) + return false; + + bool result = _with_first_idle_cmd([&] (Command &cmd) { + cmd.op = Command::Operation::CREATE_SNAPSHOT; }); + + execute(); + return result; + } + + bool discard_snapshot(Generation snap_gen) + { + if (!ready_to_submit_request()) + return false; + + bool result = _with_first_idle_cmd([&] (Command &cmd) { + cmd.op = Command::Operation::DISCARD_SNAPSHOT; + cmd.gen = snap_gen; + }); + + execute(); + return result; + } + + /*********************************************************** + ** Manange/Disolve interface needed for FS notifications ** + ***********************************************************/ + void manage_snapshots_file_system(Snapshots_file_system &snapshots_fs) { if (_snapshots_fs.valid()) { @@ -773,571 +1132,6 @@ class Vfs_tresor::Wrapper } } - template - void with_node(char const *name, char const *path, FN const &fn) - { - char xml_buffer[128] { }; - - Genode::Xml_generator xml { - xml_buffer, sizeof(xml_buffer), name, - [&] { xml.attribute("path", path); } - }; - - Genode::Xml_node node { xml_buffer, sizeof(xml_buffer) }; - fn(node); - } - - Wrapper(Vfs::Env &vfs_env, Xml_node config) : _vfs_env { vfs_env } - { - _read_config(config); - - using S = Genode::String<32>; - - S const block_path = - config.attribute_value("block", S()); - if (block_path.valid()) - with_node("block_io", block_path.string(), - [&] (Xml_node const &node) { - _block_io.construct(vfs_env, node); - }); - - S const trust_anchor_path = - config.attribute_value("trust_anchor", S()); - if (trust_anchor_path.valid()) - with_node("trust_anchor", trust_anchor_path.string(), - [&] (Xml_node const &node) { - _trust_anchor.construct(vfs_env, node); - }); - - S const crypto_path = - config.attribute_value("crypto", S()); - if (crypto_path.valid()) - with_node("crypto", crypto_path.string(), - [&] (Xml_node const &node) { - _crypto.construct(vfs_env, node); - }); - - add_module(COMMAND_POOL, *this); - add_module(META_TREE, _meta_tree); - add_module(CRYPTO, *_crypto); - add_module(TRUST_ANCHOR, *_trust_anchor); - add_module(CLIENT_DATA, *this); - add_module(BLOCK_IO, *_block_io); - - _initialize_tresor(); - } - - Tresor::Request_pool &tresor() - { - if (!_request_pool.constructed()) { - struct Tresor_Not_Initialized { }; - throw Tresor_Not_Initialized(); - } - - return *_request_pool; - } - - Genode::uint64_t max_vba() - { - return _sb_control->max_vba(); - } - - struct Invalid_Request : Genode::Exception { }; - - struct Helper_request - { - enum { BLOCK_SIZE = 512, }; - enum State { NONE, PENDING, IN_PROGRESS, COMPLETE, ERROR }; - - State state { NONE }; - - Tresor::Block block_data { }; - Tresor::Request tresor_request { }; - - bool pending() const { return state == PENDING; } - bool in_progress() const { return state == IN_PROGRESS; } - bool complete() const { return state == COMPLETE; } - }; - - Helper_request _helper_read_request { }; - Helper_request _helper_write_request { }; - - struct Frontend_request - { - enum State { - NONE, - PENDING, IN_PROGRESS, COMPLETE, - ERROR, ERROR_EOF - }; - State state { NONE }; - size_t count { 0 }; - Tresor::Request tresor_request { }; - void *data { nullptr }; - uint64_t offset { 0 }; - uint64_t helper_offset { 0 }; - - bool pending() const { return state == PENDING; } - bool in_progress() const { return state == IN_PROGRESS; } - bool complete() const { return state == COMPLETE; } - - static char const *state_to_string(State s) - { - switch (s) { - case State::NONE: return "NONE"; - case State::PENDING: return "PENDING"; - case State::IN_PROGRESS: return "IN_PROGRESS"; - case State::COMPLETE: return "COMPLETE"; - case State::ERROR: return "ERROR"; - case State::ERROR_EOF: return "ERROR_EOF"; - } - return ""; - } - }; - - uint64_t _next_client_request_tag() - { - static uint64_t _client_request_tag { 0 }; - return _client_request_tag++; - } - - void const *_lookup_write_buffer(Genode::uint64_t /* tag */, Genode::uint64_t /* vba */) - { - if (_helper_write_request.in_progress()) - return (void const*)&_helper_write_request.block_data; - if (_frontend_request.in_progress()) - return (void const*)_frontend_request.data; - - return nullptr; - } - - void *_lookup_read_buffer(Genode::uint64_t /* tag */, Genode::uint64_t /* vba */) - { - if (_helper_read_request.in_progress()) - return (void *)&_helper_read_request.block_data; - if (_frontend_request.in_progress()) - return (void *)_frontend_request.data; - - return nullptr; - } - - Frontend_request _frontend_request { }; - - Frontend_request const & frontend_request() const - { - return _frontend_request; - } - - void ack_frontend_request(Vfs_handle &/* handle */) - { - // assert current state was *_COMPLETE - _frontend_request.state = Frontend_request::State::NONE; - _frontend_request.tresor_request = Tresor::Request { }; - } - - 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; - } - - uint64_t const tag = _next_client_request_tag(); - - /* short-cut for SYNC requests */ - if (op == Tresor::Request::Operation::SYNC) { - _frontend_request.tresor_request = Tresor::Request( - op, - false, - 0, - 0, - 1, - 0, - (Genode::uint32_t)tag, - 0, - COMMAND_POOL, 0); - _frontend_request.count = 0; - _frontend_request.state = Frontend_request::State::PENDING; - if (_verbose) { - Genode::log("Req: (front req: ", - _frontend_request.tresor_request, ")"); - } - return true; - } - - file_size const offset = handle.seek(); - bool unaligned_request = false; - - /* unaligned request if any condition is true */ - unaligned_request |= (offset % Tresor::BLOCK_SIZE) != 0; - unaligned_request |= (data.num_bytes < Tresor::BLOCK_SIZE); - - size_t count = data.num_bytes; - - if ((count % Tresor::BLOCK_SIZE) != 0 && - !unaligned_request) - { - count = count - (count % Tresor::BLOCK_SIZE); - } - - if (unaligned_request) { - _helper_read_request.tresor_request = Tresor::Request( - Tresor::Request::Operation::READ, - false, - offset / Tresor::BLOCK_SIZE, - (uint64_t)&_helper_read_request.block_data, - 1, - 0, - (Genode::uint32_t)tag, - 0, - COMMAND_POOL, 0); - _helper_read_request.state = Helper_request::State::PENDING; - - _frontend_request.helper_offset = (offset % Tresor::BLOCK_SIZE); - if (count >= (Tresor::BLOCK_SIZE - _frontend_request.helper_offset)) { - - uint64_t const count_u64 { - Tresor::BLOCK_SIZE - _frontend_request.helper_offset }; - - if (count_u64 > ~(size_t)0) { - class Exception_3 { }; - throw Exception_3 { }; - } - _frontend_request.count = (size_t)count_u64; - } else { - _frontend_request.count = count; - } - - /* skip handling by Tresor library, helper requests will do that for us */ - _frontend_request.state = Frontend_request::State::IN_PROGRESS; - - } else { - _frontend_request.count = count; - _frontend_request.state = Frontend_request::State::PENDING; - } - - _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, gen, COMMAND_POOL, 0); - - if (_verbose) { - if (unaligned_request) { - Genode::log("Unaligned req: ", - "off: ", offset, " bytes: ", count, - " (front req: ", _frontend_request.tresor_request, - " (helper req: ", _helper_read_request.tresor_request, - " off: ", _frontend_request.helper_offset, - " count: ", _frontend_request.count, ")"); - } else { - Genode::log("Req: ", - "off: ", offset, " bytes: ", count, - " (front req: ", _frontend_request.tresor_request, ")"); - } - } - - return true; - } - - void _snapshots_fs_update_snapshot_registry(); - - void _extend_fs_trigger_watch_response(); - - void _extend_progress_fs_trigger_watch_response(); - - void _rekey_fs_trigger_watch_response(); - - void _rekey_progress_fs_trigger_watch_response(); - - void _deinit_fs_trigger_watch_response(); - - void handle_frontend_request() - { - bool progress { true }; - while (progress) { - - progress = false; - execute_modules(progress); - } - _vfs_env.io().commit(); - - Tresor::Superblock_info const sb_info { - _sb_control->sb_info() }; - - using ES = Extending::State; - if (_extend_obj.state == ES::UNKNOWN && sb_info.valid) { - if (sb_info.extending_ft) { - - _extend_obj.state = ES::IN_PROGRESS; - _extend_obj.type = Extending::Type::FT; - _extend_fs_trigger_watch_response(); - - } else - - if (sb_info.extending_vbd) { - - _extend_obj.state = ES::IN_PROGRESS; - _extend_obj.type = Extending::Type::VBD; - _extend_fs_trigger_watch_response(); - - } else { - - _extend_obj.state = ES::IDLE; - _extend_fs_trigger_watch_response(); - } - } - - if (_extend_obj.in_progress()) { - - Virtual_block_address const current_nr_of_pbas = - _sb_control->resizing_nr_of_pbas(); - - /* initial query */ - if (_extend_obj.resizing_nr_of_pbas == 0) - _extend_obj.resizing_nr_of_pbas = current_nr_of_pbas; - - /* update user-facing state */ - uint64_t const last_percent_done = _extend_obj.percent_done; - _extend_obj.percent_done = - (_extend_obj.resizing_nr_of_pbas - current_nr_of_pbas) - * 100 / _extend_obj.resizing_nr_of_pbas; - - if (last_percent_done != _extend_obj.percent_done) - _extend_progress_fs_trigger_watch_response(); - } - - using RS = Rekeying::State; - if (_rekey_obj.state == RS::UNKNOWN && sb_info.valid) { - _rekey_obj.state = - sb_info.rekeying ? RS::IN_PROGRESS : RS::IDLE; - - _rekey_fs_trigger_watch_response(); - } - - if (_rekey_obj.in_progress()) { - _rekey_obj.rekeying_vba = _sb_control->rekeying_vba(); - - /* update user-facing state */ - uint64_t const last_percent_done = _rekey_obj.percent_done; - _rekey_obj.percent_done = - _rekey_obj.rekeying_vba * 100 / _rekey_obj.max_vba; - - if (last_percent_done != _rekey_obj.percent_done) - _rekey_progress_fs_trigger_watch_response(); - } - } - - bool client_request_acceptable() - { - return _request_pool->ready_to_submit_request(); - } - - bool start_rekeying() - { - if (!_request_pool->ready_to_submit_request()) { - return false; - } - - Tresor::Request req( - Tresor::Request::Operation::REKEY, - false, - 0, 0, 0, - _rekey_obj.key_id, - 0, 0, - COMMAND_POOL, 0); - - if (_verbose) { - Genode::log("Req: (background req: ", req, ")"); - } - - _request_pool->submit_request(req); - _rekey_obj.state = Rekeying::State::IN_PROGRESS; - _rekey_obj.last_result = Rekeying::Rekeying::FAILED; - _rekey_obj.max_vba = _sb_control->max_vba(); - _rekey_obj.rekeying_vba = _sb_control->rekeying_vba(); - _rekey_fs_trigger_watch_response(); - _rekey_progress_fs_trigger_watch_response(); - - // XXX kick-off rekeying - handle_frontend_request(); - return true; - } - - Rekeying const rekeying_progress() const - { - return _rekey_obj; - } - - bool start_deinitialize() - { - if (!_request_pool->ready_to_submit_request()) { - return false; - } - - Tresor::Request req( - Tresor::Request::Operation::DEINITIALIZE, - false, - 0, 0, 0, - 0, - 0, 0, - COMMAND_POOL, 0); - - if (_verbose) { - Genode::log("Req: (background req: ", req, ")"); - } - - _request_pool->submit_request(req); - _deinit_obj.state = Deinitialize::State::IN_PROGRESS; - _deinit_obj.last_result = Deinitialize::Deinitialize::FAILED; - _deinit_fs_trigger_watch_response(); - - // XXX kick-off deinitialize - handle_frontend_request(); - return true; - } - - Deinitialize const deinitialize_progress() const - { - return _deinit_obj; - } - - - bool start_extending(Extending::Type type, - Tresor::Number_of_blocks blocks) - { - if (!_request_pool->ready_to_submit_request()) { - return false; - } - - Tresor::Request::Operation op = - Tresor::Request::Operation::INVALID; - - switch (type) { - case Extending::Type::VBD: - op = Tresor::Request::Operation::EXTEND_VBD; - break; - case Extending::Type::FT: - op = Tresor::Request::Operation::EXTEND_FT; - break; - case Extending::Type::INVALID: - return false; - } - - Tresor::Request req(op, false, - 0, 0, blocks, 0, 0, 0, - COMMAND_POOL, 0); - - if (_verbose) { - Genode::log("Req: (background req: ", req, ")"); - } - - _request_pool->submit_request(req); - _extend_obj.type = type; - _extend_obj.state = Extending::State::IN_PROGRESS; - _extend_obj.last_result = Extending::Result::NONE; - _extend_obj.resizing_nr_of_pbas = 0; - _extend_fs_trigger_watch_response(); - _extend_progress_fs_trigger_watch_response(); - - // XXX kick-off extending - handle_frontend_request(); - return true; - } - - Extending const extending_progress() const - { - return _extend_obj; - } - - void snapshot_generations(Tresor::Snapshot_generations &generations) - { - if (!_request_pool.constructed()) { - _initialize_tresor(); - } - _sb_control->snapshot_generations(generations); - handle_frontend_request(); - } - - - Frontend_request _create_snapshot_request { }; - - bool create_snapshot() - { - if (!_request_pool.constructed()) { - _initialize_tresor(); - } - - if (!_request_pool->ready_to_submit_request()) { - return false; - } - - if (_create_snapshot_request.tresor_request.valid()) { - return false; - } - - Tresor::Request::Operation const op = - Tresor::Request::Operation::CREATE_SNAPSHOT; - - _create_snapshot_request.tresor_request = - Tresor::Request(op, false, 0, 0, 1, 0, 0, 0, - COMMAND_POOL, 0); - - if (_verbose) { - Genode::log("Req: (req: ", _create_snapshot_request.tresor_request, ")"); - } - - _request_pool->submit_request(_create_snapshot_request.tresor_request); - - _create_snapshot_request.state = - Frontend_request::State::IN_PROGRESS; - - // XXX kick-off snapshot creation request - handle_frontend_request(); - return true; - } - - Frontend_request _discard_snapshot_request { }; - - bool discard_snapshot(Generation snap_gen) - { - if (!_request_pool.constructed()) { - _initialize_tresor(); - } - - if (!_request_pool->ready_to_submit_request()) { - return false; - } - - if (_discard_snapshot_request.tresor_request.valid()) { - return false; - } - - Tresor::Request::Operation const op = - Tresor::Request::Operation::DISCARD_SNAPSHOT; - - _discard_snapshot_request.tresor_request = - 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, ")"); - } - - _request_pool->submit_request(_discard_snapshot_request.tresor_request); - - _discard_snapshot_request.state = - Frontend_request::State::IN_PROGRESS; - - // XXX kick-off snapshot creation request - handle_frontend_request(); - return true; - } - - Genode::Mutex _frontend_mtx { }; - - Genode::Mutex &frontend_mtx() { return _frontend_mtx; } }; @@ -1348,6 +1142,46 @@ class Vfs_tresor::Data_file_system : public Single_file_system Wrapper &_w; Generation _snap_gen; + using OP = Tresor::Request::Operation; + using FR = Wrapper::Result; + using RR = Vfs::File_io_service::Read_result; + using SR = Vfs::File_io_service::Sync_result; + using WR = Vfs::File_io_service::Write_result; + + static RR read_result(FR r) + { + switch (r) { + case FR::OK: return RR::READ_OK; + case FR::EOF: return RR::READ_OK; + case FR::ERROR: return RR::READ_ERR_IO; + case FR::UNKNOWN: return RR::READ_ERR_INVALID; + } + return RR::READ_ERR_INVALID; + } + + static SR sync_result(FR r) + { + switch (r) { + case FR::OK: return SR::SYNC_OK; + case FR::EOF: return SR::SYNC_ERR_INVALID; + case FR::ERROR: return SR::SYNC_ERR_INVALID; + case FR::UNKNOWN: return SR::SYNC_ERR_INVALID; + } + return SR::SYNC_ERR_INVALID; + } + + static WR write_result(FR r) + { + switch (r) { + case FR::OK: return WR::WRITE_OK; + case FR::EOF: return WR::WRITE_OK; + case FR::ERROR: return WR::WRITE_ERR_IO; + case FR::UNKNOWN: return WR::WRITE_ERR_INVALID; + } + return WR::WRITE_ERR_INVALID; + } + + public: struct Vfs_handle : Single_vfs_handle @@ -1367,142 +1201,46 @@ class Vfs_tresor::Data_file_system : public Single_file_system Read_result read(Byte_range_ptr const &dst, size_t &out_count) override { - Genode::Mutex::Guard guard { _w.frontend_mtx() }; - - using State = Wrapper::Frontend_request::State; - - State state = _w.frontend_request().state; - if (state == State::NONE) { - - if (!_w.client_request_acceptable()) { - return READ_QUEUED; + RR result = RR::READ_ERR_INVALID; + _w.handle_io_request(*this, dst, OP::READ, _snap_gen, + [&] { result = READ_QUEUED; }, + [&] (FR fresult, size_t count) { + result = read_result(fresult); + out_count = count; } - using Op = Tresor::Request::Operation; - - bool const accepted = - _w.submit_frontend_request(*this, dst, Op::READ, _snap_gen); - if (!accepted) { return READ_ERR_IO; } - } - - _w.handle_frontend_request(); - state = _w.frontend_request().state; - - if ( state == State::PENDING - || state == State::IN_PROGRESS) { - return READ_QUEUED; - } - - if (state == State::COMPLETE) { - out_count = _w.frontend_request().count; - _w.ack_frontend_request(*this); - return READ_OK; - } - - if (state == State::ERROR_EOF) { - out_count = 0; - _w.ack_frontend_request(*this); - return READ_OK; - } - - if (state == State::ERROR) { - out_count = 0; - _w.ack_frontend_request(*this); - return READ_ERR_IO; - } - - return READ_ERR_IO; + ); + return result; } Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override { - Genode::Mutex::Guard guard { _w.frontend_mtx() }; - - using State = Wrapper::Frontend_request::State; - - State state = _w.frontend_request().state; - if (state == State::NONE) { - - if (!_w.client_request_acceptable()) - return Write_result::WRITE_ERR_WOULD_BLOCK; - - 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_gen); - if (!accepted) { return WRITE_ERR_IO; } - } - - _w.handle_frontend_request(); - state = _w.frontend_request().state; - - if ( state == State::PENDING - || state == State::IN_PROGRESS) { - return WRITE_ERR_WOULD_BLOCK; - } - - if (state == State::COMPLETE) { - out_count = _w.frontend_request().count; - _w.ack_frontend_request(*this); - return WRITE_OK; - } - - if (state == State::ERROR_EOF) { - out_count = 0; - _w.ack_frontend_request(*this); - return WRITE_OK; - } - - if (state == State::ERROR) { - out_count = 0; - _w.ack_frontend_request(*this); - return WRITE_ERR_IO; - } - - return WRITE_ERR_IO; + WR result = WR::WRITE_ERR_INVALID; + _w.handle_io_request(*this, + Byte_range_ptr(const_cast(src.start), + src.num_bytes), + OP::WRITE, _snap_gen, + [&] { result = WRITE_ERR_WOULD_BLOCK; }, + [&] (FR fresult, size_t count) { + result = write_result(fresult); + out_count = count; + } + ); + return result; } Sync_result sync() override { - Genode::Mutex::Guard guard { _w.frontend_mtx() }; - - using State = Wrapper::Frontend_request::State; - - State state = _w.frontend_request().state; - if (state == State::NONE) { - - if (!_w.client_request_acceptable()) { - return SYNC_QUEUED; + SR result = SR::SYNC_ERR_INVALID; + _w.handle_io_request(*this, + Byte_range_ptr(nullptr, 0), + OP::SYNC, 0, + [&] { result = SYNC_QUEUED; }, + [&] (FR fresult, size_t) { + result = sync_result(fresult); } - using Op = Tresor::Request::Operation; - - bool const accepted = - _w.submit_frontend_request(*this, Byte_range_ptr(nullptr, 0), - Op::SYNC, 0); - if (!accepted) { return SYNC_ERR_INVALID; } - } - - _w.handle_frontend_request(); - state = _w.frontend_request().state; - - if ( state == State::PENDING - || state == State::IN_PROGRESS) { - return SYNC_QUEUED; - } - - if (state == State::COMPLETE) { - _w.ack_frontend_request(*this); - return SYNC_OK; - } - - if (state == State::ERROR) { - _w.ack_frontend_request(*this); - return SYNC_ERR_INVALID; - } - - return SYNC_ERR_INVALID; + ); + return result; } bool read_ready() const override { return true; } @@ -1516,8 +1254,11 @@ class Vfs_tresor::Data_file_system : public Single_file_system _w(w), _snap_gen(snap_gen) { } - ~Data_file_system() { /* XXX sync on close */ } - + ~Data_file_system() + { + /* XXX sync on close */ + /* XXX invalidate any still pending request */ + } /********************************* ** Directory-service interface ** @@ -1525,12 +1266,6 @@ class Vfs_tresor::Data_file_system : public Single_file_system Stat_result stat(char const *path, Stat &out) override { - try { - (void)_w.tresor(); - } catch (...) { - return STAT_ERR_NO_ENTRY; - } - Stat_result result = Single_file_system::stat(path, out); /* max_vba range is from 0 ... N - 1 */ @@ -1538,16 +1273,12 @@ class Vfs_tresor::Data_file_system : public Single_file_system return result; } - /******************************** ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override - { - return FTRUNCATE_OK; - } - + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { + return FTRUNCATE_OK; } /*************************** ** File-system interface ** @@ -1560,12 +1291,6 @@ class Vfs_tresor::Data_file_system : public Single_file_system if (!_single_file(path)) return OPEN_ERR_UNACCESSIBLE; - try { - (void)_w.tresor(); - } catch (...) { - return OPEN_ERR_UNACCESSIBLE; - } - *out_handle = new (alloc) Vfs_handle(*this, *this, alloc, _w, _snap_gen); @@ -1624,7 +1349,7 @@ class Vfs_tresor::Extend_file_system : public Vfs::Single_file_system * For now trigger extending execution via this hook * like we do in the Data_file_system. */ - _w.handle_frontend_request(); + _w.execute(); Wrapper::Extending const & extending { _w.extending_progress() }; @@ -1647,8 +1372,7 @@ class Vfs_tresor::Extend_file_system : public Vfs::Single_file_system Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override { using Type = Wrapper::Extending::Type; - using State = Wrapper::Extending::State; - if (_w.extending_progress().state != State::IDLE) { + if (!_w.extending_progress().idle()) { return WRITE_ERR_IO; } @@ -1749,15 +1473,12 @@ class Vfs_tresor::Extend_file_system : public Vfs::Single_file_system return result; } - /******************************** ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override - { - return FTRUNCATE_OK; - } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { + return FTRUNCATE_OK; } }; @@ -1809,7 +1530,7 @@ class Vfs_tresor::Extend_progress_file_system : public Vfs::Single_file_system * For now trigger extending execution via this hook * like we do in the Data_file_system. */ - _w.handle_frontend_request(); + _w.execute(); Wrapper::Extending const & extending { _w.extending_progress() }; @@ -1920,10 +1641,8 @@ class Vfs_tresor::Extend_progress_file_system : public Vfs::Single_file_system ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override - { - return FTRUNCATE_OK; - } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { + return FTRUNCATE_OK; } }; @@ -1978,7 +1697,7 @@ class Vfs_tresor::Rekey_file_system : public Vfs::Single_file_system * For now trigger rekeying execution via this hook * like we do in the Data_file_system. */ - _w.handle_frontend_request(); + _w.execute(); Wrapper::Rekeying const & rekeying { _w.rekeying_progress() }; @@ -2000,8 +1719,7 @@ class Vfs_tresor::Rekey_file_system : public Vfs::Single_file_system Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override { - using State = Wrapper::Rekeying::State; - if (_w.rekeying_progress().state != State::IDLE) { + if (!_w.rekeying_progress().idle()) { return WRITE_ERR_IO; } @@ -2101,10 +1819,8 @@ class Vfs_tresor::Rekey_file_system : public Vfs::Single_file_system ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override - { - return FTRUNCATE_OK; - } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { + return FTRUNCATE_OK; } }; @@ -2156,7 +1872,7 @@ class Vfs_tresor::Rekey_progress_file_system : public Vfs::Single_file_system * For now trigger rekeying execution via this hook * like we do in the Data_file_system. */ - _w.handle_frontend_request(); + _w.execute(); Wrapper::Rekeying const & rekeying { _w.rekeying_progress() }; @@ -2265,10 +1981,8 @@ class Vfs_tresor::Rekey_progress_file_system : public Vfs::Single_file_system ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override - { - return FTRUNCATE_OK; - } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { + return FTRUNCATE_OK; } }; @@ -2290,18 +2004,14 @@ class Vfs_tresor::Deinitialize_file_system : public Vfs::Single_file_system Wrapper::Deinitialize const & deinitialize_progress { wrapper.deinitialize_progress() }; - bool const in_progress { - deinitialize_progress.state == - Wrapper::Deinitialize::State::IN_PROGRESS }; + bool const in_progress { deinitialize_progress.in_progress() }; bool const last_result { !in_progress && deinitialize_progress.last_result != Wrapper::Deinitialize::Result::NONE }; - bool const success { - deinitialize_progress.last_result == - Wrapper::Deinitialize::Result::SUCCESS }; + bool const success { deinitialize_progress.success() }; Content_string const result { Wrapper::Deinitialize::state_to_cstring(deinitialize_progress.state), @@ -2331,16 +2041,12 @@ class Vfs_tresor::Deinitialize_file_system : public Vfs::Single_file_system out_count = 0; return READ_OK; } - _w.handle_frontend_request(); + _w.execute(); Wrapper::Deinitialize const & deinitialize_progress { _w.deinitialize_progress() }; - bool const in_progress { - deinitialize_progress.state == - Wrapper::Deinitialize::State::IN_PROGRESS }; - - if (in_progress) + if (deinitialize_progress.in_progress()) return READ_QUEUED; Content_string const result { content_string(_w) }; @@ -2352,8 +2058,7 @@ class Vfs_tresor::Deinitialize_file_system : public Vfs::Single_file_system Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override { - using State = Wrapper::Deinitialize::State; - if (_w.deinitialize_progress().state != State::IDLE) { + if (!_w.deinitialize_progress().idle()) { return WRITE_ERR_IO; } @@ -2448,15 +2153,12 @@ class Vfs_tresor::Deinitialize_file_system : public Vfs::Single_file_system return result; } - /******************************** ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override - { - return FTRUNCATE_OK; - } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { + return FTRUNCATE_OK; } }; @@ -2544,15 +2246,12 @@ class Vfs_tresor::Create_snapshot_file_system : public Vfs::Single_file_system return result; } - /******************************** ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override - { - return FTRUNCATE_OK; - } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { + return FTRUNCATE_OK; } }; @@ -2644,10 +2343,8 @@ class Vfs_tresor::Discard_snapshot_file_system : public Vfs::Single_file_system ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override - { - return FTRUNCATE_OK; - } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { + return FTRUNCATE_OK; } }; @@ -3233,20 +2930,14 @@ class Vfs_tresor::Snapshots_file_system : public Vfs::File_system return READ_ERR_IO; } - bool read_ready(Vfs::Vfs_handle const &) const override - { - return true; - } + bool read_ready(Vfs::Vfs_handle const &) const override { + return true; } - bool write_ready(Vfs::Vfs_handle const &) const override - { - return false; - } + bool write_ready(Vfs::Vfs_handle const &) const override { + return false; } - Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override - { - return FTRUNCATE_OK; - } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { + return FTRUNCATE_OK; } }; @@ -3540,14 +3231,14 @@ void Vfs_tresor::Wrapper::_deinit_fs_trigger_watch_response() void Vfs_tresor::Snapshots_file_system::Snapshot_registry::update(Vfs::Env &vfs_env) { - Tresor::Snapshot_generations generations { }; - _wrapper.snapshot_generations(generations); + Tresor::Snapshots_info snap_info { }; + _wrapper.snapshots_info(snap_info); bool trigger_watch_response { false }; /* alloc new */ for (size_t i = 0; i < MAX_NR_OF_SNAPSHOTS; i++) { - Generation const snap_gen = generations.items[i]; + Generation const snap_gen = snap_info.generations[i]; if (snap_gen == INVALID_GENERATION) continue; @@ -3573,7 +3264,7 @@ 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++) { - Generation const snap_gen = generations.items[i]; + Generation const snap_gen = snap_info.generations[i]; if (snap_gen == INVALID_GENERATION) continue; diff --git a/repos/gems/src/lib/vfs/tresor_crypto/aes_cbc/aes_cbc.cc b/repos/gems/src/lib/vfs/tresor_crypto/aes_cbc.cc similarity index 98% rename from repos/gems/src/lib/vfs/tresor_crypto/aes_cbc/aes_cbc.cc rename to repos/gems/src/lib/vfs/tresor_crypto/aes_cbc.cc index 04edcfe60b..895148ae81 100644 --- a/repos/gems/src/lib/vfs/tresor_crypto/aes_cbc/aes_cbc.cc +++ b/repos/gems/src/lib/vfs/tresor_crypto/aes_cbc.cc @@ -12,13 +12,16 @@ * under the terms of the GNU Affero General Public License version 3. */ +/* base includes */ #include #include -#include - +/* tresor includes */ #include -#include + +/* vfs tresor crypt includes */ +#include +#include namespace { diff --git a/repos/gems/src/lib/vfs/tresor_crypto/aes_cbc/dummy.ads b/repos/gems/src/lib/vfs/tresor_crypto/aes_cbc/dummy.ads deleted file mode 100644 index 49400e28c4..0000000000 --- a/repos/gems/src/lib/vfs/tresor_crypto/aes_cbc/dummy.ads +++ /dev/null @@ -1,17 +0,0 @@ --- --- \brief Integration of the Tresor block encryption --- \author Martin Stein --- \author Josef Soentgen --- \date 2020-11-10 --- - --- --- Copyright (C) 2020 Genode Labs GmbH --- --- This file is part of the Genode OS framework, which is distributed --- under the terms of the GNU Affero General Public License version 3. --- - -package Dummy -is -end Dummy; diff --git a/repos/gems/src/lib/tresor/include/tresor/crypto/interface.h b/repos/gems/src/lib/vfs/tresor_crypto/interface.h similarity index 100% rename from repos/gems/src/lib/tresor/include/tresor/crypto/interface.h rename to repos/gems/src/lib/vfs/tresor_crypto/interface.h diff --git a/repos/gems/src/lib/vfs/tresor_crypto/memcopy/memcopy.cc b/repos/gems/src/lib/vfs/tresor_crypto/memcopy.cc similarity index 97% rename from repos/gems/src/lib/vfs/tresor_crypto/memcopy/memcopy.cc rename to repos/gems/src/lib/vfs/tresor_crypto/memcopy.cc index 18d62cbed3..1bc1e85d3a 100644 --- a/repos/gems/src/lib/vfs/tresor_crypto/memcopy/memcopy.cc +++ b/repos/gems/src/lib/vfs/tresor_crypto/memcopy.cc @@ -12,12 +12,12 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* Genode includes */ +/* base includes */ #include #include -/* tresor_crypto includes */ -#include +/* vfs tresor crypt includes */ +#include namespace { diff --git a/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc b/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc index 5aee3d367b..6c82931dc8 100644 --- a/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc +++ b/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc @@ -18,8 +18,8 @@ #include #include -/* Tresor includes */ -#include +/* vfs tresor crypto includes */ +#include namespace Vfs_tresor_crypto { diff --git a/repos/gems/src/lib/tresor/include/tresor/vfs/io_job.h b/repos/gems/src/lib/vfs/tresor_trust_anchor/io_job.h similarity index 100% rename from repos/gems/src/lib/tresor/include/tresor/vfs/io_job.h rename to repos/gems/src/lib/vfs/tresor_trust_anchor/io_job.h diff --git a/repos/gems/src/lib/vfs/tresor_trust_anchor/vfs.cc b/repos/gems/src/lib/vfs/tresor_trust_anchor/vfs.cc index 9233372031..ba36c540b5 100644 --- a/repos/gems/src/lib/vfs/tresor_trust_anchor/vfs.cc +++ b/repos/gems/src/lib/vfs/tresor_trust_anchor/vfs.cc @@ -21,10 +21,8 @@ /* OpenSSL includes */ #include -/* tresor includes */ -#include - -/* local includes */ +/* vfs tresor trust anchor includes */ +#include #include enum { PRIVATE_KEY_SIZE = 32 };