From b4c468173322dbb61be86dfbf739a5a5215ab0c4 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Thu, 14 Dec 2023 13:54:57 +0100 Subject: [PATCH] tresor: streamline design further * differentiates request types that where merged formerly per module; e.g. instead of type Superblock_control::Request, there are now types * Superblock_control::Read_vbas * Superblock_control::Write_vbas * Superblock_control::Rekey * Superblock_control::Initialize * ... each holding only the state and functionality that is required for exactly that request * removes all classes of the Tresor module framework and adapts all Tresor- and File-Vault- related libs, apps, and tests accordingly * the former "channel" state is merged into the new request types, meaning, a request manages no longer only the "call" to a functionality but also the execution of that functionality; every request has a lifetime equal to the "call" and an execute method to be driven forward * state that is used by a request but has a longer lifetime (e.g. VFS file handles in Tresor::Crypto) is managed by the top level of the user and handed over via the execute arguments; however, the synchronization of multiple requests on this state is done by the module (e.g. Tresor::Crypto) * requests are now driven explicitly as first argument of the (overloaded) execute method of their module; the module can, however, stall a request by returning false without doing anything (used for synchronization on resources) * introduces Request_helper, Generated_request and Generatable_request in the Tresor namespace in order to avoid the redundancy of sub-request generation and execution * moves access to Client-Data pointers up to Tresor::Virtual_block_device in order to simplify Tresor::Block_io and Tresor::Crypto * removes Tresor::Client_data and introduces pure interface Client_data_interface in order to remove Tresor::Client_data and move management of Client Data to the top level of a Tresor user * introduces pure interface Crypto_files_interface in order to move management of Crypto files to the top level of a Tresor user * moves management of Block-IO and Trust-Anchor files to the top level of a Tresor user * adapts all execute methods, so, that they return the progress state instead of modifying a reference argument * removes Tresor::Request_and Tresor:Request and instead implements scheduling at the top level of the Tresor user * the Tresor Tester uses a list as schedule that holds Command objects; this list ensures, that commands are started in the order of configuration the Command type is a merge of the state of all possible commands that can be configured at the Tresor Tester; the actual Tresor requests (if any) are then allocated on-demand only * the Tresor VFS plugin does not use a dynamic data structure for scheduling; the plugin has 5 members that each reflect a distinct type of operation: * initialize operation * deinitialize operation * data operation * extend operation * rekey operation consequently, of each type, there can be only one operation in-flight at a time; at the user front-end each operation (except "initialize") can be controlled through a dedicated VFS file; for each of these files, the VFS expects only one handle to be open at a time and only one file operation (read, write, sync) active at a time; once an operation gets started it is finished without preemtion (except of the interleaving at rekey and extend); when multiple operations are waiting to be started the plugin follows a static priority scheme: init op > deinit op > data op > extend op > rekey op there are some operation-specific details * the initialize operation is started only by the plugin itself on startup and will be driven as side effect by subsequent user calls to file operations * the data file is the only contiguous file in the front end and the file operations work as on usual data files * the other 3 files are transactional files and the user is expected to follow this scheme when operating on them 1) stat (to determine file size) 2) seek to offset 0 3) read entire file once (this will be queued until there is no operation of this type pending anymore and return the last result: "none" | "failed" | "succeeded"; used primarily for synchronization) 4) write operation parameters (this returns immediately and marks the operation as "requested") 5) read entire file once (the same as above but this time in order to determine the operation result) * the rekey op and deinitialize op are requested by writing "true" * the extend op is requested by writing "tree=[TREE], blocks=[BLOCKS]" where TREE is either "vbd" or "ft" and BLOCKS is the number of physical 4K blocks by which the physical range of the tresor container expands (the physical range always starts at block address 0 and is always expanded upwards) * replaces the former command at the Tresor Tester with as there are no other trust anchor operations that can be requested through the Tester config anyway * removes the "sync" attribute from all commands at the Tresor Tester except from , , ; as the Tester controls scheduling now, requests are generally synchronous; at the rekeying and extension commands, the "sync" attribute determines wether subsequent commands are interleaved with the execution of these commands (if possible) * removes "debug" config attribute from Tresor VFS plugin and reworks "verbose" attribute to generate more sensible output * removes NONCOPYABLE macro and instead uses Genode::Noncopyable and in-place Constructors deletion * introduces types Attr and Execute_attr where a constructor or execute method have many arguments in order to raise readability * renames the "hashsum" file that is provided by the Tresor Trust-Anchor VFS plugin to "hash" in order to become conformant with the wording in the Tresor lib * makes the VFS Tresor test an automated test by merging in the functionality of vfs_tresor_init.run and removing the interactive front end; removes vfs_tresor_init.run as it is not needed anymore; adds consideration for autopilot file structure in the Test and adds it to autopilot.list * removes all snapshot controls and the progress files for rekeying and extending from the Tresor VFS plugin; both functionalities were tested only rudimentary by the VFS Tresor test and are not supported with the only real user, the File Vault * use /* .. */ instead of // .. * use (..) instead of { .. } in init lists Ref #5148 --- repos/gems/lib/mk/tresor.mk | 2 - repos/gems/lib/mk/vfs_tresor.mk | 2 +- repos/gems/run/tresor_tester.run | 1403 +++--- repos/gems/run/vfs_tresor.run | 180 +- repos/gems/run/vfs_tresor.sh | 170 +- repos/gems/run/vfs_tresor_init.run | 153 - repos/gems/src/app/file_vault/main.cc | 87 +- repos/gems/src/app/file_vault/sandbox.h | 3 +- repos/gems/src/app/tresor_check/main.cc | 64 +- repos/gems/src/app/tresor_init/main.cc | 138 +- .../app/tresor_init_trust_anchor/component.cc | 9 +- repos/gems/src/app/tresor_tester/main.cc | 1382 +++--- repos/gems/src/lib/tresor/block_io.cc | 220 +- repos/gems/src/lib/tresor/crypto.cc | 320 +- repos/gems/src/lib/tresor/free_tree.cc | 362 +- repos/gems/src/lib/tresor/ft_check.cc | 126 +- repos/gems/src/lib/tresor/ft_initializer.cc | 193 +- .../src/lib/tresor/include/tresor/block_io.h | 211 +- .../lib/tresor/include/tresor/client_data.h | 69 - .../include/tresor/client_data_interface.h | 47 + .../src/lib/tresor/include/tresor/crypto.h | 256 +- .../gems/src/lib/tresor/include/tresor/file.h | 47 +- .../src/lib/tresor/include/tresor/free_tree.h | 216 +- .../src/lib/tresor/include/tresor/ft_check.h | 101 +- .../tresor/include/tresor/ft_initializer.h | 107 +- .../src/lib/tresor/include/tresor/meta_tree.h | 105 +- .../src/lib/tresor/include/tresor/module.h | 223 - .../lib/tresor/include/tresor/noncopyable.h | 21 - .../lib/tresor/include/tresor/request_pool.h | 180 - .../src/lib/tresor/include/tresor/sb_check.h | 109 +- .../tresor/include/tresor/sb_initializer.h | 157 +- .../include/tresor/superblock_control.h | 710 ++- .../lib/tresor/include/tresor/trust_anchor.h | 281 +- .../src/lib/tresor/include/tresor/types.h | 234 +- .../src/lib/tresor/include/tresor/vbd_check.h | 99 +- .../tresor/include/tresor/vbd_initializer.h | 101 +- .../src/lib/tresor/include/tresor/verbosity.h | 1 - .../include/tresor/virtual_block_device.h | 358 +- repos/gems/src/lib/tresor/meta_tree.cc | 218 +- repos/gems/src/lib/tresor/module.cc | 145 - repos/gems/src/lib/tresor/request_pool.cc | 381 -- repos/gems/src/lib/tresor/sb_check.cc | 107 +- repos/gems/src/lib/tresor/sb_initializer.cc | 144 +- .../gems/src/lib/tresor/superblock_control.cc | 878 ++-- repos/gems/src/lib/tresor/trust_anchor.cc | 252 +- repos/gems/src/lib/tresor/vbd_check.cc | 127 +- repos/gems/src/lib/tresor/vbd_initializer.cc | 125 +- .../src/lib/tresor/virtual_block_device.cc | 1033 ++-- repos/gems/src/lib/vfs/tresor/splitter.cc | 225 - repos/gems/src/lib/vfs/tresor/splitter.h | 480 +- repos/gems/src/lib/vfs/tresor/vfs.cc | 4253 ++++++----------- repos/gems/src/lib/vfs/tresor_crypto/vfs.cc | 58 +- .../src/lib/vfs/tresor_trust_anchor/io_job.h | 14 +- .../src/lib/vfs/tresor_trust_anchor/vfs.cc | 69 +- tool/autopilot.list | 1 + 55 files changed, 7098 insertions(+), 9859 deletions(-) delete mode 100644 repos/gems/run/vfs_tresor_init.run delete mode 100644 repos/gems/src/lib/tresor/include/tresor/client_data.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/client_data_interface.h delete mode 100644 repos/gems/src/lib/tresor/include/tresor/module.h delete mode 100644 repos/gems/src/lib/tresor/include/tresor/noncopyable.h delete mode 100644 repos/gems/src/lib/tresor/include/tresor/request_pool.h delete mode 100644 repos/gems/src/lib/tresor/module.cc delete mode 100644 repos/gems/src/lib/tresor/request_pool.cc delete mode 100644 repos/gems/src/lib/vfs/tresor/splitter.cc diff --git a/repos/gems/lib/mk/tresor.mk b/repos/gems/lib/mk/tresor.mk index bcf420be6f..1e5417d84a 100644 --- a/repos/gems/lib/mk/tresor.mk +++ b/repos/gems/lib/mk/tresor.mk @@ -1,7 +1,6 @@ TRESOR_DIR := $(REP_DIR)/src/lib/tresor SRC_CC += crypto.cc -SRC_CC += request_pool.cc SRC_CC += hash.cc SRC_CC += trust_anchor.cc SRC_CC += block_io.cc @@ -9,7 +8,6 @@ SRC_CC += meta_tree.cc SRC_CC += virtual_block_device.cc SRC_CC += superblock_control.cc SRC_CC += free_tree.cc -SRC_CC += module.cc SRC_CC += vbd_initializer.cc SRC_CC += ft_initializer.cc SRC_CC += sb_initializer.cc diff --git a/repos/gems/lib/mk/vfs_tresor.mk b/repos/gems/lib/mk/vfs_tresor.mk index 88ed1baf9e..549024bf5c 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 splitter.cc +SRC_CC := vfs.cc INC_DIR += $(LIB_DIR) diff --git a/repos/gems/run/tresor_tester.run b/repos/gems/run/tresor_tester.run index 402ed36509..e864e69b25 100644 --- a/repos/gems/run/tresor_tester.run +++ b/repos/gems/run/tresor_tester.run @@ -238,7 +238,7 @@ append config { - + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -403,195 +400,195 @@ append config { - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + @@ -612,439 +609,439 @@ if {[benchmark_blk_count] > 0} { append config { - + - - - + + + - - - + + + - - - + + + - - - + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + } @@ -1052,18 +1049,18 @@ if {[benchmark_blk_count] > 0} { append config { - + } } append config { - + - - - - - + + + + + diff --git a/repos/gems/run/vfs_tresor.run b/repos/gems/run/vfs_tresor.run index 10c81a8e0e..7cf48b2ee6 100644 --- a/repos/gems/run/vfs_tresor.run +++ b/repos/gems/run/vfs_tresor.run @@ -1,24 +1,26 @@ assert_spec linux +set dd [installed_command dd] + create_boot_directory -proc tresor_image_file { } { - return "vfs_tresor_block.img" -} +proc tresor_image_name { } { return "vfs_tresor_block.img" } -set use_interactively [expr ![get_cmd_switch --autopilot]] +proc tresor_image_size_mb { } { return 4 } -import_from_depot [depot_user]/pkg/[drivers_interactive_pkg] \ - [depot_user]/pkg/terminal \ - [depot_user]/src/ncurses \ +proc local_tresor_image { } { return bin/[tresor_image_name] } + +proc autopilot_tresor_image { } { return /tmp/[tresor_image_name].[exec id -un] } + +import_from_depot [depot_user]/src/ncurses \ [depot_user]/src/bash \ - [depot_user]/src/coreutils \ - [depot_user]/src/nitpicker - + [depot_user]/src/coreutils build { - core lib/ld timer init - server/lx_fs + core + timer + init + lib/ld lib/vfs_tresor lib/vfs_tresor_crypto_aes_cbc lib/vfs_tresor_crypto_memcopy @@ -26,17 +28,24 @@ build { lib/vfs_import lib/vfs_jitterentropy lib/vfs_pipe - lib/vfs lib/libc lib/posix lib/libcrypto + lib/vfs + lib/libc + lib/libm + lib/posix + lib/libcrypto test/vfs_stress test/libc server/log_terminal server/report_rom server/fs_rom + server/lx_fs + server/vfs app/tresor_init_trust_anchor + app/tresor_init app/sequence } -set config { +append config { @@ -54,64 +63,20 @@ set config { + - - - - - - - - - - - - - - - - - - - - - - - - - - - - } - -append_if $use_interactively config { - - - - - - - - - - - } - -append_if [expr !$use_interactively] config { - - + - } + -append config { @@ -127,15 +92,9 @@ append config { - - - - - - + @@ -146,8 +105,7 @@ append config { - - + @@ -156,12 +114,37 @@ append config { - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -188,12 +171,12 @@ append config { - + - + @@ -202,8 +185,6 @@ append config { - - @@ -230,7 +211,7 @@ append config { - + @@ -266,21 +247,23 @@ append config { - - + + - + + + - - - + + + @@ -294,19 +277,28 @@ set shell_script "run/vfs_tresor.sh" set repo "[repository_contains $shell_script]" exec cp $repo/$shell_script bin/ +exec rm -rf [local_tresor_image] +if { [get_cmd_switch --autopilot] } { + + exec rm -rf [autopilot_tresor_image] + catch { exec $dd if=/dev/urandom of=[autopilot_tresor_image] bs=1M count=[tresor_image_size_mb] } + exec ln -sf -T [autopilot_tresor_image] [local_tresor_image] + +} else { + + catch { exec $dd if=/dev/urandom of=[local_tresor_image] bs=1M count=[tresor_image_size_mb] } +} + set boot_modules [build_artifacts] - -append boot_modules { vfs_tresor.sh encrypted_private_key superblock_hash } -lappend boot_modules [tresor_image_file] - -set fd [open [run_dir]/genode/focus w] -puts $fd " \" domain=\"default\"/>" -close $fd +append boot_modules { vfs_tresor.sh } +lappend boot_modules [tresor_image_name] build_boot_image $boot_modules -if {$use_interactively} { - run_genode_until forever -} else { - run_genode_until {.*--- Automated Tresor testing finished.*} 1800 +run_genode_until {.*"/bin/bash".* exited with exit value 0.*\n} 120 + +if { [get_cmd_switch --autopilot] } { + + exec rm -rf [local_tresor_image] + exec rm -rf [autopilot_tresor_image] } diff --git a/repos/gems/run/vfs_tresor.sh b/repos/gems/run/vfs_tresor.sh index bfc4f955eb..3fea3fd2d0 100644 --- a/repos/gems/run/vfs_tresor.sh +++ b/repos/gems/run/vfs_tresor.sh @@ -55,33 +55,25 @@ test_read_compare_1() { fi } -test_create_snapshot() { +test_deinitialize() { local tresor_dir="$1" - - echo "Create snapshot" - echo true > $tresor_dir/control/create_snapshot + echo "Deinitialize" + local state="$(< $tresor_dir/control/deinitialize)" + echo true > $tresor_dir/control/deinitialize } -test_list_snapshots() { +wait_for_deinitialize() { local tresor_dir="$1" - - echo "List content of '$tresor_dir'" - ls -l $tresor_dir/snapshots -} - -test_discard_snapshot() { - local tresor_dir="$1" - local snap_id=$2 - - echo "Discard snapshot with id: $snap_id" - echo $snap_id > $tresor_dir/control/discard_snapshot + echo "Wait for deinitialize" + local state="$(< $tresor_dir/control/deinitialize)" } test_rekey_start() { local tresor_dir="$1" echo "Start rekeying" - echo on > $tresor_dir/control/rekey + local state="$(< $tresor_dir/control/rekey)" + echo true > $tresor_dir/control/rekey echo "Reykeying started" } @@ -137,16 +129,14 @@ wait_for_rekeying() { echo "Wait for rekeying to finish..." while : ; do local done=0 - local file_content="$(< $tresor_dir/control/rekey_progress)" + local file_content="$(< $tresor_dir/control/rekey)" # XXX remove later echo "file_content: ${file_content}" case "$file_content" in - *at*) - if [ "$verbose" = "yes" ]; then - echo "Rekeying: $file_content" - fi + *failed*) + done=1; ;; - *idle*) + *succeeded*) done=1; ;; esac @@ -163,16 +153,14 @@ wait_for_vbd_extension() { echo "Wait for VBD extension to finish..." while : ; do local done=0 - local file_content="$(< $tresor_dir/control/extend_progress)" + local file_content="$(< $tresor_dir/control/extend)" # XXX remove later echo "file_content: ${file_content}" case "$file_content" in - *at*) - if [ "$verbose" = "yes" ]; then - echo "Extending VBD: $file_content" - fi + *failed*) + done=1; ;; - *idle*) + *succeeded*) done=1; ;; esac @@ -189,16 +177,14 @@ wait_for_ft_extension() { echo "Wait for FT extension to finish..." while : ; do local done=0 - local file_content="$(< $tresor_dir/control/extend_progress)" + local file_content="$(< $tresor_dir/control/extend)" # XXX remove later echo "file_content: ${file_content}" case "$file_content" in - *at*) - if [ "$verbose" = "yes" ]; then - echo "Extending FT: $file_content" - fi + *failed*) + done=1; ;; - *idle*) + *succeeded*) done=1; ;; esac @@ -212,95 +198,37 @@ wait_for_ft_extension() { main() { local tresor_dir="/dev/tresor" local data_file="$tresor_dir/current/data" - + echo "list files..." ls -l $tresor_dir - - for i in $(seq 3); do - - echo "--> Run $i:" - - test_read_seq_unaligned_512 "$data_file" "1048576" - - local pattern_file="/tmp/pattern" - produce_pattern "$i" "4096" > $pattern_file - - test_write_1 "$data_file" "419" - test_write_1 "$data_file" "63" - test_write_1 "$data_file" "333" - - test_vbd_extension "$tresor_dir" "1000" - test_read_compare_1 "$data_file" "63" - test_write_1 "$data_file" "175" - test_read_compare_1 "$data_file" "419" - test_write_1 "$data_file" "91" - test_read_compare_1 "$data_file" "175" - test_read_compare_1 "$data_file" "91" - test_read_compare_1 "$data_file" "333" - wait_for_vbd_extension "$tresor_dir" - - test_write_1 "$data_file" "32" - test_write_1 "$data_file" "77" - test_write_1 "$data_file" "199" - - #test_ft_extension "$tresor_dir" "1000" - test_read_compare_1 "$data_file" "32" - test_write_1 "$data_file" "211" - test_read_compare_1 "$data_file" "77" - test_write_1 "$data_file" "278" - test_read_compare_1 "$data_file" "199" - test_read_compare_1 "$data_file" "278" - test_read_compare_1 "$data_file" "211" - #wait_for_ft_extension "$tresor_dir" - - test_write_1 "$data_file" "0" - test_write_1 "$data_file" "8" - test_write_1 "$data_file" "16" - test_write_1 "$data_file" "490" - test_write_1 "$data_file" "468" - - test_read_compare_1 "$data_file" "0" - test_read_compare_1 "$data_file" "8" - test_read_compare_1 "$data_file" "16" - test_read_compare_1 "$data_file" "490" - - #test_rekey "$tresor_dir" - - test_rekey_start "$tresor_dir" - test_write_1 "$data_file" "0" - test_rekey_state "$tresor_dir" - test_read_compare_1 "$data_file" "490" - test_rekey_state "$tresor_dir" - test_write_1 "$data_file" "16" - test_rekey_state "$tresor_dir" - test_read_compare_1 "$data_file" "468" - test_rekey_state "$tresor_dir" - test_read_compare_1 "$data_file" "8" - test_rekey_state "$tresor_dir" - test_read_compare_1 "$data_file" "16" - test_rekey_state "$tresor_dir" - test_read_compare_1 "$data_file" "0" - test_write_1 "$data_file" "300" - test_write_1 "$data_file" "240" - test_write_1 "$data_file" "201" - test_write_1 "$data_file" "328" - wait_for_rekeying "$tresor_dir" "yes" - - echo "--> Run $i done" - - done - - echo "--> Read/Compare test" - test_read_compare_1 "$data_file" "0" - test_read_compare_1 "$data_file" "490" - test_read_compare_1 "$data_file" "468" - test_read_compare_1 "$data_file" "8" - test_read_compare_1 "$data_file" "16" - echo "--> Read/Compare test done" - - echo "--- Automated Tresor testing finished, shell is yours ---" + echo "produce pattern..." + local pattern_file="/tmp/pattern" + produce_pattern "1" "4096" > $pattern_file + echo "write..." + test_write_1 "$data_file" "20" + echo "read..." + test_read_compare_1 "$data_file" "20" + test_write_1 "$data_file" "20" + echo "extend VBD..." + test_vbd_extension "$tresor_dir" "100" + test_write_1 "$data_file" "2" + test_read_compare_1 "$data_file" "2" + wait_for_vbd_extension "$tresor_dir" + echo "extend FT..." + test_ft_extension "$tresor_dir" "100" + test_write_1 "$data_file" "2" + test_read_compare_1 "$data_file" "2" + wait_for_ft_extension "$tresor_dir" + echo "rekey..." + test_rekey_start "$tresor_dir" + test_write_1 "$data_file" "2" + test_read_compare_1 "$data_file" "2" + wait_for_rekeying "$tresor_dir" "no" + test_deinitialize "$tresor_dir" + wait_for_deinitialize "$tresor_dir" + echo "done!" } main "$@" # just drop into shell -# exit 0 +exit 0 diff --git a/repos/gems/run/vfs_tresor_init.run b/repos/gems/run/vfs_tresor_init.run deleted file mode 100644 index 3007541865..0000000000 --- a/repos/gems/run/vfs_tresor_init.run +++ /dev/null @@ -1,153 +0,0 @@ -assert_spec linux - -proc tresor_image_file { } { - return "vfs_tresor_block.img" -} - -set image_size 32 - -proc tresor_image_size_mb { } { - global image_size - return $image_size -} - -build { - core lib/ld init timer - server/lx_block - server/lx_fs - server/vfs lib/vfs - app/sequence - - app/tresor_init_trust_anchor - app/tresor_init - lib/vfs_tresor_crypto_aes_cbc - lib/vfs_tresor_trust_anchor - lib/vfs_jitterentropy - lib/libc - lib/libcrypto -} - -create_boot_directory - -append config { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -} - -install_config $config - -exec rm -rf bin/[tresor_image_file] -exec truncate -s [tresor_image_size_mb]M bin/[tresor_image_file] - -build_boot_image [list {*}[build_artifacts] [tresor_image_file]] - -run_genode_until {.*child "initialize_tresor" exited with exit value 0.*\n} 240 - -exec cp [run_dir]/genode/encrypted_private_key bin -exec cp [run_dir]/genode/superblock_hash bin diff --git a/repos/gems/src/app/file_vault/main.cc b/repos/gems/src/app/file_vault/main.cc index 9df6d65696..cf9b7a7778 100644 --- a/repos/gems/src/app/file_vault/main.cc +++ b/repos/gems/src/app/file_vault/main.cc @@ -641,8 +641,28 @@ class File_vault::Main size_t nr_of_ft_children, size_t nr_of_ft_leafs); - static bool tresor_control_file_yields_state_idle(Xml_node const &fs_query_listing, - char const *file_name); + template + static bool listing_file_starts_with(Xml_node const &fs_query_listing, + char const *file_name, + String const &str) + { + bool result { false }; + bool done { false }; + fs_query_listing.with_optional_sub_node("dir", [&] (Xml_node const &node_0) { + node_0.for_each_sub_node("file", [&] (Xml_node const &node_1) { + if (done) { + return; + } + if (node_1.attribute_value("name", String<16>()) == file_name) { + node_1.with_raw_content([&] (char const *base, size_t size) { + result = String { Cstring {base, size} } == str; + done = true; + }); + } + }); + }); + return result; + } /*************************************************** @@ -699,28 +719,6 @@ void Main::_handle_ui_config() } -bool Main::tresor_control_file_yields_state_idle(Xml_node const &fs_query_listing, - char const *file_name) -{ - bool result { false }; - bool done { false }; - fs_query_listing.with_optional_sub_node("dir", [&] (Xml_node const &node_0) { - node_0.for_each_sub_node("file", [&] (Xml_node const &node_1) { - if (done) { - return; - } - if (node_1.attribute_value("name", String<16>()) == file_name) { - node_1.with_raw_content([&] (char const *base, size_t size) { - result = String<5> { Cstring {base, size} } == "idle"; - done = true; - }); - } - }); - }); - return result; -} - - void Main::_update_sandbox_config() { Buffered_xml const config { _heap, "config", [&] (Xml_generator &xml) { @@ -940,16 +938,20 @@ void Main::_handle_resizing_fs_query_listing(Xml_node const &node) switch (_resizing_state) { case Resizing_state::WAIT_TILL_DEVICE_IS_READY: - if (tresor_control_file_yields_state_idle(node, "extend_progress")) { + if (listing_file_starts_with(node, "extend", String<10>("succeeded")) || + listing_file_starts_with(node, "extend", String<5>("none"))) { _resizing_state = Resizing_state::ISSUE_REQUEST_AT_DEVICE; Signal_transmitter(_state_handler).submit(); - } + + } else + error("failed to extend: tresor not ready"); + break; case Resizing_state::IN_PROGRESS_AT_DEVICE: - if (tresor_control_file_yields_state_idle(node, "extend_progress")) { + if (listing_file_starts_with(node, "extend", String<10>("succeeded"))) { switch (_resizing_type) { case Resizing_type::EXPAND_CLIENT_FS: @@ -972,7 +974,10 @@ void Main::_handle_resizing_fs_query_listing(Xml_node const &node) } _resizing_state = Resizing_state::DETERMINE_CLIENT_FS_SIZE; Signal_transmitter(_state_handler).submit(); - } + + } else + error("failed to extend: operation failed at tresor"); + break; default: @@ -992,13 +997,16 @@ void Main::_handle_lock_fs_query_listing(Xml_node const &node) switch (_state) { case State::LOCK_WAIT_TILL_DEINIT_REQUEST_IS_DONE: - if (tresor_control_file_yields_state_idle(node, "deinitialize")) { + if (listing_file_starts_with(node, "deinitialize", String<10>("succeeded"))) { _set_state(State::UNLOCK_OBTAIN_PARAMETERS); _setup_obtain_params_passphrase = Input_passphrase { }; _setup_obtain_params_select = Setup_obtain_params_select::PASSPHRASE_INPUT; Signal_transmitter(_state_handler).submit(); - } + + } else + error("failed to deinitialize: operation failed at tresor"); + break; default: @@ -1024,20 +1032,27 @@ void Main::_handle_rekeying_fs_query_listing(Xml_node const &node) switch (_rekeying_state) { case Rekeying_state::WAIT_TILL_DEVICE_IS_READY: - if (tresor_control_file_yields_state_idle(node, "rekey_progress")) { + if (listing_file_starts_with(node, "rekey", String<10>("succeeded")) || + listing_file_starts_with(node, "rekey", String<5>("none"))) { _rekeying_state = Rekeying_state::ISSUE_REQUEST_AT_DEVICE; Signal_transmitter(_state_handler).submit(); - } + + } else + error("failed to rekey: tresor not ready"); + break; case Rekeying_state::IN_PROGRESS_AT_DEVICE: - if (tresor_control_file_yields_state_idle(node, "rekey_progress")) { + if (listing_file_starts_with(node, "rekey", String<10>("succeeded"))) { _rekeying_state = Rekeying_state::INACTIVE; Signal_transmitter(_state_handler).submit(); - } + + } else + error("failed to rekey: operation failed at tresor"); + break; default: @@ -1465,10 +1480,8 @@ void File_vault::Main::handle_sandbox_state() update_dialog = true; update_sandbox = true; - } else { - + } else _unlock_retry_delay.schedule(Microseconds { 3000000 }); - } }); break; diff --git a/repos/gems/src/app/file_vault/sandbox.h b/repos/gems/src/app/file_vault/sandbox.h index 0087da5a4d..6f1d788f68 100644 --- a/repos/gems/src/app/file_vault/sandbox.h +++ b/repos/gems/src/app/file_vault/sandbox.h @@ -299,7 +299,6 @@ namespace File_vault { xml.node("tresor", [&] () { xml.attribute("name", "tresor"); xml.attribute("verbose", "no"); - xml.attribute("debug", "no"); xml.attribute("block", File_path { "/", tresor_img_file_name }); xml.attribute("crypto", "/crypto"); xml.attribute("trust_anchor", "/trust_anchor"); @@ -531,7 +530,7 @@ namespace File_vault { } void gen_tresor_vfs_block_start_node(Xml_generator &xml, - Child_state const &child) + Child_state const &child) { child.gen_start_node(xml, [&] () { diff --git a/repos/gems/src/app/tresor_check/main.cc b/repos/gems/src/app/tresor_check/main.cc index 2e00c3939a..523833162d 100644 --- a/repos/gems/src/app/tresor_check/main.cc +++ b/repos/gems/src/app/tresor_check/main.cc @@ -31,76 +31,44 @@ using namespace Tresor; namespace Tresor_check { class Main; } -class Tresor_check::Main : private Vfs::Env::User, private Tresor::Module_composition, public Tresor::Module, public Module_channel +class Tresor_check::Main : private Vfs::Env::User { private: - enum State { INIT, REQ_GENERATED, CHECK_SBS_SUCCEEDED }; + enum State { INIT, CHECK_SB, CHECK_SB_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 }; Signal_handler
_sigh { _env.ep(), *this, &Main::_handle_signal }; - 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") }; + Tresor::Path const _block_io_path { _config_rom.xml().sub_node("block-io").attribute_value("path", Tresor::Path()) }; + Vfs::Vfs_handle &_block_io_file { open_file(_vfs_env, _block_io_path, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Block_io _block_io { _block_io_file }; Vbd_check _vbd_check { }; Ft_check _ft_check { }; Sb_check _sb_check { }; - 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; - } - - void wakeup_vfs_user() override { _sigh.local_submit(); } + Sb_check::Check _check_superblocks { }; void _wakeup_back_end_services() { _vfs_env.io().commit(); } void _handle_signal() { - execute_modules(); + while(_sb_check.execute(_check_superblocks, _vbd_check, _ft_check, _block_io)); + if (_check_superblocks.complete()) + _env.parent().exit(_check_superblocks.success() ? 0 : -1); _wakeup_back_end_services(); } + /******************** + ** Vfs::Env::User ** + ********************/ + + void wakeup_vfs_user() override { _sigh.local_submit(); } + public: - 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(VBD_CHECK, _vbd_check); - add_module(FT_CHECK, _ft_check); - add_module(SB_CHECK, _sb_check); - add_channel(*this); - _handle_signal(); - } - - void execute(bool &progress) override - { - switch(_state) { - case INIT: - - generate_req(CHECK_SBS_SUCCEEDED, progress, _generated_req_success); - _state = REQ_GENERATED; - break; - - case CHECK_SBS_SUCCEEDED: _env.parent().exit(0); break; - default: break; - } - } + Main(Env &env) : _env(env) { _handle_signal(); } }; void Component::construct(Genode::Env &env) { static Tresor_check::Main main { env }; } diff --git a/repos/gems/src/app/tresor_init/main.cc b/repos/gems/src/app/tresor_init/main.cc index 2d818e8e04..008db35459 100644 --- a/repos/gems/src/app/tresor_init/main.cc +++ b/repos/gems/src/app/tresor_init/main.cc @@ -34,86 +34,116 @@ using namespace Tresor; namespace Tresor_init { class Main; } -class Tresor_init::Main : private Vfs::Env::User, private Tresor::Module_composition, public Tresor::Module, public Module_channel +class Tresor_init::Main : private Vfs::Env::User, private Crypto_key_files_interface { private: - enum State { INIT, REQ_GENERATED, INIT_SBS_SUCCEEDED }; + struct Crypto_key + { + Key_id const key_id; + Vfs::Vfs_handle &encrypt_file; + Vfs::Vfs_handle &decrypt_file; + }; 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 }; 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") }; + Configuration _cfg { _config_rom.xml() }; + Tresor::Path const _crypto_path { _config_rom.xml().sub_node("crypto").attribute_value("path", Tresor::Path()) }; + Tresor::Path const _block_io_path { _config_rom.xml().sub_node("block-io").attribute_value("path", Tresor::Path()) }; + Tresor::Path const _trust_anchor_path { _config_rom.xml().sub_node("trust-anchor").attribute_value("path", Tresor::Path()) }; + Vfs::Vfs_handle &_block_io_file { open_file(_vfs_env, _block_io_path, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_crypto_add_key_file { open_file(_vfs_env, { _crypto_path, "/add_key" }, Vfs::Directory_service::OPEN_MODE_WRONLY) }; + Vfs::Vfs_handle &_crypto_remove_key_file { open_file(_vfs_env, { _crypto_path, "/remove_key" }, Vfs::Directory_service::OPEN_MODE_WRONLY) }; + Vfs::Vfs_handle &_ta_decrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/decrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_ta_encrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/encrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_ta_generate_key_file { open_file(_vfs_env, { _trust_anchor_path, "/generate_key" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_ta_initialize_file { open_file(_vfs_env, { _trust_anchor_path, "/initialize" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_ta_hash_file { open_file(_vfs_env, { _trust_anchor_path, "/hash" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Trust_anchor _trust_anchor { { _ta_decrypt_file, _ta_encrypt_file, _ta_generate_key_file, _ta_initialize_file, _ta_hash_file } }; + Crypto _crypto { {*this, _crypto_add_key_file, _crypto_remove_key_file} }; + Block_io _block_io { _block_io_file }; + Constructible _crypto_keys[2] { }; Pba_allocator _pba_alloc { NR_OF_SUPERBLOCK_SLOTS }; Vbd_initializer _vbd_initializer { }; Ft_initializer _ft_initializer { }; Sb_initializer _sb_initializer { }; - bool _generated_req_success { }; - State _state { INIT }; + Sb_initializer::Initialize _init_superblocks {{ + Tree_configuration { + (Tree_level_index)(_cfg.vbd_nr_of_lvls() - 1), + (Tree_degree)_cfg.vbd_nr_of_children(), + _cfg.vbd_nr_of_leafs() + }, + Tree_configuration { + (Tree_level_index)_cfg.ft_nr_of_lvls() - 1, + (Tree_degree)_cfg.ft_nr_of_children(), + _cfg.ft_nr_of_leafs() + }, + Tree_configuration { + (Tree_level_index)_cfg.ft_nr_of_lvls() - 1, + (Tree_degree)_cfg.ft_nr_of_children(), + _cfg.ft_nr_of_leafs() + }, + _pba_alloc + }}; - NONCOPYABLE(Main); - - void _generated_req_completed(State_uint state_uint) override + Constructible &_crypto_key(Key_id key_id) { - if (!_generated_req_success) { - error("command pool: request failed because generated request failed)"); - _env.parent().exit(-1); - return; - } - _state = (State)state_uint; + for (Constructible &key : _crypto_keys) + if (key.constructed() && key->key_id == key_id) + return key; + ASSERT_NEVER_REACHED; } - void wakeup_vfs_user() override { _sigh.local_submit(); } - void _wakeup_back_end_services() { _vfs_env.io().commit(); } void _handle_signal() { - execute_modules(); + while(_sb_initializer.execute(_init_superblocks, _block_io, _trust_anchor, _vbd_initializer, _ft_initializer)); + if (_init_superblocks.complete()) + _env.parent().exit(_init_superblocks.success() ? 0 : -1); _wakeup_back_end_services(); } + /******************************** + ** Crypto_key_files_interface ** + ********************************/ + + void add_crypto_key(Key_id key_id) override + { + for (Constructible &key : _crypto_keys) + if (!key.constructed()) { + key.construct(key_id, + open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/encrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR), + open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/decrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) + ); + return; + } + ASSERT_NEVER_REACHED; + } + + void remove_crypto_key(Key_id key_id) override + { + Constructible &crypto_key = _crypto_key(key_id); + _vfs_env.root_dir().close(&crypto_key->encrypt_file); + _vfs_env.root_dir().close(&crypto_key->decrypt_file); + crypto_key.destruct(); + } + + Vfs::Vfs_handle &encrypt_file(Key_id key_id) override { return _crypto_key(key_id)->encrypt_file; } + Vfs::Vfs_handle &decrypt_file(Key_id key_id) override { return _crypto_key(key_id)->decrypt_file; } + + /******************** + ** Vfs::Env::User ** + ********************/ + + void wakeup_vfs_user() override { _sigh.local_submit(); } + public: - 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(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(); - } - - void execute(bool &progress) override - { - switch(_state) { - case INIT: - - 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; - - case INIT_SBS_SUCCEEDED: _env.parent().exit(0); break; - default: break; - } - } + Main(Env &env) : _env(env) { _handle_signal(); } }; void Component::construct(Genode::Env &env) { static Tresor_init::Main main { env }; } 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 f15f8c0988..45a8704778 100644 --- a/repos/gems/src/app/tresor_init_trust_anchor/component.cc +++ b/repos/gems/src/app/tresor_init_trust_anchor/component.cc @@ -89,9 +89,8 @@ class Main : Vfs::Env::User char const *name, Vfs::File_system &vfs, Genode::Allocator &alloc) - : - _vfs { vfs }, - _vfs_handle { nullptr } + : + _vfs(vfs), _vfs_handle(nullptr) { using Result = Vfs::Directory_service::Open_result; @@ -207,9 +206,7 @@ class Main : Vfs::Env::User public: - Main(Env &env) - : - _env { env } + Main(Env &env) : _env(env) { Xml_node const &config { _config_rom.xml() }; diff --git a/repos/gems/src/app/tresor_tester/main.cc b/repos/gems/src/app/tresor_tester/main.cc index e89b01457b..c63cc0d484 100644 --- a/repos/gems/src/app/tresor_tester/main.cc +++ b/repos/gems/src/app/tresor_tester/main.cc @@ -24,11 +24,10 @@ /* tresor includes */ #include #include -#include +#include #include #include #include -#include #include #include #include @@ -40,192 +39,182 @@ namespace Tresor_tester { + enum { VERBOSE = 0 }; + using namespace Genode; using namespace Tresor; using Salt = uint64_t; + template class Schedule; class Log_node; - class Benchmark_node; + class Start_benchmark_node; class Benchmark; - class Trust_anchor_node; - class Request_node; class Command; + class Initialize_trust_anchor_node; class Snapshot_reference; class Snapshot_reference_tree; - class Client_data; + class Request_node; 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; - } } - -struct Tresor_tester::Log_node -{ - using String = Genode::String<128>; - - String const string; - - NONCOPYABLE(Log_node); - - Log_node(Xml_node const &node) : string { node.attribute_value("string", String { }) } { } -}; - - -struct Tresor_tester::Benchmark_node -{ - using Label = String<128>; - - enum Operation { START, STOP }; - - Operation const op; - bool const label_avail; - Label const label; - - NONCOPYABLE(Benchmark_node); - - 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; - } - - 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 { } } - { } - - Benchmark_node(Operation op, bool label_avail, Label label) : op(op), label_avail(label_avail), label(label) { } -}; - - -class Tresor_tester::Benchmark +template +class Tresor_tester::Schedule : Noncopyable { private: - enum State { STARTED, STOPPED }; - - 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); + T *_tail { }; + List _list { }; public: - Benchmark(Genode::Env &env) : _env { env } { } + using Item = List::Element; - void execute_cmd(Benchmark_node const &node) + void add_tail(T &request) { - switch (node.op) { - case Benchmark_node::START: + _list.insert(&request, _tail); + _tail = &request; + } - ASSERT(_state == STOPPED); - _num_virt_blks_read = 0; - _num_virt_blks_written = 0; - _state = STARTED; - _start_node_ptr = &node; - _start_time = _timer.curr_time().trunc_to_plain_us(); - break; + bool empty() const { return !_list.first(); } - case Benchmark_node::STOP: + template + void with_head(FN && fn) + { + if (_list.first()) + fn(*_list.first()); + } - ASSERT(_state == STARTED); - uint64_t const stop_time_us { _timer.curr_time().trunc_to_plain_us().value }; - log(""); - if (_start_node_ptr->label_avail) - log("Benchmark result \"", _start_node_ptr->label, "\""); - else - log("Benchmark result"); + void remove_head() + { + T *head = _list.first(); + if (!head) + return; - double const passed_time_sec { (double)(stop_time_us - _start_time.value) / (double)(1000 * 1000) }; - log(" Ran ", passed_time_sec, " seconds."); + _list.remove(head); + if (_tail == head) + _tail = _list.first(); + } - if (_num_virt_blks_read) { + template + void try_yield_head(CAN_YIELD_TO_FN && can_yield_to) + { + T *head = _list.first(); + if (!head) + return; - 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) }; + T *next = head->Item::_next; + if (!next || !can_yield_to(*next)) + return; - log(" Have read ", mibyte_read, " mebibyte in total."); - log(" Have read ", mibyte_per_sec_read, " mebibyte per second."); - } + remove_head(); + _list.insert(head, next); + } +}; - if (_num_virt_blks_written) { +class Tresor_tester::Benchmark : Noncopyable +{ + public: - 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) }; + using Label = String<128>; - log(" Have written ", mibyte_written, " mebibyte in total."); - log(" Have written ", mibyte_per_sec_written, " mebibyte per second."); - } - log(""); - _state = STOPPED; - break; + private: + + Timer::Connection &_timer; + Label const _label; + Microseconds const _start_time; + Number_of_blocks _num_virt_blks_read { }; + Number_of_blocks _num_virt_blks_written { }; + + /* + * Noncopyable + */ + Benchmark(Benchmark const &) = delete; + Benchmark &operator = (Benchmark const &) = delete; + + public: + + Benchmark(Timer::Connection &timer, Label const &label) + : + _timer(timer), _label(label), _start_time(timer.curr_time().trunc_to_plain_us()) + { } + + ~Benchmark() + { + uint64_t const stop_time_us { _timer.curr_time().trunc_to_plain_us().value }; + log(""); + log("Benchmark result \"", _label, "\""); + + double const passed_time_sec { (double)(stop_time_us - _start_time.value) / (double)(1000 * 1000) }; + log(" Ran ", passed_time_sec, " seconds."); + + 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) }; + + log(" Have read ", mibyte_read, " mebibyte in total."); + log(" Have read ", mibyte_per_sec_read, " mebibyte per second."); } + 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) }; + + log(" Have written ", mibyte_written, " mebibyte in total."); + log(" Have written ", mibyte_per_sec_written, " mebibyte per second."); + } + log(""); } void raise_num_virt_blks_read() { _num_virt_blks_read++; } void raise_num_virt_blks_written() { _num_virt_blks_written++; } }; - -struct Tresor_tester::Trust_anchor_node +struct Tresor_tester::Start_benchmark_node : Noncopyable { - using Operation = Trust_anchor_request::Type; + Benchmark::Label const label; - Operation const op; + Start_benchmark_node(Xml_node const &node) : label(node.attribute_value("label", Benchmark::Label())) { } +}; + +struct Tresor_tester::Log_node : Noncopyable +{ + using String = Genode::String<128>; + + String const string; + + Log_node(Xml_node const &node) : string(node.attribute_value("string", String())) { } +}; + +struct Tresor_tester::Initialize_trust_anchor_node : Noncopyable +{ Passphrase const passphrase; - NONCOPYABLE(Trust_anchor_node); - - 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; - } - - Trust_anchor_node(Xml_node const &node) + Initialize_trust_anchor_node(Xml_node const &node) : - op { read_op_attr(node) }, - passphrase { op == Operation::INITIALIZE ? node.attribute_value("passphrase", Passphrase()) : Passphrase() } + passphrase(node.attribute_value("passphrase", Passphrase())) { } }; - -struct Tresor_tester::Request_node +struct Tresor_tester::Request_node : Noncopyable { - using Operation = Tresor::Request::Operation; + enum Operation { + READ, WRITE, SYNC, CREATE_SNAPSHOT, DISCARD_SNAPSHOT, REKEY, EXTEND_VBD, + EXTEND_FREE_TREE, DEINITIALIZE, INITIALIZE }; Operation const op; Virtual_block_address const vba; - Number_of_blocks const count; + Number_of_blocks const num_blocks; bool const sync; bool const salt_avail; Salt const salt; Snapshot_id const snap_id; - NONCOPYABLE(Request_node); - Operation read_op_attr(Xml_node const &node) { ASSERT(node.has_attribute("op")); @@ -234,7 +223,7 @@ struct Tresor_tester::Request_node 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_ft")) return Operation::EXTEND_FREE_TREE; 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; @@ -243,156 +232,143 @@ struct Tresor_tester::Request_node 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 } + op(read_op_attr(node)), + vba(node.attribute_value("vba", (Virtual_block_address)0)), + num_blocks(node.attribute_value("num_blocks", (Number_of_blocks)0)), + sync(node.attribute_value("sync", false)), + salt_avail(node.has_attribute("salt")), + salt(node.attribute_value("salt", (Salt)0)), + snap_id(node.attribute_value("id", (Snapshot_id)0)) { } +}; - bool has_vba() const { return op == Operation::READ || op == Operation::WRITE || op == Operation::SYNC; } +struct Tresor_tester::Command : Avl_node, Schedule::Item +{ + friend class Schedule; - bool has_salt() const { return op == Operation::READ || op == Operation::WRITE; } + using Node_type = String<64>; + using Id = uint64_t; - bool has_count() const + enum Type { + REQUEST, INIT_TRUST_ANCHOR, START_BENCHMARK, FINISH_BENCHMARK, CONSTRUCT, DESTRUCT, INITIALIZE, CHECK, + CHECK_SNAPSHOTS, LOG }; + + enum State { INIT, IN_PROGRESS, COMPLETE }; + + /* + * Noncopyable + */ + Command(Command const &) = delete; + Command &operator = (Command const &) = delete; + + Type const type; + Id const id; + State state { INIT }; + Constructible request_node { }; + Constructible init_trust_anchor_node { }; + Constructible start_benchmark_node { }; + Constructible log_node { }; + Constructible initialize_config { }; + Trust_anchor::Initialize *init_trust_anchor_ptr { }; + Sb_initializer::Initialize *init_superblocks_ptr { }; + Sb_check::Check *check_superblocks_ptr { }; + Superblock_control::Initialize *init_sb_control_ptr { }; + Superblock_control::Deinitialize *deinit_sb_control_ptr { }; + Superblock_control::Create_snapshot *create_snap_ptr { }; + Superblock_control::Discard_snapshot *discard_snap_ptr { }; + Superblock_control::Write_vbas *write_vbas_ptr { }; + Superblock_control::Read_vbas *read_vbas_ptr { }; + Superblock_control::Rekey *rekey_ptr { }; + Superblock_control::Extend_vbd *extend_vbd_ptr { }; + Superblock_control::Extend_free_tree *extend_free_tree_ptr { }; + Superblock_control::Synchronize *sync_ptr { }; + Superblock::State sb_state { Superblock::INVALID }; + Generation generation { }; + bool rekey_finished { }; + bool extend_vbd_finished { }; + bool extend_free_tree_finished { }; + bool restarted { }; + + char const *op_to_string() const { - return op == Operation::READ || op == Operation::WRITE || op == Operation::SYNC || - op == Operation::EXTEND_FT || op == Operation::EXTEND_VBD; + switch (type) { + case INITIALIZE: return "initialize tresor container"; + case REQUEST: + switch(request_node->op) { + case Request_node::INITIALIZE: return "initialize superblock control"; + case Request_node::DEINITIALIZE: return "deinitialize superblock control"; + case Request_node::CREATE_SNAPSHOT: return "create snapshot"; + case Request_node::DISCARD_SNAPSHOT: return "discard snapshot"; + case Request_node::READ: return "read"; + case Request_node::WRITE: return "write"; + case Request_node::SYNC: return "sync"; + case Request_node::REKEY: return "rekey"; + case Request_node::EXTEND_VBD: return "extend virtual block device"; + case Request_node::EXTEND_FREE_TREE: return "extend free tree"; + } + ASSERT_NEVER_REACHED; + case INIT_TRUST_ANCHOR: return "initialize trust anchor"; + case START_BENCHMARK: return "start benchmark"; + case FINISH_BENCHMARK: return "finish benchmark"; + case CONSTRUCT: return "construct"; + case DESTRUCT: return "destruct"; + case CHECK: return "check"; + case CHECK_SNAPSHOTS: return "check_snapshots"; + case LOG: return "log"; + } + ASSERT_NEVER_REACHED; } - bool has_snap_id() const { return op == Operation::DISCARD_SNAPSHOT || op == Operation::CREATE_SNAPSHOT; } + static Type type_from_node(Xml_node const &node) + { + Xml_node::Type const nt = node.type(); + if (nt == "initialize") { return INITIALIZE; } + if (nt == "request") { return REQUEST; } + if (nt == "initialize-trust-anchor") { return INIT_TRUST_ANCHOR; } + if (nt == "start-benchmark") { return START_BENCHMARK; } + if (nt == "finish-benchmark") { return FINISH_BENCHMARK; } + if (nt == "construct") { return CONSTRUCT; } + if (nt == "destruct") { return DESTRUCT; } + if (nt == "check") { return CHECK; } + if (nt == "check-snapshots") { return CHECK_SNAPSHOTS; } + if (nt == "log") { return LOG; } + ASSERT_NEVER_REACHED; + } - void print(Genode::Output &out) const { Genode::print(out, "op ", Tresor::Request::op_to_string(op)); } + bool higher(Command *other_ptr) { return other_ptr->id > id; } + + Command(Xml_node const &node, Id id) : type(type_from_node(node)), id(id) + { + switch (type) { + case INITIALIZE: initialize_config.construct(node); break; + case REQUEST: request_node.construct(node); break; + case INIT_TRUST_ANCHOR: init_trust_anchor_node.construct(node); break; + case START_BENCHMARK: start_benchmark_node.construct(node); break; + case LOG: log_node.construct(node); break; + default: break; + } + } + + template + void with_command(Command::Id id, FUNC && func) + { + if (id != this->id) { + Command *cmd_ptr { Avl_node::child(id > this->id) }; + ASSERT(cmd_ptr); + cmd_ptr->with_command(id, func); + } else + func(*this); + } + + void print(Genode::Output &out) const { Genode::print(out, "id ", id, " op \"", op_to_string(), "\""); } }; - -class Tresor_tester::Command : public Module_channel -{ - public: - - enum Type { INVALID, REQUEST, TRUST_ANCHOR, BENCHMARK, CONSTRUCT, DESTRUCT, INITIALIZE, CHECK, CHECK_SNAPSHOTS, LOG }; - - enum State { PENDING, IN_PROGRESS, CREATE_SNAP_COMPLETED, DISCARD_SNAP_COMPLETED, COMPLETED }; - - private: - - using Type_string = String<64>; - - 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 { }; - - NONCOPYABLE(Command); - - void _generated_req_completed(State_uint state_uint) override; - - static char const *_type_to_string(Type type) - { - switch (type) { - case INITIALIZE: return "initialize"; - case INVALID: return "invalid"; - case REQUEST: return "request"; - case TRUST_ANCHOR: return "trust_anchor"; - case BENCHMARK: return "benchmark"; - case CONSTRUCT: return "construct"; - case DESTRUCT: return "destruct"; - case CHECK: return "check"; - case CHECK_SNAPSHOTS: return "check_snapshots"; - case LOG: return "log"; - } - 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(Xml_node const &node, Tresor_tester::Main &main, Module_channel_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 TRUST_ANCHOR: _trust_anchor_node.construct(node); break; - case BENCHMARK: _benchmark_node.construct(node); break; - case LOG: _log_node.construct(node); break; - default: break; - } - } - - bool may_have_data_mismatch() const - { - return _type == REQUEST && _request_node->op == Tresor::Request::READ && _request_node->salt_avail; - } - - bool synchronize() const - { - switch (_type) { - case REQUEST: return _request_node->sync; - case INVALID: ASSERT_NEVER_REACHED; - default: return true; - } - ASSERT_NEVER_REACHED; - } - - void print(Genode::Output &out) const - { - 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 ; } - 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 data_mismatch (bool data_mismatch) { _data_mismatch = data_mismatch; } - - void execute(bool &progress); -}; - - -struct Tresor_tester::Snapshot_reference : public Genode::Avl_node +struct Tresor_tester::Snapshot_reference : Avl_node { Snapshot_id const id; Generation const gen; - NONCOPYABLE(Snapshot_reference); - - Snapshot_reference(Snapshot_id id, Generation gen) : id { id }, gen { gen } { } + Snapshot_reference(Snapshot_id id, Generation gen) : id(id), gen(gen) { } template void with_ref(Snapshot_id target_id, FUNC && func) const @@ -412,7 +388,6 @@ struct Tresor_tester::Snapshot_reference : public Genode::Avl_nodeid > id; } }; - struct Tresor_tester::Snapshot_reference_tree : public Avl_tree { template @@ -425,61 +400,54 @@ struct Tresor_tester::Snapshot_reference_tree : public Avl_tree _signal_handler { _env.ep(), *this, &Main::_handle_signal }; - Benchmark _benchmark { _env }; - Module_channel_id _next_command_id { 0 }; - unsigned long _num_uncompleted_cmds { 0 }; + Tresor::Path const _crypto_path { _config_rom.xml().sub_node("crypto").attribute_value("path", Tresor::Path()) }; + Tresor::Path const _block_io_path { _config_rom.xml().sub_node("block-io").attribute_value("path", Tresor::Path()) }; + Tresor::Path const _trust_anchor_path { _config_rom.xml().sub_node("trust-anchor").attribute_value("path", Tresor::Path()) }; + Vfs::Vfs_handle &_block_io_file { open_file(_vfs_env, _block_io_path, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_crypto_add_key_file { open_file(_vfs_env, { _crypto_path, "/add_key" }, Vfs::Directory_service::OPEN_MODE_WRONLY) }; + Vfs::Vfs_handle &_crypto_remove_key_file { open_file(_vfs_env, { _crypto_path, "/remove_key" }, Vfs::Directory_service::OPEN_MODE_WRONLY) }; + Vfs::Vfs_handle &_ta_decrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/decrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_ta_encrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/encrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_ta_generate_key_file { open_file(_vfs_env, { _trust_anchor_path, "/generate_key" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_ta_initialize_file { open_file(_vfs_env, { _trust_anchor_path, "/initialize" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Vfs::Vfs_handle &_ta_hash_file { open_file(_vfs_env, { _trust_anchor_path, "/hash" }, Vfs::Directory_service::OPEN_MODE_RDWR) }; + Timer::Connection _timer { _env }; + Constructible _benchmark { }; + Avl_tree _command_tree { }; + Schedule _command_schedule { }; 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") }; + Trust_anchor _trust_anchor { { _ta_decrypt_file, _ta_encrypt_file, _ta_generate_key_file, _ta_initialize_file, _ta_hash_file } }; + Crypto _crypto { {*this, _crypto_add_key_file, _crypto_remove_key_file} }; + Block_io _block_io { _block_io_file }; 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 }; - - NONCOPYABLE(Main); + Sb_check _sb_check { }; + Constructible _crypto_keys[2] { }; static void _generate_blk_data(Tresor::Block &blk_data, Virtual_block_address vba, Salt salt) { @@ -494,66 +462,16 @@ class Tresor_tester::Main : private Vfs::Env::User, private Module_composition, } } - template - void _with_first_processable_cmd(FUNC && func) + Constructible &_crypto_key(Key_id key_id) { - 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 _try_end_program() - { - if (_num_uncompleted_cmds == 0) { - if (_num_errors > 0) { - for_each_channel([&] (Command &cmd) { - if (cmd.state() != Command::COMPLETED) - return; - - if (cmd.success() && (!cmd.may_have_data_mismatch() || !cmd.data_mismatch())) - return; - - log("cmd failed: ", cmd); - }); - _env.parent().exit(-1); - } else - _env.parent().exit(0); - } + for (Constructible &key : _crypto_keys) + if (key.constructed() && key->key_id == key_id) + return key; + ASSERT_NEVER_REACHED; } void _wakeup_back_end_services() { _vfs_env.io().commit(); } - 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); @@ -561,50 +479,471 @@ class Tresor_tester::Main : private Vfs::Env::User, private Module_composition, destroy(_heap, &ref); } - public: - - Main(Genode::Env &env) : _env { env } + void _reset_snap_refs() { - 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(); + while (_snap_refs.first()) + _remove_snap_ref(*_snap_refs.first()); } - void mark_command_in_progress(Module_channel_id cmd_id) + void _remove_snap_refs_with_same_gen(Snapshot_id id) { - with_channel(cmd_id, [&] (Command &cmd) { - ASSERT(cmd.state() == Command::PENDING); - cmd.state(Command::IN_PROGRESS); - }); + 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; + } } - void mark_command_completed(Module_channel_id cmd_id, bool success) + void _mark_command_complete(Command &cmd, 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++; + cmd.state = Command::COMPLETE; + if (VERBOSE) + log("finished command: ", cmd); + if (!success) { + _num_errors++; + error("command failed: ", cmd); + } + } + + void _mark_command_in_progress(Command &cmd, bool &progress) + { + cmd.state = Command::IN_PROGRESS; + progress = true; + if (VERBOSE && !cmd.restarted) { + log("started command: ", cmd); + cmd.restarted = true; + } + } + + template + void _try_complete_command(Command &cmd, REQUEST &req, bool &progress) + { + if (!req.complete()) + return; + + _mark_command_complete(cmd, req.success()); + destroy(_heap, &req); + progress = true; + return; + } + + template + void _try_complete_multi_request_command(Command &cmd, REQUEST &req, bool cmd_finished, bool &progress) + { + if (!req.complete()) + return; + + if (!req.success()) { + _mark_command_complete(cmd, false); + destroy(_heap, &req); + progress = true; + return; + } + destroy(_heap, &req); + if (cmd_finished) { + _mark_command_complete(cmd, true); + return; + } + cmd.state = Command::INIT; + progress = true; + return; + } + + bool _execute_command(Command &cmd) + { + bool progress = false; + switch (cmd.type) { + case Command::INIT_TRUST_ANCHOR: + + switch(cmd.state) { + case Command::INIT: + { + Initialize_trust_anchor_node &node { *cmd.init_trust_anchor_node }; + cmd.init_trust_anchor_ptr = new (_heap) Trust_anchor::Initialize({node.passphrase}); + _mark_command_in_progress(cmd, progress); + break; } - }); + case Command::IN_PROGRESS: + { + Trust_anchor::Initialize &req = *cmd.init_trust_anchor_ptr; + progress |= _trust_anchor.execute(req); + _try_complete_command(cmd, req, progress); + break; + } + default: break; + } + break; + + case Command::INITIALIZE: + + switch(cmd.state) { + case Command::INIT: + { + _reset_snap_refs(); + Tresor_init::Configuration const &cfg { *cmd.initialize_config }; + cmd.init_superblocks_ptr = new (_heap) Sb_initializer::Initialize({ + Tree_configuration { + (Tree_level_index)(cfg.vbd_nr_of_lvls() - 1), + (Tree_degree)cfg.vbd_nr_of_children(), + cfg.vbd_nr_of_leafs() + }, + Tree_configuration { + (Tree_level_index)cfg.ft_nr_of_lvls() - 1, + (Tree_degree)cfg.ft_nr_of_children(), + cfg.ft_nr_of_leafs() + }, + Tree_configuration { + (Tree_level_index)cfg.ft_nr_of_lvls() - 1, + (Tree_degree)cfg.ft_nr_of_children(), + cfg.ft_nr_of_leafs() + }, + _pba_alloc + }); + _mark_command_in_progress(cmd, progress); + break; + } + case Command::IN_PROGRESS: + { + Sb_initializer::Initialize &req = *cmd.init_superblocks_ptr; + progress |= _sb_initializer.execute(req, _block_io, _trust_anchor, _vbd_initializer, _ft_initializer); + _try_complete_command(cmd, req, progress); + break; + } + default: break; + } + break; + + case Command::CONSTRUCT: + + switch(cmd.state) { + case Command::INIT: + + _meta_tree.construct(); + _free_tree.construct(); + _vbd.construct(); + _sb_control.construct(); + cmd.init_sb_control_ptr = new (_heap) Superblock_control::Initialize({cmd.sb_state}); + _mark_command_in_progress(cmd, progress); + break; + + case Command::IN_PROGRESS: + { + Superblock_control::Initialize &req = *cmd.init_sb_control_ptr; + progress |= _sb_control->execute(req, _block_io, _crypto, _trust_anchor); + _try_complete_command(cmd, req, progress); + break; + } + default: break; + } + break; + + case Command::DESTRUCT: + + switch(cmd.state) { + case Command::INIT: + + _meta_tree.destruct(); + _free_tree.destruct(); + _vbd.destruct(); + _sb_control.destruct(); + _mark_command_complete(cmd, true); + progress = true; + break; + + default: break; + } + break; + + case Command::START_BENCHMARK: + + switch(cmd.state) { + case Command::INIT: + + _benchmark.construct(_timer, cmd.start_benchmark_node->label); + _mark_command_complete(cmd, true); + progress = true; + break; + + default: break; + } + break; + + case Command::FINISH_BENCHMARK: + + switch(cmd.state) { + case Command::INIT: + + _benchmark.destruct(); + _mark_command_complete(cmd, true); + progress = true; + break; + + default: break; + } + break; + + case Command::CHECK_SNAPSHOTS: + + switch(cmd.state) { + case Command::INIT: + { + 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; + } + } + if (!snap_ref_ok) { + warning("snap (", snap_ref, ") not known to tresor"); + success = false; + } + }); + 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"); + success = false; + } + } + _mark_command_complete(cmd, success); + progress = true; + break; + } + default: break; + } + break; + + case Command::REQUEST: + + switch(cmd.state) { + case Command::INIT: + { + Request_node const &node { *cmd.request_node }; + switch (node.op) { + case Request_node::WRITE: + cmd.write_vbas_ptr = new (_heap) Superblock_control::Write_vbas({node.vba, node.num_blocks, 0, cmd.id}); + break; + case Request_node::READ: + cmd.read_vbas_ptr = new (_heap) Superblock_control::Read_vbas({node.vba, node.num_blocks, 0, cmd.id}); + break; + case Request_node::SYNC: + cmd.sync_ptr = new (_heap) Superblock_control::Synchronize({}); + break; + case Request_node::REKEY: + cmd.rekey_ptr = new (_heap) Superblock_control::Rekey({cmd.rekey_finished}); + break; + case Request_node::EXTEND_VBD: + cmd.extend_vbd_ptr = new (_heap) Superblock_control::Extend_vbd({node.num_blocks, cmd.extend_vbd_finished}); + break; + case Request_node::EXTEND_FREE_TREE: + cmd.extend_free_tree_ptr = new (_heap) Superblock_control::Extend_free_tree({node.num_blocks, cmd.extend_free_tree_finished}); + break; + case Request_node::DEINITIALIZE: + cmd.deinit_sb_control_ptr = new (_heap) Superblock_control::Deinitialize({}); + break; + case Request_node::CREATE_SNAPSHOT: + cmd.create_snap_ptr = new (_heap) Superblock_control::Create_snapshot({cmd.generation}); + break; + case Request_node::DISCARD_SNAPSHOT: + cmd.discard_snap_ptr = new (_heap) Superblock_control::Discard_snapshot({_snap_id_to_gen(node.snap_id)}); + break; + default: ASSERT_NEVER_REACHED; + } + _mark_command_in_progress(cmd, progress); + break; + } + case Command::IN_PROGRESS: + { + Request_node &node = *cmd.request_node; + switch (node.op) { + case Request_node::WRITE: + { + Superblock_control::Write_vbas &req = *cmd.write_vbas_ptr; + progress |= _sb_control->execute(req, *_vbd, *this, _block_io, *_free_tree, *_meta_tree, _crypto); + _try_complete_command(cmd, req, progress); + break; + } + case Request_node::READ: + { + Superblock_control::Read_vbas &req = *cmd.read_vbas_ptr; + progress |= _sb_control->execute(req, *_vbd, *this, _block_io, _crypto); + _try_complete_command(cmd, req, progress); + break; + } + case Request_node::SYNC: + { + Superblock_control::Synchronize &req = *cmd.sync_ptr; + progress |= _sb_control->execute(req, _block_io, _trust_anchor); + _try_complete_command(cmd, req, progress); + break; + } + case Request_node::REKEY: + { + Superblock_control::Rekey &req = *cmd.rekey_ptr; + progress |= _sb_control->execute(req, *_vbd, *_free_tree, *_meta_tree, _block_io, _crypto, _trust_anchor); + _try_complete_multi_request_command(cmd, req, cmd.rekey_finished, progress); + break; + } + case Request_node::EXTEND_VBD: + { + Superblock_control::Extend_vbd &req = *cmd.extend_vbd_ptr; + progress |= _sb_control->execute(req, *_vbd, *_free_tree, *_meta_tree, _block_io, _trust_anchor); + _try_complete_multi_request_command(cmd, req, cmd.extend_vbd_finished, progress); + break; + } + case Request_node::EXTEND_FREE_TREE: + { + Superblock_control::Extend_free_tree &req = *cmd.extend_free_tree_ptr; + progress |= _sb_control->execute(req, *_free_tree, *_meta_tree, _block_io, _trust_anchor); + _try_complete_multi_request_command(cmd, req, cmd.extend_free_tree_finished, progress); + break; + } + case Request_node::DEINITIALIZE: + { + Superblock_control::Deinitialize &req = *cmd.deinit_sb_control_ptr; + progress |= _sb_control->execute(req, _block_io, _crypto, _trust_anchor); + _try_complete_command(cmd, req, progress); + break; + } + case Request_node::CREATE_SNAPSHOT: + { + Superblock_control::Create_snapshot &req = *cmd.create_snap_ptr; + progress |= _sb_control->execute(req, _block_io, _trust_anchor); + if (req.complete() && req.success()) + _snap_refs.insert(new (_heap) Snapshot_reference { cmd.request_node->snap_id, cmd.generation }); + _try_complete_command(cmd, req, progress); + break; + } + case Request_node::DISCARD_SNAPSHOT: + { + Superblock_control::Discard_snapshot &req = *cmd.discard_snap_ptr; + progress |= _sb_control->execute(req, _block_io, _trust_anchor); + if (req.complete() && req.success()) + _remove_snap_refs_with_same_gen(node.snap_id); + _try_complete_command(cmd, req, progress); + break; + } + default: ASSERT_NEVER_REACHED; + } + break; + } + default: break; + } + break; + + case Command::LOG: + + switch(cmd.state) { + case Command::INIT: + + log("\n", cmd.log_node->string, "\n"); + _mark_command_complete(cmd, true); + progress = true; + break; + + default: break; + } + break; + + case Command::CHECK: + + switch(cmd.state) { + case Command::INIT: + + cmd.check_superblocks_ptr = new (_heap) Sb_check::Check(); + _mark_command_in_progress(cmd, progress); + break; + + case Command::IN_PROGRESS: + { + Sb_check::Check &req = *cmd.check_superblocks_ptr; + progress |= _sb_check.execute(req, _vbd_check, _ft_check, _block_io); + _try_complete_command(cmd, req, progress); + break; + } + default: break; + } + break; + + default: ASSERT_NEVER_REACHED; + } + return progress; } - Generation snap_id_to_gen(Snapshot_id id) + bool _execute_commands() + { + bool progress = false; + _command_schedule.with_head([&] (Command &head) { + + progress |= _execute_command(head); + if (head.state == Command::COMPLETE) { + _command_schedule.remove_head(); + return; + } + if (head.type != Command::REQUEST) + return; + + Request_node::Operation op = head.request_node->op; + if (op != Request_node::REKEY && + op != Request_node::EXTEND_VBD && + op != Request_node::EXTEND_FREE_TREE) + return; + + if (head.request_node->sync) + return; + + if (head.state != Command::INIT) + return; + + _command_schedule.try_yield_head([&] (Command &to_cmd) { + + if (to_cmd.type != Command::REQUEST) + return false; + + Request_node::Operation op = to_cmd.request_node->op; + return op == Request_node::READ || + op == Request_node::WRITE || + op == Request_node::SYNC || + op == Request_node::DISCARD_SNAPSHOT; + }); + }); + return progress; + } + + void _handle_signal() + { + while (_execute_commands()); + if (_command_schedule.empty()) { + if (_num_errors) { + error(_num_errors, " command", _num_errors > 1 ? "s" : "", " failed!"); + _env.parent().exit(-1); + } else { + log("All commands succeeded!"); + _env.parent().exit(0); + } + } + _wakeup_back_end_services(); + } + + template + void _with_command(Command::Id id, FUNC && func) + { + ASSERT(_command_tree.first()); + _command_tree.first()->with_command(id, func); + } + + Generation _snap_id_to_gen(Snapshot_id id) { Generation gen { INVALID_GENERATION }; _snap_refs.with_ref(id, [&] (Snapshot_reference const &ref) { @@ -613,230 +952,93 @@ class Tresor_tester::Main : private Vfs::Env::User, private Module_composition, return gen; } - 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) + /******************** + ** Vfs::Env::User ** + ********************/ + + void wakeup_vfs_user() override { _signal_handler.local_submit(); } + + + /******************************** + ** Crypto_key_files_interface ** + ********************************/ + + void add_crypto_key(Key_id key_id) override { - 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; - } + for (Constructible &key : _crypto_keys) + if (!key.constructed()) { + key.construct(key_id, + open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/encrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR), + open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/decrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) + ); + return; + } + ASSERT_NEVER_REACHED; } - void reset_snap_refs() + void remove_crypto_key(Key_id key_id) override { - while (_snap_refs.first()) - _remove_snap_ref(*_snap_refs.first()); + Constructible &crypto_key = _crypto_key(key_id); + _vfs_env.root_dir().close(&crypto_key->encrypt_file); + _vfs_env.root_dir().close(&crypto_key->decrypt_file); + crypto_key.destruct(); } - Pba_allocator &pba_alloc() { return _pba_alloc; } + Vfs::Vfs_handle &encrypt_file(Key_id key_id) override { return _crypto_key(key_id)->encrypt_file; } + Vfs::Vfs_handle &decrypt_file(Key_id key_id) override { return _crypto_key(key_id)->decrypt_file; } - void generate_blk_data(Request_tag tresor_req_tag, Virtual_block_address vba, Tresor::Block &blk_data) + + /*************************** + ** Client_data_interface ** + ***************************/ + + void obtain_data(Obtain_data_attr const &attr) override { - 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); + _with_command(attr.in_req_tag, [&] (Command &cmd) { + ASSERT(cmd.type == Command::REQUEST); + Request_node const &node { *cmd.request_node }; + if (node.salt_avail) + _generate_blk_data(attr.out_blk, attr.in_vba, node.salt); }); - _benchmark.raise_num_virt_blks_written(); + if (_benchmark.constructed()) + _benchmark->raise_num_virt_blks_written(); } - void verify_blk_data(Request_tag tresor_req_tag, Virtual_block_address vba, Tresor::Block &blk_data) + void supply_data(Supply_data_attr const &attr) override { - 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) { + _with_command(attr.in_req_tag, [&] (Command &cmd) { + ASSERT(cmd.type == Command::REQUEST); + Request_node const &node { *cmd.request_node }; + if (node.salt_avail) { Tresor::Block gen_blk_data { }; - _generate_blk_data(gen_blk_data, vba, req_node.salt); + _generate_blk_data(gen_blk_data, attr.in_vba, node.salt); - if (memcmp(&blk_data, &gen_blk_data, BLOCK_SIZE)) { - cmd.data_mismatch(true); - warning("client data mismatch: vba=", vba, " req_tag=", tresor_req_tag); + if (memcmp(&attr.in_blk, &gen_blk_data, BLOCK_SIZE)) { + warning("client data mismatch: vba=", attr.in_vba, " req_tag=", attr.in_req_tag); _num_errors++; } } }); - _benchmark.raise_num_virt_blks_read(); + if (_benchmark.constructed()) + _benchmark->raise_num_virt_blks_read(); } - void construct_tresor_modules() - { - _free_tree.construct(); - _vbd.construct(); - _sb_control.construct(); - _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); - add_module(CLIENT_DATA, *_client_data); - add_module(META_TREE, *_meta_tree); - } + public: - void destruct_tresor_modules() + Main(Genode::Env &env) : _env(env) { - remove_module(META_TREE); - remove_module(CLIENT_DATA); - remove_module(REQUEST_POOL); - remove_module(SUPERBLOCK_CONTROL); - remove_module(VIRTUAL_BLOCK_DEVICE); - remove_module(FREE_TREE); - _meta_tree.destruct(); - _client_data.destruct(); - _request_pool.destruct(); - _sb_control.destruct(); - _vbd.destruct(); - _free_tree.destruct(); - } - - void check_snapshots(Command &cmd, bool &progress) - { - 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; - } - } - if (!snap_ref_ok) { - warning("snap (", snap_ref, ") not known to tresor"); - _num_errors++; - success = false; - } + Command::Id command_id { 0 }; + _config_rom.xml().sub_node("commands").for_each_sub_node([&] (Xml_node const &node) { + Command *cmd_ptr = new (_heap) Command(node, command_id++); + _command_tree.insert(cmd_ptr); + _command_schedule.add_tail(*cmd_ptr); }); - 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; + _handle_signal(); } - - 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); } diff --git a/repos/gems/src/lib/tresor/block_io.cc b/repos/gems/src/lib/tresor/block_io.cc index e1c0b6b2ee..9abc54eee4 100644 --- a/repos/gems/src/lib/tresor/block_io.cc +++ b/repos/gems/src/lib/tresor/block_io.cc @@ -12,199 +12,79 @@ */ /* tresor includes */ -#include #include #include using namespace Tresor; -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_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 } -{ } - -char const *Block_io_request::type_to_string(Type type) +bool Block_io::Sync::execute(Vfs::Vfs_handle &file) { - switch (type) { - 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"; - } - ASSERT_NEVER_REACHED; -} + bool progress = false; + switch (_helper.state) { + case INIT: + _file.construct(_helper.state, file); + _helper.state = SYNC; + progress = true; + break; -void Block_io_channel::_generated_req_completed(State_uint state_uint) -{ - 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; - } - _state = (State)state_uint; -} - - -void Block_io_channel::_mark_req_failed(bool &progress, Error_string str) -{ - error("request failed: failed to ", str); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Block_io_channel::_mark_req_successful(bool &progress) -{ - Request &req { *_req_ptr }; - req._success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; - 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; - } - } -} - - -void Block_io_channel::_read(bool &progress) -{ - 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; + case SYNC: _file->sync(SYNC_OK, FILE_ERR, progress); break; + case SYNC_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; default: break; } + return progress; } -void Block_io_channel::_read_client_data(bool &progress) +bool Block_io::Read::execute(Vfs::Vfs_handle &file) { + bool progress = false; + switch (_helper.state) { + case INIT: - 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; + _file.construct(_helper.state, file); + _helper.state = READ; + progress = true; + break; + + case READ: _file->read(READ_OK, FILE_ERR, _attr.in_pba * BLOCK_SIZE, { (char *)&_attr.out_block, BLOCK_SIZE }, progress); break; case READ_OK: - calc_hash(_blk, req._hash); - _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 PLAINTEXT_BLK_SUPPLIED: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; - default: break; - } -} - - -void Block_io_channel::_write_client_data(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: - - _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); + _helper.mark_succeeded(progress); + if (VERBOSE_BLOCK_IO && (!VERBOSE_BLOCK_IO_PBA_FILTER || VERBOSE_BLOCK_IO_PBA == _attr.in_pba)) + log("block_io: ", *this, " hash ", hash(_attr.out_block)); break; - case CIPHERTEXT_BLK_OBTAINED: + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; + default: break; + } + return progress; +} - calc_hash(_blk, req._hash); - _file.write(WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress); break; + +bool Block_io::Write::execute(Vfs::Vfs_handle &file) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _file.construct(_helper.state, file); + _helper.state = WRITE; + progress = true; break; - case WRITE_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + case WRITE: _file->write(WRITE_OK, FILE_ERR, _attr.in_pba * BLOCK_SIZE, { (char *)&_attr.in_block, BLOCK_SIZE }, progress); break; + case WRITE_OK: + + _helper.mark_succeeded(progress); + if (VERBOSE_BLOCK_IO && (!VERBOSE_BLOCK_IO_PBA_FILTER || VERBOSE_BLOCK_IO_PBA == _attr.in_pba)) + log("block_io: ", *this, " hash ", hash(_attr.in_block)); + break; + + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; default: break; } -} - - -void Block_io_channel::_write(bool &progress) -{ - - 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_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} - - -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) -: - Module_channel { BLOCK_IO, id }, _vfs_env { vfs_env }, _path { xml_node.attribute_value("path", Tresor::Path()) } -{ } - - -Block_io::Block_io(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); - } + return progress; } diff --git a/repos/gems/src/lib/tresor/crypto.cc b/repos/gems/src/lib/tresor/crypto.cc index 8a2f7e2a64..22b40a8d98 100644 --- a/repos/gems/src/lib/tresor/crypto.cc +++ b/repos/gems/src/lib/tresor/crypto.cc @@ -13,317 +13,101 @@ /* tresor includes */ #include -#include #include using namespace Tresor; -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_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 +bool Crypto::Add_key::execute(Crypto::Attr const &crypto_attr) { - 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; - } -} + bool progress { false }; + switch (_helper.state) { + case INIT: - -char const *Crypto_request::type_to_string(Type type) -{ - switch (type) { - case ADD_KEY: return "add_key"; - case REMOVE_KEY: return "remove_key"; - case ENCRYPT_CLIENT_DATA: return "encrypt_client_data"; - case DECRYPT_CLIENT_DATA: return "decrypt_client_data"; - case ENCRYPT: return "encrypt"; - case DECRYPT: return "decrypt"; - } - ASSERT_NEVER_REACHED; -} - - -void Crypto_channel::_generated_req_completed(State_uint state_uint) -{ - 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; - } - _state = (State)state_uint; -} - - -Constructible &Crypto_channel::_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; - ASSERT_NEVER_REACHED; -} - - -void Crypto_channel::_mark_req_failed(bool &progress, char const *str) -{ - error("crypto: request (", *_req_ptr, ") failed at step \"", str, "\""); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Crypto_channel::_mark_req_successful(bool &progress) -{ - 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)); - - 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; - } - } - 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_channel::_add_key(bool &progress) -{ - 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); + _file.construct(_helper.state, crypto_attr.add_key_file); + memcpy(_write_buf, &_attr.in_key.id, sizeof(Key_id)); + memcpy(_write_buf + sizeof(Key_id), &_attr.in_key.value, sizeof(Key_value)); + _helper.state = WRITE; + progress = true; break; - case WRITE_OK: - { - 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; - } - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; - default: break; - } -} - - -void Crypto_channel::_remove_key(bool &progress) -{ - 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: _file->write(WRITE_OK, FILE_ERR, 0, { _write_buf, sizeof(_write_buf) }, progress); break; case WRITE_OK: - _key_dir(req._key_id).destruct(); - _mark_req_successful(progress); + crypto_attr.key_files.add_crypto_key(_attr.in_key.id); + _helper.mark_succeeded(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; - default: return; - } -} - - -void Crypto_channel::_encrypt_client_data(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: - - _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; - - case PLAINTEXT_BLK_OBTAINED: - - _key_dir(req._key_id)->encrypt_file.write( - WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress); - break; - - case WRITE_OK: - - _key_dir(req._key_id)->encrypt_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; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; default: break; } + return progress; } -void Crypto_channel::_encrypt(bool &progress) +bool Crypto::Remove_key::execute(Crypto::Attr const &crypto_attr) { - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: + bool progress { false }; + switch (_helper.state) { + case INIT: - _key_dir(req._key_id)->encrypt_file.write( - WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + _file.construct(_helper.state, crypto_attr.remove_key_file); + _helper.state = WRITE; + progress = true; break; + case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { (char *)&_attr.in_key_id, sizeof(Key_id) }, progress); break; case WRITE_OK: - _key_dir(req._key_id)->encrypt_file.read( - READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + crypto_attr.key_files.remove_crypto_key(_attr.in_key_id); + _helper.mark_succeeded(progress); break; - case READ_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation"); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; default: break; } + return progress; } -void Crypto_channel::_decrypt(bool &progress) +bool Crypto::Encrypt::execute(Crypto::Attr const &crypto_attr) { - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: + bool progress { false }; + switch (_helper.state) { + case INIT: - _key_dir(req._key_id)->decrypt_file.write( - WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + _file.construct(_helper.state, crypto_attr.key_files.encrypt_file(_attr.in_key_id)); + _offset = _attr.in_pba * BLOCK_SIZE; + _helper.state = WRITE; + progress = true; break; - case WRITE_OK: - - _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; + case WRITE: _file->write(WRITE_OK, FILE_ERR, _offset, { (char *)&_attr.in_out_blk, BLOCK_SIZE }, progress); break; + case WRITE_OK: _file->read(READ_OK, FILE_ERR, _offset, { (char *)&_attr.in_out_blk, BLOCK_SIZE }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file-operation error"); break; default: break; } + return progress; } -void Crypto_channel::_decrypt_client_data(bool &progress) +bool Crypto::Decrypt::execute(Crypto::Attr const &crypto_attr) { - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: + bool progress { false }; + switch (_helper.state) { + case INIT: - _key_dir(req._key_id)->decrypt_file.write( - WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + _file.construct(_helper.state, crypto_attr.key_files.decrypt_file(_attr.in_key_id)); + _offset = _attr.in_pba * BLOCK_SIZE; + _helper.state = WRITE; + progress = true; 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; + case WRITE: _file->write(WRITE_OK, FILE_ERR, _offset, { (char *)&_attr.in_out_blk, BLOCK_SIZE }, progress); break; + case WRITE_OK: _file->read(READ_OK, FILE_ERR, _offset, { (char *)&_attr.in_out_blk, BLOCK_SIZE }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file-operation error"); break; default: break; } -} - - -void Crypto_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -void Crypto_channel::execute(bool &progress) -{ - if (!_req_ptr) - 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_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} - - -Crypto_channel::Crypto_channel(Module_channel_id id, Vfs::Env &vfs_env, Xml_node const &xml_node) -: - Module_channel { CRYPTO, id }, _vfs_env { vfs_env }, _path { xml_node.attribute_value("path", Tresor::Path()) } -{ } - - -Crypto::Crypto(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); - } + return progress; } diff --git a/repos/gems/src/lib/tresor/free_tree.cc b/repos/gems/src/lib/tresor/free_tree.cc index 2b08554122..472a232d26 100644 --- a/repos/gems/src/lib/tresor/free_tree.cc +++ b/repos/gems/src/lib/tresor/free_tree.cc @@ -13,62 +13,22 @@ /* tresor includes */ #include -#include -#include #include using namespace Tresor; -char const *Free_tree_request::type_to_string(Type type) +bool Free_tree::Allocate_pbas::_can_alloc_pba_of(Type_2_node &node) { - switch (type) { - 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"; - } - ASSERT_NEVER_REACHED; -} - - -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_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 } -{ } - - -void Free_tree::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} - - -bool Free_tree_channel::_can_alloc_pba_of(Type_2_node &node) -{ - Request &req { *_req_ptr }; - if (node.pba == 0 || node.pba == INVALID_PBA || node.free_gen > req._last_secured_gen) + if (node.pba == 0 || node.pba == INVALID_PBA || node.free_gen > _attr.in_last_secured_gen) return false; if (!node.reserved) return true; - if (req._rekeying && node.last_key_id == req._prev_key_id && node.last_vba < req._rekeying_vba) + if (_attr.in_rekeying && node.last_key_id == _attr.in_prev_key_id && node.last_vba < _attr.in_rekeying_vba) return true; - for (Snapshot const &snap : req._snapshots.items) + for (Snapshot const &snap : _attr.in_snapshots.items) if (snap.valid && node.free_gen > snap.gen && node.alloc_gen < snap.gen + 1) return false; @@ -76,62 +36,48 @@ bool Free_tree_channel::_can_alloc_pba_of(Type_2_node &node) } -void Free_tree_channel::_generated_req_completed(State_uint state_uint) +void Free_tree::Allocate_pbas::_alloc_pba_of(Type_2_node &t2_node) { - 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; - } - _state = (State)state_uint; -} - - -void Free_tree_channel::_alloc_pba_of(Type_2_node &t2_node) -{ - 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 (; vbd_lvl <= _attr.in_max_lvl && _attr.in_out_new_blocks.pbas[vbd_lvl]; vbd_lvl++); - 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: + Virtual_block_address node_min_vba { vbd_node_min_vba(_vbd_degree_log_2, vbd_lvl, _attr.in_vba) }; + _attr.in_out_new_blocks.pbas[vbd_lvl] = t2_node.pba; + t2_node.alloc_gen = _attr.in_old_blocks.nodes[vbd_lvl].gen; + t2_node.free_gen = _attr.in_free_gen; + Virtual_block_address rkg_vba { _attr.in_rekeying_vba }; + switch (_attr.in_application) { + case NON_REKEYING: t2_node.reserved = true; - t2_node.pba = req._old_blocks.nodes[vbd_lvl].pba; + t2_node.pba = _attr.in_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; + if (_attr.in_rekeying) { + if (_attr.in_vba < rkg_vba) + t2_node.last_key_id = _attr.in_curr_key_id; else - t2_node.last_key_id = req._prev_key_id; + t2_node.last_key_id = _attr.in_prev_key_id; } else - t2_node.last_key_id = req._curr_key_id; + t2_node.last_key_id = _attr.in_curr_key_id; break; - case Request::ALLOC_FOR_RKG_CURR_GEN_BLKS: + case REKEYING_IN_CURRENT_GENERATION: t2_node.reserved = false; - t2_node.pba = req._old_blocks.nodes[vbd_lvl].pba; + t2_node.pba = _attr.in_old_blocks.nodes[vbd_lvl].pba; t2_node.last_vba = node_min_vba; - t2_node.last_key_id = req._prev_key_id; + t2_node.last_key_id = _attr.in_prev_key_id; break; - case Request::ALLOC_FOR_RKG_OLD_GEN_BLKS: + case REKEYING_IN_OLDER_GENERATION: { 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; + Virtual_block_address node_max_vba { vbd_node_max_vba(_vbd_degree_log_2, vbd_lvl, _attr.in_vba) }; + if (rkg_vba < node_max_vba && rkg_vba < _attr.in_vbd_max_vba) { + t2_node.last_key_id = _attr.in_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; + } else if (rkg_vba == node_max_vba || rkg_vba == _attr.in_vbd_max_vba) { + t2_node.last_key_id = _attr.in_curr_key_id; t2_node.last_vba = node_min_vba; } else ASSERT_NEVER_REACHED; @@ -142,78 +88,59 @@ void Free_tree_channel::_alloc_pba_of(Type_2_node &t2_node) } -void Free_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 = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Free_tree_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Free_tree_channel::_start_tree_traversal(bool &progress) -{ - 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); -} - - -void Free_tree_channel::_traverse_curr_node(bool &progress) +void Free_tree::Allocate_pbas::_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); + _read_block.generate(_helper, READ_BLK, SEEK_DOWN, progress, t1_node.pba, _blk); else { - _state = SEEK_LEFT_OR_UP; + _helper.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 (_num_pbas < _attr.in_num_required_pbas && _can_alloc_pba_of(t2_node)) { if (_apply_allocation) _alloc_pba_of(t2_node); _num_pbas++; } - _state = SEEK_LEFT_OR_UP; + _helper.state = SEEK_LEFT_OR_UP; progress = true; } } -void Free_tree_channel::_alloc_pbas(bool &progress) +void Free_tree::Allocate_pbas::_start_tree_traversal(bool &progress) { - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: + _num_pbas = 0; + _lvl = _attr.in_out_ft.max_lvl; + _node_idx[_lvl] = 0; + _t1_blks[_lvl].nodes[_node_idx[_lvl]] = _attr.in_out_ft.t1_node(); + _read_block.generate(_helper, READ_BLK, SEEK_DOWN, progress, _attr.in_out_ft.pba, _blk); +} - _vbd_degree_log_2 = log2(req._vbd_degree); + +bool Free_tree::Allocate_pbas::execute(Block_io &block_io, Meta_tree &meta_tree) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _vbd_degree_log_2 = log2(_attr.in_vbd_degree); _apply_allocation = false; _start_tree_traversal(progress); break; + case READ_BLK: progress |= _read_block.execute(block_io); break; case SEEK_DOWN: { if (!check_hash(_blk, _t1_blks[_lvl].nodes[_node_idx[_lvl]].hash)) { - _mark_req_failed(progress, "hash mismatch"); + _helper.mark_failed(progress, "hash mismatch"); break; } _lvl--; - _node_idx[_lvl] = req._ft.degree - 1; + _node_idx[_lvl] = _attr.in_out_ft.degree - 1; if (_lvl) _t1_blks[_lvl].decode_from_blk(_blk); else @@ -223,31 +150,31 @@ void Free_tree_channel::_alloc_pbas(bool &progress) } case SEEK_LEFT_OR_UP: - if (_lvl < req._ft.max_lvl) { - if (_node_idx[_lvl] && _num_pbas < _req_ptr->_num_required_pbas) { + if (_lvl < _attr.in_out_ft.max_lvl) { + if (_node_idx[_lvl] && _num_pbas < _attr.in_num_required_pbas) { _node_idx[_lvl]--; _traverse_curr_node(progress); } else { _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; + if (t1_node.is_volatile(_attr.in_curr_gen)) { + _helper.state = ALLOC_PBA_SUCCEEDED; progress = true; } else - _generate_req(WRITE_BLK, progress, req._mt, req._curr_gen, t1_node.pba); + _allocate_pba.generate(_helper, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, progress, _attr.in_out_mt, _attr.in_curr_gen, t1_node.pba); else { - _state = SEEK_LEFT_OR_UP; + _helper.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); + _attr.in_out_ft.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]); + _helper.mark_succeeded(progress); } else { - if (_num_pbas < req._num_required_pbas) - _mark_req_failed(progress, "not enough free pbas"); + if (_num_pbas < _attr.in_num_required_pbas) + _helper.mark_failed(progress, "not enough free pbas"); else { _apply_allocation = true; _start_tree_traversal(progress); @@ -256,68 +183,55 @@ void Free_tree_channel::_alloc_pbas(bool &progress) } break; - case WRITE_BLK: + case ALLOC_PBA: progress |= _allocate_pba.execute(meta_tree, block_io); break; + case ALLOC_PBA_SUCCEEDED: { 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; + t1_node.gen = _attr.in_curr_gen; calc_hash(_blk, t1_node.hash); - _generate_req(SEEK_LEFT_OR_UP, progress, t1_node.pba, _blk); + _write_block.generate(_helper, WRITE_BLK, SEEK_LEFT_OR_UP, progress, t1_node.pba, _blk); break; } + case WRITE_BLK: progress |= _write_block.execute(block_io); break; default: break; } + return progress; } -void Free_tree_channel::execute(bool &progress) -{ - 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) +void Free_tree::Extend_tree::_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); + _write_block.generate(_helper, WRITE_BLK, 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() +void Free_tree::Extend_tree::_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 }); + ASSERT(_attr.in_out_ft.max_lvl < TREE_MAX_LEVEL); + _attr.in_out_ft.max_lvl++; + _t1_blks[_attr.in_out_ft.max_lvl] = { }; + _t1_blks[_attr.in_out_ft.max_lvl].nodes[0] = _attr.in_out_ft.t1_node(); + _new_pbas.pbas[_attr.in_out_ft.max_lvl] = alloc_pba_from_range(_attr.in_out_first_pba, _attr.in_out_num_pbas); + _attr.in_out_ft.t1_node({ _new_pbas.pbas[_attr.in_out_ft.max_lvl], _attr.in_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]); + log(" set root: ", _attr.in_out_ft, "\n set lvl ", _attr.in_out_ft.max_lvl, " node 0: ", + _t1_blks[_attr.in_out_ft.max_lvl].nodes[0]); } -void Free_tree_channel::_add_new_branch_at(Tree_level_index dst_lvl, Tree_node_index dst_node_idx) +void Free_tree::Extend_tree::_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) { @@ -331,17 +245,17 @@ void Free_tree_channel::_add_new_branch_at(Tree_level_index dst_lvl, Tree_node_i log(" reset lvl ", lvl); } } - for (; _lvl && req._num_pbas; _lvl--) { + for (; _lvl && _attr.in_out_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 }; + _new_pbas.pbas[_lvl - 1] = alloc_pba_from_range(_attr.in_out_first_pba, _attr.in_out_num_pbas); + _t1_blks[_lvl].nodes[node_idx] = { _new_pbas.pbas[_lvl - 1], _attr.in_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) }; + for (; node_idx < _attr.in_out_ft.degree && _attr.in_out_num_pbas; node_idx++) { + _t2_blk.nodes[node_idx] = { alloc_pba_from_range(_attr.in_out_first_pba, _attr.in_out_num_pbas) }; _num_leaves++; if (VERBOSE_FT_EXTENSION) log(" set _lvl e ", _lvl, " node ", node_idx, ": ", _t2_blk.nodes[node_idx]); @@ -353,80 +267,80 @@ void Free_tree_channel::_add_new_branch_at(Tree_level_index dst_lvl, Tree_node_i } -void Free_tree_channel::_extension_step(bool &progress) +bool Free_tree::Extend_tree::execute(Block_io &block_io, Meta_tree &meta_tree) { - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: + bool progress = false; + switch (_helper.state) { + case INIT: _num_leaves = 0; - _vba = req._ft.num_leaves; + _vba = _attr.in_out_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)) { + _lvl = _attr.in_out_ft.max_lvl; + _old_pbas.pbas[_lvl] = _attr.in_out_ft.pba; + _old_generations.items[_lvl] = _attr.in_out_ft.gen; + if (_vba <= tree_max_max_vba(_attr.in_out_ft.degree, _attr.in_out_ft.max_lvl)) { - _generate_req(READ_BLK_SUCCEEDED, progress, req._ft.pba, _blk); + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _attr.in_out_ft.pba, _blk); if (VERBOSE_FT_EXTENSION) - log(" root (", req._ft, "): load to lvl ", _lvl); + log(" root (", _attr.in_out_ft, "): load to lvl ", _lvl); } else { _add_new_root_lvl(); - _add_new_branch_at(req._ft.max_lvl, 1); + _add_new_branch_at(_attr.in_out_ft.max_lvl, 1); _generate_write_blk_req(progress); if (VERBOSE_FT_EXTENSION) - log(" pbas allocated: curr gen ", req._curr_gen); + log(" pbas allocated: curr gen ", _attr.in_curr_gen); } break; + case READ_BLK: progress |= _read_block.execute(block_io); 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 (_lvl < _attr.in_out_ft.max_lvl) { + Tree_node_index node_idx = tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree); if (!check_hash(_blk, _t1_blks[_lvl + 1].nodes[node_idx].hash)) - _mark_req_failed(progress, "hash mismatch"); + _helper.mark_failed(progress, "hash mismatch"); } else - if (!check_hash(_blk, req._ft.hash)) - _mark_req_failed(progress, "hash mismatch"); + if (!check_hash(_blk, _attr.in_out_ft.hash)) + _helper.mark_failed(progress, "hash mismatch"); - Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl, req._ft.degree); + Tree_node_index node_idx = tree_node_index(_vba, _lvl, _attr.in_out_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); + _read_block.generate(_helper, READ_BLK, 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) { + if (_old_generations.items[_alloc_lvl] == _attr.in_curr_gen) { _alloc_pba = _old_pbas.pbas[_alloc_lvl]; - _state = ALLOC_PBA_SUCCEEDED; + _helper.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); + _allocate_pba.generate(_helper, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, progress, _attr.in_out_mt, _attr.in_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); + Tree_node_index t1_node_idx = tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree); if (!check_hash(_blk, _t1_blks[_lvl + 1].nodes[t1_node_idx].hash)) - _mark_req_failed(progress, "hash mismatch"); + _helper.mark_failed(progress, "hash mismatch"); - Tree_node_index t2_node_idx = t2_node_idx_for_vba(_vba, req._ft.degree); + Tree_node_index t2_node_idx = tree_node_index(_vba, _lvl, _attr.in_out_ft.degree); if (_t2_blk.nodes[t2_node_idx].valid()) - _mark_req_failed(progress, "t2 node valid"); + _helper.mark_failed(progress, "t2 node valid"); _add_new_branch_at(_lvl, t2_node_idx); _alloc_lvl = _lvl; @@ -434,41 +348,41 @@ void Free_tree_channel::_extension_step(bool &progress) 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); + _allocate_pba.generate(_helper, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, progress, _attr.in_out_mt, _attr.in_curr_gen, _alloc_pba); } break; + case ALLOC_PBA: progress |= _allocate_pba.execute(meta_tree, block_io); break; case ALLOC_PBA_SUCCEEDED: _new_pbas.pbas[_alloc_lvl] = _alloc_pba; - if (_alloc_lvl < req._ft.max_lvl) { + if (_alloc_lvl < _attr.in_out_ft.max_lvl) { _alloc_lvl++; - if (_old_generations.items[_alloc_lvl] == req._curr_gen) { + if (_old_generations.items[_alloc_lvl] == _attr.in_curr_gen) { _alloc_pba = _old_pbas.pbas[_alloc_lvl]; - _state = ALLOC_PBA_SUCCEEDED; + _helper.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); + _allocate_pba.generate(_helper, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, progress, _attr.in_out_mt, _attr.in_curr_gen, _alloc_pba); } } else { _generate_write_blk_req(progress); if (VERBOSE_FT_EXTENSION) - log(" pbas allocated: curr gen ", req._curr_gen); + log(" pbas allocated: curr gen ", _attr.in_curr_gen); } break; + case WRITE_BLK: progress |= _write_block.execute(block_io); break; case WRITE_BLK_SUCCEEDED: - if (_lvl < req._ft.max_lvl) { + if (_lvl < _attr.in_out_ft.max_lvl) { if (_lvl > 1) { - Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree); + Tree_node_index node_idx = tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree); Type_1_node &t1_node { _t1_blks[_lvl + 1].nodes[node_idx] }; - t1_node = { _new_pbas.pbas[_lvl], req._curr_gen }; + t1_node = { _new_pbas.pbas[_lvl], _attr.in_curr_gen }; calc_hash(_blk, t1_node.hash); if (VERBOSE_FT_EXTENSION) log(" set lvl ", _lvl + 1, " node ", node_idx, ": ", t1_node); @@ -476,9 +390,9 @@ void Free_tree_channel::_extension_step(bool &progress) _lvl++; _generate_write_blk_req(progress); } else { - Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree); + Tree_node_index node_idx = tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree); Type_1_node &t1_node = _t1_blks[_lvl + 1].nodes[node_idx]; - t1_node = { _new_pbas.pbas[_lvl], req._curr_gen }; + t1_node = { _new_pbas.pbas[_lvl], _attr.in_curr_gen }; calc_hash(_blk, t1_node.hash); if (VERBOSE_FT_EXTENSION) log(" set lvl ", _lvl + 1, " t1_node ", node_idx, ": ", t1_node); @@ -487,30 +401,14 @@ void Free_tree_channel::_extension_step(bool &progress) _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); + _attr.in_out_ft.t1_node({ _new_pbas.pbas[_lvl], _attr.in_curr_gen }); + calc_hash(_blk, _attr.in_out_ft.hash); + _attr.in_out_ft.num_leaves += _num_leaves; + _helper.mark_succeeded(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); - } + return progress; } diff --git a/repos/gems/src/lib/tresor/ft_check.cc b/repos/gems/src/lib/tresor/ft_check.cc index ce24a19097..388b2a1634 100644 --- a/repos/gems/src/lib/tresor/ft_check.cc +++ b/repos/gems/src/lib/tresor/ft_check.cc @@ -13,73 +13,66 @@ /* tresor includes */ #include -#include #include using namespace Tresor; -Ft_check_request::Ft_check_request(Module_id src_mod, Module_channel_id src_chan, Tree_root const &ft, bool &success) -: - Module_request { src_mod, src_chan, FT_CHECK }, _ft { ft }, _success { success } -{ } - - -bool Ft_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) +bool Ft_check::Check::_execute_node(Block_io &block_io, Tree_level_index lvl, Tree_node_index node_idx, bool &progress) { bool &check_node { _check_node[lvl][node_idx] }; if (check_node == false) return false; - Request &req { *_req_ptr }; - switch (_state) { - case REQ_IN_PROGRESS: + switch (_helper.state) { + case IN_PROGRESS: 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" }); + _helper.mark_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._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused"); + log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused"); break; } _num_remaining_leaves--; check_node = false; progress = true; if (VERBOSE_CHECK) - log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " done"); + log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " done"); } else { 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" }); + _helper.mark_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._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused"); + log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused"); break; } - _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _blk); + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, node.pba, _blk); if (VERBOSE_CHECK) - log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, + log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " (", node, "): load to lvl ", lvl - 1); } break; + case READ_BLK: progress |= _read_block.execute(block_io); break; 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" }); + _helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, ") has bad hash" }); break; } if (lvl == 2) @@ -89,11 +82,11 @@ bool Ft_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_ for (bool &cn : _check_node[lvl - 1]) cn = true; - _state = REQ_IN_PROGRESS; + _helper.state = 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"); + log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " has good hash"); break; } default: break; @@ -102,81 +95,24 @@ bool Ft_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_ } -void Ft_check_channel::execute(bool &progress) +bool Ft_check::Check::execute(Block_io &block_io) { - if (!_req_ptr) - return; - - 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++) + bool progress = false; + if (_helper.state == INIT) { + for (Tree_level_index lvl { 1 }; lvl <= _attr.in_ft.max_lvl + 1; lvl++) + for (Tree_node_index node_idx { 0 }; node_idx < _attr.in_ft.degree; node_idx++) _check_node[lvl][node_idx] = false; - _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; + _num_remaining_leaves = _attr.in_ft.num_leaves; + _t1_blks.items[_attr.in_ft.max_lvl + 1].nodes[0] = _attr.in_ft.t1_node(); + _check_node[_attr.in_ft.max_lvl + 1][0] = true; + _helper.state = IN_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; + for (Tree_level_index lvl { 1 }; lvl <= _attr.in_ft.max_lvl + 1; lvl++) + for (Tree_node_index node_idx { 0 }; node_idx < _attr.in_ft.degree; node_idx++) + if (_execute_node(block_io, lvl, node_idx, progress)) + return 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_channel::_mark_req_failed(bool &progress, Error_string str) -{ - error("ft check request (", *_req_ptr, ") failed: ", str); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Ft_check_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Ft_check_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -Ft_check::Ft_check() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } -} - - -void Ft_check::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); + _helper.mark_succeeded(progress); + return progress; } diff --git a/repos/gems/src/lib/tresor/ft_initializer.cc b/repos/gems/src/lib/tresor/ft_initializer.cc index e092ba7a28..55da497e74 100644 --- a/repos/gems/src/lib/tresor/ft_initializer.cc +++ b/repos/gems/src/lib/tresor/ft_initializer.cc @@ -13,20 +13,67 @@ */ /* tresor includes */ -#include #include #include using namespace Tresor; -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_mod, src_chan, FT_INITIALIZER }, _ft { ft }, _pba_alloc { pba_alloc }, _success { success } -{ } +void Ft_initializer::Initialize::_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 + 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; + } +} -bool Ft_initializer_channel::_execute_t2_node(Tree_node_index node_idx, bool &progress) +bool Ft_initializer::Initialize::execute(Block_io &block_io) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _num_remaining_leaves = _attr.in_tree_cfg.num_leaves; + for (Tree_level_index lvl = 0; lvl < TREE_MAX_LEVEL; lvl++) + _reset_level(lvl, DONE); + + _t1_node_states[_attr.in_tree_cfg.max_lvl + 1][0] = INIT_BLOCK; + _helper.state = EXECUTE_NODES; + progress = true; + break; + + case EXECUTE_NODES: + + for (Tree_node_index node_idx = 0; node_idx < _attr.in_tree_cfg.degree; node_idx++) + if (_execute_t2_node(node_idx, progress)) + return progress; + + for (Tree_level_index lvl = 1; lvl <= _attr.in_tree_cfg.max_lvl + 1; lvl++) + for (Tree_node_index node_idx = 0; node_idx < _attr.in_tree_cfg.degree; node_idx++) + if (_execute_t1_node(lvl, node_idx, progress)) + return progress; + + if (_num_remaining_leaves) + _helper.mark_failed(progress, "leaves remaining"); + else { + _attr.out_tree_root = _t1_blks.items[_attr.in_tree_cfg.max_lvl + 1].nodes[0]; + _helper.mark_succeeded(progress); + } + break; + + case WRITE_BLOCK: progress |= _write_block.execute(block_io); break; + default: break;; + } + return progress; +} + +bool Ft_initializer::Initialize::_execute_t2_node(Tree_node_index node_idx, bool &progress) { Node_state &node_state { _t2_node_states[node_idx] }; Type_2_node &node { _t2_blk.nodes[node_idx] }; @@ -42,8 +89,8 @@ bool Ft_initializer_channel::_execute_t2_node(Tree_node_index node_idx, bool &pr if (_num_remaining_leaves) { node = { }; - if (!_req_ptr->_pba_alloc.alloc(node.pba)) { - _mark_req_failed(progress, "allocate pba"); + if (!_attr.in_out_pba_alloc.alloc(node.pba)) { + _helper.mark_failed(progress, "allocate pba"); break; } node_state = DONE; @@ -60,13 +107,13 @@ bool Ft_initializer_channel::_execute_t2_node(Tree_node_index node_idx, bool &pr } break; - case WRITE_BLK: ASSERT_NEVER_REACHED; + case WRITING_BLOCK: ASSERT_NEVER_REACHED; } return true; } -bool Ft_initializer_channel::_execute_t1_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) +bool Ft_initializer::Initialize::_execute_t1_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) { Type_1_node &node { _t1_blks.items[lvl].nodes[node_idx] }; Node_state &node_state { _t1_node_states[lvl][node_idx] }; @@ -92,8 +139,8 @@ bool Ft_initializer_channel::_execute_t1_node(Tree_level_index lvl, Tree_node_in case INIT_NODE: { node = { }; - if (!_req_ptr->_pba_alloc.alloc(node.pba)) { - _mark_req_failed(progress, "allocate pba"); + if (!_attr.in_out_pba_alloc.alloc(node.pba)) { + _helper.mark_failed(progress, "allocate pba"); break; } if (lvl == 2) @@ -101,15 +148,13 @@ bool Ft_initializer_channel::_execute_t1_node(Tree_level_index lvl, Tree_node_in 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; + _write_block.generate(_helper, WRITE_BLOCK, EXECUTE_NODES, progress, node.pba, _blk); + node_state = WRITING_BLOCK; if (VERBOSE_FT_INIT) log("[ft_init] node: ", lvl, " ", node_idx, " assign pba: ", node.pba); break; } - case WRITE_BLK: + case WRITING_BLOCK: node_state = DONE; progress = true; @@ -119,115 +164,3 @@ bool Ft_initializer_channel::_execute_t1_node(Tree_level_index lvl, Tree_node_in } return true; } - - -void Ft_initializer_channel::_generated_req_completed(State_uint state_uint) -{ - 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; -} - - -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 - 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_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: - - _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 EXECUTE_NODES: - - 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; - - default: return; - } -} - - -void Ft_initializer_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -Ft_initializer::Ft_initializer() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } -} - - -void Ft_initializer::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} 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 7da5c7cb3d..732c62aeb8 100644 --- a/repos/gems/src/lib/tresor/include/tresor/block_io.h +++ b/repos/gems/src/lib/tresor/include/tresor/block_io.h @@ -18,147 +18,132 @@ #include #include -namespace Tresor { +namespace Tresor { class Block_io; } - class Block_io; - class Block_io_request; - class Block_io_channel; -} - -class Tresor::Block_io_request : public Module_request -{ - friend class Block_io_channel; - - public: - - enum Type { READ, WRITE, SYNC, READ_CLIENT_DATA, WRITE_CLIENT_DATA }; - - private: - - 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; - - NONCOPYABLE(Block_io_request); - - public: - - Block_io_request(Module_id, Module_channel_id, Type, Request_offset, Request_tag, Key_id, - Physical_block_address, Virtual_block_address, Block &, Hash &, bool &); - - static char const *type_to_string(Type); - - void print(Output &out) const override { Genode::print(out, type_to_string(_type), " pba ", _pba); } -}; - -class Tresor::Block_io_channel : public Module_channel +class Tresor::Block_io : Noncopyable { private: - using Request = Block_io_request; + Vfs::Vfs_handle &_file; + addr_t _user { }; - enum State { - REQ_SUBMITTED, REQ_COMPLETE, CIPHERTEXT_BLK_OBTAINED, PLAINTEXT_BLK_SUPPLIED, REQ_GENERATED, - READ_OK, WRITE_OK, SYNC_OK, FILE_ERR }; + public: - 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 }; + class Read; + class Write; + class Sync; - NONCOPYABLE(Block_io_channel); + Block_io(Vfs::Vfs_handle &file) : _file(file) { } - void _generated_req_completed(State_uint) override; - - template - void _generate_req(State_uint state, bool &progress, ARGS &&... args) + template + bool execute(REQ &req) { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); + if (!_user) + _user = (addr_t)&req; + + if (_user != (addr_t)&req) + return false; + + bool progress = req.execute(_file); + if (req.complete()) + _user = 0; + + return progress; } - 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 &); + static constexpr char const *name() { return "block_io"; } }; -class Tresor::Block_io : public Module +class Tresor::Block_io::Read : Noncopyable { + public: + + using Module = Block_io; + + struct Attr + { + Physical_block_address const in_pba; + Block &out_block; + }; + private: - using Request = Block_io_request; - using Channel = Block_io_channel; + enum State { INIT, COMPLETE, READ, READ_OK, FILE_ERR }; - Constructible _channels[1] { }; - - NONCOPYABLE(Block_io); + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; public: - struct Read : Request + Read(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "read pba ", _attr.in_pba); } + + bool execute(Vfs::Vfs_handle &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Block_io::Write : Noncopyable +{ + public: + + using Module = Block_io; + + struct Attr { - 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) { } + Physical_block_address const in_pba; + Block const &in_block; }; - 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) { } - }; + private: - 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) { } - }; + enum State { INIT, COMPLETE, WRITE, WRITE_OK, FILE_ERR }; - 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, Hash &h, bool &s) - : Request(m, c, Request::WRITE_CLIENT_DATA, o, t, k, p, v, *(Block*)0, h, s) { } - }; + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; - 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, Hash &h, bool &s) - : Request(m, c, Request::READ_CLIENT_DATA, o, t, k, p, v, *(Block*)0, h, s) { } - }; + public: - Block_io(Vfs::Env &, Xml_node const &); + Write(Attr const &attr) : _helper(*this), _attr(attr) { } - void execute(bool &) override; + void print(Output &out) const { Genode::print(out, "write pba ", _attr.in_pba); } + + bool execute(Vfs::Vfs_handle &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Block_io::Sync : Noncopyable +{ + public: + + using Module = Block_io; + + struct Attr { }; + + private: + + enum State { INIT, COMPLETE, SYNC, SYNC_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; + + public: + + Sync(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "sync"); } + + bool execute(Vfs::Vfs_handle &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; #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 deleted file mode 100644 index f7f7a53d09..0000000000 --- a/repos/gems/src/lib/tresor/include/tresor/client_data.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * \brief Module that provides access to the client request data - * \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__CLIENT_DATA_H_ -#define _TRESOR__CLIENT_DATA_H_ - -/* tresor includes */ -#include - -namespace Tresor { class Client_data_request; } - -namespace Vfs_tresor { class Client_data; } - -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 { OBTAIN_PLAINTEXT_BLK, SUPPLY_PLAINTEXT_BLK }; - - private: - - 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; - - NONCOPYABLE(Client_data_request); - - public: - - 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_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 } - { } - - static char const *type_to_string(Type type) - { - switch (type) { - case OBTAIN_PLAINTEXT_BLK: return "obtain_plaintext_blk"; - case SUPPLY_PLAINTEXT_BLK: return "supply_plaintext_blk"; - } - ASSERT_NEVER_REACHED; - } - - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } -}; - -#endif /* _TRESOR__CLIENT_DATA_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/client_data_interface.h b/repos/gems/src/lib/tresor/include/tresor/client_data_interface.h new file mode 100644 index 0000000000..9456ebcda7 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/client_data_interface.h @@ -0,0 +1,47 @@ +/* + * \brief Interface for providing access to the client request data + * \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__CLIENT_DATA_INTERFACE_H_ +#define _TRESOR__CLIENT_DATA_INTERFACE_H_ + +/* tresor includes */ +#include + +namespace Tresor { class Client_data_interface; } + +struct Tresor::Client_data_interface : Interface +{ + struct Obtain_data_attr + { + Request_offset const in_req_off; + Request_tag const in_req_tag; + Physical_block_address const in_pba; + Virtual_block_address const in_vba; + Block &out_blk; + }; + + virtual void obtain_data(Obtain_data_attr const &) = 0; + + struct Supply_data_attr + { + Request_offset const in_req_off; + Request_tag const in_req_tag; + Physical_block_address const in_pba; + Virtual_block_address const in_vba; + Block const &in_blk; + }; + + virtual void supply_data(Supply_data_attr const &) = 0; +}; + +#endif /* _TRESOR__CLIENT_DATA_INTERFACE_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/crypto.h b/repos/gems/src/lib/tresor/include/tresor/crypto.h index 0098ab9083..3eaaa2d519 100644 --- a/repos/gems/src/lib/tresor/include/tresor/crypto.h +++ b/repos/gems/src/lib/tresor/include/tresor/crypto.h @@ -21,155 +21,187 @@ namespace Tresor { class Crypto; - class Crypto_request; - class Crypto_channel; + class Crypto_key_files_interface; } -class Tresor::Crypto_request : public Module_request +struct Tresor::Crypto_key_files_interface : Interface { - friend class Crypto_channel; + virtual void add_crypto_key(Key_id) = 0; - public: + virtual void remove_crypto_key(Key_id) = 0; - enum Type { ADD_KEY, REMOVE_KEY, DECRYPT, ENCRYPT, DECRYPT_CLIENT_DATA, ENCRYPT_CLIENT_DATA }; + virtual Vfs::Vfs_handle &encrypt_file(Key_id) = 0; - private: - - 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; - - NONCOPYABLE(Crypto_request); - - public: - - 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 &); - - static const char *type_to_string(Type); - - void print(Output &) const override; + virtual Vfs::Vfs_handle &decrypt_file(Key_id) = 0; }; -class Tresor::Crypto_channel : public Module_channel +class Tresor::Crypto : Noncopyable { - private: + public: - using Request = Crypto_request; - - enum State { - REQ_SUBMITTED, REQ_COMPLETE, PLAINTEXT_BLK_OBTAINED, PLAINTEXT_BLK_SUPPLIED, REQ_GENERATED, - READ_OK, WRITE_OK, FILE_ERR }; - - struct Key_directory + struct Attr { - 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 } { } + Crypto_key_files_interface &key_files; + Vfs::Vfs_handle &add_key_file; + Vfs::Vfs_handle &remove_key_file; }; - 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 { }; + private: - NONCOPYABLE(Crypto_channel); + Attr const _attr; + addr_t _user { }; - void _generated_req_completed(State_uint) override; + public: - void _request_submitted(Module_request &) override; + class Encrypt; + class Decrypt; + class Add_key; + class Remove_key; - bool _request_complete() override { return _state == REQ_COMPLETE; } + Crypto(Attr const &attr) : _attr(attr) { } - template - void _generate_req(State_uint state, bool &progress, ARGS &&... args) + template + bool execute(REQ &req) { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); + if (!_user) + _user = (addr_t)&req; + + if (_user != (addr_t)&req) + return false; + + bool progress = req.execute(_attr); + if (req.complete()) + _user = 0; + + return progress; } - 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_channel(Module_channel_id, Vfs::Env &, Xml_node const &); - - void execute(bool &); + static constexpr char const *name() { return "crypto"; } }; -class Tresor::Crypto : public Module +class Tresor::Crypto::Encrypt : Noncopyable { + public: + + using Module = Crypto; + + struct Attr + { + Key_id const in_key_id; + Physical_block_address const in_pba; + Block &in_out_blk; + }; + private: - using Request = Crypto_request; - using Channel = Crypto_channel; + enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR }; - Constructible _channels[1] { }; - - NONCOPYABLE(Crypto); + Request_helper _helper; + Attr const _attr; + off_t _offset { }; + Constructible > _file { }; public: - struct Add_key : Request + Encrypt(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "encrypt pba ", _attr.in_pba); } + + bool execute(Crypto::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Crypto::Decrypt : Noncopyable +{ + public: + + using Module = Crypto; + + struct Attr { - 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) { } + Key_id const in_key_id; + Physical_block_address const in_pba; + Block &in_out_blk; }; - 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) { } - }; + private: - 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) { } - }; + enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR }; - 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) { } - }; + Request_helper _helper; + Attr const _attr; + off_t _offset { }; + Constructible > _file { }; - Crypto(Vfs::Env &, Xml_node const &); + public: - void execute(bool &) override; + Decrypt(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "decrypt pba ", _attr.in_pba); } + + bool execute(Crypto::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Crypto::Add_key : Noncopyable +{ + public: + + using Module = Crypto; + + struct Attr { Key const &in_key; }; + + private: + + enum State { INIT, COMPLETE, WRITE, WRITE_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + char _write_buf[sizeof(Key_id) + sizeof(Key_value)] { }; + Constructible > _file { }; + + public: + + Add_key(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "add key id ", _attr.in_key.id); } + + bool execute(Crypto::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Crypto::Remove_key : Noncopyable +{ + public: + + using Module = Crypto; + + struct Attr { Key_id const in_key_id; }; + + private: + + enum State { INIT, COMPLETE, WRITE, WRITE_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; + + public: + + Remove_key(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "remove key id ", _attr.in_key_id); } + + bool execute(Crypto::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; #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 index 188865e87b..c8a3a4f305 100644 --- a/repos/gems/src/lib/tresor/include/tresor/file.h +++ b/repos/gems/src/lib/tresor/include/tresor/file.h @@ -33,8 +33,17 @@ namespace Tresor { template class File; template class Read_write_file; template class Write_only_file; + + inline Vfs::Vfs_handle &open_file(Vfs::Env &env, Tresor::Path const &path, Vfs::Directory_service::Open_mode mode) + { + using Open_result = Vfs::Directory_service::Open_result; + Vfs::Vfs_handle *handle { nullptr }; + ASSERT(env.root_dir().open(path.string(), mode, &handle, env.alloc()) == Open_result::OPEN_OK); + return *handle; + } } + template class Tresor::File { @@ -43,34 +52,34 @@ class Tresor::File 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; + Vfs::Env *_env { }; + Tresor::Path const *_path { }; 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; - } + /* + * Noncopyable + */ + File(File const &) = delete; + File &operator = (File const &) = delete; public: - File(HOST_STATE &host_state, Vfs::Vfs_handle &handle) : _host_state { host_state }, _handle { handle } { } + 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(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path const &path, Vfs::Directory_service::Open_mode mode) + : _env(&env), _path(&path), _host_state(host_state), _handle(open_file(*_env, *_path, mode)) { } ~File() { ASSERT(_state == IDLE); - _env.root_dir().close(&_handle); + if (_env) + _env->root_dir().close(&_handle); } void read(HOST_STATE succeeded, HOST_STATE failed, Vfs::file_offset off, Byte_range_ptr dst, bool &progress) @@ -116,7 +125,7 @@ class Tresor::File default: - error("read failed"); + error("file: read failed"); _host_state = failed; _state = IDLE; progress = true; @@ -167,7 +176,7 @@ class Tresor::File default: - error("write failed"); + error("file: write failed"); _host_state = failed; _state = IDLE; progress = true; @@ -204,7 +213,7 @@ class Tresor::File default: - error("sync failed"); + error("file: sync failed"); _host_state = failed; _state = IDLE; progress = true; @@ -218,15 +227,15 @@ class Tresor::File 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 } { } + Read_write_file(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path const &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 } { } + Write_only_file(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path const &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 c2618e86be..3f9a434c36 100644 --- a/repos/gems/src/lib/tresor/include/tresor/free_tree.h +++ b/repos/gems/src/lib/tresor/include/tresor/free_tree.h @@ -16,80 +16,68 @@ /* tresor includes */ #include +#include +#include -namespace Tresor { +namespace Tresor { class Free_tree; } - class Free_tree; - class Free_tree_request; - class Free_tree_channel; -} - -class Tresor::Free_tree_request : public Module_request +class Tresor::Free_tree : Noncopyable { - friend class Free_tree_channel; - public: - enum Type { ALLOC_FOR_NON_RKG, ALLOC_FOR_RKG_CURR_GEN_BLKS, ALLOC_FOR_RKG_OLD_GEN_BLKS, EXTENSION_STEP }; + class Allocate_pbas; + class Extend_tree; - private: + template + bool execute(REQUEST &req, Block_io &block_io, Meta_tree &meta_tree) { return req.execute(block_io, meta_tree); } - 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; - - NONCOPYABLE(Free_tree_request); - - public: - - 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 &); - - static char const *type_to_string(Type); - - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } + static constexpr char const *name() { return "free_tree"; } }; - -class Tresor::Free_tree_channel : public Module_channel +class Tresor::Free_tree::Allocate_pbas : Noncopyable { + public: + + using Module = Free_tree; + + enum Application { NON_REKEYING, REKEYING_IN_CURRENT_GENERATION, REKEYING_IN_OLDER_GENERATION }; + + struct Attr + { + Tree_root &in_out_ft; + Tree_root &in_out_mt; + Snapshots const &in_snapshots; + Generation const in_last_secured_gen; + Generation const in_curr_gen; + Generation const in_free_gen; + Number_of_blocks const in_num_required_pbas; + Tree_walk_pbas &in_out_new_blocks; + Type_1_node_walk const &in_old_blocks; + Tree_level_index const in_max_lvl; + Virtual_block_address const in_vba; + Tree_degree const in_vbd_degree; + Virtual_block_address const in_vbd_max_vba; + bool const in_rekeying; + Key_id const in_prev_key_id; + Key_id const in_curr_key_id; + Virtual_block_address const in_rekeying_vba; + Application const in_application; + }; + private: - using Request = Free_tree_request; - enum State { - REQ_SUBMITTED, REQ_GENERATED, SEEK_DOWN, SEEK_LEFT_OR_UP, WRITE_BLK, READ_BLK_SUCCEEDED, - ALLOC_PBA_SUCCEEDED, WRITE_BLK_SUCCEEDED, REQ_COMPLETE }; + INIT, COMPLETE, SEEK_DOWN, SEEK_LEFT_OR_UP, READ_BLK, READ_BLK_SUCCEEDED, + ALLOC_PBA, ALLOC_PBA_SUCCEEDED, WRITE_BLK, WRITE_BLK_SUCCEEDED }; - Request *_req_ptr { nullptr }; - State _state { REQ_COMPLETE }; + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; 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] { }; @@ -98,36 +86,71 @@ class Tresor::Free_tree_channel : public Module_channel 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) - { - _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 &); + Generatable_request _read_block { }; + Generatable_request _write_block { }; + Generatable_request _allocate_pba { }; void _alloc_pba_of(Type_2_node &); - void _traverse_curr_node(bool &); + bool _can_alloc_pba_of(Type_2_node &); - void _mark_req_successful(bool &); + void _traverse_curr_node(bool &); void _start_tree_traversal(bool &); - void _advance_to_next_node(); + public: + + Allocate_pbas(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Allocate_pbas() { } + + void print(Output &out) const { Genode::print(out, "allocate pbas"); } + + bool execute(Block_io &, Meta_tree &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Free_tree::Extend_tree : Noncopyable +{ + public: + + using Module = Free_tree; + + struct Attr + { + Generation const in_curr_gen; + Tree_root &in_out_ft; + Tree_root &in_out_mt; + Physical_block_address &in_out_first_pba; + Number_of_blocks &in_out_num_pbas; + }; + + private: + + enum State { + INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, WRITE_BLK, + WRITE_BLK_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Number_of_leaves _num_leaves { 0 }; + Virtual_block_address _vba { }; + Tree_walk_pbas _old_pbas { }; + Tree_walk_generations _old_generations { }; + Tree_walk_pbas _new_pbas { }; + Tree_level_index _lvl { 0 }; + Block _blk { }; + Type_1_node_block _t1_blks[TREE_MAX_NR_OF_LEVELS] { }; + Type_2_node_block _t2_blk { }; + Tree_level_index _alloc_lvl { 0 }; + Physical_block_address _alloc_pba { 0 }; + Generatable_request _read_block { }; + Generatable_request _write_block { }; + Generatable_request _allocate_pba { }; void _add_new_branch_at(Tree_level_index, Tree_node_index); @@ -135,41 +158,18 @@ class Tresor::Free_tree_channel : public Module_channel 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 } { } + Extend_tree(Attr const &attr) : _helper(*this), _attr(attr) { } - void execute(bool &); -}; + ~Extend_tree() { } -class Tresor::Free_tree : public Module -{ - private: + void print(Output &out) const { Genode::print(out, "extend tree"); } - using Channel = Free_tree_channel; - using Request = Free_tree_request; + bool execute(Block_io &, Meta_tree &); - Constructible _channels[1] { }; - - NONCOPYABLE(Free_tree); - - void execute(bool &) override; - - public: - - 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) { } - }; - - Free_tree(); + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; #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 a8168311e7..2db3e92627 100644 --- a/repos/gems/src/lib/tresor/include/tresor/ft_check.h +++ b/repos/gems/src/lib/tresor/include/tresor/ft_check.h @@ -16,95 +16,54 @@ /* tresor includes */ #include +#include -namespace Tresor { +namespace Tresor { class Ft_check; } - class Ft_check; - class Ft_check_request; - class Ft_check_channel; -} - - -class Tresor::Ft_check_request : public Module_request +struct Tresor::Ft_check : Noncopyable { - friend class Ft_check_channel; + class Check : Noncopyable + { + public: - private: + using Module = Ft_check; - Tree_root const &_ft; - bool &_success; + struct Attr { Tree_root const &in_ft; }; - NONCOPYABLE(Ft_check_request); + private: - public: + enum State { INIT, IN_PROGRESS, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED }; - Ft_check_request(Module_id, Module_channel_id, Tree_root const &, bool &); + using Helper = Request_helper; - void print(Output &out) const override { Genode::print(out, "check ", _ft); } -}; + Helper _helper; + Attr const _attr; + 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 }; + Block _blk { }; + Generatable_request _read_block { }; + bool _execute_node(Block_io &, Tree_level_index, Tree_node_index, bool &); -class Tresor::Ft_check_channel : public Module_channel -{ - private: + public: - using Request = Ft_check_request; + Check(Attr const &attr) : _helper(*this), _attr(attr) { } - enum State : State_uint { REQ_SUBMITTED, REQ_IN_PROGRESS, REQ_COMPLETE, REQ_GENERATED, READ_BLK_SUCCEEDED }; + void print(Output &out) const { Genode::print(out, "check ", _attr.in_ft); } - 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 }; + bool execute(Block_io &); - NONCOPYABLE(Ft_check_channel); + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; - void _generated_req_completed(State_uint) override; + Ft_check() { } - void _request_submitted(Module_request &) override; + bool execute(Check &req, Block_io &block_io) { return req.execute(block_io); } - 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) - { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); - } - - public: - - Ft_check_channel(Module_channel_id id) : Module_channel { FT_CHECK, id } { } - - void execute(bool &); -}; - - -class Tresor::Ft_check : public Module -{ - private: - - using Channel = Ft_check_channel; - - Constructible _channels[1] { }; - - NONCOPYABLE(Ft_check); - - public: - - Ft_check(); - - void execute(bool &) override; + static constexpr char const *name() { return "ft_check"; } }; #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 6b07ff3a2e..e79ccd51e8 100644 --- a/repos/gems/src/lib/tresor/include/tresor/ft_initializer.h +++ b/repos/gems/src/lib/tresor/include/tresor/ft_initializer.h @@ -17,97 +17,68 @@ /* tresor includes */ #include +#include -namespace Tresor { +namespace Tresor { class Ft_initializer; } - class Ft_initializer; - class Ft_initializer_request; - class Ft_initializer_channel; -} - - -class Tresor::Ft_initializer_request : public Module_request +class Tresor::Ft_initializer : Noncopyable { - friend class Ft_initializer_channel; - - private: - - Tree_root &_ft; - Pba_allocator &_pba_alloc; - bool &_success; - - NONCOPYABLE(Ft_initializer_request); - public: - Ft_initializer_request(Module_id, Module_channel_id, Tree_root &, Pba_allocator &, bool &); + class Initialize : Noncopyable + { + public: - void print(Output &out) const override { Genode::print(out, "init"); } -}; + using Module = Ft_initializer; + struct Attr + { + Tree_configuration const in_tree_cfg; + Type_1_node &out_tree_root; + Pba_allocator &in_out_pba_alloc; + }; -class Tresor::Ft_initializer_channel : public Module_channel -{ - private: + private: - using Request = Ft_initializer_request; + enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITING_BLOCK }; - enum State { REQ_GENERATED, REQ_SUBMITTED, EXECUTE_NODES, REQ_COMPLETE }; + enum State { INIT, COMPLETE, EXECUTE_NODES, WRITE_BLOCK }; - enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITE_BLK }; + using Helper = Request_helper; - 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 { }; + Helper _helper; + Attr const _attr; + 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 }; + Block _blk { }; + Generatable_request _write_block { }; - NONCOPYABLE(Ft_initializer_channel); + void _reset_level(Tree_level_index, Node_state); - void _reset_level(Tree_level_index, Node_state); + bool _execute_t2_node(Tree_node_index, bool &); - void _generated_req_completed(State_uint) override; + bool _execute_t1_node(Tree_level_index, Tree_node_index, bool &); - bool _request_complete() override { return _state == REQ_COMPLETE; } + public: - void _request_submitted(Module_request &) override; + Initialize(Attr const &attr) : _helper(*this), _attr(attr) { } - bool _execute_t2_node(Tree_node_index, bool &); + ~Initialize() { } - bool _execute_t1_node(Tree_level_index, Tree_node_index, bool &); + void print(Output &out) const { Genode::print(out, "initialize"); } - void _mark_req_failed(bool &, char const *); + bool execute(Block_io &); - void _mark_req_successful(bool &); + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; - public: - - Ft_initializer_channel(Module_channel_id id) : Module_channel { FT_INITIALIZER, id } { } - - void execute(bool &); -}; - - -class Tresor::Ft_initializer : public Module -{ - private: - - using Channel = Ft_initializer_channel; - - Constructible _channels[1] { }; - - NONCOPYABLE(Ft_initializer); - - public: - - Ft_initializer(); - - void execute(bool &) override; + bool execute(Initialize &req, Block_io &block_io) { return req.execute(block_io); } + static constexpr char const *name() { return "ft_initializer"; } }; #endif /* _TRESOR__FT_INITIALIZER_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 d529b56ce6..18619af7a5 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 VBD COW allocations on the meta tree + * \brief Module for doing PBA allocations for the Free Tree via the Meta Tree * \author Martin Stein * \date 2023-02-13 */ @@ -16,74 +16,49 @@ /* tresor includes */ #include +#include -namespace Tresor { +namespace Tresor { class Meta_tree; } - class Meta_tree; - class Meta_tree_request; - class Meta_tree_channel; -} - -class Tresor::Meta_tree_request : public Module_request +class Tresor::Meta_tree : Noncopyable { - friend class Meta_tree_channel; - public: - enum Type { ALLOC_PBA }; + class Allocate_pba; - private: + bool execute(Allocate_pba &, Block_io &); - Type const _type; - Tree_root &_mt; - Generation const _curr_gen; - Physical_block_address &_pba; - bool &_success; - - NONCOPYABLE(Meta_tree_request); - - public: - - Meta_tree_request(Module_id, Module_channel_id, Type, Tree_root &, Generation, Physical_block_address &, bool &); - - static char const *type_to_string(Type); - - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } + static constexpr char const *name() { return "meta_tree"; } }; -class Tresor::Meta_tree_channel : public Module_channel +class Tresor::Meta_tree::Allocate_pba : Noncopyable { + public: + + using Module = Meta_tree; + + struct Attr + { + Tree_root &in_out_mt; + Generation const in_curr_gen; + Physical_block_address &in_out_pba; + }; + private: - using Request = Meta_tree_request; + enum State { INIT, COMPLETE, READ_BLK, SEEK_DOWN, SEEK_LEFT_OR_UP, WRITE_BLK, WRITE_BLK_SUCCEEDED }; - enum State { REQ_SUBMITTED, REQ_GENERATED, SEEK_DOWN, SEEK_LEFT_OR_UP, WRITE_BLK, COMPLETE }; + using Helper = Request_helper; - State _state { COMPLETE }; - Request *_req_ptr { nullptr }; + Helper _helper; + Attr const _attr; 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) - { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); - } - - void _request_submitted(Module_request &) override; - - bool _request_complete() override { return _state == COMPLETE; } - - void _mark_req_failed(bool &, char const *); + Generatable_request _read_block { }; + Generatable_request _write_block { }; bool _can_alloc_pba_of(Type_2_node &); @@ -91,38 +66,20 @@ class Tresor::Meta_tree_channel : public Module_channel void _traverse_curr_node(bool &); - void _mark_req_successful(bool &); - void _start_tree_traversal(bool &); public: - Meta_tree_channel(Module_channel_id id) : Module_channel { META_TREE, id } { } + Allocate_pba(Attr const &attr) : _helper(*this), _attr(attr) { } - void execute(bool &); -}; + ~Allocate_pba() { } -class Tresor::Meta_tree : public Module -{ - private: + void print(Output &out) const { Genode::print(out, "allocate pba"); } - using Channel = Meta_tree_channel; + bool execute(Block_io &); - Constructible _channels[1] { }; - - NONCOPYABLE(Meta_tree); - - void execute(bool &) 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(); + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; #endif /* _TRESOR__META_TREE_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/module.h b/repos/gems/src/lib/tresor/include/tresor/module.h deleted file mode 100644 index 9c960c32fb..0000000000 --- a/repos/gems/src/lib/tresor/include/tresor/module.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * \brief Framework for component internal modularization - * \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__MODULE_H_ -#define _TRESOR__MODULE_H_ - -/* base includes */ -#include - -/* tresor includes */ -#include -#include -#include - -namespace Tresor { - - using namespace Genode; - - using Module_id = uint64_t; - using Module_channel_id = uint64_t; - - 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, 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; -} - - -class Tresor::Module_request : public Interface -{ - private: - - 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_id, Module_channel_id, Module_id); - - void dst_chan_id(Module_channel_id id) { _dst_chan_id = id; } - - 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() { } -}; - - -class Tresor::Module_channel : private Avl_node -{ - friend class Module; - friend class Avl_node; - friend class Avl_tree; - - 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() { } -}; - - -class Tresor::Module : public Interface -{ - private: - - Avl_tree _channels { }; - - NONCOPYABLE(Module); - - public: - - template - void with_channel(Module_channel_id id, FUNC && func) - { - ASSERT(_channels.first()); - _channels.first()->with_channel(id, func); - } - - 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) - { - 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; - } - }); - } - - template - void for_each_completed_request(FUNC && handle_request) - { - 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 &) { } -}; - - -class Tresor::Module_composition -{ - private: - - Module *_module_ptrs[MAX_MODULE_ID + 1] { }; - - public: - - void add_module(Module_id module_id, Module &mod); - - void remove_module(Module_id module_id); - - 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 deleted file mode 100644 index 1ff52ef79c..0000000000 --- a/repos/gems/src/lib/tresor/include/tresor/noncopyable.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * \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 deleted file mode 100644 index 93a1dd9969..0000000000 --- a/repos/gems/src/lib/tresor/include/tresor/request_pool.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * \brief Module for scheduling requests for processing - * \author Martin Stein - * \date 2023-03-17 - */ - -/* - * 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__REQUEST_POOL_H_ -#define _TRESOR__REQUEST_POOL_H_ - -/* tresor includes */ -#include -#include - -namespace Tresor { - - class Request; - class Request_pool; - class Request_pool_channel; - class Request_pool_channel_queue; -} - -class Tresor::Request : public Module_request -{ - NONCOPYABLE(Request); - - friend class Request_pool_channel; - - public: - - enum Operation { - READ, WRITE, SYNC, CREATE_SNAPSHOT, DISCARD_SNAPSHOT, REKEY, EXTEND_VBD, - EXTEND_FT, RESUME_REKEYING, DEINITIALIZE, INITIALIZE, }; - - private: - - 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; - - public: - - 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 &); -}; - - -class Tresor::Request_pool_channel_queue -{ - 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 76dad0a18a..1cace44139 100644 --- a/repos/gems/src/lib/tresor/include/tresor/sb_check.h +++ b/repos/gems/src/lib/tresor/include/tresor/sb_check.h @@ -16,95 +16,60 @@ /* tresor includes */ #include +#include +#include +#include -namespace Tresor { +namespace Tresor { class Sb_check; } - class Sb_check; - class Sb_check_request; - class Sb_check_channel; -} - - -class Tresor::Sb_check_request : public Module_request +struct Tresor::Sb_check : Noncopyable { - friend class Sb_check_channel; + class Check : Noncopyable + { + public: - private: + using Module = Sb_check; - bool &_success; + private: - NONCOPYABLE(Sb_check_request); + enum State { + INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, CHECK_VBD, CHECK_VBD_SUCCEEDED, CHECK_FT, CHECK_FT_SUCCEEDED, + CHECK_MT, CHECK_MT_SUCCEEDED}; - public: + using Helper = Request_helper; - Sb_check_request(Module_id, Module_channel_id, bool &); + Helper _helper; + 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 { }; + Generatable_request _check_vbd { }; + Generatable_request _check_ft { }; + Generatable_request _read_block { }; - void print(Output &out) const override { Genode::print(out, "check"); } -}; + public: + Check() : _helper(*this) { } -class Tresor::Sb_check_channel : public Module_channel -{ - private: + ~Check() { } - using Request = Sb_check_request; + void print(Output &out) const { Genode::print(out, "check"); } - enum State { REQ_SUBMITTED, REQ_COMPLETE, READ_BLK_SUCCESSFUL, REQ_GENERATED, CHECK_VBD_SUCCESSFUL, CHECK_FT_SUCCESSFUL, CHECK_MT_SUCCESSFUL}; + bool execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io); - 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 }; + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; - NONCOPYABLE(Sb_check_channel); + Sb_check() { } - void _generated_req_completed(State_uint) override; + bool execute(Check &check, Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io) { return check.execute(vbd_check, ft_check, block_io); }; - 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 &); -}; - - -class Tresor::Sb_check : public Module -{ - private: - - using Channel = Sb_check_channel; - - Constructible _channels[1] { }; - - NONCOPYABLE(Sb_check); - - public: - - Sb_check(); - - void execute(bool &) override; + static constexpr char const *name() { return "sb_check"; } }; #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 c387ab0d0c..823875d6b0 100644 --- a/repos/gems/src/lib/tresor/include/tresor/sb_initializer.h +++ b/repos/gems/src/lib/tresor/include/tresor/sb_initializer.h @@ -17,107 +17,78 @@ /* tresor includes */ #include +#include +#include +#include +#include -namespace Tresor { +namespace Tresor { class Sb_initializer; } - class Sb_initializer; - class Sb_initializer_request; - class Sb_initializer_channel; -} - - -class Tresor::Sb_initializer_request : public Module_request +class Tresor::Sb_initializer : Noncopyable { - friend class Sb_initializer_channel; - - private: - - 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(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 &); - - void print(Output &out) const override { Genode::print(out, "init"); } -}; - - -class Tresor::Sb_initializer_channel : public Module_channel -{ - private: - - using Request = Sb_initializer_request; - - enum State { - 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 { 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 }; - - 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) + class Initialize : Noncopyable { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); + public: + + using Module = Sb_initializer; + + struct Attr + { + Tree_configuration const in_vbd_cfg; + Tree_configuration const in_ft_cfg; + Tree_configuration const in_mt_cfg; + Pba_allocator &in_out_pba_alloc; + }; + + private: + + enum State { + INIT, COMPLETE, START_NEXT_SB, SB_COMPLETE, INIT_FT, INIT_FT_SUCCEEDED, INIT_MT_SUCCEEDED, + WRITE_HASH_TO_TA, GENERATE_KEY, GENERATE_KEY_SUCCEEDED, ENCRYPT_KEY, ENCRYPT_KEY_SUCCEEDED, + SECURE_SB_SUCCEEDED, INIT_VBD, INIT_VBD_SUCCEEDED, WRITE_BLK, WRITE_BLK_SUCCEEDED, + SYNC_BLOCK_IO, WRITE_SB_HASH }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Superblock_index _sb_idx { 0 }; + Superblock _sb { }; + Block _blk { }; + Hash _hash { }; + Type_1_node _vbd_root { }; + Type_1_node _ft_root { }; + Type_1_node _mt_root { }; + Generatable_request _write_block { }; + Generatable_request _sync_block_io { }; + Generatable_request _generate_key { }; + Generatable_request _write_sb_hash { }; + Generatable_request _encrypt_key { }; + Generatable_request _init_ft { }; + Generatable_request _init_vbd { }; + + public: + + Initialize(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Initialize() { } + + void print(Output &out) const { Genode::print(out, "initialize"); } + + bool execute(Block_io &, Trust_anchor &, Vbd_initializer &, Ft_initializer &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + bool execute(Initialize &req, Block_io &block_io, Trust_anchor &trust_anchor, Vbd_initializer &vbd_initializer, Ft_initializer &ft_initializer) + { + return req.execute(block_io, trust_anchor, vbd_initializer, ft_initializer); } - void _mark_req_successful(bool &); - - public: - - Sb_initializer_channel(Module_channel_id id) : Module_channel { SB_INITIALIZER, id } { } - - void execute(bool &); -}; - - -class Tresor::Sb_initializer : public Module -{ - private: - - using Channel = Sb_initializer_channel; - - Constructible _channels[1] { }; - - NONCOPYABLE(Sb_initializer); - - public: - - Sb_initializer(); - - void execute(bool &) override; + static constexpr char const *name() { return "sb_initializer"; } }; #endif /* _TRESOR__SB_INITIALIZER_H_ */ 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 09e2127525..31cf7db032 100644 --- a/repos/gems/src/lib/tresor/include/tresor/superblock_control.h +++ b/repos/gems/src/lib/tresor/include/tresor/superblock_control.h @@ -20,153 +20,558 @@ #include #include -namespace Tresor { +namespace Tresor { class Superblock_control; } - class Superblock_control; - class Superblock_control_request; - class Superblock_control_channel; -} - -class Tresor::Superblock_control_request : Module_request, Noncopyable -{ - friend class Superblock_control_channel; - - public: - - enum Type { - READ_VBA, WRITE_VBA, SYNC, INITIALIZE, DEINITIALIZE, VBD_EXTENSION_STEP, - FT_EXTENSION_STEP, CREATE_SNAPSHOT, DISCARD_SNAPSHOT, INITIALIZE_REKEYING, - REKEY_VBA }; - - private: - - 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(Module_id, Module_channel_id, Type, Request_offset, - Request_tag, Number_of_blocks, Virtual_block_address, - bool &, bool &, Superblock::State &, Generation &); - - static char const *type_to_string(Type); - - void print(Output &) const override; -}; - - -class Tresor::Superblock_control_channel : public Module_channel +class Tresor::Superblock_control : Noncopyable { private: - using Request = Superblock_control_request; - - 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 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 }; - - 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) + class Secure_superblock : Noncopyable { - generate_req(complete_state, progress, args..., _gen_req_success); - if (_state == SECURE_SB) - _secure_sb_state = SECURE_SB_REQ_GENERATED; - else - _state = REQ_GENERATED; - } + public: - void _start_secure_sb(bool &); + using Module = Superblock_control; - void _secure_sb(bool &); + struct Attr { }; - void _tree_ext_step(Superblock::State, bool, String<4>, bool &); + struct Execute_attr + { + Superblock &sb; + Superblock_index &sb_idx; + Generation &curr_gen; + Block_io &block_io; + Trust_anchor &trust_anchor; + }; - void _rekey_vba(bool &); + private: - void _init_rekeying(bool &); + enum State { + INIT, COMPLETE, WRITE_BLOCK, WRITE_BLOCK_SUCCEEDED, SYNC_BLOCK_IO, SYNC_BLOCK_IO_SUCCEEDED, + ENCRYPT_KEY, ENCRYPT_CURR_KEY_SUCCEEDED, ENCRYPT_PREV_KEY_SUCCEEDED, WRITE_SB_HASH, + WRITE_SB_HASH_SUCCEEDED }; - void _discard_snap(bool &); + using Helper = Request_helper; - void _create_snap(bool &); + Helper _helper; + Attr const _attr; + Superblock _sb_ciphertext { }; + Block _blk { }; + Hash _hash { }; + Generation _gen { }; + Generatable_request _write_block { }; + Generatable_request _sync_block_io { }; + Generatable_request _encrypt_key { }; + Generatable_request _write_sb_hash { }; - void _sync(bool &); + public: - void _initialize(bool &); + Secure_superblock(Attr const &attr) : _helper(*this), _attr(attr) { } - void _deinitialize(bool &); + ~Secure_superblock() { } - public: + void print(Output &out) const { Genode::print(out, "secure sb"); } - void execute(bool &); + bool execute(Execute_attr const &); - Superblock_control_channel(Module_channel_id, Superblock &, Superblock_index &, Generation &); -}; - -class Tresor::Superblock_control : public Module -{ - private: - - using Channel = Superblock_control_channel; - - enum { NUM_CHANNELS = 1 }; + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; Superblock _sb { }; - Superblock_index _sb_idx { INVALID_SB_IDX }; - Generation _curr_gen { INVALID_GENERATION }; - Constructible _channels[NUM_CHANNELS] { }; - - void execute(bool &) override; + Superblock_index _sb_idx { }; + Generation _curr_gen { }; public: + class Write_vbas : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr + { + Virtual_block_address const in_first_vba; + Number_of_blocks const in_num_vbas; + Request_offset const in_client_req_offset; + Request_tag const in_client_req_tag; + }; + + struct Execute_attr + { + Virtual_block_device &vbd; + Client_data_interface &client_data; + Block_io &block_io; + Free_tree &free_tree; + Meta_tree &meta_tree; + Crypto &crypto; + Superblock &sb; + Generation const &curr_gen; + }; + + private: + + enum State { INIT, COMPLETE, WRITE_VBA, WRITE_VBA_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Number_of_blocks _num_written_vbas { }; + Constructible _ft { }; + Constructible _mt { }; + Generatable_request _write_vba { }; + + void _start_write_vba(Execute_attr const &, bool &); + + public: + + Write_vbas(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Write_vbas() { } + + void print(Output &out) const { Genode::print(out, "write vba"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Extend_free_tree : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr + { + Number_of_blocks const in_num_pbas; + bool &out_extension_finished; + }; + + struct Execute_attr + { + Superblock_control &sb_control; + Free_tree &free_tree; + Meta_tree &meta_tree; + Block_io &block_io; + Trust_anchor &trust_anchor; + Superblock &sb; + Generation const &curr_gen; + }; + + private: + + enum State { INIT, COMPLETE, EXTEND_FREE_TREE, EXTEND_FREE_TREE_SUCCEEDED, SECURE_SB, SECURE_SB_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Number_of_blocks _num_pbas { }; + Physical_block_address _pba { }; + Number_of_blocks _nr_of_leaves { }; + Constructible _ft { }; + Constructible _mt { }; + Generatable_request _secure_sb { }; + Generatable_request _extend_free_tree { }; + + public: + + Extend_free_tree(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Extend_free_tree() { } + + void print(Output &out) const { Genode::print(out, "rekey vba"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Extend_vbd : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr + { + Number_of_blocks const in_num_pbas; + bool &out_extension_finished; + }; + + struct Execute_attr + { + Superblock_control &sb_control; + Virtual_block_device &vbd; + Free_tree &free_tree; + Meta_tree &meta_tree; + Block_io &block_io; + Trust_anchor &trust_anchor; + Superblock &sb; + Generation const &curr_gen; + }; + + private: + + enum State { INIT, COMPLETE, EXTEND_VBD, EXTEND_VBD_SUCCEEDED, SECURE_SB, SECURE_SB_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Number_of_blocks _num_pbas { }; + Physical_block_address _pba { }; + Number_of_blocks _nr_of_leaves { }; + Constructible _ft { }; + Constructible _mt { }; + Generatable_request _secure_sb { }; + Generatable_request _extend_vbd { }; + + public: + + Extend_vbd(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Extend_vbd() { } + + void print(Output &out) const { Genode::print(out, "extend vbd"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Rekey : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr { bool &out_rekeying_finished; }; + + struct Execute_attr + { + Superblock &sb; + Generation const &curr_gen; + Block_io &block_io; + Crypto &crypto; + Trust_anchor &trust_anchor; + Free_tree &free_tree; + Meta_tree &meta_tree; + Virtual_block_device &vbd; + Superblock_control &sb_control; + }; + + private: + + enum State { + INIT, COMPLETE, REKEY_VBA, REKEY_VBA_SUCCEEDED, SECURE_SB, SECURE_SB_SUCCEEDED, REMOVE_KEY, + REMOVE_KEY_SUCCEEDED, GENERATE_KEY, GENERATE_KEY_SUCCEEDED, ADD_KEY, ADD_KEY_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Constructible _ft { }; + Constructible _mt { }; + Generation _gen { }; + Generatable_request _rekey_vba { }; + Generatable_request _remove_key { }; + Generatable_request _secure_sb { }; + Generatable_request _add_key { }; + Generatable_request _generate_key { }; + + public: + + Rekey(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Rekey() { } + + void print(Output &out) const { Genode::print(out, "continue rekeying"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Read_vbas : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr + { + Virtual_block_address const in_first_vba; + Number_of_blocks const in_num_vbas; + Request_offset const in_client_req_offset; + Request_tag const in_client_req_tag; + }; + + struct Execute_attr + { + Virtual_block_device &vbd; + Client_data_interface &client_data; + Block_io &block_io; + Crypto &crypto; + Superblock const &sb; + Generation const &curr_gen; + }; + + private: + + enum State { INIT, COMPLETE, READ_VBA, READ_VBA_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Number_of_blocks _num_read_vbas { }; + Generatable_request _read_vba { }; + + void _start_read_vba(Execute_attr const &, bool &progress); + + public: + + Read_vbas(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Read_vbas() { } + + void print(Output &out) const { Genode::print(out, "read vbas"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Create_snapshot : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr { Generation &out_gen; }; + + struct Execute_attr + { + Superblock &sb; + Generation &curr_gen; + Block_io &block_io; + Trust_anchor &trust_anchor; + Superblock_control &sb_control; + }; + + private: + + enum State { INIT, COMPLETE, SECURE_SB, SECURE_SB_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Generation _gen { }; + Generatable_request _secure_sb { }; + + public: + + Create_snapshot(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Create_snapshot() { } + + void print(Output &out) const { Genode::print(out, "create snapshot"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Synchronize : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr { }; + + struct Execute_attr + { + Superblock &sb; + Generation const &curr_gen; + Block_io &block_io; + Trust_anchor &trust_anchor; + Superblock_control &sb_control; + }; + + private: + + enum State { INIT, COMPLETE, SECURE_SB, SECURE_SB_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Generatable_request _secure_sb { }; + + public: + + Synchronize(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Synchronize() { } + + void print(Output &out) const { Genode::print(out, "sync"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Deinitialize : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr { }; + + struct Execute_attr + { + Superblock &sb; + Generation const &curr_gen; + Block_io &block_io; + Crypto &crypto; + Trust_anchor &trust_anchor; + Superblock_control &sb_control; + }; + + private: + + enum State { + INIT, COMPLETE, SECURE_SB, SECURE_SB_SUCCEEDED, REMOVE_KEY, + REMOVE_CURR_KEY_SUCCEEDED, REMOVE_PREV_KEY_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Generatable_request _secure_sb { }; + Generatable_request _remove_key { }; + + public: + + Deinitialize(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Deinitialize() { } + + void print(Output &out) const { Genode::print(out, "deinitialize"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Initialize : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr { Superblock::State &out_sb_state; }; + + struct Execute_attr + { + Superblock &sb; + Superblock_index &sb_idx; + Generation &curr_gen; + Block_io &block_io; + Crypto &crypto; + Trust_anchor &trust_anchor; + Superblock_control &sb_control; + }; + + private: + + enum State { + INIT, COMPLETE, READ_SB_HASH, READ_SB_HASH_SUCCEEDED, READ_BLOCK, READ_BLOCK_SUCCEEDED, + DECRYPT_KEY, DECRYPT_CURR_KEY_SUCCEEDED, DECRYPT_PREV_KEY_SUCCEEDED, ADD_KEY, + ADD_CURR_KEY_SUCCEEDED, ADD_PREV_KEY_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Generation _gen { }; + Hash _hash { }; + Block _blk { }; + Superblock _sb_ciphertext { }; + Generatable_request _read_block { }; + Generatable_request _read_sb_hash { }; + Generatable_request _decrypt_key { }; + Generatable_request _add_key { }; + + public: + + Initialize(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Initialize() { } + + void print(Output &out) const { Genode::print(out, "initialize"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Discard_snapshot : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr { Generation const in_gen; }; + + struct Execute_attr + { + Superblock &sb; + Generation &curr_gen; + Block_io &block_io; + Trust_anchor &trust_anchor; + Superblock_control &sb_control; + }; + + private: + + enum State { INIT, COMPLETE, SECURE_SB, SECURE_SB_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Generatable_request _secure_sb { }; + + public: + + Discard_snapshot(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Discard_snapshot() { } + + void print(Output &out) const { Genode::print(out, "discard snapshot"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + Virtual_block_address max_vba() const { return _sb.valid() ? _sb.max_vba() : 0; }; Virtual_block_address resizing_nr_of_pbas() const { return _sb.resizing_nr_of_pbas; } @@ -177,7 +582,62 @@ class Tresor::Superblock_control : public Module Superblock_info sb_info() const; - Superblock_control(); + bool execute(Extend_free_tree &req, Free_tree &free_tree, Meta_tree &meta_tree, Block_io &block_io, Trust_anchor &trust_anchor) + { + return req.execute({ *this, free_tree, meta_tree, block_io, trust_anchor, _sb, _curr_gen }); + } + + bool execute(Extend_vbd &req, Virtual_block_device &vbd, Free_tree &free_tree, Meta_tree &meta_tree, Block_io &block_io, Trust_anchor &trust_anchor) + { + return req.execute({ *this, vbd, free_tree, meta_tree, block_io, trust_anchor, _sb, _curr_gen }); + } + + bool execute(Rekey &req, Virtual_block_device &vbd, Free_tree &free_tree, Meta_tree &meta_tree, Block_io &block_io, Crypto &crypto, Trust_anchor &trust_anchor) + { + return req.execute({ _sb, _curr_gen, block_io, crypto, trust_anchor, free_tree, meta_tree, vbd, *this }); + } + + bool execute(Secure_superblock &req, Block_io &block_io, Trust_anchor &trust_anchor) + { + return req.execute({_sb, _sb_idx, _curr_gen, block_io, trust_anchor }); + } + + bool execute(Synchronize &req, Block_io &block_io, Trust_anchor &trust_anchor) + { + return req.execute({_sb, _curr_gen, block_io, trust_anchor, *this }); + } + + bool execute(Deinitialize &req, Block_io &block_io, Crypto &crypto, Trust_anchor &trust_anchor) + { + return req.execute({_sb, _curr_gen, block_io, crypto, trust_anchor, *this }); + } + + bool execute(Initialize &req, Block_io &block_io, Crypto &crypto, Trust_anchor &trust_anchor) + { + return req.execute({_sb, _sb_idx, _curr_gen, block_io, crypto, trust_anchor, *this }); + } + + bool execute(Create_snapshot &req, Block_io &block_io, Trust_anchor &trust_anchor) + { + return req.execute({_sb, _curr_gen, block_io, trust_anchor, *this }); + } + + bool execute(Discard_snapshot &req, Block_io &block_io, Trust_anchor &trust_anchor) + { + return req.execute({_sb, _curr_gen, block_io, trust_anchor, *this }); + } + + bool execute(Read_vbas &req, Virtual_block_device &vbd, Client_data_interface &client_data, Block_io &block_io, Crypto &crypto) + { + return req.execute({ vbd, client_data, block_io, crypto, _sb, _curr_gen }); + } + + bool execute(Write_vbas &req, Virtual_block_device &vbd, Client_data_interface &client_data, Block_io &block_io, Free_tree &free_tree, Meta_tree &meta_tree, Crypto &crypto) + { + return req.execute({ vbd, client_data, block_io, free_tree, meta_tree, crypto, _sb, _curr_gen }); + } + + static constexpr char const *name() { return "sb_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 b9a08d8ed2..4a2c29133e 100644 --- a/repos/gems/src/lib/tresor/include/tresor/trust_anchor.h +++ b/repos/gems/src/lib/tresor/include/tresor/trust_anchor.h @@ -18,141 +18,232 @@ #include #include -namespace Tresor { +namespace Tresor { class Trust_anchor; } - class Trust_anchor; - class Trust_anchor_request; - class Trust_anchor_channel; -} - -class Tresor::Trust_anchor_request : public Module_request +class Tresor::Trust_anchor : Noncopyable { - friend class Trust_anchor_channel; - public: - enum Type { CREATE_KEY, ENCRYPT_KEY, DECRYPT_KEY, WRITE_HASH, READ_HASH, INITIALIZE }; + struct Attr + { + Vfs::Vfs_handle &decrypt_file; + Vfs::Vfs_handle &encrypt_file; + Vfs::Vfs_handle &generate_key_file; + Vfs::Vfs_handle &initialize_file; + Vfs::Vfs_handle &hash_file; + }; private: - Type const _type; - Key_value &_key_plaintext; - Key_value &_key_ciphertext; - Hash &_hash; - Passphrase const _pass; - bool &_success; - - NONCOPYABLE(Trust_anchor_request); + Attr const _attr; + addr_t _user { }; public: - Trust_anchor_request(Module_id src, Module_channel_id, Type, Key_value &, Key_value &, Hash &, Passphrase, bool &); + class Encrypt_key; + class Decrypt_key; + class Generate_key; + class Initialize; + class Read_hash; + class Write_hash; - static char const *type_to_string(Type); + Trust_anchor(Attr const &attr) : _attr(attr) { } - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } + template + bool execute(REQ &req) + { + if (!_user) + _user = (addr_t)&req; + + if (_user != (addr_t)&req) + return false; + + bool progress = req.execute(_attr); + if (req.complete()) + _user = 0; + + return progress; + } + + static constexpr char const *name() { return "trust_anchor"; } }; -class Tresor::Trust_anchor_channel : public Module_channel +class Tresor::Trust_anchor::Encrypt_key : Noncopyable { + public: + + using Module = Trust_anchor; + + struct Attr + { + Key_value &out_key_ciphertext; + Key_value const &in_key_plaintext; + }; + private: - using Request = Trust_anchor_request; + enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR }; - enum State { REQ_SUBMITTED, REQ_COMPLETE, READ_OK, WRITE_OK, FILE_ERR }; + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; - State _state { REQ_COMPLETE }; - Vfs::Env &_vfs_env; + public: + + Encrypt_key(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "encrypt key"); } + + bool execute(Trust_anchor::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Trust_anchor::Decrypt_key : Noncopyable +{ + public: + + using Module = Trust_anchor; + + struct Attr + { + Key_value &out_key_plaintext; + Key_value const &in_key_ciphertext; + }; + + private: + + enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; + + public: + + Decrypt_key(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "decrypt key"); } + + bool execute(Trust_anchor::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Trust_anchor::Initialize : Noncopyable +{ + public: + + using Module = Trust_anchor; + + struct Attr { Passphrase const &in_passphrase; }; + + private: + + enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; 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 &); + Initialize(Attr const &attr) : _helper(*this), _attr(attr) { } - Trust_anchor_channel(Module_channel_id, Vfs::Env &, Xml_node const &); + void print(Output &out) const { Genode::print(out, "initialize"); } + + bool execute(Trust_anchor::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; -class Tresor::Trust_anchor : public Module +class Tresor::Trust_anchor::Generate_key : Noncopyable { + public: + + using Module = Trust_anchor; + + struct Attr { Key_value &out_key_plaintext; }; + private: - using Request = Trust_anchor_request; - using Channel = Trust_anchor_channel; + enum State { INIT, COMPLETE, READ, READ_OK, FILE_ERR }; - Constructible _channels[1] { }; - - NONCOPYABLE(Trust_anchor); + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; public: - 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) { } - }; + Generate_key(Attr const &attr) : _helper(*this), _attr(attr) { } - 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) { } - }; + void print(Output &out) const { Genode::print(out, "generate key"); } - 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 execute(Trust_anchor::Attr const &); - 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) { } - }; + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; - 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) { } - }; +class Tresor::Trust_anchor::Write_hash : Noncopyable +{ + public: - 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) { } - }; + using Module = Trust_anchor; - Trust_anchor(Vfs::Env &, Xml_node const &); + struct Attr { Hash const &in_hash; }; - void execute(bool &) override; + private: + + enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; + char _result_buf[3]; + + public: + + Write_hash(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "write hash"); } + + bool execute(Trust_anchor::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Trust_anchor::Read_hash : Noncopyable +{ + public: + + using Module = Trust_anchor; + + struct Attr { Hash &out_hash; }; + + private: + + enum State { INIT, COMPLETE, READ, READ_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; + + public: + + Read_hash(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "read hash"); } + + bool execute(Trust_anchor::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; #endif /* _TRESOR__TRUST_ANCHOR_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/types.h b/repos/gems/src/lib/tresor/include/tresor/types.h index 9ad7c43a7d..db254df4d8 100644 --- a/repos/gems/src/lib/tresor/include/tresor/types.h +++ b/repos/gems/src/lib/tresor/include/tresor/types.h @@ -23,7 +23,7 @@ /* tresor includes */ #include -#include +#include namespace Tresor { @@ -101,8 +101,15 @@ namespace Tresor { struct Tree_walk_generations; struct Level_indent; struct Tree_root; + struct Tree_configuration; class Pba_allocator; + template + class Request_helper; + + template + class Generatable_request; + template class Fixed_length; @@ -124,8 +131,7 @@ namespace Tresor { return first_pba - 1; } - inline Tree_node_index - t1_node_idx_for_vba_typed(Virtual_block_address vba, Tree_level_index lvl, Tree_degree degr) + inline Tree_node_index tree_node_index(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 }; @@ -133,19 +139,6 @@ namespace Tresor { return (Tree_node_index)(degr_mask & (vba >> vba_rshift)); } - template - inline Tree_node_index t1_node_idx_for_vba(T1 vba, T2 lvl, T3 degr) - { - return t1_node_idx_for_vba_typed((Virtual_block_address)vba, (Tree_level_index)lvl, (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) @@ -167,6 +160,120 @@ namespace Tresor { } +template +class Tresor::Request_helper : Noncopyable +{ + private: + + REQ const &_req; + bool _success { false }; + + public: + + using Module = REQ::Module; + + STATE state { STATE::INIT }; + + Request_helper(REQ &req) : _req(req) { } + + bool complete() const { return state == STATE::COMPLETE; } + + void mark_failed(bool &progress, Error_string const &err_str) + { + error(Module::name(), ": request (", _req, ") failed: ", err_str); + _success = false; + state = STATE::COMPLETE; + progress = true; + } + + void mark_succeeded(bool &progress) + { + _success = true; + state = STATE::COMPLETE; + progress = true; + } + + void generated_req_failed(bool &progress) { mark_failed(progress, "generated request failed"); } + + void generated_req_succeeded(STATE target_state, bool &progress) + { + state = target_state; + progress = true; + } + + void req_generated(STATE target_state, bool &progress) + { + state = target_state; + progress = true; + } + + bool success() const { return _success; } +}; + + +template +class Tresor::Generatable_request +{ + private: + + struct Generated_request + { + OWNER &owner; + OWNER_STATE succeeded_state; + REQUEST req; + + template + Generated_request(OWNER &owner, OWNER_STATE generated_state, OWNER_STATE succeeded_state, + bool &progress, ARGS &&... args) + : + owner(owner), succeeded_state(succeeded_state), req(typename REQUEST::Attr(args...)) + { + owner.req_generated(generated_state, progress); + if (VERBOSE_MODULE_COMMUNICATION) + log(OWNER::Module::name(), " --", req, "--> ", REQUEST::Module::name()); + } + + template + bool execute(REQUEST::Module &dst_mod, ARGS &&... args) + { + bool progress = false; + progress |= dst_mod.execute(req, args...); + if (req.complete()) { + if (VERBOSE_MODULE_COMMUNICATION) + log(OWNER::Module::name(), " <--", req, "-- ", REQUEST::Module::name()); + + if (!req.success()) { + owner.generated_req_failed(progress); + return progress; + } + owner.generated_req_succeeded(succeeded_state, progress); + } + return progress; + } + }; + + Constructible _generated_req { }; + + public: + + template + void generate(ARGS &&... args) + { + _generated_req.construct(args...); + } + + template + bool execute(REQUEST::Module &dst_mod, ARGS &&... args) + { + bool progress = _generated_req->execute(dst_mod, args...); + if (_generated_req->req.complete()) + _generated_req.destruct(); + + return progress; + } +}; + + class Tresor::Pba_allocator { private: @@ -176,7 +283,7 @@ class Tresor::Pba_allocator public: - Pba_allocator(Physical_block_address const first_pba) : _first_pba { first_pba } { } + Pba_allocator(Physical_block_address const first_pba) : _first_pba(first_pba) { } Number_of_blocks num_used_pbas() { return _num_used_pbas; } @@ -317,10 +424,7 @@ class Tresor::Block_scanner public: - Block_scanner(Block const &blk) - : - _blk { blk } - { } + Block_scanner(Block const &blk) : _blk(blk) { } template void fetch(T &dst); @@ -387,10 +491,7 @@ class Tresor::Block_generator public: - Block_generator(Block &blk) - : - _blk { blk } - { } + Block_generator(Block &blk) : _blk(blk) { } template void append(T const &src); @@ -503,6 +604,14 @@ struct Tresor::Tree_root }; +struct Tresor::Tree_configuration +{ + Tree_level_index max_lvl; + Tree_degree degree; + Number_of_leaves num_leaves; +}; + + struct Tresor::Type_1_node_block { Type_1_node nodes[NUM_NODES_PER_BLK] { }; @@ -526,6 +635,11 @@ struct Tresor::Type_1_node_block struct Tresor::Type_1_node_block_walk { Type_1_node_block items[TREE_MAX_NR_OF_LEVELS] { }; + + Type_1_node &node(Virtual_block_address vba, Tree_level_index lvl, Tree_degree degr) + { + return items[lvl].nodes[tree_node_index(vba, lvl, degr)]; + } }; @@ -685,8 +799,8 @@ struct Tresor::Snapshots snap.encode_to_blk(generator); } - void discard_disposable_snapshots(Generation curr_gen, - Generation last_secured_gen) + void discard_disposable_snapshots(Generation last_secured_gen, + Generation curr_gen) { for (Snapshot &snap : items) { @@ -752,31 +866,31 @@ struct Tresor::Superblock enum State { INVALID, NORMAL, REKEYING, EXTENDING_VBD, EXTENDING_FT }; - State state { INVALID }; // offset 0 - Virtual_block_address rekeying_vba { 0 }; // offset 1 - Number_of_blocks resizing_nr_of_pbas { 0 }; // offset 9 - Number_of_leaves resizing_nr_of_leaves { 0 }; // offset 17 - Key previous_key { }; // offset 25 - Key current_key { }; // offset 61 - Snapshots snapshots { }; // offset 97 - 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 { }; // 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 { }; // 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 - // offset 3713 + State state { INVALID }; /* offset 0 */ + Virtual_block_address rekeying_vba { 0 }; /* offset 1 */ + Number_of_blocks resizing_nr_of_pbas { 0 }; /* offset 9 */ + Number_of_leaves resizing_nr_of_leaves { 0 }; /* offset 17 */ + Key previous_key { }; /* offset 25 */ + Key current_key { }; /* offset 61 */ + Snapshots snapshots { }; /* offset 97 */ + 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 { }; /* 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 { }; /* 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 */ + /* offset 3713 */ static State decode_state(On_disc_state val) { @@ -981,6 +1095,19 @@ struct Tresor::Snapshots_info for (Generation &gen : generations) gen = INVALID_GENERATION; } + + void print(Output &out) const + { + bool first { true }; + for (unsigned idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { + + if (!generations[idx]) + continue; + + Genode::print(out, "snapshot ", first ? "" : "\n", idx, ": ", generations[idx]); + first = false; + } + } }; @@ -1028,8 +1155,7 @@ class Tresor::Pba_allocation { Pba_allocation(Type_1_node_walk const &t1_node_walk, Tree_walk_pbas const &new_pbas) : - _t1_node_walk { t1_node_walk }, - _new_pbas { new_pbas } + _t1_node_walk(t1_node_walk), _new_pbas(new_pbas) { } void print(Output &out) const 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 5a23231c2c..d45bbd2d92 100644 --- a/repos/gems/src/lib/tresor/include/tresor/vbd_check.h +++ b/repos/gems/src/lib/tresor/include/tresor/vbd_check.h @@ -16,94 +16,51 @@ /* tresor includes */ #include +#include -namespace Tresor { +namespace Tresor { class Vbd_check; } - class Vbd_check; - class Vbd_check_request; - class Vbd_check_channel; -} - - -class Tresor::Vbd_check_request : public Module_request +struct Tresor::Vbd_check : Noncopyable { - friend class Vbd_check_channel; + class Check : Noncopyable + { + public: - private: + using Module = Vbd_check; - Tree_root const &_vbd; - bool &_success; + struct Attr { Tree_root const &in_vbd; }; - NONCOPYABLE(Vbd_check_request); + private: - public: + enum State { INIT, IN_PROGRESS, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED }; - Vbd_check_request(Module_id, Module_channel_id, Tree_root const &, bool &); + Request_helper _helper; + Attr const _attr; + Type_1_node_block_walk _t1_blks { }; + bool _check_node[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { }; + Block _blk { }; + Number_of_leaves _num_remaining_leaves { 0 }; + Generatable_request, State, Block_io::Read> _read_block { }; - void print(Output &out) const override { Genode::print(out, "check ", _vbd); } -}; + bool _execute_node(Block_io &, Tree_level_index, Tree_node_index, bool &); + public: -class Tresor::Vbd_check_channel : public Module_channel -{ - private: + Check(Attr const &attr) : _helper(*this), _attr(attr) { } - using Request = Vbd_check_request; + void print(Output &out) const { Genode::print(out, "check ", _attr.in_vbd); } - enum State : State_uint { REQ_SUBMITTED, REQ_IN_PROGRESS, REQ_COMPLETE, REQ_GENERATED, READ_BLK_SUCCEEDED }; + bool execute(Block_io &); - 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 }; + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; - NONCOPYABLE(Vbd_check_channel); + Vbd_check() { } - void _generated_req_completed(State_uint) override; + bool execute(Check &req, Block_io &block_io) { return req.execute(block_io); } - 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) - { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); - } - - public: - - Vbd_check_channel(Module_channel_id id) : Module_channel { VBD_CHECK, id } { } - - void execute(bool &); -}; - - -class Tresor::Vbd_check : public Module -{ - private: - - using Channel = Vbd_check_channel; - - Constructible _channels[1] { }; - - NONCOPYABLE(Vbd_check); - - public: - - Vbd_check(); - - void execute(bool &) override; + static constexpr char const *name() { return "vbd_check"; } }; #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 ac8db70ca4..03e9f33b80 100644 --- a/repos/gems/src/lib/tresor/include/tresor/vbd_initializer.h +++ b/repos/gems/src/lib/tresor/include/tresor/vbd_initializer.h @@ -17,92 +17,65 @@ /* tresor includes */ #include +#include -namespace Tresor { +namespace Tresor { class Vbd_initializer; } - class Vbd_initializer; - class Vbd_initializer_request; - class Vbd_initializer_channel; -} - - -class Tresor::Vbd_initializer_request : public Module_request +class Tresor::Vbd_initializer : Noncopyable { - friend class Vbd_initializer_channel; - - private: - - Tree_root &_vbd; - Pba_allocator &_pba_alloc; - bool &_success; - - NONCOPYABLE(Vbd_initializer_request); - public: - Vbd_initializer_request(Module_id, Module_channel_id, Tree_root &, Pba_allocator &, bool &); + class Initialize : Noncopyable + { + public: - void print(Output &out) const override { Genode::print(out, "init"); } -}; + using Module = Vbd_initializer; + struct Attr + { + Tree_configuration const in_tree_cfg; + Type_1_node &out_tree_root; + Pba_allocator &in_out_pba_alloc; + }; -class Tresor::Vbd_initializer_channel : public Module_channel -{ - private: + private: - using Request = Vbd_initializer_request; + enum State { INIT, COMPLETE, WRITE_BLOCK, EXECUTE_NODES }; - enum State { REQ_GENERATED, SUBMITTED, COMPLETE, EXECUTE_NODES }; + enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITING_BLOCK }; - enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITE_BLOCK }; + using Helper = Request_helper; - 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 { }; + Helper _helper; + Attr const _attr; + 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 { }; + Generatable_request _write_block { }; - NONCOPYABLE(Vbd_initializer_channel); + void _reset_level(Tree_level_index, Node_state); - void _generated_req_completed(State_uint) override; + bool _execute_node(Tree_level_index, Tree_node_index, bool &); - bool _request_complete() override { return _state == COMPLETE; } + public: - void _request_submitted(Module_request &) override; + Initialize(Attr const &attr) : _helper(*this), _attr(attr) { } - void _reset_level(Tree_level_index, Node_state); + ~Initialize() { } - bool _execute_node(Tree_level_index, Tree_node_index, bool &); + void print(Output &out) const { Genode::print(out, "initialize"); } - void _mark_req_failed(bool &, char const *); + bool execute(Block_io &); - void _mark_req_successful(bool &); + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; - public: + bool execute(Initialize &req, Block_io &block_io) { return req.execute(block_io); } - Vbd_initializer_channel(Module_channel_id id) : Module_channel { VBD_INITIALIZER, id } { } - - void execute(bool &); -}; - - -class Tresor::Vbd_initializer : public Module -{ - private: - - using Channel = Vbd_initializer_channel; - - Constructible _channels[1] { }; - - NONCOPYABLE(Vbd_initializer); - - public: - - Vbd_initializer(); - - void execute(bool &) override; + static constexpr char const *name() { return "vbd_initializer"; } }; #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 a9f32f1287..3b3ac5c05a 100644 --- a/repos/gems/src/lib/tresor/include/tresor/verbosity.h +++ b/repos/gems/src/lib/tresor/include/tresor/verbosity.h @@ -24,7 +24,6 @@ namespace Tresor { enum { VERBOSE_REKEYING = 0 }; enum { VERBOSE_READ_VBA = 0 }; enum { VERBOSE_WRITE_VBA = 0 }; - enum { VERBOSE_CRYPTO = 0 }; enum { VERBOSE_BLOCK_IO = 0 }; enum { VERBOSE_BLOCK_IO_PBA_FILTER = 0 }; enum { VERBOSE_BLOCK_IO_PBA = 0 }; 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 0c9b6a44fd..b5df8f4655 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 @@ -17,134 +17,270 @@ /* tresor includes */ #include #include +#include +#include +#include -namespace Tresor { +namespace Tresor { class Virtual_block_device; } - class Virtual_block_device; - class Virtual_block_device_request; - class Virtual_block_device_channel; -} - -class Tresor::Virtual_block_device_request : public Module_request +class Tresor::Virtual_block_device : Noncopyable { - friend class Virtual_block_device_channel; - public: - enum Type { REKEY_VBA, READ_VBA, WRITE_VBA, EXTENSION_STEP }; - - private: - - 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; - Virtual_block_address const _rekeying_vba; - bool &_success; - - NONCOPYABLE(Virtual_block_device_request); - - public: - - 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_address); - - 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 : public Module_channel -{ - private: - - using Request = Virtual_block_device_request; - - enum State { - SUBMITTED, REQ_GENERATED, REQ_COMPLETE, READ_BLK_SUCCEEDED, WRITE_BLK_SUCCEEDED, - DECRYPT_LEAF_DATA_SUCCEEDED, ENCRYPT_LEAF_DATA_SUCCEEDED, ALLOC_PBAS_SUCCEEDED }; - - 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); + class Rekey_vba; + class Read_vba; + class Write_vba; + class Extend_tree; template - void _generate_req(State_uint complete_state, bool &progress, ARGS &&... args) + bool execute(REQUEST &req, ARGS &&... args) { return req.execute(args...); } + + static constexpr char const *name() { return "vbd"; } +}; + +class Tresor::Virtual_block_device::Rekey_vba : Noncopyable +{ + public: + + using Module = Virtual_block_device; + + struct Attr { - generate_req(complete_state, progress, args..., _gen_req_success); - _state = REQ_GENERATED; - } + Snapshots &in_out_snapshots; + Tree_root &in_out_ft; + Tree_root &in_out_mt; + Virtual_block_address const in_vba; + Generation const in_curr_gen; + Generation const in_last_secured_gen; + Key_id const in_curr_key_id; + Key_id const in_prev_key_id; + Tree_degree const in_vbd_degree; + Virtual_block_address const in_vbd_highest_vba; + }; - void _request_submitted(Module_request &) override; + private: - bool _request_complete() override { return _state == REQ_COMPLETE; } + enum State { + INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, WRITE_BLK, WRITE_BLK_SUCCEEDED, + DECRYPT_BLOCK, DECRYPT_BLOCK_SUCCEEDED, ENCRYPT_BLOCK, ENCRYPT_BLOCK_SUCCEEDED, + ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED }; - void _generated_req_completed(State_uint) override; + using Helper = Request_helper; - void _generate_ft_req(State, bool, Free_tree_request::Type); + Helper _helper; + Attr const _attr; + Tree_level_index _lvl { 0 }; + Type_1_node_block_walk _t1_blks { }; + Block _encoded_blk { }; + Block _data_blk { }; + Generation _free_gen { 0 }; + Tree_walk_pbas _old_pbas { }; + Tree_walk_pbas _new_pbas { }; + Snapshot_index _snap_idx { 0 }; + Type_1_node_walk _t1_nodes { }; + Number_of_blocks _num_blks { 0 }; + Hash _hash { }; + bool _first_snapshot { false }; + Generatable_request _read_block { }; + Generatable_request _write_block { }; + Generatable_request _encrypt_block { }; + Generatable_request _decrypt_block { }; + Generatable_request _alloc_pbas { }; - Snapshot &snap() { return _req_ptr->_snapshots.items[_snap_idx]; } + bool _check_and_decode_read_blk(bool &); + + void _start_alloc_pbas(bool &, Free_tree::Allocate_pbas::Application); void _generate_write_blk_req(bool &); bool _find_next_snap_to_rekey_vba_at(Snapshot_index &) const; - void _read_vba(bool &); + void _generate_ft_alloc_req_for_rekeying(Tree_level_index, bool &); + + public: + + Rekey_vba(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Rekey_vba() { } + + void print(Output &out) const { Genode::print(out, "rekey vba"); } + + bool execute(Block_io &, Crypto &, Free_tree &, Meta_tree &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Virtual_block_device::Read_vba : Noncopyable +{ + public: + + using Module = Virtual_block_device; + + struct Attr + { + Snapshot const &in_snap; + Virtual_block_address const in_vba; + Key_id const in_key_id; + Tree_degree const in_vbd_degree; + Request_offset const in_client_req_offset; + Request_tag const in_client_req_tag; + }; + + private: + + enum State { INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, DECRYPT_BLOCK, DECRYPT_BLOCK_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Tree_level_index _lvl { 0 }; + Type_1_node_block_walk _t1_blks { }; + Hash _hash { }; + Block _blk { }; + Tree_walk_pbas _new_pbas { }; + Generatable_request _read_block { }; + Generatable_request _decrypt_block { }; bool _check_and_decode_read_blk(bool &); - Tree_node_index _node_idx(Tree_level_index, Virtual_block_address) const; + public: - Type_1_node &_node(Tree_level_index, Virtual_block_address); + Read_vba(Attr const &attr) : _helper(*this), _attr(attr) { } - void _mark_req_successful(bool &); + ~Read_vba() { } - void _mark_req_failed(bool &, char const *); + void print(Output &out) const { Genode::print(out, "read vba"); } + + bool execute(Client_data_interface &, Block_io &, Crypto &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Virtual_block_device::Write_vba : Noncopyable +{ + public: + + using Module = Virtual_block_device; + + struct Attr + { + Snapshot &in_out_snap; + Snapshots const &in_snapshots; + Tree_root &in_out_ft; + Tree_root &in_out_mt; + Virtual_block_address const in_vba; + Key_id const in_curr_key_id; + Key_id const in_prev_key_id; + Tree_degree const in_vbd_degree; + Virtual_block_address const in_vbd_highest_vba; + Request_offset const in_client_req_offset; + Request_tag const in_client_req_tag; + Generation const in_curr_gen; + Generation const in_last_secured_gen; + bool in_rekeying; + Virtual_block_address const in_rekeying_vba; + }; + + private: + + enum State { + INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, DECRYPT_BLOCK, DECRYPT_BLOCK_SUCCEEDED, + WRITE_BLK, WRITE_BLK_SUCCEEDED, ENCRYPT_BLOCK, ENCRYPT_BLOCK_SUCCEEDED, ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Tree_level_index _lvl { 0 }; + Type_1_node_block_walk _t1_blks { }; + Hash _hash { }; + Type_1_node_walk _t1_nodes { }; + Block _data_blk { }; + Block _encoded_blk { }; + Tree_walk_pbas _new_pbas { }; + Number_of_blocks _num_blks { 0 }; + Generation _free_gen { 0 }; + Generatable_request _read_block { }; + Generatable_request _decrypt_block { }; + Generatable_request _encrypt_block { }; + Generatable_request _alloc_pbas { }; + Generatable_request _write_block { }; + + bool _check_and_decode_read_blk(bool &); 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_write_vba(bool &); - void _generate_ft_alloc_req_for_rekeying(Tree_level_index, bool &); + void _generate_write_blk_req(bool &); + + public: + + Write_vba(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Write_vba() { } + + void print(Output &out) const { Genode::print(out, "write vba"); } + + bool execute(Client_data_interface &, Block_io &, Free_tree &, Meta_tree &, Crypto &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Virtual_block_device::Extend_tree : Noncopyable +{ + public: + + using Module = Virtual_block_device; + + struct Attr + { + Number_of_leaves &out_num_leaves; + Snapshots &in_out_snapshots; + Tree_degree const in_snap_degr; + Generation const in_curr_gen; + Generation const in_last_secured_gen; + Physical_block_address &in_out_first_pba; + Number_of_blocks &in_out_num_pbas; + Tree_root &in_out_ft; + Tree_root &in_out_mt; + Tree_degree const in_vbd_degree; + Virtual_block_address const in_vbd_highest_vba; + Key_id const in_curr_key_id; + Key_id const in_prev_key_id; + bool in_rekeying; + Virtual_block_address const in_rekeying_vba; + }; + + private: + + enum State { + INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, WRITE_BLK, WRITE_BLK_SUCCEEDED, ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Tree_level_index _lvl { 0 }; + Snapshot_index _snap_idx { 0 }; + Virtual_block_address _vba { 0 }; + Tree_walk_pbas _old_pbas { }; + Block _encoded_blk { }; + Tree_walk_pbas _new_pbas { }; + Type_1_node_block_walk _t1_blks { }; + Number_of_blocks _num_blks { 0 }; + Type_1_node_walk _t1_nodes { }; + Block _data_blk { }; + Generation _free_gen { 0 }; + Generatable_request _read_block { }; + Generatable_request _write_block { }; + Generatable_request _alloc_pbas { }; void _add_new_root_lvl_to_snap(); @@ -152,32 +288,22 @@ class Tresor::Virtual_block_device_channel : public Module_channel void _set_new_pbas_identical_to_curr_pbas(); + void _generate_write_blk_req(bool &); + 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 } { } + Extend_tree(Attr const &attr) : _helper(*this), _attr(attr) { } - void execute(bool &); -}; + ~Extend_tree() { } -class Tresor::Virtual_block_device : public Module -{ - private: + void print(Output &out) const { Genode::print(out, "extend tree"); } - using Channel = Virtual_block_device_channel; + bool execute(Block_io &, Free_tree &, Meta_tree &); - Constructible _channels[1] { }; - - NONCOPYABLE(Virtual_block_device); - - void execute(bool &) override; - - public: - - Virtual_block_device(); + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; #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 1bbe5512bf..b16c7d2662 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 VBD COW allocations on the meta tree + * \brief Module for doing PBA allocations for the Free Tree via the Meta Tree * \author Martin Stein * \date 2023-02-13 */ @@ -13,149 +13,32 @@ /* tresor includes */ #include -#include #include using namespace Tresor; -char const *Meta_tree_request::type_to_string(Type type) +bool Meta_tree::execute(Allocate_pba &req, Block_io &block_io) { return req.execute(block_io); } + + +void Meta_tree::Allocate_pba::_start_tree_traversal(bool &progress) { - switch (type) { - case ALLOC_PBA: return "alloc pba"; - } - ASSERT_NEVER_REACHED; -} - - -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_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} - - -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; + _lvl = _attr.in_out_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); + _t1_blks[_lvl].nodes[_node_idx[_lvl]] = _attr.in_out_mt.t1_node(); + _read_block.generate(_helper, READ_BLK, SEEK_DOWN, progress, _attr.in_out_mt.pba, _blk); } -void Meta_tree_channel::_traverse_curr_node(bool &progress) +bool Meta_tree::Allocate_pba::execute(Block_io &block_io) { - 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; - } - } 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); - } - } - _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; - + bool progress = false; + switch (_helper.state) { + case INIT: _start_tree_traversal(progress); break; + case READ_BLK: progress |= _read_block.execute(block_io); break; case SEEK_DOWN: if (!check_hash(_blk, _t1_blks[_lvl].nodes[_node_idx[_lvl]].hash)) { - _mark_req_failed(progress, "hash mismatch"); + _helper.mark_failed(progress, "hash mismatch"); break; } _lvl--; @@ -169,54 +52,91 @@ void Meta_tree_channel::execute(bool &progress) case SEEK_LEFT_OR_UP: - if (_lvl < req._mt.max_lvl) { - if (_node_idx[_lvl] < req._mt.degree - 1) { + if (_lvl < _attr.in_out_mt.max_lvl) { + if (_node_idx[_lvl] < _attr.in_out_mt.degree - 1) { _node_idx[_lvl]++; _traverse_curr_node(progress); } else { _lvl++; - _state = SEEK_LEFT_OR_UP; + _helper.state = SEEK_LEFT_OR_UP; progress = true; } } else - _mark_req_failed(progress, "not enough free pbas"); + _helper.mark_failed(progress, "not enough free pbas"); break; - case WRITE_BLK: + case WRITE_BLK: progress |= _write_block.execute(block_io); break; + case WRITE_BLK_SUCCEEDED: - if (_lvl < req._mt.max_lvl) { + if (_lvl < _attr.in_out_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; + t1_node.gen = _attr.in_curr_gen; calc_hash(_blk, t1_node.hash); - _generate_req(WRITE_BLK, progress, t1_node.pba, _blk); + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, t1_node.pba, _blk); } else { - req._mt.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]); - _mark_req_successful(progress); + _attr.in_out_mt.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]); + _helper.mark_succeeded(progress); } break; default: break; } + return progress; } -void Meta_tree_channel::_request_submitted(Module_request &mod_req) +bool Meta_tree::Allocate_pba::_can_alloc_pba_of(Type_2_node &node) { - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; + return node.valid() && node.alloc_gen != _attr.in_curr_gen; } -Meta_tree::Meta_tree() +void Meta_tree::Allocate_pba::_alloc_pba_of(Type_2_node &t2_node, Physical_block_address &pba) { - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); + Physical_block_address old_pba { pba }; + pba = t2_node.pba; + t2_node.pba = old_pba; + t2_node.alloc_gen = _attr.in_curr_gen; + t2_node.free_gen = _attr.in_curr_gen; + t2_node.reserved = false; +} + +void Meta_tree::Allocate_pba::_traverse_curr_node(bool &progress) +{ + if (_lvl) { + Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] }; + if (t1_node.pba) + _read_block.generate(_helper, READ_BLK, SEEK_DOWN, progress, t1_node.pba, _blk); + else { + _helper.state = SEEK_LEFT_OR_UP; + progress = true; + } + } else { + Type_2_node &t2_node { _t2_blk.nodes[_node_idx[_lvl]] }; + if (_can_alloc_pba_of(t2_node)) { + _alloc_pba_of(t2_node, _attr.in_out_pba); + for (Tree_level_index lvl { 1 }; lvl <= _attr.in_out_mt.max_lvl; lvl++) { + Type_1_node &t1_node { _t1_blks[lvl].nodes[_node_idx[lvl]] }; + if (!t1_node.is_volatile(_attr.in_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); + } + } + _helper.state = WRITE_BLK_SUCCEEDED; + } else + _helper.state = SEEK_LEFT_OR_UP; + progress = true; } } diff --git a/repos/gems/src/lib/tresor/module.cc b/repos/gems/src/lib/tresor/module.cc deleted file mode 100644 index 17bab9a658..0000000000 --- a/repos/gems/src/lib/tresor/module.cc +++ /dev/null @@ -1,145 +0,0 @@ -/* - * \brief Framework for component internal modularization - * \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 - -using namespace Tresor; - - -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_chan_id { src_chan_id }, _dst_module_id { dst_module_id } -{ } - - -char const *Tresor::module_name(Module_id id) -{ - switch (id) { - case CRYPTO: return "crypto"; - case BLOCK_IO: return "block_io"; - case CACHE: return "cache"; - case META_TREE: return "meta_tree"; - case FREE_TREE: return "free_tree"; - case VIRTUAL_BLOCK_DEVICE: return "vbd"; - case SUPERBLOCK_CONTROL: return "sb_control"; - case CLIENT_DATA: return "client_data"; - case TRUST_ANCHOR: return "trust_anchor"; - case COMMAND_POOL: return "command_pool"; - 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 SPLITTER: return "splitter"; - case REQUEST_POOL: return "request_pool"; - default: break; - } - 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 deleted file mode 100644 index aefba814c2..0000000000 --- a/repos/gems/src/lib/tresor/request_pool.cc +++ /dev/null @@ -1,381 +0,0 @@ -/* - * \brief Module for scheduling requests for processing - * \author Martin Stein - * \date 2023-03-17 - */ - -/* - * 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 - -using namespace Tresor; - -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::print(Output &out) const -{ - 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; - default: break; - } -} - - -char const *Request::op_to_string(Operation op) -{ - 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; -} - - -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; -} - - -void Request_pool_channel::_try_prepone_requests(bool &progress) -{ - enum { MAX_NUM_REQUESTS_PREPONED = 8 }; - bool requests_preponed { false }; - bool at_req_that_cannot_be_preponed { false }; - _num_requests_preponed = 0; - - 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_channel::_extend_tree(Superblock_control_request::Type type, bool &progress) -{ - 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_channel::_initialize(bool &progress) -{ - switch (_state) { - case REQ_SUBMITTED: - - _gen_sb_control_req(progress, Superblock_control_request::INITIALIZE, INITIALIZE_SB_CTRL_SUCCEEDED); - break; - - case INITIALIZE_SB_CTRL_SUCCEEDED: - - switch (_sb_state) { - case Superblock::INVALID: ASSERT_NEVER_REACHED; - case Superblock::NORMAL: - - _chan_queue.dequeue(*this); - _reset(); - 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; - - default: break; - } -} - - -void Request_pool_channel::_forward_to_sb_ctrl(bool &progress, Superblock_control_request::Type type) -{ - 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 (!_chan_queue.empty()) - _chan_queue.head().execute(progress); -} - - -void Request_pool_channel::execute(bool &progress) -{ - 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() -{ - 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)); -} - - -void Request_pool_channel::_generated_req_completed(State_uint state_uint) -{ - 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; -} - - -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; - } -} - - -bool Request_pool_channel_queue::is_tail(Channel const &chan) const -{ - Slot_index slot_idx; - ASSERT(!empty()); - if (_tail) - slot_idx = _tail - 1; - else - slot_idx = NUM_SLOTS - 1; - - 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 74a4d09725..310d9e3fbc 100644 --- a/repos/gems/src/lib/tresor/sb_check.cc +++ b/repos/gems/src/lib/tresor/sb_check.cc @@ -13,64 +13,41 @@ /* tresor includes */ #include -#include -#include -#include using namespace Tresor; -Sb_check_request::Sb_check_request(Module_id src_mod, Module_channel_id src_chan, bool &success) -: - Module_request { src_mod, src_chan, SB_CHECK }, _success { success } -{ } - - -void Sb_check_channel::_generated_req_completed(State_uint state_uint) +bool Sb_check::Check::execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io) { - 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; - } - _state = (State)state_uint; -} - - -void Sb_check_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - switch (_state) { - case REQ_SUBMITTED: + bool progress = false; + switch (_helper.state) { + case INIT: _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); + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _sb_idx, _blk); break; - case READ_BLK_SUCCESSFUL: + case READ_BLK: progress |= _read_block.execute(block_io); break; + case READ_BLK_SUCCEEDED: _sb.decode_from_blk(_blk); if (_scan_for_highest_gen_sb_done) { if (!_sb.valid()) { - _mark_req_failed(progress, "no valid superblock");; + _helper.mark_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); + _check_vbd.generate(_helper, CHECK_VBD, CHECK_VBD_SUCCEEDED, progress, *_tree_root); if (VERBOSE_CHECK) log(" check snap ", _snap_idx, " (", snap, ")"); } else { - _state = CHECK_VBD_SUCCESSFUL; + _helper.state = CHECK_VBD_SUCCEEDED; progress = true; if (VERBOSE_CHECK) log(" skip snap ", _snap_idx, " as it is unused"); @@ -83,85 +60,45 @@ void Sb_check_channel::execute(bool &progress) } if (_sb_idx < MAX_SUPERBLOCK_INDEX) { _sb_idx++; - _generate_req(READ_BLK_SUCCESSFUL, progress, _sb_idx, _blk); + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, 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); + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _highest_gen_sb_idx, _blk); if (VERBOSE_CHECK) log("check superblock ", _highest_gen_sb_idx, "\n read superblock"); } } break; - case CHECK_VBD_SUCCESSFUL: + case CHECK_VBD: progress |= _check_vbd.execute(vbd_check, block_io); break; + case CHECK_VBD_SUCCEEDED: if (_snap_idx < MAX_SNAP_IDX) { _snap_idx++; - _state = READ_BLK_SUCCESSFUL; + _helper.state = READ_BLK_SUCCEEDED; 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); + _check_ft.generate(_helper, CHECK_FT, CHECK_FT_SUCCEEDED, progress, *_tree_root); if (VERBOSE_CHECK) log(" check free tree"); } break; - case CHECK_FT_SUCCESSFUL: + case CHECK_FT: progress |= _check_ft.execute(ft_check, block_io); break; + case CHECK_FT_SUCCEEDED: _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); + _check_ft.generate(_helper, CHECK_MT, CHECK_MT_SUCCEEDED, progress, *_tree_root); if (VERBOSE_CHECK) log(" check meta tree"); break; - case CHECK_MT_SUCCESSFUL: _mark_req_successful(progress); break; + case CHECK_MT: progress |= _check_ft.execute(ft_check, block_io); break; + case CHECK_MT_SUCCEEDED: _helper.mark_succeeded(progress); break; default: break; } -} - - -void Sb_check_channel::_mark_req_failed(bool &progress, char const *str) -{ - 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_channel::_mark_req_successful(bool &progress) -{ - Request &req { *_req_ptr }; - req._success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Sb_check_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -Sb_check::Sb_check() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } -} - - -void Sb_check::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); + return progress; } diff --git a/repos/gems/src/lib/tresor/sb_initializer.cc b/repos/gems/src/lib/tresor/sb_initializer.cc index 5c7cfe1324..ada8d7410f 100644 --- a/repos/gems/src/lib/tresor/sb_initializer.cc +++ b/repos/gems/src/lib/tresor/sb_initializer.cc @@ -14,158 +14,100 @@ /* tresor includes */ #include -#include -#include -#include -#include #include using namespace Tresor; -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_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_channel::_generated_req_completed(State_uint state_uint) +bool Sb_initializer::Initialize::execute(Block_io &block_io, Trust_anchor &trust_anchor, Vbd_initializer &vbd_initializer, Ft_initializer &ft_initializer) { - 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_channel::_request_submitted(Module_request &mod_req) -{ - _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_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: + bool progress = false; + switch (_helper.state) { + case INIT: { - _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; + _init_vbd.generate(_helper, INIT_VBD, INIT_VBD_SUCCEEDED, progress, _attr.in_vbd_cfg, _vbd_root, _attr.in_out_pba_alloc); break; } + case INIT_VBD: progress |= _init_vbd.execute(vbd_initializer, block_io); break; 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); + _init_ft.generate(_helper, INIT_FT, INIT_FT_SUCCEEDED, progress, _attr.in_ft_cfg, _ft_root, _attr.in_out_pba_alloc); break; + case INIT_FT: progress |= _init_ft.execute(ft_initializer, block_io); 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); + _init_ft.generate(_helper, INIT_FT, INIT_MT_SUCCEEDED, progress, _attr.in_mt_cfg, _mt_root, _attr.in_out_pba_alloc); break; case INIT_MT_SUCCEEDED: - _generate_req(CREATE_KEY_SUCCEEDED, progress, _sb.current_key.value); + _generate_key.generate(_helper, GENERATE_KEY, GENERATE_KEY_SUCCEEDED, progress, _sb.current_key.value); break; - case CREATE_KEY_SUCCEEDED: + case GENERATE_KEY: progress |= _generate_key.execute(trust_anchor); break; + case GENERATE_KEY_SUCCEEDED: - _generate_req(ENCRYPT_KEY_SUCCEEDED, progress, _sb.current_key.value, _sb.current_key.value); + _encrypt_key.generate(_helper, ENCRYPT_KEY, ENCRYPT_KEY_SUCCEEDED, progress, _sb.current_key.value, _sb.current_key.value); break; + case ENCRYPT_KEY: progress |= _encrypt_key.execute(trust_anchor); break; case ENCRYPT_KEY_SUCCEEDED: { 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.pba = _vbd_root.pba; + snap.gen = _vbd_root.gen; + snap.hash = _vbd_root.hash; + snap.nr_of_leaves = _attr.in_vbd_cfg.num_leaves; + snap.max_level = _attr.in_vbd_cfg.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.degree = _attr.in_vbd_cfg.degree; + _sb.first_pba = _attr.in_out_pba_alloc.first_pba() - NR_OF_SUPERBLOCK_SLOTS; + _sb.nr_of_pbas = _attr.in_out_pba_alloc.num_used_pbas() + NR_OF_SUPERBLOCK_SLOTS; + _sb.free_number = _ft_root.pba; + _sb.free_gen = _ft_root.gen; + _sb.free_hash = _ft_root.hash; + _sb.free_max_level = _attr.in_ft_cfg.max_lvl; + _sb.free_degree = _attr.in_ft_cfg.degree; + _sb.free_leaves = _attr.in_ft_cfg.num_leaves; + _sb.meta_number = _mt_root.pba; + _sb.meta_gen = _mt_root.gen; + _sb.meta_hash = _mt_root.hash; + _sb.meta_max_level = _attr.in_mt_cfg.max_lvl; + _sb.meta_degree = _attr.in_mt_cfg.degree; + _sb.meta_leaves = _attr.in_mt_cfg.num_leaves; _sb.encode_to_blk(_blk); - _generate_req(WRITE_BLK_SUCCEEDED, progress, _sb_idx, _blk); + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _sb_idx, _blk); break; } + case WRITE_BLK: progress |= _write_block.execute(block_io); break; case WRITE_BLK_SUCCEEDED: - _generate_req(_sb_idx ? SB_COMPLETE : WRITE_HASH_TO_TA, progress); - progress = true; + _sync_block_io.generate(_helper, SYNC_BLOCK_IO, _sb_idx ? SB_COMPLETE : WRITE_HASH_TO_TA, progress); break; + case SYNC_BLOCK_IO: progress |= _sync_block_io.execute(block_io); break; case WRITE_HASH_TO_TA: calc_hash(_blk, _hash); - _generate_req(SB_COMPLETE, progress, _hash); + _write_sb_hash.generate(_helper, WRITE_SB_HASH, SB_COMPLETE, progress, _hash); break; + case WRITE_SB_HASH: progress |= _write_sb_hash.execute(trust_anchor); break; case SB_COMPLETE: 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); + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _sb_idx, _blk); } else - _mark_req_successful(progress); + _helper.mark_succeeded(progress); break; default: break; } -} - - -Sb_initializer::Sb_initializer() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } -} - - -void Sb_initializer::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); + return progress; } diff --git a/repos/gems/src/lib/tresor/superblock_control.cc b/repos/gems/src/lib/tresor/superblock_control.cc index c78c098103..1a5e673feb 100644 --- a/repos/gems/src/lib/tresor/superblock_control.cc +++ b/repos/gems/src/lib/tresor/superblock_control.cc @@ -19,585 +19,588 @@ using namespace Tresor; -Superblock_control_request:: -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_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) +void Superblock_control::Write_vbas::_start_write_vba(Execute_attr const &attr, bool &progress) { - switch (type) { - case READ_VBA: return "read_vba"; - case WRITE_VBA: return "write_vba"; - case SYNC: return "sync"; - case INITIALIZE: return "initialize"; - case DEINITIALIZE: return "deinitialize"; - case VBD_EXTENSION_STEP: return "vbd_ext_step"; - case FT_EXTENSION_STEP: return "ft_ext_step"; - case CREATE_SNAPSHOT: return "create_snap"; - case DISCARD_SNAPSHOT: return "discard_snap"; - case INITIALIZE_REKEYING: return "init_rekeying"; - case REKEY_VBA: return "rekey_vba"; + Virtual_block_address vba = _attr.in_first_vba + _num_written_vbas; + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + if (attr.sb.curr_snap().gen != attr.curr_gen) { + Snapshot &snap { attr.sb.curr_snap() }; + attr.sb.curr_snap_idx = attr.sb.snapshots.alloc_idx(attr.curr_gen, attr.sb.last_secured_generation); + attr.sb.curr_snap() = snap; + attr.sb.curr_snap().keep = false; } - ASSERT_NEVER_REACHED; + Key_id key_id { attr.sb.state == Superblock::REKEYING && vba >= attr.sb.rekeying_vba ? + attr.sb.previous_key.id : attr.sb.current_key.id }; + + _ft.construct(attr.sb.free_number, attr.sb.free_gen, attr.sb.free_hash, attr.sb.free_max_level, attr.sb.free_degree, attr.sb.free_leaves); + _mt.construct(attr.sb.meta_number, attr.sb.meta_gen, attr.sb.meta_hash, attr.sb.meta_max_level, attr.sb.meta_degree, attr.sb.meta_leaves); + _write_vba.generate( + _helper, WRITE_VBA, WRITE_VBA_SUCCEEDED, progress, attr.sb.snapshots.items[attr.sb.curr_snap_idx], attr.sb.snapshots, + *_ft, *_mt, vba, key_id, attr.sb.previous_key.id, attr.sb.degree, attr.sb.max_vba(), _attr.in_client_req_offset, + _attr.in_client_req_tag, attr.curr_gen, attr.sb.last_secured_generation, attr.sb.state == Superblock::REKEYING, + attr.sb.rekeying_vba); + + if (VERBOSE_WRITE_VBA) + log("write vba ", vba, ": snap ", attr.sb.curr_snap_idx, " key ", key_id, " gen ", attr.curr_gen); } -void Superblock_control_channel::_mark_req_failed(bool &progress, char const *str) +bool Superblock_control::Write_vbas::execute(Execute_attr const &attr) { - error("sb control: request (", *_req_ptr, ") failed at step \"", str, "\""); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} + bool progress = false; + switch (_helper.state) { + case INIT: - -void Superblock_control_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Superblock_control_channel::_generated_req_completed(State_uint state_uint) -{ - 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 - _state = (State)state_uint; -} - - -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) -{ - 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, _sb.rekeying_vba); -} - - -void Superblock_control_channel::_access_vba(Virtual_block_device_request::Type type, bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: - { - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - if (req._vba > _sb.max_vba()) { - _mark_req_failed(progress, "VBA greater than max VBA"); + if (_attr.in_first_vba + _attr.in_num_vbas - 1 > attr.sb.max_vba()) { + _helper.mark_failed(progress, "invalid VBA range"); 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); - + _start_write_vba(attr, progress); break; - } - case ACCESS_VBA_AT_VBD_SUCCEEDED: _mark_req_successful(progress); break; - default: break; - } -} + case WRITE_VBA: progress |= _write_vba.execute(attr.vbd, attr.client_data, attr.block_io, attr.free_tree, attr.meta_tree, attr.crypto); break; + case WRITE_VBA_SUCCEEDED: -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(progress, "check number of unused blocks"); - break; - } - if (_sb.state == Superblock::NORMAL) { - - req._client_req_finished = false; - _sb.state = sb_state; - _sb.resizing_nr_of_pbas = req._nr_of_blks; - _sb.resizing_nr_of_leaves = 0; - _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); - - _start_secure_sb(progress); - break; - - } else if (_sb.state == sb_state) { - - _pba = last_used_pba + 1; - req._nr_of_blks = _sb.resizing_nr_of_pbas; - - 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); - - req._nr_of_blks = _sb.resizing_nr_of_pbas; - _pba = _sb.first_pba + _sb.nr_of_pbas; - if (tree_name == "vbd") { - - _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); - } + if (++_num_written_vbas < _attr.in_num_vbas) { + _start_write_vba(attr, progress); } else - _mark_req_failed(progress, "check superblock state"); - + _helper.mark_succeeded(progress); break; - } - case TREE_EXT_STEP_IN_TREE_SUCCEEDED: - { - if (req._nr_of_blks >= _sb.resizing_nr_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 }; - Physical_block_address const new_first_unused_pba { _sb.first_pba + (_sb.nr_of_pbas + nr_of_added_pbas) }; - 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 += _nr_of_leaves; - if (tree_name == "vbd") - _sb.curr_snap_idx = _sb.snapshots.newest_snap_idx(); - - if (!req._nr_of_blks) { - _sb.state = Superblock::NORMAL; - req._client_req_finished = true; - } - _start_secure_sb(progress); - break; - } - case SECURE_SB: _secure_sb(progress); break; - case SECURE_SB_SUCCEEDED: _mark_req_successful(progress); break; default: break; } + return progress; } -void Superblock_control_channel::_rekey_vba(bool &progress) +void Superblock_control::Read_vbas::_start_read_vba(Execute_attr const &attr, bool &progress) { - switch (_state) { - case REQ_SUBMITTED: + Virtual_block_address vba = _attr.in_first_vba + _num_read_vbas; + Key_id key_id { attr.sb.state == Superblock::REKEYING && vba >= attr.sb.rekeying_vba ? + attr.sb.previous_key.id : attr.sb.current_key.id }; - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - if (_sb.state != Superblock::REKEYING) { - _mark_req_failed(progress, "check superblock state"); + _read_vba.generate( + _helper, READ_VBA, READ_VBA_SUCCEEDED, progress, attr.sb.snapshots.items[attr.sb.curr_snap_idx], vba, key_id, + attr.sb.degree, _attr.in_client_req_offset, _attr.in_client_req_tag); + + if (VERBOSE_READ_VBA) + log("read vba ", vba, ": snap ", attr.sb.curr_snap_idx, " key ", key_id, " gen ", attr.curr_gen); +} + + +bool Superblock_control::Read_vbas::execute(Execute_attr const &attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + if (_attr.in_first_vba + _attr.in_num_vbas - 1 > attr.sb.max_vba()) { + _helper.mark_failed(progress, "invalid VBA range"); break; } - _generate_vbd_req( - Virtual_block_device_request::REKEY_VBA, REKEY_VBA_AT_VBD_SUCCEEDED, - progress, _sb.current_key.id, _sb.rekeying_vba); + _start_read_vba(attr, progress); + break; - _state = REQ_GENERATED; - if (VERBOSE_REKEYING) { - 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); + case READ_VBA: progress |= _read_vba.execute(attr.vbd, attr.client_data, attr.block_io, attr.crypto); break; + case READ_VBA_SUCCEEDED: + + if (++_num_read_vbas < _attr.in_num_vbas) { + _start_read_vba(attr, progress); + } else + _helper.mark_succeeded(progress); + break; + + default: break; + } + return progress; +} + + +bool Superblock_control::Extend_free_tree::execute(Execute_attr const &attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + { + _num_pbas = _attr.in_num_pbas; + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + Physical_block_address last_used_pba { attr.sb.first_pba + (attr.sb.nr_of_pbas - 1) }; + Number_of_blocks nr_of_unused_pbas { MAX_PBA - last_used_pba }; + + if (_num_pbas > nr_of_unused_pbas) { + _helper.mark_failed(progress, "check number of unused blocks"); + break; + } + if (attr.sb.state == Superblock::NORMAL) { + + _attr.out_extension_finished = false; + attr.sb.state = Superblock::EXTENDING_FT; + attr.sb.resizing_nr_of_pbas = _num_pbas; + attr.sb.resizing_nr_of_leaves = 0; + _pba = last_used_pba + 1; + if (VERBOSE_FT_EXTENSION) + log("free_tree ext init: pbas ", _pba, "..", + _pba + (Number_of_blocks)attr.sb.resizing_nr_of_pbas - 1, + " leaves ", (Number_of_blocks)attr.sb.resizing_nr_of_leaves); + + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); + break; + + } else if (attr.sb.state == Superblock::EXTENDING_FT) { + + _pba = last_used_pba + 1; + _num_pbas = attr.sb.resizing_nr_of_pbas; + + if (VERBOSE_FT_EXTENSION) + log("free_tree ext step: pbas ", _pba, "..", + _pba + (Number_of_blocks)attr.sb.resizing_nr_of_pbas - 1, + " leaves ", (Number_of_blocks)attr.sb.resizing_nr_of_leaves); + + _num_pbas = attr.sb.resizing_nr_of_pbas; + _pba = attr.sb.first_pba + attr.sb.nr_of_pbas; + + _ft.construct(attr.sb.free_number, attr.sb.free_gen, attr.sb.free_hash, attr.sb.free_max_level, attr.sb.free_degree, attr.sb.free_leaves); + _mt.construct(attr.sb.meta_number, attr.sb.meta_gen, attr.sb.meta_hash, attr.sb.meta_max_level, attr.sb.meta_degree, attr.sb.meta_leaves); + _extend_free_tree.generate(_helper, EXTEND_FREE_TREE, EXTEND_FREE_TREE_SUCCEEDED, progress, attr.curr_gen, *_ft, *_mt, _pba, _num_pbas); + + } else + _helper.mark_failed(progress, "check superblock state"); + + break; + } + case EXTEND_FREE_TREE: progress |= _extend_free_tree.execute(attr.free_tree, attr.block_io, attr.meta_tree); break; + case EXTEND_FREE_TREE_SUCCEEDED: + { + if (_num_pbas >= attr.sb.resizing_nr_of_pbas) { + _helper.mark_failed(progress, "check number of pbas"); + break; + } + Number_of_blocks const nr_of_added_pbas { attr.sb.resizing_nr_of_pbas - _num_pbas }; + Physical_block_address const new_first_unused_pba { attr.sb.first_pba + (attr.sb.nr_of_pbas + nr_of_added_pbas) }; + if (_pba != new_first_unused_pba) { + _helper.mark_failed(progress, "check new first unused pba"); + break; + } + attr.sb.nr_of_pbas = attr.sb.nr_of_pbas + nr_of_added_pbas; + attr.sb.resizing_nr_of_pbas = _num_pbas; + attr.sb.resizing_nr_of_leaves += _nr_of_leaves; + attr.sb.curr_snap_idx = attr.sb.snapshots.newest_snap_idx(); + + if (!_num_pbas) { + attr.sb.state = Superblock::NORMAL; + _attr.out_extension_finished = true; + } + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); + break; + } + case SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; + case SECURE_SB_SUCCEEDED: _helper.mark_succeeded(progress); break; + default: break; + } + return progress; +} + + +bool Superblock_control::Extend_vbd::execute(Execute_attr const &attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + { + _num_pbas = _attr.in_num_pbas; + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + Physical_block_address last_used_pba { attr.sb.first_pba + (attr.sb.nr_of_pbas - 1) }; + Number_of_blocks nr_of_unused_pbas { MAX_PBA - last_used_pba }; + + if (_num_pbas > nr_of_unused_pbas) { + _helper.mark_failed(progress, "check number of unused blocks"); + break; + } + if (attr.sb.state == Superblock::NORMAL) { + + _attr.out_extension_finished = false; + attr.sb.state = Superblock::EXTENDING_VBD; + attr.sb.resizing_nr_of_pbas = _num_pbas; + attr.sb.resizing_nr_of_leaves = 0; + _pba = last_used_pba + 1; + if (VERBOSE_VBD_EXTENSION) + log("vbd ext init: pbas ", _pba, "..", + _pba + (Number_of_blocks)attr.sb.resizing_nr_of_pbas - 1, + " leaves ", (Number_of_blocks)attr.sb.resizing_nr_of_leaves); + + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); + break; + + } else if (attr.sb.state == Superblock::EXTENDING_VBD) { + + _pba = last_used_pba + 1; + _num_pbas = attr.sb.resizing_nr_of_pbas; + + if (VERBOSE_VBD_EXTENSION) + log("vbd ext step: pbas ", _pba, "..", + _pba + (Number_of_blocks)attr.sb.resizing_nr_of_pbas - 1, + " leaves ", (Number_of_blocks)attr.sb.resizing_nr_of_leaves); + + _num_pbas = attr.sb.resizing_nr_of_pbas; + _pba = attr.sb.first_pba + attr.sb.nr_of_pbas; + + _ft.construct(attr.sb.free_number, attr.sb.free_gen, attr.sb.free_hash, attr.sb.free_max_level, attr.sb.free_degree, attr.sb.free_leaves); + _mt.construct(attr.sb.meta_number, attr.sb.meta_gen, attr.sb.meta_hash, attr.sb.meta_max_level, attr.sb.meta_degree, attr.sb.meta_leaves); + _extend_vbd.generate( + _helper, EXTEND_VBD, EXTEND_VBD_SUCCEEDED, progress, _nr_of_leaves, attr.sb.snapshots, + attr.sb.degree, attr.curr_gen, attr.sb.last_secured_generation, _pba, _num_pbas, *_ft, + *_mt, attr.sb.degree, attr.sb.max_vba(), attr.sb.previous_key.id, attr.sb.current_key.id, + attr.sb.state == Superblock::REKEYING, attr.sb.rekeying_vba); + + } else + _helper.mark_failed(progress, "check superblock state"); + + break; + } + case EXTEND_VBD: progress |= _extend_vbd.execute(attr.vbd, attr.block_io, attr.free_tree, attr.meta_tree); break; + case EXTEND_VBD_SUCCEEDED: + { + if (_num_pbas >= attr.sb.resizing_nr_of_pbas) { + _helper.mark_failed(progress, "check number of pbas"); + break; + } + Number_of_blocks const nr_of_added_pbas { attr.sb.resizing_nr_of_pbas - _num_pbas }; + Physical_block_address const new_first_unused_pba { attr.sb.first_pba + (attr.sb.nr_of_pbas + nr_of_added_pbas) }; + if (_pba != new_first_unused_pba) { + _helper.mark_failed(progress, "check new first unused pba"); + break; + } + attr.sb.nr_of_pbas = attr.sb.nr_of_pbas + nr_of_added_pbas; + attr.sb.resizing_nr_of_pbas = _num_pbas; + attr.sb.resizing_nr_of_leaves += _nr_of_leaves; + attr.sb.curr_snap_idx = attr.sb.snapshots.newest_snap_idx(); + + if (!_num_pbas) { + attr.sb.state = Superblock::NORMAL; + _attr.out_extension_finished = true; + } + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); + break; + } + case SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; + case SECURE_SB_SUCCEEDED: _helper.mark_succeeded(progress); break; + default: break; + } + return progress; +} + + +bool Superblock_control::Rekey::execute(Execute_attr const &attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + _attr.out_rekeying_finished = false; + switch (attr.sb.state) { + case Superblock::NORMAL: + + attr.sb.state = Superblock::REKEYING; + attr.sb.rekeying_vba = 0; + attr.sb.previous_key = attr.sb.current_key; + attr.sb.current_key.id++; + _generate_key.generate(_helper, GENERATE_KEY, GENERATE_KEY_SUCCEEDED, progress, attr.sb.current_key.value); + break; + + case Superblock::REKEYING: + + _ft.construct(attr.sb.free_number, attr.sb.free_gen, attr.sb.free_hash, attr.sb.free_max_level, attr.sb.free_degree, attr.sb.free_leaves); + _mt.construct(attr.sb.meta_number, attr.sb.meta_gen, attr.sb.meta_hash, attr.sb.meta_max_level, attr.sb.meta_degree, attr.sb.meta_leaves); + _rekey_vba.generate( + _helper, REKEY_VBA, REKEY_VBA_SUCCEEDED, progress, attr.sb.snapshots, *_ft, *_mt, attr.sb.rekeying_vba, + attr.curr_gen, attr.sb.last_secured_generation, attr.sb.current_key.id, attr.sb.previous_key.id, attr.sb.degree, attr.sb.max_vba()); + + if (VERBOSE_REKEYING) + log("rekey vba ", attr.sb.rekeying_vba, ":\n update vbd: keys ", attr.sb.previous_key.id, ",", attr.sb.current_key.id, + " generations ", attr.sb.last_secured_generation, ",", attr.curr_gen); + break; + + default: + + _helper.mark_failed(progress, "bad superblock state"); + break; } break; - case REKEY_VBA_AT_VBD_SUCCEEDED: + case GENERATE_KEY: progress |= _generate_key.execute(attr.trust_anchor); break; + case GENERATE_KEY_SUCCEEDED: + + _add_key.generate(_helper, ADD_KEY, ADD_KEY_SUCCEEDED, progress, attr.sb.current_key); + if (VERBOSE_REKEYING) + log("start rekeying:\n update sb: keys ", attr.sb.previous_key.id, ",", attr.sb.current_key.id); + break; + + case ADD_KEY: progress |= _add_key.execute(attr.crypto); break; + case ADD_KEY_SUCCEEDED: + + if (VERBOSE_REKEYING) + log(" secure sb: gen ", attr.curr_gen); + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); + break; + + case REKEY_VBA: progress |= _rekey_vba.execute(attr.vbd, attr.block_io, attr.crypto, attr.free_tree, attr.meta_tree); break; + case REKEY_VBA_SUCCEEDED: { Number_of_leaves max_nr_of_leaves { 0 }; - for (Snapshot const &snap : _sb.snapshots.items) { + for (Snapshot const &snap : attr.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_ptr->_client_req_finished = false; - _start_secure_sb(progress); + if (attr.sb.rekeying_vba < max_nr_of_leaves - 1) { + attr.sb.rekeying_vba++; + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); if (VERBOSE_REKEYING) - log(" secure sb: gen ", _curr_gen); + log(" secure sb: gen ", attr.curr_gen); } else { - _generate_req(REMOVE_PREV_KEY_SUCCEEDED, progress, _sb.previous_key.id); + _remove_key.generate(_helper, REMOVE_KEY, REMOVE_KEY_SUCCEEDED, progress, attr.sb.previous_key.id); if (VERBOSE_REKEYING) - log(" remove key ", _sb.previous_key.id); + log(" remove key ", attr.sb.previous_key.id); } break; } - case REMOVE_PREV_KEY_SUCCEEDED: + case REMOVE_KEY: progress |= _remove_key.execute(attr.crypto); break; + case REMOVE_KEY_SUCCEEDED: - _sb.previous_key = { }; - _sb.state = Superblock::NORMAL; - _req_ptr->_client_req_finished = true; - _start_secure_sb(progress); + attr.sb.previous_key = { }; + attr.sb.state = Superblock::NORMAL; + _attr.out_rekeying_finished = true; + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); if (VERBOSE_REKEYING) - log(" secure sb: gen ", _curr_gen); + log(" secure sb: gen ", attr.curr_gen); break; - case SECURE_SB: _secure_sb(progress); break; - case SECURE_SB_SUCCEEDED: _mark_req_successful(progress); break; + case SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; + case SECURE_SB_SUCCEEDED: _helper.mark_succeeded(progress); break; default: break; } + return progress; } -void Superblock_control_channel::_start_secure_sb(bool &progress) +bool Superblock_control::Secure_superblock::execute(Execute_attr const &attr) { - _state = SECURE_SB; - _secure_sb_state = STARTED; - progress = true; -} + bool progress = false; + switch (_helper.state) { + case INIT: - -void Superblock_control_channel::_secure_sb(bool &progress) -{ - switch (_secure_sb_state) { - case STARTED: - - _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); + attr.sb.curr_snap().gen = attr.curr_gen; + _sb_ciphertext.copy_all_but_key_values_from(attr.sb); + _encrypt_key.generate( + _helper, ENCRYPT_KEY, ENCRYPT_CURR_KEY_SUCCEEDED, progress, _sb_ciphertext.current_key.value, attr.sb.current_key.value); break; + case ENCRYPT_KEY: progress |= _encrypt_key.execute(attr.trust_anchor); break; case ENCRYPT_CURR_KEY_SUCCEEDED: - 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); + if (attr.sb.state == Superblock::REKEYING) + _encrypt_key.generate( + _helper, ENCRYPT_KEY, ENCRYPT_PREV_KEY_SUCCEEDED, progress, attr.sb.previous_key.value, _sb_ciphertext.previous_key.value); + else { + _sb_ciphertext.encode_to_blk(_blk); + _write_block.generate(_helper, WRITE_BLOCK, WRITE_BLOCK_SUCCEEDED, progress, attr.sb_idx, _blk); + } break; - case ENCRYPT_PREV_KEY_SUCCEEDED: _generate_req(SYNC_CACHE_SUCCEEDED, progress); break; - case SYNC_CACHE_SUCCEEDED: + case ENCRYPT_PREV_KEY_SUCCEEDED: _sb_ciphertext.encode_to_blk(_blk); - _generate_req(WRITE_SB_SUCCEEDED, progress, _sb_idx, _blk); + _write_block.generate(_helper, WRITE_BLOCK, WRITE_BLOCK_SUCCEEDED, progress, attr.sb_idx, _blk); break; - case WRITE_SB_SUCCEEDED: _generate_req(SYNC_BLK_IO_SUCCEEDED, progress); break; - case SYNC_BLK_IO_SUCCEEDED: + case WRITE_BLOCK: progress |= _write_block.execute(attr.block_io); break; + case WRITE_BLOCK_SUCCEEDED: _sync_block_io.generate(_helper, SYNC_BLOCK_IO, SYNC_BLOCK_IO_SUCCEEDED, progress); break; + case SYNC_BLOCK_IO: progress |= _sync_block_io.execute(attr.block_io); break; + case SYNC_BLOCK_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++; + _write_sb_hash.generate(_helper, WRITE_SB_HASH, WRITE_SB_HASH_SUCCEEDED, progress, _hash); + if (attr.sb_idx < MAX_SUPERBLOCK_INDEX) + attr.sb_idx++; else - _sb_idx = 0; + attr.sb_idx = 0; - _gen = _curr_gen; - _curr_gen++; + _gen = attr.curr_gen; + attr.curr_gen++; break; } + case WRITE_SB_HASH: progress |= _write_sb_hash.execute(attr.trust_anchor); break; case WRITE_SB_HASH_SUCCEEDED: - _sb.last_secured_generation = _gen; - _state = SECURE_SB_SUCCEEDED; + attr.sb.last_secured_generation = _gen; + _helper.mark_succeeded(progress); break; default: break; } + return progress; } -void Superblock_control_channel::_init_rekeying(bool &progress) +bool Superblock_control::Discard_snapshot::execute(Execute_attr const &attr) { - switch (_state) { - case REQ_SUBMITTED: + bool progress = false; + switch (_helper.state) { + case INIT: - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - if (_sb.state != Superblock::NORMAL) { - _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.id++; - _generate_req(CREATE_KEY_SUCCEEDED, progress, _sb.current_key.value); - break; - - case CREATE_KEY_SUCCEEDED: - - _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 SECURE_SB: _secure_sb(progress); break; - case SECURE_SB_SUCCEEDED: _mark_req_successful(progress); break; - default: break; - } -} - - -void Superblock_control_channel::_discard_snap(bool &progress) -{ - switch (_state) { - case REQ_SUBMITTED: - - for (Snapshot &snap : _sb.snapshots.items) - if (snap.valid && snap.gen == _req_ptr->_gen && snap.keep) + for (Snapshot &snap : attr.sb.snapshots.items) + if (snap.valid && snap.gen == _attr.in_gen && snap.keep) snap.keep = false; - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - _start_secure_sb(progress); - break; - - case SECURE_SB: _secure_sb(progress); break; - case SECURE_SB_SUCCEEDED: - - _req_ptr->_gen = _gen; - _mark_req_successful(progress); + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); break; + case SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; + case SECURE_SB_SUCCEEDED: _helper.mark_succeeded(progress); break; default: break; } + return progress; } -void Superblock_control_channel::_create_snap(bool &progress) +bool Superblock_control::Create_snapshot::execute(Execute_attr const &attr) { - switch (_state) { - case REQ_SUBMITTED: - - if (_sb.curr_snap().keep) { - _req_ptr->_gen = _sb.curr_snap().gen; - _mark_req_successful(progress); + bool progress = false; + switch (_helper.state) { + case INIT: + { + Snapshot &snap = attr.sb.curr_snap(); + if (snap.keep) { + _attr.out_gen = snap.gen; + _helper.mark_succeeded(progress); } else { - _sb.curr_snap().keep = true; - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - _start_secure_sb(progress); + snap.keep = true; + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); } break; - - case SECURE_SB: _secure_sb(progress); break; + } + case SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; case SECURE_SB_SUCCEEDED: - _req_ptr->_gen = _gen; - _mark_req_successful(progress); + _attr.out_gen = attr.sb.curr_snap().gen; + _helper.mark_succeeded(progress); break; default: break; } + return progress; } -void Superblock_control_channel::_sync(bool &progress) +bool Superblock_control::Synchronize::execute(Execute_attr const &attr) { - switch (_state) { - case REQ_SUBMITTED: + bool progress = false; + switch (_helper.state) { + case INIT: - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - _sb.last_secured_generation = _curr_gen; - _start_secure_sb(progress); + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + attr.sb.last_secured_generation = attr.curr_gen; + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); break; - case SECURE_SB: _secure_sb(progress); break; - case SECURE_SB_SUCCEEDED: _mark_req_successful(progress); break; + case SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; + case SECURE_SB_SUCCEEDED: _helper.mark_succeeded(progress); break; default: break; } + return progress; } -void Superblock_control_request::print(Output &out) const +bool Superblock_control::Initialize::execute(Execute_attr const &attr) { - 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 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; - + bool progress = false; + switch (_helper.state) { + case INIT: _read_sb_hash.generate(_helper, READ_SB_HASH, READ_SB_HASH_SUCCEEDED, progress, _hash); break; + case READ_SB_HASH: progress |= _read_sb_hash.execute(attr.trust_anchor); break; case READ_SB_HASH_SUCCEEDED: - _sb_idx = 0; - _generate_req(READ_SB_SUCCEEDED, progress, _sb_idx, _blk); + attr.sb_idx = 0; + _read_block.generate(_helper, READ_BLOCK, READ_BLOCK_SUCCEEDED, progress, attr.sb_idx, _blk); break; - case READ_SB_SUCCEEDED: + case READ_BLOCK: progress |= _read_block.execute(attr.block_io); break; + case READ_BLOCK_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); + attr.sb.copy_all_but_key_values_from(_sb_ciphertext); + _decrypt_key.generate(_helper, DECRYPT_KEY, DECRYPT_CURR_KEY_SUCCEEDED, progress, attr.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); + if (attr.sb_idx < MAX_SUPERBLOCK_INDEX) { + attr.sb_idx++; + _read_block.generate(_helper, READ_BLOCK, READ_BLOCK_SUCCEEDED, progress, attr.sb_idx, _blk); } else - _mark_req_failed(progress, "superblock not found"); - break; - - case DECRYPT_CURR_KEY_SUCCEEDED: - - _generate_req(ADD_CURR_KEY_SUCCEEDED, progress, _sb.current_key); + _helper.mark_failed(progress, "superblock not found"); break; + case DECRYPT_KEY: progress |= _decrypt_key.execute(attr.trust_anchor); break; + case DECRYPT_CURR_KEY_SUCCEEDED: _add_key.generate(_helper, ADD_KEY, ADD_CURR_KEY_SUCCEEDED, progress, attr.sb.current_key); break; + case ADD_KEY: progress |= _add_key.execute(attr.crypto); break; 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); + _decrypt_key.generate(_helper, DECRYPT_KEY, DECRYPT_PREV_KEY_SUCCEEDED, progress, attr.sb.previous_key.value, _sb_ciphertext.previous_key.value); else { - _curr_gen = _gen + 1; - _req_ptr->_sb_state = _sb.state; - _mark_req_successful(progress); + attr.curr_gen = _gen + 1; + _attr.out_sb_state = attr.sb.state; + _helper.mark_succeeded(progress); } break; - case DECRYPT_PREV_KEY_SUCCEEDED: - - _generate_req(ADD_PREV_KEY_SUCCEEDED, progress, _sb.previous_key); - break; - + case DECRYPT_PREV_KEY_SUCCEEDED: _add_key.generate(_helper, ADD_KEY, ADD_PREV_KEY_SUCCEEDED, progress, attr.sb.previous_key); break; case ADD_PREV_KEY_SUCCEEDED: - _curr_gen = _gen + 1; - _req_ptr->_sb_state = _sb.state; - _mark_req_successful(progress); + attr.curr_gen = _gen + 1; + _attr.out_sb_state = attr.sb.state; + _helper.mark_succeeded(progress); break; default: break; } + return progress; } -void Superblock_control_channel::_deinitialize(bool &progress) +bool Superblock_control::Deinitialize::execute(Execute_attr const &attr) { - switch (_state) { - case REQ_SUBMITTED: + bool progress = false; + switch (_helper.state) { + case INIT: - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - _sb.last_secured_generation = _curr_gen; - _start_secure_sb(progress); + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + attr.sb.last_secured_generation = attr.curr_gen; + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, 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 SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; + case SECURE_SB_SUCCEEDED: _remove_key.generate(_helper, REMOVE_KEY, REMOVE_CURR_KEY_SUCCEEDED, progress, attr.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); + if (attr.sb.state == Superblock::REKEYING) + _remove_key.generate(_helper, REMOVE_KEY, REMOVE_PREV_KEY_SUCCEEDED, progress, attr.sb.previous_key.id); else - _mark_req_successful(progress); + _helper.mark_succeeded(progress); break; + case REMOVE_KEY: progress |= _remove_key.execute(attr.crypto); break; case REMOVE_PREV_KEY_SUCCEEDED: - _sb.state = Superblock::INVALID; - _mark_req_successful(progress); + attr.sb.state = Superblock::INVALID; + _helper.mark_succeeded(progress); break; default: break; } -} - - -void Superblock_control_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - 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_each_channel([&] (Channel &chan) { - chan.execute(progress); }); + return progress; } @@ -624,26 +627,3 @@ Superblock_info Superblock_control::sb_info() const true, _sb.state == Superblock::REKEYING, _sb.state == Superblock::EXTENDING_FT, _sb.state == Superblock::EXTENDING_VBD }; } - - -void Superblock_control_channel::_request_submitted(Module_request &req) -{ - _req_ptr = static_cast(&req); - _state = REQ_SUBMITTED; -} - - -Superblock_control::Superblock_control() -{ - for (Module_channel_id id { 0 }; id < NUM_CHANNELS; id++) { - _channels[id].construct(id, _sb, _sb_idx, _curr_gen); - add_channel(*_channels[id]); - } -} - - -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 d3a8cb17c2..aeb2d547da 100644 --- a/repos/gems/src/lib/tresor/trust_anchor.cc +++ b/repos/gems/src/lib/tresor/trust_anchor.cc @@ -16,174 +16,132 @@ using namespace Tresor; -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_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) +bool Trust_anchor::Encrypt_key::execute(Trust_anchor::Attr const &ta_attr) { - switch (type) { - case CREATE_KEY: return "create_key"; - case ENCRYPT_KEY: return "encrypt_key"; - case DECRYPT_KEY: return "decrypt_key"; - case WRITE_HASH: return "write_hash"; - case READ_HASH: return "read_hash"; - case INITIALIZE: return "initialize"; - } - ASSERT_NEVER_REACHED; -} + bool progress = false; + switch (_helper.state) { + case INIT: + _file.construct(_helper.state, ta_attr.encrypt_file); + _helper.state = WRITE; + progress = true; + break; -void Trust_anchor_channel::_mark_req_failed(bool &progress, Error_string str) -{ - error("trust_anchor: request (", *_req_ptr, ") failed: ", str); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Trust_anchor_channel::_mark_req_successful(bool &progress) -{ - Request &req { *_req_ptr }; - req._success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -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; + case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { (char *)&_attr.in_key_plaintext, KEY_SIZE }, progress); break; + case WRITE_OK: _file->read(READ_OK, FILE_ERR, 0, { (char *)&_attr.out_key_ciphertext, KEY_SIZE }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; default: break; } + return progress; } -void Trust_anchor_channel::_create_key(bool &progress) +bool Trust_anchor::Decrypt_key::execute(Trust_anchor::Attr const &ta_attr) { - 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; + bool progress = false; + switch (_helper.state) { + case INIT: + + _file.construct(_helper.state, ta_attr.decrypt_file); + _helper.state = WRITE; + progress = true; + break; + + case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { (char *)&_attr.in_key_ciphertext, KEY_SIZE }, progress); break; + case WRITE_OK: _file->read(READ_OK, FILE_ERR, 0, { (char *)&_attr.out_key_plaintext, KEY_SIZE }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; default: break; } + return progress; } -void Trust_anchor_channel::_initialize(bool &progress) +bool Trust_anchor::Write_hash::execute(Trust_anchor::Attr const &ta_attr) { - 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; + bool progress = false; + switch (_helper.state) { + case INIT: + + _file.construct(_helper.state, ta_attr.hash_file); + _helper.state = WRITE; + progress = true; + break; + + case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { (char *)&_attr.in_hash, HASH_SIZE }, progress); break; + case WRITE_OK: _file->read(READ_OK, FILE_ERR, 0, { _result_buf, sizeof(_result_buf) }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; + default: break; + } + return progress; +} + + +bool Trust_anchor::Read_hash::execute(Trust_anchor::Attr const &ta_attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _file.construct(_helper.state, ta_attr.hash_file); + _helper.state = READ; + progress = true; + break; + + case READ: _file->read(READ_OK, FILE_ERR, 0, { (char *)&_attr.out_hash, HASH_SIZE }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; + default: break; + } + return progress; +} + + +bool Trust_anchor::Generate_key::execute(Trust_anchor::Attr const &ta_attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _file.construct(_helper.state, ta_attr.generate_key_file); + _helper.state = READ; + progress = true; + break; + + case READ: _file->read(READ_OK, FILE_ERR, 0, { (char *)&_attr.out_key_plaintext, KEY_SIZE }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; + default: break; + } + return progress; +} + + +bool Trust_anchor::Initialize::execute(Trust_anchor::Attr const &ta_attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _file.construct(_helper.state, ta_attr.initialize_file); + _helper.state = WRITE; + progress = true; + break; + + case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { _attr.in_passphrase.string(), _attr.in_passphrase.length() - 1 }, progress); break; + case WRITE_OK: _file->read(READ_OK, FILE_ERR, 0, { _result_buf, sizeof(_result_buf) }, progress); break; case READ_OK: if (strcmp(_result_buf, "ok", sizeof(_result_buf))) - _mark_req_failed(progress, { "trust anchor did not return \"ok\""}); + _helper.mark_failed(progress, {"trust anchor did not return \"ok\""}); else - _mark_req_successful(progress); + _helper.mark_succeeded(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + case FILE_ERR: _helper.mark_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; - - 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; - } -} - - -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_each_channel([&] (Channel &chan) { - chan.execute(progress); }); + return progress; } diff --git a/repos/gems/src/lib/tresor/vbd_check.cc b/repos/gems/src/lib/tresor/vbd_check.cc index 2a7f539477..cfbb7e9ed4 100644 --- a/repos/gems/src/lib/tresor/vbd_check.cc +++ b/repos/gems/src/lib/tresor/vbd_check.cc @@ -13,52 +13,31 @@ /* tresor includes */ #include -#include #include using namespace Tresor; -Vbd_check_request::Vbd_check_request(Module_id src_mod, Module_channel_id src_chan, Tree_root const &vbd, bool &success) -: - Module_request { src_mod, src_chan, VBD_CHECK }, _vbd { vbd }, _success { success } -{ } - - -void Vbd_check_channel::_generated_req_completed(State_uint state_uint) -{ - 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; -} - - -bool Vbd_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) +bool Vbd_check::Check::_execute_node(Block_io &block_io, Tree_level_index lvl, Tree_node_index node_idx, bool &progress) { 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: + switch (_helper.state) { + case 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" }); + _helper.mark_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"); + log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": expectedly invalid"); break; } if (node.gen == INITIAL_GENERATION) { @@ -66,33 +45,34 @@ bool Vbd_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node check_node = false; progress = true; if (VERBOSE_CHECK) - log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": uninitialized"); + log(Level_indent { lvl, _attr.in_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" }); + _helper.mark_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"); + log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": expectedly invalid"); break; } } - _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _blk); + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, node.pba, _blk); if (VERBOSE_CHECK) - log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, " (", node, + log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, " (", node, "): load to lvl ", lvl - 1); break; + case READ_BLK: progress |= _read_block.execute(block_io); 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" }); + _helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, ") has bad hash" }); break; } if (lvl == 1) @@ -103,10 +83,10 @@ bool Vbd_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node cn = true; } check_node = false; - _state = REQ_IN_PROGRESS; + _helper.state = IN_PROGRESS; progress = true; if (VERBOSE_CHECK) - log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": good hash"); + log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": good hash"); break; default: break; @@ -115,69 +95,24 @@ bool Vbd_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node } -void Vbd_check_channel::execute(bool &progress) +bool Vbd_check::Check::execute(Block_io &block_io) { - 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++) + bool progress = false; + if (_helper.state == INIT) { + for (Tree_level_index lvl { 1 }; lvl <= _attr.in_vbd.max_lvl + 1; lvl++) + for (Tree_node_index node_idx { 0 }; node_idx < _attr.in_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; + _num_remaining_leaves = _attr.in_vbd.num_leaves; + _t1_blks.items[_attr.in_vbd.max_lvl + 1].nodes[0] = _attr.in_vbd.t1_node(); + _check_node[_attr.in_vbd.max_lvl + 1][0] = true; + _helper.state = 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; + for (Tree_level_index lvl { 1 }; lvl <= _attr.in_vbd.max_lvl + 1; lvl++) + for (Tree_node_index node_idx { 0 }; node_idx < _attr.in_vbd.degree; node_idx++) + if (_execute_node(block_io, lvl, node_idx, progress)) + return progress; - _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; -} - - -void Vbd_check_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Vbd_check_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -Vbd_check::Vbd_check() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } -} - - -void Vbd_check::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); + _helper.mark_succeeded(progress); + return progress; } diff --git a/repos/gems/src/lib/tresor/vbd_initializer.cc b/repos/gems/src/lib/tresor/vbd_initializer.cc index 192036fcdf..3d8dee368b 100644 --- a/repos/gems/src/lib/tresor/vbd_initializer.cc +++ b/repos/gems/src/lib/tresor/vbd_initializer.cc @@ -13,20 +13,12 @@ */ /* tresor includes */ -#include #include #include using namespace Tresor; -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_mod, src_chan, VBD_INITIALIZER }, _vbd { vbd }, _pba_alloc { pba_alloc }, _success { success } -{ } - - -bool Vbd_initializer_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) +bool Vbd_initializer::Initialize::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) { Type_1_node &node = _t1_blks.items[lvl].nodes[node_idx]; Node_state &node_state = _node_states[lvl][node_idx]; @@ -58,8 +50,8 @@ bool Vbd_initializer_channel::_execute_node(Tree_level_index lvl, Tree_node_inde if (lvl == 1) if (_num_remaining_leaves) { node = { }; - if (!_req_ptr->_pba_alloc.alloc(node.pba)) { - _mark_req_failed(progress, "allocate pba"); + if (!_attr.in_out_pba_alloc.alloc(node.pba)) { + _helper.mark_failed(progress, "allocate pba"); break; } node_state = DONE; @@ -76,21 +68,20 @@ bool Vbd_initializer_channel::_execute_node(Tree_level_index lvl, Tree_node_inde } else { node = { }; - if (!_req_ptr->_pba_alloc.alloc(node.pba)) { - _mark_req_failed(progress, "allocate pba"); + if (!_attr.in_out_pba_alloc.alloc(node.pba)) { + _helper.mark_failed(progress, "allocate pba"); break; } _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; + _write_block.generate(_helper, WRITE_BLOCK, EXECUTE_NODES, progress, node.pba, _blk); + node_state = WRITING_BLOCK; if (VERBOSE_VBD_INIT) log("[vbd_init] node: ", lvl, " ", node_idx, " assign pba: ", node.pba); } break; - case WRITE_BLOCK: + case WRITING_BLOCK: ASSERT(lvl > 1); node_state = DONE; @@ -103,103 +94,47 @@ bool Vbd_initializer_channel::_execute_node(Tree_level_index lvl, Tree_node_inde } -void Vbd_initializer_channel::_generated_req_completed(State_uint state_uint) +bool Vbd_initializer::Initialize::execute(Block_io &block_io) { - 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; -} + bool progress = false; + switch (_helper.state) { + case INIT: - -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_channel::_mark_req_successful(bool &progress) -{ - _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; -} - - -void Vbd_initializer_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = SUBMITTED; -} - - -void Vbd_initializer_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - Request &req { *_req_ptr }; - switch (_state) { - case SUBMITTED: - - _num_remaining_leaves = req._vbd.num_leaves; + _num_remaining_leaves = _attr.in_tree_cfg.num_leaves; for (Tree_level_index lvl = 0; lvl < TREE_MAX_LEVEL; lvl++) - _reset_level(lvl, Vbd_initializer_channel::DONE); + _reset_level(lvl, Vbd_initializer::Initialize::DONE); - _node_states[req._vbd.max_lvl + 1][0] = Vbd_initializer_channel::INIT_BLOCK; - _state = EXECUTE_NODES; + _node_states[_attr.in_tree_cfg.max_lvl + 1][0] = Vbd_initializer::Initialize::INIT_BLOCK; + _helper.state = EXECUTE_NODES; progress = true; - return; + break; case EXECUTE_NODES: - 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++) + for (Tree_level_index lvl = 0; lvl <= _attr.in_tree_cfg.max_lvl + 1; lvl++) + for (Tree_node_index node_idx = 0; node_idx < _attr.in_tree_cfg.degree; node_idx++) if (_execute_node(lvl, node_idx, progress)) - return; + return progress; if (_num_remaining_leaves) - _mark_req_failed(progress, "leaves remaining"); - else - _mark_req_successful(progress); - return; + _helper.mark_failed(progress, "leaves remaining"); + else { + _attr.out_tree_root = _t1_blks.items[_attr.in_tree_cfg.max_lvl + 1].nodes[0]; + _helper.mark_succeeded(progress); + } + break; - default: return; + case WRITE_BLOCK: progress |= _write_block.execute(block_io); break; + default: break; } + return progress; } -void Vbd_initializer_channel::_reset_level(Tree_level_index lvl, Node_state state) +void Vbd_initializer::Initialize::_reset_level(Tree_level_index lvl, Node_state state) { 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() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } -} - - -void Vbd_initializer::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} diff --git a/repos/gems/src/lib/tresor/virtual_block_device.cc b/repos/gems/src/lib/tresor/virtual_block_device.cc index 035247e95b..2ffdb87a1b 100644 --- a/repos/gems/src/lib/tresor/virtual_block_device.cc +++ b/repos/gems/src/lib/tresor/virtual_block_device.cc @@ -14,161 +14,167 @@ /* tresor includes */ #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, Virtual_block_address rekeying_vba) -: - 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 }, _rekeying_vba { rekeying_vba }, _success { success } -{ } - - -char const *Virtual_block_device_request::type_to_string(Type op) -{ - switch (op) { - case READ_VBA: return "read_vba"; - case WRITE_VBA: return "write_vba"; - case REKEY_VBA: return "rekey_vba"; - case EXTENSION_STEP: return "extension_step"; - } - ASSERT_NEVER_REACHED; -} - - -void Virtual_block_device_channel::_generated_req_completed(State_uint state_uint) -{ - 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; - } - _state = (State)state_uint; -} - - -void Virtual_block_device_channel::_generate_write_blk_req(bool &progress) +bool Virtual_block_device::Read_vba::_check_and_decode_read_blk(bool &progress) { + Hash const *node_hash_ptr; + calc_hash(_blk, _hash); 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); + if (_lvl < _attr.in_snap.max_level) + node_hash_ptr = &_t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree).hash; + else + node_hash_ptr = &_attr.in_snap.hash; + } else { + Type_1_node &node = _t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree); + if (node.gen == INITIAL_GENERATION) + return true; + + node_hash_ptr = &node.hash; + } + if (_hash != *node_hash_ptr) { + _helper.mark_failed(progress, "check hash of read block"); + return false; + } + if (_lvl) + _t1_blks.items[_lvl].decode_from_blk(_blk); + + return true; } -void Virtual_block_device_channel::_read_vba(bool &progress) +bool Virtual_block_device::Read_vba::execute(Client_data_interface &client_data, Block_io &block_io, Crypto &crypto) { - Request &req { *_req_ptr }; - switch (_state) { - case SUBMITTED: + bool progress = false; + switch (_helper.state) { + case INIT: - _snap_idx = req._curr_snap_idx; - _vba = req._vba; - _lvl = snap().max_level; - _generate_req(READ_BLK_SUCCEEDED, progress, snap().pba, _encoded_blk); + _lvl = _attr.in_snap.max_level; + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _attr.in_snap.pba, _blk); if (VERBOSE_READ_VBA) - log(" load branch:\n ", Branch_lvl_prefix("root: "), snap()); + log(" load branch:\n ", Branch_lvl_prefix("root: "), _attr.in_snap); break; + case READ_BLK: progress |= _read_block.execute(block_io); break; case READ_BLK_SUCCEEDED: { if (!_check_and_decode_read_blk(progress)) break; if (!_lvl) { - _mark_req_successful(progress); + if (VERBOSE_READ_VBA) + log(" ", Branch_lvl_prefix("ciphertext: "), _blk, " ", hash(_blk)); + + _decrypt_block.generate( + _helper, DECRYPT_BLOCK, DECRYPT_BLOCK_SUCCEEDED, progress, _attr.in_key_id, _new_pbas.pbas[_lvl], _blk); break; } - Type_1_node &node { _node(_lvl, req._vba) }; + Type_1_node &node { _t1_blks.node(_attr.in_vba, _lvl, _attr.in_vbd_degree) }; if (VERBOSE_READ_VBA) - log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", _node_idx(_lvl, req._vba), ": "), node); + log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", tree_node_index(_attr.in_vba, _lvl, _attr.in_vbd_degree), ": "), node); - if (_lvl > 1) - _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _encoded_blk); + _lvl--; + _new_pbas.pbas[_lvl] = node.pba; + if (_lvl) + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _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); + memset(&_blk, 0, BLOCK_SIZE); + _helper.state = DECRYPT_BLOCK_SUCCEEDED; + progress = true; } else - _generate_req( - READ_BLK_SUCCEEDED, progress, node.pba, _vba, req._curr_key_id, - req._client_req_tag, req._client_req_offset, _hash); - _lvl--; + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _blk); break; } + case DECRYPT_BLOCK: progress |= _decrypt_block.execute(crypto); break; + case DECRYPT_BLOCK_SUCCEEDED: + + if (VERBOSE_READ_VBA) + log(" ", Branch_lvl_prefix("plaintext: "), _blk, " ", hash(_blk)); + + client_data.supply_data( + {_attr.in_client_req_offset, _attr.in_client_req_tag, _new_pbas.pbas[_lvl], _attr.in_vba, _blk}); + + _helper.mark_succeeded(progress); + break; + default: break; } + return progress; } -void Virtual_block_device_channel::_update_nodes_of_branch_of_written_vba() +void Virtual_block_device::Rekey_vba::_start_alloc_pbas(bool &progress, Free_tree::Allocate_pbas::Application application) { - 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()); + _alloc_pbas.generate( + _helper, ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED, progress, _attr.in_out_ft, _attr.in_out_mt, _attr.in_out_snapshots, + _attr.in_last_secured_gen, _attr.in_curr_gen, _free_gen, _num_blks, _new_pbas, _t1_nodes, + _attr.in_out_snapshots.items[_snap_idx].max_level, _attr.in_vba, _attr.in_vbd_degree, _attr.in_vbd_highest_vba, true, + _attr.in_prev_key_id, _attr.in_curr_key_id, _attr.in_vba, application); } -bool Virtual_block_device_channel::_check_and_decode_read_blk(bool &progress) +void Virtual_block_device::Rekey_vba::_generate_write_blk_req(bool &progress) { - Request &req { *_req_ptr }; - Hash *node_hash_ptr; + if (_lvl) { + _t1_blks.items[_lvl].encode_to_blk(_encoded_blk); + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _encoded_blk); + } else + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _data_blk); +} + + +void Virtual_block_device::Rekey_vba::_generate_ft_alloc_req_for_rekeying(Tree_level_index min_lvl, bool &progress) +{ + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + ASSERT(min_lvl <= snap.max_level); + _num_blks = 0; + if (_first_snapshot) + _free_gen = _attr.in_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] = _t1_blks.node(_attr.in_vba, lvl + 1, _attr.in_vbd_degree); + } else { + Type_1_node &node { _t1_blks.node(_attr.in_vba, lvl + 1, _attr.in_vbd_degree) }; + _t1_nodes.nodes[lvl] = { _new_pbas.pbas[lvl], node.gen, node.hash}; + } + + _start_alloc_pbas(progress, _first_snapshot ? + Free_tree::Allocate_pbas::REKEYING_IN_CURRENT_GENERATION : + Free_tree::Allocate_pbas::REKEYING_IN_OLDER_GENERATION); +} + + +bool Virtual_block_device::Rekey_vba::_check_and_decode_read_blk(bool &progress) +{ + Hash const *node_hash_ptr; if (_lvl) { calc_hash(_encoded_blk, _hash); - if (_lvl < snap().max_level) - node_hash_ptr = &_node(_lvl + 1, _vba).hash; + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + if (_lvl < snap.max_level) + node_hash_ptr = &_t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree).hash; else - node_hash_ptr = &snap().hash; + node_hash_ptr = &snap.hash; } else { - Type_1_node &node { _node(_lvl + 1, _vba) }; - if (req._type == Request::READ_VBA) { - if (node.gen == INITIAL_GENERATION) - return true; - } else - calc_hash(_data_blk, _hash); - + Type_1_node &node { _t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree) }; + calc_hash(_data_blk, _hash); node_hash_ptr = &node.hash; } if (_hash != *node_hash_ptr) { - _mark_req_failed(progress, "check hash of read block"); + _helper.mark_failed(progress, "check hash of read block"); return false; } if (_lvl) @@ -178,230 +184,33 @@ bool Virtual_block_device_channel::_check_and_decode_read_blk(bool &progress) } -Tree_node_index Virtual_block_device_channel::_node_idx(Tree_level_index lvl, Virtual_block_address vba) const +bool Virtual_block_device::Rekey_vba::execute(Block_io &block_io, Crypto &crypto, Free_tree &free_tree, Meta_tree &meta_tree) { - return t1_node_idx_for_vba(vba, lvl, _req_ptr->_snap_degr); -} - - -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)]; -} - - -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; - } - } -} - - -void Virtual_block_device_channel::_generate_ft_alloc_req_for_write_vba(bool &progress) -{ - 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 - _t1_nodes.nodes[lvl] = _node(lvl + 1, _vba); - - _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 READ_BLK_SUCCEEDED: - - if (!_check_and_decode_read_blk(progress)) - break; - - if (VERBOSE_WRITE_VBA) - log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", _node_idx(_lvl, _vba), ": "), _node(_lvl, _vba)); - - 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, _hash); - } - _lvl--; - break; - - case ALLOC_PBAS_SUCCEEDED: - - if (VERBOSE_WRITE_VBA) - log(" alloc pba", _num_blks > 1 ? "s" : "", ": ", Pba_allocation(_t1_nodes, _new_pbas)); - - _generate_req( - WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[0], _vba, req._curr_key_id, - req._client_req_tag, req._client_req_offset, _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_channel::_mark_req_failed(bool &progress, char const *str) -{ - 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_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -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; - } - } - } - 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(); + bool progress = false; + switch (_helper.state) { + case INIT: + { + _snap_idx = _attr.in_out_snapshots.newest_snap_idx(); + Snapshot &snap = _attr.in_out_snapshots.items[_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); + _lvl = snap.max_level; + _old_pbas.pbas[_lvl] = snap.pba; + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, snap.pba, _encoded_blk); if (VERBOSE_REKEYING) log(" snapshot ", _snap_idx, ":\n load branch:\n ", - Branch_lvl_prefix("root: "), snap()); + Branch_lvl_prefix("root: "), snap); break; - + } + case READ_BLK: progress |= _read_block.execute(block_io); break; case READ_BLK_SUCCEEDED: if (!_check_and_decode_read_blk(progress)) break; if (_lvl) { - Type_1_node &node { _node(_lvl, req._vba) }; + Type_1_node &node { _t1_blks.node(_attr.in_vba, _lvl, _attr.in_vbd_degree) }; if (VERBOSE_REKEYING) - log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", _node_idx(_lvl, req._vba), ": "), node); + log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", tree_node_index(_attr.in_vba, _lvl, _attr.in_vbd_degree), ": "), node); if (!_first_snapshot && _old_pbas.pbas[_lvl - 1] == node.pba) { @@ -420,23 +229,24 @@ void Virtual_block_device_channel::_rekey_vba(bool &progress) } else { _lvl--; _old_pbas.pbas[_lvl] = node.pba; - _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _lvl ? _encoded_blk : _data_blk); + _read_block.generate(_helper, READ_BLK, 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); + _decrypt_block.generate(_helper, DECRYPT_BLOCK, DECRYPT_BLOCK_SUCCEEDED, progress, _attr.in_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: + case DECRYPT_BLOCK: progress |= _decrypt_block.execute(crypto); break; + case DECRYPT_BLOCK_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: progress |= _alloc_pbas.execute(free_tree, block_io, meta_tree); break; case ALLOC_PBAS_SUCCEEDED: if (VERBOSE_REKEYING) @@ -447,80 +257,400 @@ void Virtual_block_device_channel::_rekey_vba(bool &progress) log(" update branch:"); _lvl--; - _state = WRITE_BLK_SUCCEEDED; + _helper.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); + _encrypt_block.generate( + _helper, ENCRYPT_BLOCK, ENCRYPT_BLOCK_SUCCEEDED, progress, _attr.in_curr_key_id, _new_pbas.pbas[0], _data_blk); break; - case ENCRYPT_LEAF_DATA_SUCCEEDED: + case ENCRYPT_BLOCK: progress |= _encrypt_block.execute(crypto); break; + case ENCRYPT_BLOCK_SUCCEEDED: _generate_write_blk_req(progress); if (VERBOSE_REKEYING) log(" update branch:\n ", Branch_lvl_prefix("leaf data: "), _data_blk); break; + case WRITE_BLK: progress |= _write_block.execute(block_io); break; case WRITE_BLK_SUCCEEDED: - - if (_lvl < snap().max_level) { - Type_1_node &node { _node(_lvl + 1, req._vba) }; + { + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + if (_lvl < snap.max_level) { + Type_1_node &node { _t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree) }; 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); + log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", tree_node_index(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree), ": "), node); } else { - snap().pba = _new_pbas.pbas[_lvl]; - calc_hash(_encoded_blk, snap().hash); + snap.pba = _new_pbas.pbas[_lvl]; + calc_hash(_encoded_blk, snap.hash); if (VERBOSE_REKEYING) - log(" ", Branch_lvl_prefix("root: "), snap()); + log(" ", Branch_lvl_prefix("root: "), snap); Snapshot_index snap_idx; if (_find_next_snap_to_rekey_vba_at(snap_idx)) { _snap_idx = snap_idx; + Snapshot &next_snap = _attr.in_out_snapshots.items[_snap_idx]; _first_snapshot = false; - _lvl = snap().max_level; - if (_old_pbas.pbas[_lvl] == snap().pba) + _lvl = next_snap.max_level; + if (_old_pbas.pbas[_lvl] == next_snap.pba) progress = true; else { - _old_pbas.pbas[_lvl] = snap().pba; - _generate_req(READ_BLK_SUCCEEDED, progress, snap().pba, _encoded_blk); + _old_pbas.pbas[_lvl] = next_snap.pba; + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, next_snap.pba, _encoded_blk); if (VERBOSE_REKEYING) log(" snapshot ", _snap_idx, ":\n load branch:\n ", - Branch_lvl_prefix("root: "), snap()); + Branch_lvl_prefix("root: "), next_snap); } } else - _mark_req_successful(progress); + _helper.mark_succeeded(progress); } break; - + } default: break; } + return progress; +} + + +bool Virtual_block_device::Rekey_vba::_find_next_snap_to_rekey_vba_at(Snapshot_index &result) const +{ + bool result_valid { false }; + Snapshot &curr_snap { _attr.in_out_snapshots.items[_snap_idx] }; + for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { + Snapshot const &snap { _attr.in_out_snapshots.items[idx] }; + if (snap.valid && snap.contains_vba(_attr.in_vba)) { + if (result_valid) { + if (snap.gen < curr_snap.gen && snap.gen > _attr.in_out_snapshots.items[result].gen) + result = idx; + } else + if (snap.gen < curr_snap.gen) { + result = idx; + result_valid = true; + } + } + } + return result_valid; +} + + +void Virtual_block_device::Write_vba::_update_nodes_of_branch_of_written_vba() +{ + Type_1_node &node { _t1_blks.node(_attr.in_vba, 1, _attr.in_vbd_degree) }; + node = Type_1_node { _new_pbas.pbas[0], _attr.in_curr_gen, _hash }; + if (VERBOSE_WRITE_VBA) + log(" ", Branch_lvl_prefix("lvl 1 node ", tree_node_index(_attr.in_vba, 1, _attr.in_vbd_degree), ": "), node); + + for (Tree_level_index lvl = 1; lvl < _attr.in_out_snap.max_level; lvl++) { + Type_1_node &node { _t1_blks.node(_attr.in_vba, lvl + 1, _attr.in_vbd_degree) }; + node.pba = _new_pbas.pbas[lvl]; + node.gen = _attr.in_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 ", tree_node_index(_attr.in_vba, lvl + 1, _attr.in_vbd_degree), ": "), node); + } + _attr.in_out_snap.pba = _new_pbas.pbas[_attr.in_out_snap.max_level]; + _attr.in_out_snap.gen = _attr.in_curr_gen; + _t1_blks.items[_attr.in_out_snap.max_level].encode_to_blk(_encoded_blk); + calc_hash(_encoded_blk, _attr.in_out_snap.hash); + if (VERBOSE_WRITE_VBA) + log(" ", Branch_lvl_prefix("root: "), _attr.in_out_snap); +} + + +bool Virtual_block_device::Write_vba::_check_and_decode_read_blk(bool &progress) +{ + Hash *node_hash_ptr; + if (_lvl) { + calc_hash(_encoded_blk, _hash); + if (_lvl < _attr.in_out_snap.max_level) + node_hash_ptr = &_t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree).hash; + else + node_hash_ptr = &_attr.in_out_snap.hash; + } else { + Type_1_node &node { _t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree) }; + calc_hash(_data_blk, _hash); + node_hash_ptr = &node.hash; + } + if (_hash != *node_hash_ptr) { + _helper.mark_failed(progress, "check hash of read block"); + return false; + } + if (_lvl) + _t1_blks.items[_lvl].decode_from_blk(_encoded_blk); + + return true; +} + + +void Virtual_block_device::Write_vba::_set_new_pbas_and_num_blks_for_alloc() +{ + _num_blks = 0; + for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) { + if (lvl > _attr.in_out_snap.max_level) + _new_pbas.pbas[lvl] = 0; + else if (lvl == _attr.in_out_snap.max_level) { + if (_attr.in_out_snap.gen < _attr.in_curr_gen) { + _num_blks++; + _new_pbas.pbas[lvl] = 0; + } else if (_attr.in_out_snap.gen == _attr.in_curr_gen) + _new_pbas.pbas[lvl] = _attr.in_out_snap.pba; + else + ASSERT_NEVER_REACHED; + } else { + Type_1_node const &node { _t1_blks.node(_attr.in_vba, lvl + 1, _attr.in_vbd_degree) }; + if (node.gen < _attr.in_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 == _attr.in_curr_gen) + _new_pbas.pbas[lvl] = node.pba; + else + ASSERT_NEVER_REACHED; + } + } } -void Virtual_block_device_channel::_add_new_root_lvl_to_snap() +bool Virtual_block_device::Write_vba::execute(Client_data_interface &client_data, Block_io &block_io, Free_tree &free_tree, Meta_tree &meta_tree, Crypto &crypto) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _lvl = _attr.in_out_snap.max_level; + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _attr.in_out_snap.pba, _encoded_blk); + if (VERBOSE_WRITE_VBA) + log(" load branch:\n ", Branch_lvl_prefix("root: "), _attr.in_out_snap); + break; + + case READ_BLK: progress |= _read_block.execute(block_io); break; + case READ_BLK_SUCCEEDED: + { + if (!_check_and_decode_read_blk(progress)) + break; + + Type_1_node &node = _t1_blks.node(_attr.in_vba, _lvl, _attr.in_vbd_degree); + if (VERBOSE_WRITE_VBA) + log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", tree_node_index(_attr.in_vba, _lvl, _attr.in_vbd_degree), ": "), node); + + if (_lvl > 1) + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, node.pba, _encoded_blk); + else { + _set_new_pbas_and_num_blks_for_alloc(); + if (_num_blks) + _generate_ft_alloc_req_for_write_vba(progress); + else { + client_data.obtain_data({_attr.in_client_req_offset, _attr.in_client_req_tag, _new_pbas.pbas[0], _attr.in_vba, _data_blk}); + _encrypt_block.generate( + _helper, ENCRYPT_BLOCK, ENCRYPT_BLOCK_SUCCEEDED, progress, _attr.in_curr_key_id, _new_pbas.pbas[0], _data_blk); + } + } + _lvl--; + break; + } + case ALLOC_PBAS: progress |= _alloc_pbas.execute(free_tree, block_io, meta_tree); break; + case ALLOC_PBAS_SUCCEEDED: + + if (VERBOSE_WRITE_VBA) + log(" alloc pba", _num_blks > 1 ? "s" : "", ": ", Pba_allocation(_t1_nodes, _new_pbas)); + + client_data.obtain_data({_attr.in_client_req_offset, _attr.in_client_req_tag, _new_pbas.pbas[0], _attr.in_vba, _data_blk}); + _encrypt_block.generate( + _helper, ENCRYPT_BLOCK, ENCRYPT_BLOCK_SUCCEEDED, progress, _attr.in_curr_key_id, _new_pbas.pbas[0], _data_blk); + break; + + case ENCRYPT_BLOCK: progress |= _encrypt_block.execute(crypto); break; + case ENCRYPT_BLOCK_SUCCEEDED: + + calc_hash(_data_blk, _hash); + _generate_write_blk_req(progress); + break; + + case WRITE_BLK: progress |= _write_block.execute(block_io); break; + case WRITE_BLK_SUCCEEDED: + + if (!_lvl) + _update_nodes_of_branch_of_written_vba(); + + if (_lvl < _attr.in_out_snap.max_level) { + _lvl++; + _generate_write_blk_req(progress); + } else + _helper.mark_succeeded(progress); + break; + + default: break; + } + return progress; +} + + +void Virtual_block_device::Write_vba::_generate_ft_alloc_req_for_write_vba(bool &progress) +{ + for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) + if (lvl > _attr.in_out_snap.max_level) + _t1_nodes.nodes[lvl] = Type_1_node { }; + else if (lvl == _attr.in_out_snap.max_level) + _t1_nodes.nodes[lvl] = Type_1_node { _attr.in_out_snap.pba, _attr.in_out_snap.gen, _attr.in_out_snap.hash }; + else + _t1_nodes.nodes[lvl] = _t1_blks.node(_attr.in_vba, lvl + 1, _attr.in_vbd_degree); + + _free_gen = _attr.in_curr_gen; + _alloc_pbas.generate( + _helper, ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED, progress, _attr.in_out_ft, _attr.in_out_mt, _attr.in_snapshots, + _attr.in_last_secured_gen, _attr.in_curr_gen, _free_gen, _num_blks, _new_pbas, _t1_nodes, + _attr.in_out_snap.max_level, _attr.in_vba, _attr.in_vbd_degree, _attr.in_vbd_highest_vba, _attr.in_rekeying, + _attr.in_prev_key_id, 0, _attr.in_rekeying_vba, Free_tree::Allocate_pbas::NON_REKEYING); +} + + +void Virtual_block_device::Write_vba::_generate_write_blk_req(bool &progress) +{ + if (_lvl) { + _t1_blks.items[_lvl].encode_to_blk(_encoded_blk); + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _encoded_blk); + } else + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _data_blk); +} + + +bool Virtual_block_device::Extend_tree::execute(Block_io &block_io, Free_tree &free_tree, Meta_tree &meta_tree) +{ + bool progress = false; + switch (_helper.state) { + case State::INIT: + { + _attr.out_num_leaves = 0; + _snap_idx = _attr.in_out_snapshots.newest_snap_idx(); + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + _vba = snap.nr_of_leaves; + _lvl = snap.max_level; + _old_pbas.pbas[_lvl] = snap.pba; + if (_vba <= tree_max_max_vba(_attr.in_snap_degr, snap.max_level)) { + _read_block.generate(_helper, READ_BLK, 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(_attr.in_out_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: progress |= _read_block.execute(block_io); break; + case READ_BLK_SUCCEEDED: + { + _t1_blks.items[_lvl].decode_from_blk(_encoded_blk); + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + if (_lvl == snap.max_level) { + if (!check_hash(_encoded_blk, snap.hash)) { + _helper.mark_failed(progress, "check root node hash"); + break; + } + } else { + if (!check_hash(_encoded_blk, _t1_blks.node(_vba, _lvl + 1, _attr.in_vbd_degree).hash)) { + _helper.mark_failed(progress, "check inner node hash"); + break; + } + } + Tree_node_index node_idx { tree_node_index(_vba, _lvl, _attr.in_vbd_degree) }; + if (_lvl > 1) { + Type_1_node &node { _t1_blks.node(_vba, _lvl, _attr.in_vbd_degree) }; + if (node.valid()) { + _old_pbas.pbas[_lvl - 1] = node.pba; + _read_block.generate(_helper, READ_BLK, 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 ALLOC_PBAS: progress |= _alloc_pbas.execute(free_tree, block_io, meta_tree); break; + case ALLOC_PBAS_SUCCEEDED: + { + if (VERBOSE_VBD_EXTENSION) { + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + 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]); + + log(" write 1 lvl ", _lvl, " pba ", _new_pbas.pbas[_lvl]); + } + _generate_write_blk_req(progress); + break; + } + case WRITE_BLK: progress |= _write_block.execute(block_io); break; + case WRITE_BLK_SUCCEEDED: + { + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + if (_lvl < snap.max_level) { + _lvl++; + Type_1_node &node { _t1_blks.node(_vba, _lvl, _attr.in_vbd_degree) }; + calc_hash(_encoded_blk, node.hash); + node.pba = _new_pbas.pbas[_lvl - 1]; + _generate_write_blk_req(progress); + if (VERBOSE_VBD_EXTENSION) + log(" update lvl ", _lvl, " node ", tree_node_index(_vba, _lvl, _attr.in_vbd_degree), " ", node, + "\n write 2 lvl ", _lvl, " pba ", _new_pbas.pbas[_lvl]); + } else { + if (snap.gen < _attr.in_curr_gen) { + _snap_idx = _attr.in_out_snapshots.alloc_idx(_attr.in_curr_gen, _attr.in_last_secured_gen); + if (VERBOSE_VBD_EXTENSION) + log(" new snap ", _snap_idx); + } + Snapshot &new_snap = _attr.in_out_snapshots.items[_snap_idx]; + Number_of_leaves num_leaves { snap.nr_of_leaves + _attr.out_num_leaves }; + new_snap = { { }, _new_pbas.pbas[_lvl], _attr.in_curr_gen, num_leaves, snap.max_level, true, 0, false }; + calc_hash(_encoded_blk, new_snap.hash); + _helper.mark_succeeded(progress); + if (VERBOSE_VBD_EXTENSION) + log(" update snap ", _snap_idx, " ", new_snap); + } + break; + } + default: break; + } + return progress; +} + + +void Virtual_block_device::Extend_tree::_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 }; + Snapshot *snap { _attr.in_out_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 (snap[idx].gen < _attr.in_curr_gen) { + idx = _attr.in_out_snapshots.alloc_idx(_attr.in_curr_gen, _attr.in_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, + { }, alloc_pba_from_range(_attr.in_out_first_pba, _attr.in_out_num_pbas), _attr.in_curr_gen, snap[old_idx].nr_of_leaves, new_lvl, true, 0, false }; if (VERBOSE_VBD_EXTENSION) @@ -528,27 +658,26 @@ void Virtual_block_device_channel::_add_new_root_lvl_to_snap() } -void Virtual_block_device_channel::_add_new_branch_to_snap(Tree_level_index mount_lvl, Tree_node_index mount_node_idx) +void Virtual_block_device::Extend_tree::_add_new_branch_to_snap(Tree_level_index mount_lvl, Tree_node_index mount_node_idx) { - Request &req { *_req_ptr }; - req._num_leaves = 0; + _attr.out_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) + if (!_attr.in_out_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) + if (!_attr.in_out_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, { } }; + node = { alloc_pba_from_range(_attr.in_out_first_pba, _attr.in_out_num_pbas), INITIAL_GENERATION, { } }; if (VERBOSE_VBD_EXTENSION) log(" update lvl ", lvl, " node ", node_idx, " ", node); @@ -558,38 +687,48 @@ void Virtual_block_device_channel::_add_new_branch_to_snap(Tree_level_index moun if (!try_add_node_at_lvl_and_node_idx()) return; } else - for (; node_idx < req._snap_degr; node_idx++) { + for (; node_idx < _attr.in_snap_degr; node_idx++) { if (!try_add_node_at_lvl_and_node_idx()) return; - req._num_leaves++; + _attr.out_num_leaves++; } } } -void Virtual_block_device_channel::_set_new_pbas_identical_to_curr_pbas() +void Virtual_block_device::Extend_tree::_set_new_pbas_identical_to_curr_pbas() { + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; for (Tree_level_index lvl { 0 }; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) - if (lvl > snap().max_level) + if (lvl > snap.max_level) _new_pbas.pbas[lvl] = 0; - else if (lvl == snap().max_level) - _new_pbas.pbas[lvl] = snap().pba; + else if (lvl == snap.max_level) + _new_pbas.pbas[lvl] = snap.pba; else - _new_pbas.pbas[lvl] = _node(lvl + 1, _vba).pba; + _new_pbas.pbas[lvl] = _t1_blks.node(_vba, lvl + 1, _attr.in_vbd_degree).pba; } -void Virtual_block_device_channel::_generate_ft_alloc_req_for_resizing(Tree_level_index min_lvl, bool &progress) +void Virtual_block_device::Extend_tree::_generate_write_blk_req(bool &progress) { - Request &req { *_req_ptr }; - Snapshot &snap { req._snapshots.items[_snap_idx] }; + if (_lvl) { + _t1_blks.items[_lvl].encode_to_blk(_encoded_blk); + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _encoded_blk); + } else + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _data_blk); +} + + +void Virtual_block_device::Extend_tree::_generate_ft_alloc_req_for_resizing(Tree_level_index min_lvl, bool &progress) +{ + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; if (min_lvl > snap.max_level) { - _mark_req_failed(progress, "check parent lvl for alloc"); + _helper.mark_failed(progress, "check parent lvl for alloc"); return; } _num_blks = 0; - _free_gen = req._curr_gen; + _free_gen = _attr.in_curr_gen; for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) { if (lvl > snap.max_level) { @@ -600,7 +739,7 @@ void Virtual_block_device_channel::_generate_ft_alloc_req_for_resizing(Tree_leve _new_pbas.pbas[lvl] = 0; _t1_nodes.nodes[lvl] = { snap.pba, snap.gen, snap.hash }; } else { - Type_1_node &node { _node(lvl + 1, _vba) }; + Type_1_node &node { _t1_blks.node(_vba, lvl + 1, _attr.in_vbd_degree) }; if (lvl >= min_lvl) { _num_blks++; _new_pbas.pbas[lvl] = 0; @@ -622,155 +761,9 @@ void Virtual_block_device_channel::_generate_ft_alloc_req_for_resizing(Tree_leve } } } - _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 { - if (!check_hash(_encoded_blk, _node(_lvl + 1, _vba).hash)) { - _mark_req_failed(progress, "check inner node hash"); - break; - } - } - 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 ALLOC_PBAS_SUCCEEDED: - { - if (VERBOSE_VBD_EXTENSION) { - 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]); - - log(" write 1 lvl ", _lvl, " pba ", _new_pbas.pbas[_lvl]); - } - _generate_write_blk_req(progress); - break; - } - case WRITE_BLK_SUCCEEDED: - { - 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(" 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()); - } - break; - } - default: 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_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} - - -void Virtual_block_device_channel::_generate_ft_req(State complete_state, bool progress, Free_tree_request::Type type) -{ - 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, req._rekeying_vba, *(Physical_block_address*)0, - *(Number_of_blocks*)0); -} - - -Virtual_block_device::Virtual_block_device() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } + _alloc_pbas.generate( + _helper, ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED, progress, _attr.in_out_ft, _attr.in_out_mt, _attr.in_out_snapshots, + _attr.in_last_secured_gen, _attr.in_curr_gen, _free_gen, _num_blks, _new_pbas, _t1_nodes, + snap.max_level, _vba, _attr.in_vbd_degree, _attr.in_vbd_highest_vba, _attr.in_rekeying, + _attr.in_prev_key_id, 0, _attr.in_rekeying_vba, Free_tree::Allocate_pbas::NON_REKEYING); } diff --git a/repos/gems/src/lib/vfs/tresor/splitter.cc b/repos/gems/src/lib/vfs/tresor/splitter.cc deleted file mode 100644 index caabf35828..0000000000 --- a/repos/gems/src/lib/vfs/tresor/splitter.cc +++ /dev/null @@ -1,225 +0,0 @@ -/* - * \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 index bf244687b9..ff6fd528e0 100644 --- a/repos/gems/src/lib/vfs/tresor/splitter.h +++ b/repos/gems/src/lib/vfs/tresor/splitter.h @@ -16,141 +16,393 @@ #define _TRESOR__IO_SPLITTER_H_ /* tresor includes */ -#include +#include -namespace Tresor { +namespace Tresor { class Splitter; } - 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 +struct Tresor::Splitter : Noncopyable { - friend class Splitter_channel; - public: - enum Operation { READ, WRITE }; + class Read : Noncopyable + { + public: + + using Module = Splitter; + + struct Attr + { + Request_offset const in_off; + Generation const in_gen; + char *const in_buf_start; + size_t const in_buf_num_bytes; + }; + + struct Execute_attr + { + Superblock_control &sb_control; + Virtual_block_device &vbd; + Client_data_interface &client_data; + Block_io &block_io; + Crypto &crypto; + }; + + private: + + enum State { + INIT, COMPLETE, READ_FIRST_VBA, READ_FIRST_VBA_SUCCEEDED, READ_LAST_VBA, READ_LAST_VBA_SUCCEEDED, + READ_MIDDLE_VBAS, READ_MIDDLE_VBAS_SUCCEEDED }; + + Request_helper _helper; + Attr const _attr; + addr_t _curr_off { }; + addr_t _curr_buf_addr { }; + Block _blk { }; + Generation _gen { }; + Constructible _read_vbas { }; + + Virtual_block_address _curr_vba() const { return (Virtual_block_address)(_curr_off / BLOCK_SIZE); } + + void _generate_read(State target_state, bool &progress) + { + Number_of_blocks num_blocks = + target_state == READ_MIDDLE_VBAS ? _num_remaining_bytes() / BLOCK_SIZE : 1; + + _read_vbas.construct(Superblock_control::Read_vbas::Attr{_curr_vba(), num_blocks, 0, 0}); + _helper.state = target_state; + progress = true; + } + + bool _execute_read(State succeeded_state, Execute_attr const &attr) + { + bool progress = attr.sb_control.execute(*_read_vbas, attr.vbd, attr.client_data, attr.block_io, attr.crypto); + if (_read_vbas->complete()) { + if (_read_vbas->success()) + _helper.generated_req_succeeded(succeeded_state, progress); + else + _helper.generated_req_failed(progress); + } + return progress; + } + + addr_t _curr_buf_off() const + { + ASSERT(_curr_off >= _attr.in_off && _curr_off <= _attr.in_off + _attr.in_buf_num_bytes); + return _curr_off - _attr.in_off; + } + + addr_t _num_remaining_bytes() const + { + ASSERT(_curr_off >= _attr.in_off && _curr_off <= _attr.in_off + _attr.in_buf_num_bytes); + return _attr.in_off + _attr.in_buf_num_bytes - _curr_off; + } + + void _advance_curr_off(size_t advance, bool &progress) + { + _curr_off += advance; + if (!_num_remaining_bytes()) { + _helper.mark_succeeded(progress); + } else if (_curr_off % BLOCK_SIZE) { + _curr_buf_addr = (addr_t)&_blk; + _generate_read(READ_FIRST_VBA, progress); + } else if (_num_remaining_bytes() < BLOCK_SIZE) { + _curr_buf_addr = (addr_t)&_blk; + _generate_read(READ_LAST_VBA, progress); + } else { + _curr_buf_addr = (addr_t)_attr.in_buf_start + _curr_buf_off(); + _generate_read(READ_MIDDLE_VBAS, progress); + } + } + + public: + + Read(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "read"); } + + bool execute(Execute_attr const &attr) + { + bool progress = false; + switch (_helper.state) { + case INIT: + + _gen = _attr.in_gen; + _advance_curr_off(_attr.in_off, progress); + break; + + case READ_FIRST_VBA: progress |= _execute_read(READ_FIRST_VBA_SUCCEEDED, attr); break; + case READ_FIRST_VBA_SUCCEEDED: + { + size_t num_outside_bytes { _curr_off % BLOCK_SIZE }; + size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) }; + memcpy(_attr.in_buf_start, (void *)((addr_t)&_blk + num_outside_bytes), num_inside_bytes); + _advance_curr_off(num_inside_bytes, progress); + break; + } + case READ_MIDDLE_VBAS: progress |= _execute_read(READ_MIDDLE_VBAS_SUCCEEDED, attr); break; + case READ_MIDDLE_VBAS_SUCCEEDED: + + _advance_curr_off((_num_remaining_bytes() / BLOCK_SIZE) * BLOCK_SIZE, progress); + break; + + case READ_LAST_VBA: progress |= _execute_read(READ_LAST_VBA_SUCCEEDED, attr); break; + case READ_LAST_VBA_SUCCEEDED: + + memcpy((void *)((addr_t)_attr.in_buf_start + _curr_buf_off()), &_blk, _num_remaining_bytes()); + _advance_curr_off(_num_remaining_bytes(), progress); + break; + + default: break; + } + return progress; + } + + Block &destination_buffer(Virtual_block_address vba) + { + return *(Block *)(_curr_buf_addr + (vba - _curr_vba()) * BLOCK_SIZE); + } + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Write : Noncopyable + { + public: + + using Module = Splitter; + + struct Attr + { + Request_offset const in_off; + Generation const in_gen; + char const *const in_buf_start; + size_t const in_buf_num_bytes; + }; + + struct Execute_attr + { + Superblock_control &sb_control; + Virtual_block_device &vbd; + Client_data_interface &client_data; + Block_io &block_io; + Free_tree &free_tree; + Meta_tree &meta_tree; + Crypto &crypto; + }; + + private: + + enum State { + INIT, COMPLETE, READ_FIRST_VBA, READ_FIRST_VBA_SUCCEEDED, READ_LAST_VBA, READ_LAST_VBA_SUCCEEDED, + WRITE_FIRST_VBA, WRITE_FIRST_VBA_SUCCEEDED, WRITE_LAST_VBA, WRITE_LAST_VBA_SUCCEEDED, + WRITE_MIDDLE_VBAS, WRITE_MIDDLE_VBAS_SUCCEEDED }; + + + Request_helper _helper; + Attr const _attr; + addr_t _curr_off { }; + addr_t _curr_buf_addr { }; + Block _blk { }; + Generation _gen { }; + Constructible _read_vbas { }; + Constructible _write_vbas { }; + + Virtual_block_address _curr_vba() const { return (Virtual_block_address)(_curr_off / BLOCK_SIZE); } + + addr_t _curr_buf_off() const + { + ASSERT(_curr_off >= _attr.in_off && _curr_off <= _attr.in_off + _attr.in_buf_num_bytes); + return _curr_off - _attr.in_off; + } + + addr_t _num_remaining_bytes() const + { + ASSERT(_curr_off >= _attr.in_off && _curr_off <= _attr.in_off + _attr.in_buf_num_bytes); + return _attr.in_off + _attr.in_buf_num_bytes - _curr_off; + } + + void _generate_sb_control_request(State target_state, bool &progress) + { + Number_of_blocks num_blocks = + target_state == WRITE_MIDDLE_VBAS ? _num_remaining_bytes() / BLOCK_SIZE : 1; + + switch (target_state) { + case READ_FIRST_VBA: + case READ_LAST_VBA: _read_vbas.construct(Superblock_control::Read_vbas::Attr{_curr_vba(), num_blocks, 0, 0}); break; + case WRITE_FIRST_VBA: + case WRITE_MIDDLE_VBAS: + case WRITE_LAST_VBA: _write_vbas.construct(Superblock_control::Write_vbas::Attr{_curr_vba(), num_blocks, 0, 0}); break; + default: ASSERT_NEVER_REACHED; + } + _helper.state = target_state; + progress = true; + } + + void _advance_curr_off(size_t advance, bool &progress) + { + _curr_off += advance; + if (!_num_remaining_bytes()) { + _helper.mark_succeeded(progress); + } else if (_curr_off % BLOCK_SIZE) { + _curr_buf_addr = (addr_t)&_blk; + _generate_sb_control_request(READ_FIRST_VBA, progress); + } else if (_num_remaining_bytes() < BLOCK_SIZE) { + _curr_buf_addr = (addr_t)&_blk; + _generate_sb_control_request(READ_LAST_VBA, progress); + } else { + _curr_buf_addr = (addr_t)_attr.in_buf_start + _curr_buf_off(); + _generate_sb_control_request(WRITE_MIDDLE_VBAS, progress); + } + } + + bool _execute_read(State succeeded_state, Execute_attr const &attr) + { + bool progress = attr.sb_control.execute(*_read_vbas, attr.vbd, attr.client_data, attr.block_io, attr.crypto); + if (_read_vbas->complete()) { + if (_read_vbas->success()) + _helper.generated_req_succeeded(succeeded_state, progress); + else + _helper.generated_req_failed(progress); + } + return progress; + } + + bool _execute_write(State succeeded_state, Execute_attr const &attr) + { + bool progress = attr.sb_control.execute(*_write_vbas, attr.vbd, attr.client_data, attr.block_io, attr.free_tree, attr.meta_tree, attr.crypto); + if (_write_vbas->complete()) { + if (_write_vbas->success()) + _helper.generated_req_succeeded(succeeded_state, progress); + else + _helper.generated_req_failed(progress); + } + return progress; + } + + public: + + Write(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "write"); } + + bool execute(Execute_attr const &attr) + { + bool progress = false; + switch (_helper.state) { + case INIT: + + _gen = _attr.in_gen; + _advance_curr_off(_attr.in_off, progress); + break; + + case READ_FIRST_VBA: progress |= _execute_read(READ_FIRST_VBA_SUCCEEDED, attr); break; + case READ_FIRST_VBA_SUCCEEDED: + { + 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), _attr.in_buf_start, num_inside_bytes); + _curr_buf_addr = (addr_t)&_blk; + _generate_sb_control_request(WRITE_FIRST_VBA, progress); + break; + } + case WRITE_FIRST_VBA: progress |= _execute_write(WRITE_FIRST_VBA_SUCCEEDED, attr); break; + case WRITE_FIRST_VBA_SUCCEEDED: + { + 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, progress); + break; + } + case WRITE_MIDDLE_VBAS: progress |= _execute_write(WRITE_MIDDLE_VBAS_SUCCEEDED, attr); break; + case WRITE_MIDDLE_VBAS_SUCCEEDED: + + _advance_curr_off((_num_remaining_bytes() / BLOCK_SIZE) * BLOCK_SIZE, progress); + break; + + case READ_LAST_VBA: progress |= _execute_read(READ_LAST_VBA_SUCCEEDED, attr); break; + case READ_LAST_VBA_SUCCEEDED: + + memcpy(&_blk, (void *)((addr_t)_attr.in_buf_start + _curr_buf_off()), _num_remaining_bytes()); + _curr_buf_addr = (addr_t)&_blk; + _generate_sb_control_request(WRITE_LAST_VBA, progress); + break; + + case WRITE_LAST_VBA: progress |= _execute_write(WRITE_LAST_VBA_SUCCEEDED, attr); break; + case WRITE_LAST_VBA_SUCCEEDED: _advance_curr_off(_num_remaining_bytes(), progress); break; + default: break; + } + return progress; + } + + Block const &source_buffer(Virtual_block_address vba) + { + return *(Block *)(_curr_buf_addr + (vba - _curr_vba()) * BLOCK_SIZE); + } + + Block &destination_buffer() + { + ASSERT(_helper.state == READ_FIRST_VBA || _helper.state == READ_LAST_VBA); + return _blk; + } + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; 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); + Read *_read_ptr { }; + Write *_write_ptr { }; 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 + bool execute(Read &req, Read::Execute_attr const &attr) { - ASSERT(_curr_off >= _req_ptr->_off && _curr_off <= _req_ptr->_off + _req_ptr->_buf.num_bytes); - return _curr_off - _req_ptr->_off; + if (!_read_ptr && !_write_ptr) + _read_ptr = &req; + + if (_read_ptr != &req) + return false; + + bool progress = req.execute(attr); + if (req.complete()) + _read_ptr = nullptr; + + return progress; } - addr_t _num_remaining_bytes() const + bool execute(Write &req, Write::Execute_attr const &attr) { - 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; + if (!_write_ptr && !_write_ptr) + _write_ptr = &req; + + if (_write_ptr != &req) + return false; + + bool progress = req.execute(attr); + if (req.complete()) + _write_ptr = nullptr; + + return progress; } - template - void _generate_req(State_uint state, bool &progress, ARGS &&... args) + Block const &source_buffer(Virtual_block_address vba) { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); + ASSERT(_write_ptr); + return _write_ptr->source_buffer(vba); } - void _mark_req_successful(bool &); + Block &destination_buffer(Virtual_block_address vba) + { + if (_read_ptr) + return _read_ptr->destination_buffer(vba); + if (_write_ptr) + return _write_ptr->destination_buffer(); + ASSERT_NEVER_REACHED; + } - 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); } + static constexpr char const *name() { return "sb_control"; } }; - -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 87474c3f49..e918404e87 100644 --- a/repos/gems/src/lib/vfs/tresor/vfs.cc +++ b/repos/gems/src/lib/vfs/tresor/vfs.cc @@ -21,2370 +21,1517 @@ /* tresor includes */ #include -#include +#include #include #include #include -#include #include #include #include -#include "splitter.h" +/* vfs tresor includes */ +#include + +using namespace Genode; +using namespace Vfs; +using namespace Tresor; namespace Vfs_tresor { - using namespace Vfs; - using namespace Genode; - using namespace Tresor; + class Request_interface; + class Data_operation; class Data_file_system; - + class Extend_operation; class Extend_file_system; - class Extend_progress_file_system; + class Rekey_operation; class Rekey_file_system; - class Rekey_progress_file_system; + class Deinitialize_operation; class Deinitialize_file_system; - class Create_snapshot_file_system; - class Discard_snapshot_file_system; + class Control_local_factory; + class Control_file_system; + class Current_local_factory; + class Current_file_system; + class Local_factory; + class File_system; + class Plugin; +} - struct Control_local_factory; - class Control_file_system; - - struct Snapshot_local_factory; - class Snapshot_file_system; - - struct Snapshots_local_factory; - class Snapshots_file_system; - - struct Local_factory; - class File_system; - - class Client_data; - class Wrapper; - - template - class Pointer - { - private: - - T *_obj; - - public: - - struct Invalid : Genode::Exception { }; - - Pointer() : _obj(nullptr) { } - - Pointer(T &obj) : _obj(&obj) { } - - T &obj() const - { - if (_obj == nullptr) - throw Invalid(); - - return *_obj; - } - - bool valid() const { return _obj != nullptr; } - }; -} /* namespace Vfs_tresor */ - - -class Vfs_tresor::Client_data : public Tresor::Module, public Tresor::Module_channel +class Vfs_tresor::Data_operation : private Noncopyable { + public: + + enum Result { PENDING, SUCCEEDED, FAILED }; + + struct Execute_attr + { + Splitter &splitter; + Superblock_control &sb_control; + Client_data_interface &client_data; + Virtual_block_device &vbd; + Free_tree &free_tree; + Meta_tree &meta_tree; + Block_io &block_io; + Crypto &crypto; + Trust_anchor &trust_anchor; + }; + private: - using Request = Client_data_request; + enum State { + INIT, READ_REQUESTED, READ_STARTED, READ, READ_COMPLETE, WRITE_REQUESTED, WRITE_STARTED, WRITE, + WRITE_COMPLETE, SYNC_REQUESTED, SYNC_STARTED, SYNC, SYNC_COMPLETE }; - Lookup_buffer &_lookup; + State _state { INIT }; + bool const _verbose; + Generation _generation { }; + addr_t _seek { }; + bool _success { }; + Constructible _dst { }; + Constructible _src { }; + Constructible _write { }; + Constructible _read { }; + Constructible _sync { }; - NONCOPYABLE(Client_data); - - void _request_submitted(Module_request &mod_req) override + bool _range_violation(Superblock_control &sb_control, addr_t start, size_t num_bytes) const { - 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; - } } + addr_t last_byte = num_bytes ? start - 1 + num_bytes : start; + addr_t last_file_byte = (sb_control.max_vba() * BLOCK_SIZE) + (BLOCK_SIZE - 1); + return last_byte > last_file_byte; } - bool _request_complete() override { return true; } - public: - Client_data(Lookup_buffer &lb) : Module_channel { CLIENT_DATA, 0 }, _lookup { lb } { add_channel(*this);} + Data_operation(bool verbose) : _verbose(verbose) { } + + Result write(addr_t seek, Const_byte_range_ptr const &src) + { + switch (_state) { + case INIT: + + _seek = seek; + _src.construct(src.start, src.num_bytes); + _state = WRITE_REQUESTED; + if (_verbose) + log("write (seek ", _seek, " num_bytes ", _src->num_bytes, ") requested"); + return PENDING; + + case WRITE_REQUESTED: + case WRITE_STARTED: + case WRITE: return PENDING; + case WRITE_COMPLETE: + + _src.destruct(); + _state = INIT; + return _success ? SUCCEEDED : FAILED; + + default: break; + } + ASSERT_NEVER_REACHED; + } + + Result read(addr_t seek, Byte_range_ptr const &dst) + { + switch (_state) { + case INIT: + + _seek = seek; + _dst.construct(dst.start, dst.num_bytes); + _state = READ_REQUESTED; + if (_verbose) + log("read (seek ", _seek, " num_bytes ", _dst->num_bytes, ") requested"); + return PENDING; + + case READ_REQUESTED: + case READ_STARTED: + case READ: return PENDING; + case READ_COMPLETE: + + _dst.destruct(); + _state = INIT; + return _success ? SUCCEEDED : FAILED; + + default: break; + } + ASSERT_NEVER_REACHED; + } + + Result sync() + { + switch (_state) { + case INIT: + + _state = SYNC_REQUESTED; + if (_verbose) + log("sync requested"); + return PENDING; + + case SYNC_REQUESTED: + case SYNC_STARTED: + case SYNC: return PENDING; + case SYNC_COMPLETE: + + _state = INIT; + return _success ? SUCCEEDED : FAILED; + + default: break; + } + ASSERT_NEVER_REACHED; + } + + bool complete() const { return _state == WRITE_COMPLETE || _state == READ_COMPLETE || _state == SYNC_COMPLETE; } + + bool requested() const { return _state == WRITE_REQUESTED || _state == READ_REQUESTED || _state == SYNC_REQUESTED; } + + void start() + { + switch (_state) { + case WRITE_REQUESTED: _state = WRITE_STARTED; break; + case READ_REQUESTED: _state = READ_STARTED; break; + case SYNC_REQUESTED: _state = SYNC_STARTED; break; + default: ASSERT_NEVER_REACHED; + } + } + + bool execute(Execute_attr const &attr) + { + bool progress = false; + switch (_state) { + case WRITE_STARTED: + + if (_range_violation(attr.sb_control, _seek, _src->num_bytes)) { + _success = false; + _state = WRITE_COMPLETE; + progress = true; + if (_verbose) + log("write (seek ", _seek, " num_bytes ", _src->num_bytes, ") failed: range violation"); + break; + } + _write.construct(Splitter::Write::Attr{_seek, _generation, _src->start, _src->num_bytes}); + _state = WRITE; + progress = true; + if (_verbose) + log("write (seek ", _seek, " num_bytes ", _src->num_bytes, ") started"); + break; + + case WRITE: + + progress |= attr.splitter.execute( + *_write, {attr.sb_control, attr.vbd, attr.client_data, attr.block_io, + attr.free_tree, attr.meta_tree, attr.crypto}); + + if (_write->complete()) { + _success = _write->success(); + _write.destruct(); + _state = WRITE_COMPLETE; + progress = true; + if (_verbose) + log("write (seek ", _seek, " num_bytes ", _src->num_bytes, ") ", _success ? "succeeded" : "failed"); + } + break; + + case READ_STARTED: + + if (_range_violation(attr.sb_control, _seek, _dst->num_bytes)) { + _success = false; + _state = READ_COMPLETE; + progress = true; + if (_verbose) + log("read (seek ", _seek, " num_bytes ", _dst->num_bytes, ") failed: range violation"); + break; + } + _read.construct(Splitter::Read::Attr{_seek, _generation, _dst->start, _dst->num_bytes}); + _state = READ; + progress = true; + if (_verbose) + log("read (seek ", _seek, " num_bytes ", _dst->num_bytes, ") started"); + break; + + case READ: + + progress |= attr.splitter.execute( + *_read, {attr.sb_control, attr.vbd, attr.client_data, attr.block_io, attr.crypto}); + + if (_read->complete()) { + _success = _read->success(); + _read.destruct(); + _state = READ_COMPLETE; + progress = true; + if (_verbose) + log("read (seek ", _seek, " num_bytes ", _dst->num_bytes, ") ", _success ? "succeeded" : "failed"); + } + break; + + case SYNC_STARTED: + + _sync.construct(Superblock_control::Synchronize::Attr{}); + _state = SYNC; + progress = true; + if (_verbose) + log("sync started"); + break; + + case SYNC: + + progress |= attr.sb_control.execute(*_sync, attr.block_io, attr.trust_anchor); + if (_sync->complete()) { + _success = _sync->success(); + _sync.destruct(); + _state = SYNC_COMPLETE; + progress = true; + if (_verbose) + log("sync ", _success ? "succeeded" : "failed"); + } + break; + + default: break; + } + return progress; + } }; +class Vfs_tresor::Rekey_operation : private Noncopyable +{ + public: -class Vfs_tresor::Wrapper -: - private Tresor::Module_composition, - public Tresor::Module + enum Result { NONE, SUCCEEDED, FAILED, PENDING }; + + struct Execute_attr + { + Rekey_file_system *rekey_fs_ptr; + Superblock_control &sb_control; + Virtual_block_device &vbd; + Free_tree &free_tree; + Meta_tree &meta_tree; + Block_io &block_io; + Crypto &crypto; + Trust_anchor &trust_anchor; + }; + + private: + + enum State { INIT, REQUESTED, STARTED, REKEY, PAUSED, RESUMED, COMPLETE }; + + State _state { INIT }; + bool const _verbose; + bool _success { }; + bool _complete { }; + Constructible _rekey { }; + + public: + + Rekey_operation(bool verbose) : _verbose(verbose) { } + + bool request() + { + switch (_state) { + case INIT: + case COMPLETE: + + _state = REQUESTED; + if (_verbose) + log("rekey requested"); + return true; + + default: return false; + } + ASSERT_NEVER_REACHED; + } + + Result result() const + { + switch (_state) { + case INIT: return NONE; + case COMPLETE: return _success ? SUCCEEDED : FAILED; + default: return PENDING; + } + ASSERT_NEVER_REACHED; + } + + bool execute(Execute_attr const &attr); + + void resume() + { + switch (_state) { + case PAUSED: _state = RESUMED; break; + default: ASSERT_NEVER_REACHED; + } + } + + void start() + { + switch (_state) { + case REQUESTED: _state = STARTED; break; + default: ASSERT_NEVER_REACHED; + } + } + + bool complete() const { return _state == COMPLETE; } + + bool paused() const { return _state == PAUSED; } + + bool requested() const { return _state == REQUESTED; } +}; + +class Vfs_tresor::Deinitialize_operation : private Noncopyable +{ + public: + + enum Result { NONE, SUCCEEDED, FAILED, PENDING }; + + struct Execute_attr + { + Deinitialize_file_system *deinit_fs_ptr; + Superblock_control &sb_control; + Block_io &block_io; + Crypto &crypto; + Trust_anchor &trust_anchor; + }; + + private: + + enum State { INIT, REQUESTED, STARTED, DEINIT_SB_CONTROL, COMPLETE }; + + State _state { INIT }; + bool const _verbose; + bool _success { }; + Constructible _deinit_sb_control { }; + + public: + + Deinitialize_operation(bool verbose) : _verbose(verbose) { } + + bool request() + { + switch (_state) { + case INIT: + case COMPLETE: + + _state = REQUESTED; + if (_verbose) + log("deinitialize requested"); + return true; + + default: return false; + } + ASSERT_NEVER_REACHED; + } + + void start() + { + switch (_state) { + case REQUESTED: _state = STARTED; break; + default: ASSERT_NEVER_REACHED; + } + } + + Result result() const + { + switch (_state) { + case INIT: return NONE; + case COMPLETE: return _success ? SUCCEEDED : FAILED; + default: return PENDING; + } + ASSERT_NEVER_REACHED; + } + + bool complete() const { return _state == COMPLETE; } + + bool requested() const { return _state == REQUESTED; } + + bool execute(Execute_attr const &attr); +}; + +class Vfs_tresor::Extend_operation : private Noncopyable +{ + public: + + enum Result { NONE, SUCCEEDED, FAILED, PENDING }; + + struct Execute_attr + { + Extend_file_system *extend_fs_ptr; + Superblock_control &sb_control; + Virtual_block_device &vbd; + Free_tree &free_tree; + Meta_tree &meta_tree; + Block_io &block_io; + Trust_anchor &trust_anchor; + }; + + private: + + enum State { + INIT, EXTEND_FT_REQUESTED, EXTEND_FT_STARTED, EXTEND_FT, EXTEND_FT_PAUSED, EXTEND_FT_RESUMED, + EXTEND_VBD_REQUESTED, EXTEND_VBD_STARTED, EXTEND_VBD, EXTEND_VBD_PAUSED, EXTEND_VBD_RESUMED, COMPLETE }; + + State _state { INIT }; + bool const _verbose; + bool _success { }; + bool _complete { }; + Number_of_blocks _num_blocks { }; + Constructible _extend_ft { }; + Constructible _extend_vbd { }; + + public: + + Extend_operation(bool verbose) : _verbose(verbose) { } + + bool request_for_free_tree(Number_of_blocks num_blocks) + { + switch (_state) { + case INIT: + case COMPLETE: + + _num_blocks = num_blocks; + _state = EXTEND_FT_REQUESTED; + if (_verbose) + log("extend free tree requested"); + return true; + + default: break; + } + return false; + } + + bool request_for_vbd(Number_of_blocks num_blocks) + { + switch (_state) { + case INIT: + case COMPLETE: + + _num_blocks = num_blocks; + _state = EXTEND_VBD_REQUESTED; + if (_verbose) + log("extend virtual block device requested"); + return true; + + default: return false; + } + ASSERT_NEVER_REACHED; + } + + Result result() const + { + switch (_state) { + case INIT: return NONE; + case COMPLETE: return _success ? SUCCEEDED : FAILED; + default: return PENDING; + } + ASSERT_NEVER_REACHED; + } + + bool execute(Execute_attr const &attr); + + void resume() + { + switch (_state) { + case EXTEND_FT_PAUSED: _state = EXTEND_FT_RESUMED; break; + case EXTEND_VBD_PAUSED: _state = EXTEND_VBD_RESUMED; break; + default: ASSERT_NEVER_REACHED; + } + } + + void start() + { + switch (_state) { + case EXTEND_FT_REQUESTED: _state = EXTEND_FT_STARTED; break; + case EXTEND_VBD_REQUESTED: _state = EXTEND_VBD_STARTED; break; + default: ASSERT_NEVER_REACHED; + } + } + + bool complete() const { return _state == COMPLETE; } + + bool paused() const { return _state == EXTEND_FT_PAUSED || _state == EXTEND_VBD_PAUSED; } + + bool requested() const { return _state == EXTEND_FT_REQUESTED || _state == EXTEND_VBD_REQUESTED; } +}; + +class Vfs_tresor::Plugin : private Noncopyable, private Client_data_interface, private Crypto_key_files_interface { private: - NONCOPYABLE(Wrapper); - - Vfs::Env &_vfs_env; - - Constructible _request_pool { }; - Constructible _free_tree { }; - Constructible _vbd { }; - Constructible _sb_control { }; - Tresor::Meta_tree _meta_tree { }; - Constructible _trust_anchor { }; - Constructible _crypto { }; - Constructible _block_io { }; - - Constructible _splitter { }; - Constructible _client_data { }; - - - public: - - enum class Result { UNKNOWN, OK, ERROR, EOF }; - - - private: - - class Command : public Module_channel - { - 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; - } - }); - } - - template - bool _with_first_idle_cmd(FUNC && func) - { - bool done { false }; - for_each_channel([&] (Command &cmd) { - if (done) - return; - - 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); - } - }); - return done; - } + enum State { + INIT_SB_CONTROL, NO_OPERATION, DATA_OPERATION, REKEY_OPERATION, EXTEND_OPERATION, + DEINITIALIZE_OPERATION, DEINITIALIZED }; enum { MAX_NUM_COMMANDS = 16 }; - Constructible _commands[MAX_NUM_COMMANDS] { }; - bool ready_to_submit_request() + struct Crypto_key { - bool result = false; - for_each_channel([&] (Command const &cmd) { - if (cmd.state() == Command::State::IDLE) - result = true; - }); - return result; - } - - public: - - struct Control_request - { - enum State { UNKNOWN, IDLE, IN_PROGRESS, }; - enum Result { NONE, SUCCESS, FAILED, }; - - State state; - Result last_result; - - 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) { - case State::UNKNOWN: return "unknown"; - case State::IDLE: return "idle"; - case State::IN_PROGRESS: return "in-progress"; - } - return "-"; - } + Key_id const key_id; + Vfs_handle &encrypt_file; + Vfs_handle &decrypt_file; }; - 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) - { - if (Genode::strcmp("vbd", s, 3) == 0) { - return Type::VBD; - } else - - if (Genode::strcmp("ft", s, 2) == 0) { - return Type::FT; - } - - return Type::INVALID; - } - - 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"; - } - return nullptr; - } - }; - - private: + Vfs::Env &_vfs_env; + bool const _verbose; + Tresor::Path const _crypto_path; + Tresor::Path const _block_io_path; + Tresor::Path const _trust_anchor_path; + Vfs_handle &_block_io_file { open_file(_vfs_env, _block_io_path, Directory_service::OPEN_MODE_RDWR) }; + Vfs_handle &_crypto_add_key_file { open_file(_vfs_env, { _crypto_path, "/add_key" }, Directory_service::OPEN_MODE_WRONLY) }; + Vfs_handle &_crypto_remove_key_file { open_file(_vfs_env, { _crypto_path, "/remove_key" }, Directory_service::OPEN_MODE_WRONLY) }; + Vfs_handle &_ta_decrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/decrypt" }, Directory_service::OPEN_MODE_RDWR) }; + Vfs_handle &_ta_encrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/encrypt" }, Directory_service::OPEN_MODE_RDWR) }; + Vfs_handle &_ta_generate_key_file { open_file(_vfs_env, { _trust_anchor_path, "/generate_key" }, Directory_service::OPEN_MODE_RDWR) }; + Vfs_handle &_ta_initialize_file { open_file(_vfs_env, { _trust_anchor_path, "/initialize" }, Directory_service::OPEN_MODE_RDWR) }; + Vfs_handle &_ta_hash_file { open_file(_vfs_env, { _trust_anchor_path, "/hash" }, Directory_service::OPEN_MODE_RDWR) }; + Tresor::Free_tree _free_tree { }; + Tresor::Virtual_block_device _vbd { }; + Superblock_control _sb_control { }; + Meta_tree _meta_tree { }; + Trust_anchor _trust_anchor { { _ta_decrypt_file, _ta_encrypt_file, _ta_generate_key_file, _ta_initialize_file, _ta_hash_file } }; + Crypto _crypto { {*this, _crypto_add_key_file, _crypto_remove_key_file} }; + Block_io _block_io { _block_io_file }; + Splitter _splitter { }; + Extend_file_system * _extend_fs_ptr { }; + Rekey_file_system * _rekey_fs_ptr { }; + Deinitialize_file_system *_deinit_fs_ptr { }; + Constructible _crypto_keys[2] { }; + Superblock_control::Initialize *_init_sb_control_ptr { }; + Superblock::State _sb_state { Superblock::INVALID }; + Data_operation _data_operation { _verbose }; + Rekey_operation _rekey_operation { _verbose }; + Extend_operation _extend_operation { _verbose }; + Deinitialize_operation _deinit_operation { _verbose }; + State _state { INIT_SB_CONTROL }; /* - * 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. + * Noncopyable */ - Rekeying _rekey_obj { }; - Extending _extend_obj { }; - Deinitialize _deinit_obj { }; + Plugin(Plugin const &) = delete; + Plugin &operator = (Plugin const &) = delete; - 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) + Constructible &_crypto_key(Key_id key_id) { - ASSERT(_io_handle_ptr == nullptr); - - bool done = _with_first_idle_cmd([&] (Command &cmd) { - setup_fn(cmd); - - _io_cmd_ptr = &cmd; - _io_handle_ptr = &handle; - }); - return done; + for (Constructible &key : _crypto_keys) + if (key.constructed() && key->key_id == key_id) + return key; + ASSERT_NEVER_REACHED; } - template - bool _with_io_active_cmd_for_handle(Vfs_handle const &handle, - PENDING_FN const &pending_fn, - COMPLETE_FN const &complete_fn) + bool _try_start_operation() { - bool found = false; - if (_io_handle_ptr && _io_handle_ptr == &handle) { - if (_io_cmd_ptr) { - Command &cmd = *_io_cmd_ptr; + if (_deinit_operation.requested()) { + _deinit_operation.start(); + _state = DEINITIALIZE_OPERATION; + return true; + } + if (_data_operation.requested()) { + _data_operation.start(); + _state = DATA_OPERATION; + return true; + } + if (_extend_operation.requested()) { + _extend_operation.start(); + _state = EXTEND_OPERATION; + return true; + } + if (_rekey_operation.requested()) { + _rekey_operation.start(); + _state = REKEY_OPERATION; + return true; + } + return false; + } - 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); + bool _try_resume_operation() + { + if (_extend_operation.paused()) { + _extend_operation.resume(); + _state = EXTEND_OPERATION; + return true; + } + if (_rekey_operation.paused()) { + _rekey_operation.resume(); + _state = REKEY_OPERATION; + return true; + } + return false; + } - _io_cmd_ptr = nullptr; - _io_handle_ptr = nullptr; - break; - } - found = true; + bool _execute_operations() + { + bool progress = false; + switch (_state) { + case INIT_SB_CONTROL: + + progress |= _sb_control.execute(*_init_sb_control_ptr, _block_io, _crypto, _trust_anchor) ; + if (_init_sb_control_ptr->complete()) { + + ASSERT(_init_sb_control_ptr->success()); + destroy(_vfs_env.alloc(), _init_sb_control_ptr); + _init_sb_control_ptr = nullptr; + if (_verbose) + log("initialize succeeded"); + + if (!_try_start_operation()) + _state = NO_OPERATION; + progress = true; } + break; + + case DATA_OPERATION: + + progress |= _data_operation.execute({_splitter, _sb_control, *this, _vbd, _free_tree, _meta_tree, _block_io, _crypto, _trust_anchor}) ; + if (_data_operation.complete()) { + if (!_try_resume_operation()) + if (!_try_start_operation()) + _state = NO_OPERATION; + progress = true; + } + break; + + case DEINITIALIZE_OPERATION: + + progress |= _deinit_operation.execute({_deinit_fs_ptr, _sb_control, _block_io, _crypto, _trust_anchor}) ; + if (_deinit_operation.complete()) { + _state = DEINITIALIZED; + progress = true; + } + break; + + case EXTEND_OPERATION: + + progress |= _extend_operation.execute({_extend_fs_ptr, _sb_control, _vbd, _free_tree, _meta_tree, _block_io, _trust_anchor}) ; + if (_extend_operation.complete()) { + if (!_try_start_operation()) + _state = NO_OPERATION; + progress = true; + } + if (_extend_operation.paused()) { + if (_data_operation.requested()) { + _data_operation.start(); + _state = DATA_OPERATION; + } else + _extend_operation.resume(); + progress = true; + } + break; + + case REKEY_OPERATION: + + progress |= _rekey_operation.execute({_rekey_fs_ptr, _sb_control, _vbd, _free_tree, _meta_tree, _block_io, _crypto, _trust_anchor}) ; + if (_rekey_operation.complete()) { + if (!_try_start_operation()) + _state = NO_OPERATION; + progress = true; + } + if (_rekey_operation.paused()) { + if (_data_operation.requested()) { + _data_operation.start(); + _state = DATA_OPERATION; + } else + _rekey_operation.resume(); + progress = true; + } + break; + + case NO_OPERATION: progress |= _try_start_operation(); break; + default: break; } - return found; + return progress; } - Pointer _snapshots_fs { }; - Pointer _extend_fs { }; - Pointer _extend_progress_fs { }; - Pointer _rekey_fs { }; - Pointer _rekey_progress_fs { }; - Pointer _deinit_fs { }; - - /* configuration options */ - bool _verbose { false }; - bool _debug { false }; - - void _read_config(Xml_node config) + void _execute() { - _verbose = config.attribute_value("verbose", _verbose); - _debug = config.attribute_value("debug", _debug); + while (_execute_operations()) ; + _wakeup_back_end_services(); } - struct Could_not_open_block_backend : Genode::Exception { }; - struct No_valid_superblock_found : Genode::Exception { }; + void _wakeup_back_end_services() { _vfs_env.io().commit(); } - void _initialize_tresor() + size_t _data_file_size() const { return (_sb_control.max_vba() + 1) * BLOCK_SIZE; } + + /******************************** + ** Crypto_key_files_interface ** + ********************************/ + + void add_crypto_key(Key_id key_id) override { - _free_tree.construct(); - _vbd.construct(); - _sb_control.construct(); - _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); - } - } - - void _process_completed(Command &cmd) - { - 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 _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: - - 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); - }); - - _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(); + for (Constructible &key : _crypto_keys) + if (!key.constructed()) { + key.construct(key_id, + open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/encrypt" }, Directory_service::OPEN_MODE_RDWR), + open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/decrypt" }, Directory_service::OPEN_MODE_RDWR) + ); return; } - } - - execute(); - - _with_io_active_cmd_for_handle(handle, - [&] { pending_fn(); }, - [&] (Command const &cmd) { - complete_fn(cmd.result, - cmd.buffer_num_bytes); - }); + ASSERT_NEVER_REACHED; } - void execute() + void remove_crypto_key(Key_id key_id) override { - 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(); - } + Constructible &crypto_key = _crypto_key(key_id); + _vfs_env.root_dir().close(&crypto_key->encrypt_file); + _vfs_env.root_dir().close(&crypto_key->decrypt_file); + crypto_key.destruct(); } - bool start_rekeying() + Vfs_handle &encrypt_file(Key_id key_id) override { return _crypto_key(key_id)->encrypt_file; } + Vfs_handle &decrypt_file(Key_id key_id) override { return _crypto_key(key_id)->decrypt_file; } + + /*************************** + ** Client_data_interface ** + ***************************/ + + void obtain_data(Obtain_data_attr const &attr) override { - 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; + attr.out_blk = _splitter.source_buffer(attr.in_vba); } - Rekeying const rekeying_progress() const { - return _rekey_obj; } - - bool start_deinitialize() + void supply_data(Supply_data_attr const &attr) override { - 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; + _splitter.destination_buffer(attr.in_vba) = attr.in_blk; } - Deinitialize const deinitialize_progress() const { - return _deinit_obj; } + public: - bool start_extending(Extending::Type type, - Tresor::Number_of_blocks blocks) + Plugin(Vfs::Env &vfs_env, Xml_node const &config) + : + _vfs_env(vfs_env), + _verbose(config.attribute_value("verbose", _verbose)), + _crypto_path(config.attribute_value("crypto", Tresor::Path())), + _block_io_path(config.attribute_value("block", Tresor::Path())), + _trust_anchor_path(config.attribute_value("trust_anchor", Tresor::Path())) { - 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; + _init_sb_control_ptr = new (_vfs_env.alloc()) Superblock_control::Initialize({_sb_state}); + if (_verbose) + log("initialize started"); } - Extending const extending_progress() const { - return _extend_obj; } - - void snapshots_info(Tresor::Snapshots_info &info) + template + void with_data_file_size(FUNC && func) { - info = _sb_control->snapshots_info(); - execute(); + _execute(); + if (_state != INIT_SB_CONTROL) + func(_data_file_size()); } - bool create_snapshot() + template + void with_data_operation(FUNC && func) { - if (!ready_to_submit_request()) - return false; - - bool result = _with_first_idle_cmd([&] (Command &cmd) { - cmd.op = Command::Operation::CREATE_SNAPSHOT; }); - - execute(); - return result; + _execute(); + func(_data_operation); + _execute(); } - bool discard_snapshot(Generation snap_gen) + template + void with_rekey_operation(FUNC && func) { - 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; + _execute(); + func(_rekey_operation); + _execute(); } - /*********************************************************** - ** Manange/Disolve interface needed for FS notifications ** - ***********************************************************/ - - void manage_snapshots_file_system(Snapshots_file_system &snapshots_fs) + template + void with_extend_operation(FUNC && func) { - if (_snapshots_fs.valid()) { - - class Already_managing_an_snapshots_file_system { }; - throw Already_managing_an_snapshots_file_system { }; - } - _snapshots_fs = snapshots_fs; + _execute(); + func(_extend_operation); + _execute(); } - void dissolve_snapshots_file_system(Snapshots_file_system &snapshots_fs) + template + void with_deinit_operation(FUNC && func) { - if (_snapshots_fs.valid()) { - - if (&_snapshots_fs.obj() != &snapshots_fs) { - - class Snapshots_file_system_not_managed { }; - throw Snapshots_file_system_not_managed { }; - } - _snapshots_fs = Pointer { }; - - } else { - - class No_snapshots_file_system_managed { }; - throw No_snapshots_file_system_managed { }; - } + _execute(); + func(_deinit_operation); + _execute(); } void manage_extend_file_system(Extend_file_system &extend_fs) { - if (_extend_fs.valid()) { - - class Already_managing_an_extend_file_system { }; - throw Already_managing_an_extend_file_system { }; - } - _extend_fs = extend_fs; + ASSERT(!_extend_fs_ptr); + _extend_fs_ptr = &extend_fs; } void dissolve_extend_file_system(Extend_file_system &extend_fs) { - if (_extend_fs.valid()) { - - if (&_extend_fs.obj() != &extend_fs) { - - class Extend_file_system_not_managed { }; - throw Extend_file_system_not_managed { }; - } - _extend_fs = Pointer { }; - - } else { - - class No_extend_file_system_managed { }; - throw No_extend_file_system_managed { }; - } - } - - void manage_extend_progress_file_system(Extend_progress_file_system &extend_progress_fs) - { - if (_extend_progress_fs.valid()) { - - class Already_managing_an_extend_progres_file_system { }; - throw Already_managing_an_extend_progres_file_system { }; - } - _extend_progress_fs = extend_progress_fs; - } - - void dissolve_extend_progress_file_system(Extend_progress_file_system &extend_progress_fs) - { - if (_extend_progress_fs.valid()) { - - if (&_extend_progress_fs.obj() != &extend_progress_fs) { - - class Extend_file_system_not_managed { }; - throw Extend_file_system_not_managed { }; - } - _extend_progress_fs = Pointer { }; - - } else { - - class No_extend_file_system_managed { }; - throw No_extend_file_system_managed { }; - } + ASSERT(_extend_fs_ptr == &extend_fs); + _extend_fs_ptr = nullptr; } void manage_rekey_file_system(Rekey_file_system &rekey_fs) { - if (_rekey_fs.valid()) { - - class Already_managing_an_rekey_file_system { }; - throw Already_managing_an_rekey_file_system { }; - } - _rekey_fs = rekey_fs; + ASSERT(!_rekey_fs_ptr); + _rekey_fs_ptr = &rekey_fs; } void dissolve_rekey_file_system(Rekey_file_system &rekey_fs) { - if (_rekey_fs.valid()) { - - if (&_rekey_fs.obj() != &rekey_fs) { - - class Rekey_file_system_not_managed { }; - throw Rekey_file_system_not_managed { }; - } - _rekey_fs = Pointer { }; - - } else { - - class No_rekey_file_system_managed { }; - throw No_rekey_file_system_managed { }; - } - } - - void manage_rekey_progress_file_system(Rekey_progress_file_system &rekey_progress_fs) - { - if (_rekey_progress_fs.valid()) { - - class Already_managing_an_rekey_progress_file_system { }; - throw Already_managing_an_rekey_progress_file_system { }; - } - _rekey_progress_fs = rekey_progress_fs; - } - - void dissolve_rekey_progress_file_system(Rekey_progress_file_system &rekey_progress_fs) - { - if (_rekey_progress_fs.valid()) { - - if (&_rekey_progress_fs.obj() != &rekey_progress_fs) { - - class Rekey_progress_file_system_not_managed { }; - throw Rekey_progress_file_system_not_managed { }; - } - _rekey_progress_fs = Pointer { }; - - } else { - - class No_rekey_progress_file_system_managed { }; - throw No_rekey_progress_file_system_managed { }; - } + ASSERT(_rekey_fs_ptr == &rekey_fs); + _rekey_fs_ptr = nullptr; } void manage_deinit_file_system(Deinitialize_file_system &deinit_fs) { - if (_deinit_fs.valid()) { - - class Already_managing_an_deinit_file_system { }; - throw Already_managing_an_deinit_file_system { }; - } - _deinit_fs = deinit_fs; + ASSERT(!_deinit_fs_ptr); + _deinit_fs_ptr = &deinit_fs; } void dissolve_deinit_file_system(Deinitialize_file_system &deinit_fs) { - if (_deinit_fs.valid()) { - - if (&_deinit_fs.obj() != &deinit_fs) { - - class Deinitialize_file_system_not_managed { }; - throw Deinitialize_file_system_not_managed { }; - } - _deinit_fs = Pointer { }; - - } else { - - class No_deinit_file_system_managed { }; - throw No_deinit_file_system_managed { }; - } + ASSERT(_deinit_fs_ptr == &deinit_fs); + _deinit_fs_ptr = nullptr; } + bool verbose() const { return _verbose; } }; -class Vfs_tresor::Data_file_system : public Single_file_system +class Vfs_tresor::Data_file_system : private Noncopyable, public Single_file_system { private: - 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) + class Vfs_handle : private Noncopyable, public Single_vfs_handle { - 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; - } + private: - 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; - } + Plugin &_plugin; - 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: + Vfs_handle(Directory_service &dir_service, File_io_service &file_io_service, + Allocator &alloc, Plugin &plugin) + : + Single_vfs_handle(dir_service, file_io_service, alloc, 0), _plugin(plugin) + { } + + /*********************** + ** Single_vfs_handle ** + ***********************/ + + Read_result read(Byte_range_ptr const &dst, size_t &out_count) override + { + out_count = 0; + Read_result result = READ_QUEUED; + _plugin.with_data_operation([&] (Data_operation &data_operation) { + + switch (data_operation.read(seek(), dst)) { + case Data_operation::PENDING: break; + case Data_operation::SUCCEEDED: + + out_count = dst.num_bytes; + result = READ_OK; + break; + + case Data_operation::FAILED: result = READ_ERR_IO; break; + }; + }); + return result; + } + + Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override + { + out_count = 0; + Write_result result = WRITE_ERR_WOULD_BLOCK; + _plugin.with_data_operation([&] (Data_operation &data_operation) { + + switch (data_operation.write(seek(), src)) { + case Data_operation::PENDING: break; + case Data_operation::SUCCEEDED: + + out_count = src.num_bytes; + result = WRITE_OK; + break; + + case Data_operation::FAILED: result = WRITE_ERR_IO; break; + }; + }); + return result; + } + + Sync_result sync() override + { + Sync_result result = SYNC_QUEUED; + _plugin.with_data_operation([&] (Data_operation &data_operation) { + + switch (data_operation.sync()) { + case Data_operation::PENDING: break; + case Data_operation::SUCCEEDED: + + result = SYNC_OK; + break; + + case Data_operation::FAILED: result = SYNC_ERR_INVALID; break; + }; + }); + return result; + } + + bool read_ready() const override { return true; } + bool write_ready() const override { return true; } + }; + + Plugin &_plugin; public: - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; - Generation _snap_gen { INVALID_GENERATION }; - - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w, - Generation snap_gen) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w), _snap_gen(snap_gen) - { } - - Read_result read(Byte_range_ptr const &dst, size_t &out_count) override - { - 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; - } - ); - return result; - } - - Write_result write(Const_byte_range_ptr const &src, - size_t &out_count) override - { - 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 - { - 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); - } - ); - return result; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } - }; - - Data_file_system(Wrapper &w, Generation snap_gen) + Data_file_system(Plugin &plugin) : - Single_file_system(Node_type::CONTINUOUS_FILE, type_name(), - Node_rwx::rw(), Xml_node("")), - _w(w), _snap_gen(snap_gen) + Single_file_system(Node_type::CONTINUOUS_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _plugin(plugin) { } - ~Data_file_system() - { - /* XXX sync on close */ - /* XXX invalidate any still pending request */ - } + static char const *type_name() { return "data"; } - /********************************* - ** Directory-service interface ** - *********************************/ + /************************ + ** Single_file_system ** + ************************/ Stat_result stat(char const *path, Stat &out) override { - Stat_result result = Single_file_system::stat(path, out); - - /* max_vba range is from 0 ... N - 1 */ - out.size = (_w.max_vba() + 1) * Tresor::BLOCK_SIZE; + Stat_result result = STAT_ERR_NO_ENTRY; + _plugin.with_data_file_size([&] (size_t size) { + result = Single_file_system::stat(path, out); + out.size = size; + }); return result; } - /******************************** - ** File I/O service interface ** - ********************************/ + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { return FTRUNCATE_OK; } - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } - - /*************************** - ** File-system interface ** - ***************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Allocator &alloc) override + Open_result open(char const *path, unsigned, Vfs::Vfs_handle **out_handle, Allocator &alloc) override { if (!_single_file(path)) return OPEN_ERR_UNACCESSIBLE; - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w, _snap_gen); - + *out_handle = new (alloc) Vfs_handle(*this, *this, alloc, _plugin); return OPEN_OK; } - static char const *type_name() { return "data"; } char const *type() override { return type_name(); } }; -class Vfs_tresor::Extend_file_system : public Vfs::Single_file_system +class Vfs_tresor::Extend_file_system : private Noncopyable, public Single_file_system { private: - typedef Registered Registered_watch_handle; - typedef Registry Watch_handle_registry; + using Registered_watch_handle = Registered; + using Watch_handle_registry = Registry; + using Content_string = String<11>; - Watch_handle_registry _handle_registry { }; - - Wrapper &_w; - - using Content_string = String<32>; - - static file_size copy_content(Content_string const &content, - char *dst, size_t const count) + class Vfs_handle : private Noncopyable, public Single_vfs_handle { - copy_cstring(dst, content.string(), count); - size_t const length_without_nul = content.length() - 1; - return count > length_without_nul - 1 ? length_without_nul - : count; - } + private: - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; + Plugin &_plugin; - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w) - { } - - Read_result read(Byte_range_ptr const &dst, size_t &out_count) override - { - /* EOF */ - if (seek() != 0) { - out_count = 0; - return READ_OK; - } - - /* - * For now trigger extending execution via this hook - * like we do in the Data_file_system. - */ - _w.execute(); - - Wrapper::Extending const & extending { - _w.extending_progress() }; - - if (extending.in_progress()) - return READ_QUEUED; - - if (extending.idle()) { - Content_string const content { - extending.success() ? "successful" - : "failed" }; - copy_content(content, dst.start, dst.num_bytes); + static Read_result _read_ok(Content_string const &content, Byte_range_ptr const &dst, size_t &out_count) + { + copy_cstring(dst.start, content.string(), dst.num_bytes); out_count = dst.num_bytes; return READ_OK; } - return READ_ERR_IO; - } + public: - Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override - { - using Type = Wrapper::Extending::Type; - if (!_w.extending_progress().idle()) { - return WRITE_ERR_IO; + Vfs_handle(Directory_service &dir_service, File_io_service &file_io_service, + Allocator &alloc, Plugin &plugin) + : + Single_vfs_handle(dir_service, file_io_service, alloc, 0), _plugin(plugin) + { } + + /*********************** + ** Single_vfs_handle ** + ***********************/ + + Read_result read(Byte_range_ptr const &dst, size_t &out_count) override + { + out_count = 0; + if (seek() == dst.num_bytes) { + return READ_OK; + } + if (seek() || dst.num_bytes < Content_string::capacity()) { + if (_plugin.verbose()) + log("reading extend file failed: malformed arguments"); + return READ_ERR_IO; + } + Read_result result = READ_QUEUED; + _plugin.with_extend_operation([&] (Extend_operation &extend_operation) { + + switch (extend_operation.result()) { + case Extend_operation::NONE: result = _read_ok("none", dst, out_count); break; + case Extend_operation::SUCCEEDED: result = _read_ok("succeeded", dst, out_count); break; + case Extend_operation::FAILED: result = _read_ok("failed", dst, out_count); break; + case Extend_operation::PENDING: break; + } + }); + return result; } - char tree[16]; - Arg_string::find_arg(src.start, "tree").string(tree, sizeof (tree), "-"); - Type type = Wrapper::Extending::string_to_type(tree); - if (type == Type::INVALID) { - return WRITE_ERR_IO; + Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override + { + out_count = 0; + char tree_arg[16]; + Arg_string::find_arg(src.start, "tree").string(tree_arg, sizeof(tree_arg), "-"); + unsigned long blocks_arg = Arg_string::find_arg(src.start, "blocks").ulong_value(0); + if (seek() || !blocks_arg) { + if (_plugin.verbose()) + log("writing extend file failed: malformed arguments"); + return WRITE_ERR_IO; + } + Write_result result = WRITE_ERR_IO; + _plugin.with_extend_operation([&] (Extend_operation &extend_operation) { + + if (!strcmp("ft", tree_arg, 2)) { + + if (!extend_operation.request_for_free_tree(blocks_arg)) { + result = WRITE_ERR_IO; + if (_plugin.verbose()) + log("writing extend file failed: failed to request operation"); + return; + } + + } else if (!strcmp("vbd", tree_arg, 3)) { + + if (!extend_operation.request_for_vbd(blocks_arg)) { + result = WRITE_ERR_IO; + if (_plugin.verbose()) + log("writing extend file failed: failed to request operation"); + return; + } + + } else { + + result = WRITE_ERR_IO; + if (_plugin.verbose()) + log("writing extend file failed: malformed tree argument"); + return; + } + out_count = src.num_bytes; + result = WRITE_OK; + }); + return result; } - unsigned long blocks = Arg_string::find_arg(src.start, "blocks").ulong_value(0); - if (blocks == 0) { - return WRITE_ERR_IO; - } - - bool const okay = _w.start_extending(type, blocks); - if (!okay) { - return WRITE_ERR_IO; - } - - out_count = src.num_bytes; - return WRITE_OK; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } + bool read_ready() const override { return true; } + bool write_ready() const override { return true; } }; + Watch_handle_registry _handle_registry { }; + Plugin &_plugin; + public: - Extend_file_system(Wrapper &w) + Extend_file_system(Plugin &plugin) : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("")), - _w(w) + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _plugin(plugin) { - _w.manage_extend_file_system(*this); + _plugin.manage_extend_file_system(*this); } static char const *type_name() { return "extend"; } - char const *type() override { return type_name(); } - void trigger_watch_response() { _handle_registry.for_each([this] (Registered_watch_handle &handle) { handle.watch_response(); }); } - Watch_result watch(char const *path, - Vfs_watch_handle **handle, - Allocator &alloc) override + /************************ + ** Single_file_system ** + ************************/ + + Watch_result watch(char const *path, Vfs_watch_handle **handle, Allocator &alloc) override { if (!_single_file(path)) return WATCH_ERR_UNACCESSIBLE; try { - *handle = new (alloc) - Registered_watch_handle(_handle_registry, *this, alloc); - + *handle = new (alloc) Registered_watch_handle(_handle_registry, *this, alloc); return WATCH_OK; } - catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } + catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } } void close(Vfs_watch_handle *handle) override { - destroy(handle->alloc(), - static_cast(handle)); + destroy(handle->alloc(), static_cast(handle)); } - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override - { - if (!_single_file(path)) - return OPEN_ERR_UNACCESSIBLE; - - try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); - return OPEN_OK; - } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } - } - - Stat_result stat(char const *path, Stat &out) override - { - Stat_result result = Single_file_system::stat(path, out); - out.size = Content_string::size(); - return result; - } - - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } -}; - - -class Vfs_tresor::Extend_progress_file_system : public Vfs::Single_file_system -{ - private: - - typedef Registered Registered_watch_handle; - typedef Registry Watch_handle_registry; - - Watch_handle_registry _handle_registry { }; - - Wrapper &_w; - - using Content_string = String<32>; - - static file_size copy_content(Content_string const &content, - char *dst, size_t const count) - { - copy_cstring(dst, content.string(), count); - size_t const length_without_nul = content.length() - 1; - return count > length_without_nul - 1 ? length_without_nul - : count; - } - - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; - - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w) - { } - - Read_result read(Byte_range_ptr const &dst, - size_t &out_count) override - { - /* EOF */ - if (seek() != 0) { - out_count = 0; - return READ_OK; - } - - /* - * For now trigger extending execution via this hook - * like we do in the Data_file_system. - */ - _w.execute(); - - Wrapper::Extending const & extending { - _w.extending_progress() }; - - if (extending.idle()) { - Content_string const content { "idle" }; - copy_content(content, dst.start, dst.num_bytes); - out_count = dst.num_bytes; - return READ_OK; - } - - if (extending.in_progress()) { - char const * const type = - Wrapper::Extending::type_to_string(extending.type); - Content_string const content { type, " at ", extending.percent_done, "%" }; - copy_content(content, dst.start, dst.num_bytes); - out_count = dst.num_bytes; - return READ_OK; - } - - return READ_ERR_IO; - } - - Write_result write(Const_byte_range_ptr const &, - size_t &) override - { - return WRITE_ERR_IO; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } - }; - - public: - - Extend_progress_file_system(Wrapper &w) - : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("")), - _w(w) - { - _w.manage_extend_progress_file_system(*this); - } - - static char const *type_name() { return "extend_progress"; } - char const *type() override { return type_name(); } - void trigger_watch_response() - { - _handle_registry.for_each([this] (Registered_watch_handle &handle) { - handle.watch_response(); }); - } - - Watch_result watch(char const *path, - Vfs_watch_handle **handle, - Allocator &alloc) override - { - if (!_single_file(path)) - return WATCH_ERR_UNACCESSIBLE; - - try { - *handle = new (alloc) - Registered_watch_handle(_handle_registry, *this, alloc); - - return WATCH_OK; - } - catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } - catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } - } - - void close(Vfs_watch_handle *handle) override - { - destroy(handle->alloc(), - static_cast(handle)); - } - - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override + Open_result open(char const *path, unsigned, Vfs::Vfs_handle **out_handle, Allocator &alloc) override { if (!_single_file(path)) return OPEN_ERR_UNACCESSIBLE; try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); + *out_handle = new (alloc) Vfs_handle(*this, *this, alloc, _plugin); return OPEN_OK; } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } + catch (Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } + catch (Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } } Stat_result stat(char const *path, Stat &out) override { Stat_result result = Single_file_system::stat(path, out); - out.size = Content_string::size(); + out.size = Content_string::capacity(); return result; } - - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { return FTRUNCATE_OK; } }; -class Vfs_tresor::Rekey_file_system : public Vfs::Single_file_system +class Vfs_tresor::Rekey_file_system : private Noncopyable, public Single_file_system { private: - typedef Registered Registered_watch_handle; - typedef Registry Watch_handle_registry; + using Registered_watch_handle = Registered; + using Watch_handle_registry = Registry; Watch_handle_registry _handle_registry { }; - Wrapper &_w; + Plugin &_plugin; - using Content_string = String<32>; + using Content_string = String<11>; - static file_size copy_content(Content_string const &content, - char *dst, size_t const count) + class Vfs_handle : private Noncopyable, public Single_vfs_handle { - copy_cstring(dst, content.string(), count); - size_t const length_without_nul = content.length() - 1; - return count > length_without_nul - 1 ? length_without_nul - : count; - } + private: - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; + Plugin &_plugin; - /* store VBA in case the handle is kept open */ - Virtual_block_address _last_rekeying_vba; - - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w), - _last_rekeying_vba(_w.rekeying_progress().rekeying_vba) - { } - - Read_result read(Byte_range_ptr const &dst, size_t &out_count) override - { - /* EOF */ - if (seek() != 0) { - out_count = 0; - return READ_OK; - } - - /* - * For now trigger rekeying execution via this hook - * like we do in the Data_file_system. - */ - _w.execute(); - - Wrapper::Rekeying const & rekeying { - _w.rekeying_progress() }; - - if (rekeying.in_progress()) - return READ_QUEUED; - - if (rekeying.idle()) { - Content_string const content { - rekeying.success() ? "successful" - : "failed" }; - copy_content(content, dst.start, dst.num_bytes); + static Read_result _read_ok(Content_string const &content, Byte_range_ptr const &dst, size_t &out_count) + { + copy_cstring(dst.start, content.string(), dst.num_bytes); out_count = dst.num_bytes; return READ_OK; } - return READ_ERR_IO; - } + public: - Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override - { - if (!_w.rekeying_progress().idle()) { - return WRITE_ERR_IO; + Vfs_handle(Directory_service &dir_service, File_io_service &file_io_service, + Allocator &alloc, Plugin &plugin) + : + Single_vfs_handle(dir_service, file_io_service, alloc, 0), _plugin(plugin) + { } + + /*********************** + ** Single_vfs_handle ** + ***********************/ + + Read_result read(Byte_range_ptr const &dst, size_t &out_count) override + { + out_count = 0; + if (seek() == dst.num_bytes) { + return READ_OK; + } + if (seek() || dst.num_bytes < Content_string::capacity()) { + if (_plugin.verbose()) + log("reading rekey file failed: malformed arguments"); + return READ_ERR_IO; + } + Read_result result = READ_QUEUED; + _plugin.with_rekey_operation([&] (Rekey_operation &rekey_operation) { + + switch (rekey_operation.result()) { + case Rekey_operation::NONE: result = _read_ok("none", dst, out_count); break; + case Rekey_operation::SUCCEEDED: result = _read_ok("succeeded", dst, out_count); break; + case Rekey_operation::FAILED: result = _read_ok("failed", dst, out_count); break; + case Rekey_operation::PENDING: break; + } + }); + return result; } - bool start_rekeying { false }; - Genode::ascii_to(src.start, start_rekeying); + Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override + { + out_count = 0; + bool rekey_arg { false }; + Genode::ascii_to(src.start, rekey_arg); + if (seek() || !rekey_arg) { + if (_plugin.verbose()) + log("writing rekey file failed: malformed arguments"); + return WRITE_ERR_IO; + } + Write_result result = WRITE_ERR_IO; + _plugin.with_rekey_operation([&] (Rekey_operation &rekey_operation) { - if (!start_rekeying) { - return WRITE_ERR_IO; + if (!rekey_operation.request()) { + result = WRITE_ERR_IO; + if (_plugin.verbose()) + log("writing rekey file failed: failed to request operation"); + return; + } + out_count = src.num_bytes; + result = WRITE_OK; + }); + return result; } - if (!_w.start_rekeying()) { - return WRITE_ERR_IO; - } - - out_count = src.num_bytes; - return WRITE_OK; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } + bool read_ready() const override { return true; } + bool write_ready() const override { return true; } }; public: - Rekey_file_system(Wrapper &w) + Rekey_file_system(Plugin &plugin) : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("")), - _w(w) + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _plugin(plugin) { - _w.manage_rekey_file_system(*this); + _plugin.manage_rekey_file_system(*this); } static char const *type_name() { return "rekey"; } - char const *type() override { return type_name(); } - void trigger_watch_response() { _handle_registry.for_each([this] (Registered_watch_handle &handle) { handle.watch_response(); }); } - Watch_result watch(char const *path, - Vfs_watch_handle **handle, - Allocator &alloc) override - { - if (!_single_file(path)) - return WATCH_ERR_UNACCESSIBLE; - - try { - *handle = new (alloc) - Registered_watch_handle(_handle_registry, *this, alloc); - - return WATCH_OK; - } - catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } - catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } - } - - void close(Vfs_watch_handle *handle) override - { - destroy(handle->alloc(), - static_cast(handle)); - } - - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override - { - if (!_single_file(path)) - return OPEN_ERR_UNACCESSIBLE; - - try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); - return OPEN_OK; - } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } - } - - Stat_result stat(char const *path, Stat &out) override - { - Stat_result result = Single_file_system::stat(path, out); - out.size = Content_string::size(); - return result; - } - - - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } -}; - - -class Vfs_tresor::Rekey_progress_file_system : public Vfs::Single_file_system -{ - private: - - typedef Registered Registered_watch_handle; - typedef Registry Watch_handle_registry; - - Watch_handle_registry _handle_registry { }; - - Wrapper &_w; - - using Content_string = String<32>; - - static file_size copy_content(Content_string const &content, - char *dst, size_t const count) - { - copy_cstring(dst, content.string(), count); - size_t const length_without_nul = content.length() - 1; - return count > length_without_nul - 1 ? length_without_nul - : count; - } - - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; - - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w) - { } - - Read_result read(Byte_range_ptr const &dst, - size_t &out_count) override - { - /* EOF */ - if (seek() != 0) { - out_count = 0; - return READ_OK; - } - - /* - * For now trigger rekeying execution via this hook - * like we do in the Data_file_system. - */ - _w.execute(); - - Wrapper::Rekeying const & rekeying { - _w.rekeying_progress() }; - - if (rekeying.idle()) { - Content_string const content { "idle" }; - copy_content(content, dst.start, dst.num_bytes); - out_count = dst.num_bytes; - return READ_OK; - } - - if (rekeying.in_progress()) { - Content_string const content { "at ", rekeying.percent_done, "%" }; - copy_content(content, dst.start, dst.num_bytes); - out_count = dst.num_bytes; - return READ_OK; - } - - return READ_ERR_IO; - } - - Write_result write(Const_byte_range_ptr const &, - size_t &) override - { - return WRITE_ERR_IO; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } - }; - - public: - - Rekey_progress_file_system(Wrapper &w) - : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("")), - _w(w) - { - _w.manage_rekey_progress_file_system(*this); - } - - static char const *type_name() { return "rekey_progress"; } + /************************ + ** Single_file_system ** + ************************/ char const *type() override { return type_name(); } - void trigger_watch_response() - { - _handle_registry.for_each([this] (Registered_watch_handle &handle) { - handle.watch_response(); }); - } - - Watch_result watch(char const *path, - Vfs_watch_handle **handle, - Allocator &alloc) override + Watch_result watch(char const *path, Vfs_watch_handle **handle, Allocator &alloc) override { if (!_single_file(path)) return WATCH_ERR_UNACCESSIBLE; try { - *handle = new (alloc) - Registered_watch_handle(_handle_registry, *this, alloc); - + *handle = new (alloc) Registered_watch_handle(_handle_registry, *this, alloc); return WATCH_OK; } - catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } + catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } } void close(Vfs_watch_handle *handle) override { - destroy(handle->alloc(), - static_cast(handle)); + destroy(handle->alloc(), static_cast(handle)); } - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override + Open_result open(char const *path, unsigned, Vfs::Vfs_handle **out_handle, Allocator &alloc) override { if (!_single_file(path)) return OPEN_ERR_UNACCESSIBLE; try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); + *out_handle = new (alloc) Vfs_handle(*this, *this, alloc, _plugin); return OPEN_OK; } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } + catch (Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } + catch (Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } } Stat_result stat(char const *path, Stat &out) override { Stat_result result = Single_file_system::stat(path, out); - out.size = Content_string::size(); + out.size = Content_string::capacity(); return result; } - - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { return FTRUNCATE_OK; } }; -class Vfs_tresor::Deinitialize_file_system : public Vfs::Single_file_system +class Vfs_tresor::Deinitialize_file_system : private Noncopyable, public Single_file_system { private: - typedef Registered Registered_watch_handle; - typedef Registry Watch_handle_registry; + using Registered_watch_handle = Registered; + using Watch_handle_registry = Registry; + using Content_string = String<11>; Watch_handle_registry _handle_registry { }; + Plugin &_plugin; - Wrapper &_w; - - using Content_string = String<32>; - - static Content_string content_string(Wrapper const &wrapper) + class Vfs_handle : public Single_vfs_handle { - Wrapper::Deinitialize const & deinitialize_progress { - wrapper.deinitialize_progress() }; + private: - bool const in_progress { deinitialize_progress.in_progress() }; + Plugin &_plugin; - bool const last_result { - !in_progress && - deinitialize_progress.last_result != - Wrapper::Deinitialize::Result::NONE }; - - bool const success { deinitialize_progress.success() }; - - Content_string const result { - Wrapper::Deinitialize::state_to_cstring(deinitialize_progress.state), - " last-result:", - last_result ? success ? "success" : "failed" : "none", - "\n" }; - - return result; - } - - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; - - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w) - { } - - Read_result read(Byte_range_ptr const &dst, size_t &out_count) override - { - if (seek() != 0) { - out_count = 0; + static Read_result _read_ok(Content_string const &content, Byte_range_ptr const &dst, size_t &out_count) + { + copy_cstring(dst.start, content.string(), dst.num_bytes); + out_count = dst.num_bytes; return READ_OK; } - _w.execute(); - Wrapper::Deinitialize const & deinitialize_progress { - _w.deinitialize_progress() }; + public: - if (deinitialize_progress.in_progress()) - return READ_QUEUED; + Vfs_handle(Directory_service &dir_service, File_io_service &file_io_service, + Allocator &alloc, Plugin &plugin) + : + Single_vfs_handle(dir_service, file_io_service, alloc, 0), _plugin(plugin) + { } - Content_string const result { content_string(_w) }; - copy_cstring(dst.start, result.string(), dst.num_bytes); - out_count = dst.num_bytes; + /*********************** + ** Single_vfs_handle ** + ***********************/ - return READ_OK; - } + Read_result read(Byte_range_ptr const &dst, size_t &out_count) override + { + out_count = 0; + if (seek() == dst.num_bytes) { + return READ_OK; + } + if (seek() || dst.num_bytes < Content_string::capacity()) { + if (_plugin.verbose()) + log("reading deinitialize file failed: malformed arguments"); + return READ_ERR_IO; + } + Read_result result = READ_QUEUED; + _plugin.with_deinit_operation([&] (Deinitialize_operation &deinit_operation) { - Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override - { - if (!_w.deinitialize_progress().idle()) { - return WRITE_ERR_IO; + switch (deinit_operation.result()) { + case Deinitialize_operation::NONE: result = _read_ok("none", dst, out_count); break; + case Deinitialize_operation::SUCCEEDED: result = _read_ok("succeeded", dst, out_count); break; + case Deinitialize_operation::FAILED: result = _read_ok("failed", dst, out_count); break; + case Deinitialize_operation::PENDING: break; + } + }); + return result; } - bool start_deinitialize { false }; - Genode::ascii_to(src.start, start_deinitialize); + Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override + { + out_count = 0; + bool deinitialize_arg { false }; + Genode::ascii_to(src.start, deinitialize_arg); + if (seek() || !deinitialize_arg) { + if (_plugin.verbose()) + log("writing deinitialize file failed: malformed arguments"); - if (!start_deinitialize) { - return WRITE_ERR_IO; + return WRITE_ERR_IO; + } + Write_result result = WRITE_ERR_IO; + _plugin.with_deinit_operation([&] (Deinitialize_operation &deinit_operation) { + + if (!deinit_operation.request()) { + result = WRITE_ERR_IO; + if (_plugin.verbose()) + log("writing deinitialize file failed: failed to request operation"); + return; + } + out_count = src.num_bytes; + result = WRITE_OK; + }); + return result; } - if (!_w.start_deinitialize()) { - return WRITE_ERR_IO; - } - - out_count = src.num_bytes; - return WRITE_OK; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } + bool read_ready() const override { return true; } + bool write_ready() const override { return true; } }; public: - Deinitialize_file_system(Wrapper &w) + Deinitialize_file_system(Plugin &plugin) : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("")), - _w(w) + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _plugin(plugin) { - _w.manage_deinit_file_system(*this); + _plugin.manage_deinit_file_system(*this); } static char const *type_name() { return "deinitialize"; } - char const *type() override { return type_name(); } - void trigger_watch_response() { _handle_registry.for_each([this] (Registered_watch_handle &handle) { handle.watch_response(); }); } - Watch_result watch(char const *path, - Vfs_watch_handle **handle, - Allocator &alloc) override + /************************ + ** Single_file_system ** + ************************/ + + char const *type() override { return type_name(); } + + Watch_result watch(char const *path, Vfs_watch_handle **handle, Allocator &alloc) override { if (!_single_file(path)) return WATCH_ERR_UNACCESSIBLE; try { - *handle = new (alloc) - Registered_watch_handle(_handle_registry, *this, alloc); - + *handle = new (alloc) Registered_watch_handle(_handle_registry, *this, alloc); return WATCH_OK; } - catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } + catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } } void close(Vfs_watch_handle *handle) override { - destroy(handle->alloc(), - static_cast(handle)); + destroy(handle->alloc(), static_cast(handle)); } - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override + Open_result open(char const *path, unsigned, Vfs::Vfs_handle **out_handle, Allocator &alloc) override { if (!_single_file(path)) return OPEN_ERR_UNACCESSIBLE; try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); + *out_handle = new (alloc) Vfs_handle(*this, *this, alloc, _plugin); return OPEN_OK; } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } + catch (Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } + catch (Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } } Stat_result stat(char const *path, Stat &out) override { Stat_result result = Single_file_system::stat(path, out); - out.size = content_string(_w).length() - 1; + out.size = Content_string::capacity(); return result; } - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { return FTRUNCATE_OK; } }; -class Vfs_tresor::Create_snapshot_file_system : public Vfs::Single_file_system +class Vfs_tresor::Current_local_factory : private Noncopyable, public File_system_factory { private: - Wrapper &_w; + Data_file_system _data_fs; - struct Vfs_handle : Single_vfs_handle + /************************* + ** File_system_factory ** + *************************/ + + Vfs::File_system *create(Vfs::Env&, Xml_node node) override { - Wrapper &_w; + if (node.has_type(Data_file_system::type_name())) + return &_data_fs; - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w) - { } - - Read_result read(Byte_range_ptr const &, size_t &) override - { - return READ_ERR_IO; - } - - Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override - { - bool create_snapshot { false }; - Genode::ascii_to(src.start, create_snapshot); - Genode::String<64> str(Genode::Cstring(src.start, src.num_bytes)); - if (!create_snapshot) - return WRITE_ERR_IO; - - if (!_w.create_snapshot()) { - out_count = 0; - return WRITE_OK; - } - out_count = src.num_bytes; - return WRITE_OK; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } - }; + return nullptr; + } public: - Create_snapshot_file_system(Wrapper &w) - : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::wo(), Xml_node("")), - _w(w) - { } - - static char const *type_name() { return "create_snapshot"; } - - char const *type() override { return type_name(); } - - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override - { - if (!_single_file(path)) - return OPEN_ERR_UNACCESSIBLE; - - try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); - return OPEN_OK; - } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } - } - - Stat_result stat(char const *path, Stat &out) override - { - Stat_result result = Single_file_system::stat(path, out); - return result; - } - - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } + Current_local_factory(Vfs::Env &, Plugin &plugin) : _data_fs(plugin) { } }; -class Vfs_tresor::Discard_snapshot_file_system : public Vfs::Single_file_system +class Vfs_tresor::Current_file_system : private Current_local_factory, public Dir_file_system { private: - Wrapper &_w; + using Config = String<128>; - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; - - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w) - { } - - Read_result read(Byte_range_ptr const &, size_t &) override - { - return READ_ERR_IO; - } - - Write_result write(Const_byte_range_ptr const &src, - size_t &out_count) override - { - out_count = 0; - Generation snap_gen { INVALID_GENERATION }; - Genode::ascii_to(src.start, snap_gen); - if (snap_gen == INVALID_GENERATION) - return WRITE_ERR_IO; - - if (!_w.discard_snapshot(snap_gen)) { - out_count = 0; - return WRITE_OK; - } - return WRITE_ERR_IO; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } - }; - - public: - - Discard_snapshot_file_system(Wrapper &w) - : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::wo(), Xml_node("")), - _w(w) - { } - - static char const *type_name() { return "discard_snapshot"; } - - char const *type() override { return type_name(); } - - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override - { - if (!_single_file(path)) - return OPEN_ERR_UNACCESSIBLE; - - try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); - return OPEN_OK; - } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } - } - - Stat_result stat(char const *path, Stat &out) override - { - Stat_result result = Single_file_system::stat(path, out); - return result; - } - - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } -}; - - -struct Vfs_tresor::Snapshot_local_factory : File_system_factory -{ - Data_file_system _block_fs; - - Snapshot_local_factory(Vfs::Env & /* env */, - Wrapper &tresor, - Generation snap_gen) - : _block_fs(tresor, snap_gen) { } - - Vfs::File_system *create(Vfs::Env&, Xml_node node) override - { - if (node.has_type(Data_file_system::type_name())) - return &_block_fs; - - return nullptr; - } -}; - - -class Vfs_tresor::Snapshot_file_system : private Snapshot_local_factory, - public Vfs::Dir_file_system -{ - private: - - Generation _snap_gen; - - typedef String<128> Config; - - static Config _config(Generation snap_gen, bool readonly) + static Config _config() { char buf[Config::capacity()] { }; - - Xml_generator xml(buf, sizeof(buf), "dir", [&] () { - - xml.attribute("name", !readonly ? String<16>("current") : String<16>(snap_gen)); + Xml_generator xml(buf, sizeof(buf), "dir", [&] () + { + xml.attribute("name", String<16>("current")); xml.node("data", [&] () { - xml.attribute("readonly", readonly); + xml.attribute("readonly", false); }); }); @@ -2393,895 +1540,397 @@ class Vfs_tresor::Snapshot_file_system : private Snapshot_local_factory, public: - Snapshot_file_system(Vfs::Env &vfs_env, - Wrapper &tresor, - Generation snap_gen, - bool readonly = false) + Current_file_system(Vfs::Env &vfs_env, Plugin &plugin) : - Snapshot_local_factory(vfs_env, tresor, snap_gen), - Vfs::Dir_file_system(vfs_env, Xml_node(_config(snap_gen, readonly).string()), *this), - _snap_gen(snap_gen) + Current_local_factory(vfs_env, plugin), + Dir_file_system(vfs_env, Xml_node(_config().string()), *this) { } - static char const *type_name() { return "snapshot"; } + static char const *type_name() { return "current"; } + + /********************* + ** Dir_file_system ** + *********************/ char const *type() override { return type_name(); } - - Generation snap_gen() const { return _snap_gen; } }; -class Vfs_tresor::Snapshots_file_system : public Vfs::File_system +class Vfs_tresor::Control_local_factory : private Noncopyable, public File_system_factory { private: - typedef Registered Registered_watch_handle; - typedef Registry Watch_handle_registry; - - Watch_handle_registry _handle_registry { }; - - Vfs::Env &_vfs_env; - - bool _root_dir(char const *path) { return strcmp(path, "/snapshots") == 0; } - bool _top_dir(char const *path) { return strcmp(path, "/") == 0; } - - struct Snapshot_registry - { - Genode::Allocator &_alloc; - Wrapper &_wrapper; - Snapshots_file_system &_snapshots_fs; - uint32_t _number_of_snapshots { 0 }; - Genode::Registry> _registry { }; - - struct Invalid_index : Genode::Exception { }; - struct Invalid_path : Genode::Exception { }; - - - - Snapshot_registry(Genode::Allocator &alloc, - Wrapper &wrapper, - Snapshots_file_system &snapshots_fs) - : - _alloc { alloc }, - _wrapper { wrapper }, - _snapshots_fs { snapshots_fs } - { } - - void update(Vfs::Env &vfs_env); - - uint32_t number_of_snapshots() const { return _number_of_snapshots; } - - Snapshot_file_system const &by_index(uint64_t idx) const - { - uint64_t i = 0; - Snapshot_file_system const *fsp { nullptr }; - auto lookup = [&] (Snapshot_file_system const &fs) { - if (i == idx) { - fsp = &fs; - } - ++i; - }; - _registry.for_each(lookup); - if (fsp == nullptr) { - throw Invalid_index(); - } - return *fsp; - } - - Snapshot_file_system &_by_gen(Generation snap_gen) - { - Snapshot_file_system *fsp { nullptr }; - auto lookup = [&] (Snapshot_file_system &fs) { - if (fs.snap_gen() == snap_gen) { - fsp = &fs; - } - }; - _registry.for_each(lookup); - if (fsp == nullptr) - throw Invalid_path(); - - return *fsp; - } - - Snapshot_file_system &by_path(char const *path) - { - if (!path) - throw Invalid_path(); - - if (path[0] == '/') - path++; - - Generation snap_gen { INVALID_GENERATION }; - Genode::ascii_to(path, snap_gen); - return _by_gen(snap_gen); - } - }; + Plugin &_plugin; + Rekey_file_system _rekey_fs; + Deinitialize_file_system _deinitialize_fs; + Extend_file_system _extend_fs; public: - void update_snapshot_registry() - { - _snap_reg.update(_vfs_env); - } - - void trigger_watch_response() - { - _handle_registry.for_each([this] (Registered_watch_handle &handle) { - handle.watch_response(); }); - } - - Watch_result watch(char const *path, - Vfs_watch_handle **handle, - Allocator &alloc) override - { - if (!_root_dir(path)) - return WATCH_ERR_UNACCESSIBLE; - - try { - *handle = new (alloc) - Registered_watch_handle(_handle_registry, *this, alloc); - - return WATCH_OK; - } - catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } - catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } - } - - void close(Vfs_watch_handle *handle) override - { - destroy(handle->alloc(), - static_cast(handle)); - } - - struct Snap_vfs_handle : Vfs::Vfs_handle - { - using Vfs_handle::Vfs_handle; - - virtual Read_result read(Byte_range_ptr const &, size_t &out_count) = 0; - - virtual Write_result write(Const_byte_range_ptr const &, size_t &out_count) = 0; - - virtual Sync_result sync() - { - return SYNC_OK; - } - - virtual bool read_ready() const = 0; - }; - - - struct Dir_vfs_handle : Snap_vfs_handle - { - Snapshot_registry const &_snap_reg; - - bool const _root_dir { false }; - - Read_result _query_snapshots(size_t index, - size_t &out_count, - Dirent &out) - { - if (index >= _snap_reg.number_of_snapshots()) { - out_count = sizeof(Dirent); - out.type = Dirent_type::END; - return READ_OK; - } - - try { - Snapshot_file_system const &fs = _snap_reg.by_index(index); - Genode::String<32> name { fs.snap_gen() }; - - out = { - .fileno = (Genode::addr_t)this | index, - .type = Dirent_type::DIRECTORY, - .rwx = Node_rwx::rx(), - .name = { name.string() }, - }; - out_count = sizeof(Dirent); - return READ_OK; - } catch (Snapshot_registry::Invalid_index) { - return READ_ERR_INVALID; - } - } - - Read_result _query_root(size_t index, - size_t &out_count, - Dirent &out) - { - if (index == 0) { - out = { - .fileno = (Genode::addr_t)this, - .type = Dirent_type::DIRECTORY, - .rwx = Node_rwx::rx(), - .name = { "snapshots" } - }; - } else { - out.type = Dirent_type::END; - } - - out_count = sizeof(Dirent); - return READ_OK; - } - - Dir_vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Snapshot_registry const &snap_reg, - bool root_dir) - : - Snap_vfs_handle(ds, fs, alloc, 0), - _snap_reg(snap_reg), _root_dir(root_dir) - { } - - Read_result read(Byte_range_ptr const &dst, size_t &out_count) override - { - out_count = 0; - - if (dst.num_bytes < sizeof(Dirent)) - return READ_ERR_INVALID; - - size_t index = size_t(seek() / sizeof(Dirent)); - - Dirent &out = *(Dirent*)dst.start; - - if (!_root_dir) { - - /* opended as "/snapshots" */ - return _query_snapshots(index, out_count, out); - - } else { - /* opened as "/" */ - return _query_root(index, out_count, out); - } - } - - Write_result write(Const_byte_range_ptr const &, size_t &) override - { - return WRITE_ERR_INVALID; - } - - bool read_ready() const override { return true; } - }; - - struct Dir_snap_vfs_handle : Vfs::Vfs_handle - { - Vfs_handle &vfs_handle; - - Dir_snap_vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Vfs::Vfs_handle &vfs_handle) - : Vfs_handle(ds, fs, alloc, 0), vfs_handle(vfs_handle) { } - - ~Dir_snap_vfs_handle() - { - vfs_handle.close(); - } - }; - - Snapshot_registry _snap_reg; - Wrapper &_wrapper; - - char const *_sub_path(char const *path) const - { - /* skip heading slash in path if present */ - if (path[0] == '/') { - path++; - } - - Genode::size_t const name_len = strlen(type_name()); - if (strcmp(path, type_name(), name_len) != 0) { - return nullptr; - } - - path += name_len; - - /* - * The first characters of the first path element are equal to - * the current directory name. Let's check if the length of the - * first path element matches the name length. - */ - if (*path != 0 && *path != '/') { - return 0; - } - - return path; - } - - - Snapshots_file_system(Vfs::Env &vfs_env, - Genode::Xml_node /* node */, - Wrapper &wrapper) + Control_local_factory(Vfs::Env &, Xml_node, Plugin &plugin) : - _vfs_env { vfs_env }, - _snap_reg { vfs_env.alloc(), wrapper, *this }, - _wrapper { wrapper } + _plugin(plugin), _rekey_fs(plugin), _deinitialize_fs(plugin), _extend_fs(plugin) + { } + + ~Control_local_factory() { - _wrapper.manage_snapshots_file_system(*this); + _plugin.dissolve_rekey_file_system(_rekey_fs); + _plugin.dissolve_deinit_file_system(_deinitialize_fs); + _plugin.dissolve_extend_file_system(_extend_fs); } - static char const *type_name() { return "snapshots"; } + /************************* + ** File_system_factory ** + *************************/ - char const *type() override { return type_name(); } - - - /********************************* - ** Directory service interface ** - *********************************/ - - Dataspace_capability dataspace(char const * /* path */) override + Vfs::File_system *create(Vfs::Env&, Xml_node node) override { - return Genode::Dataspace_capability(); - } + if (node.has_type(Rekey_file_system::type_name())) + return &_rekey_fs; - void release(char const * /* path */, Dataspace_capability) override - { - } + if (node.has_type(Deinitialize_file_system::type_name())) + return &_deinitialize_fs; - Open_result open(char const *path, - unsigned mode, - Vfs::Vfs_handle **out_handle, - Allocator &alloc) override - { - path = _sub_path(path); - if (!path || path[0] != '/') { - return OPEN_ERR_UNACCESSIBLE; - } - - try { - Snapshot_file_system &fs = _snap_reg.by_path(path); - return fs.open(path, mode, out_handle, alloc); - } catch (Snapshot_registry::Invalid_path) { } - - return OPEN_ERR_UNACCESSIBLE; - } - - Opendir_result opendir(char const *path, - bool create, - Vfs::Vfs_handle **out_handle, - Allocator &alloc) override - { - if (create) { - return OPENDIR_ERR_PERMISSION_DENIED; - } - - bool const top = _top_dir(path); - if (_root_dir(path) || top) { - _snap_reg.update(_vfs_env); - - *out_handle = new (alloc) Dir_vfs_handle(*this, *this, alloc, - _snap_reg, top); - return OPENDIR_OK; - } else { - char const *sub_path = _sub_path(path); - if (!sub_path) { - return OPENDIR_ERR_LOOKUP_FAILED; - } - try { - Snapshot_file_system &fs = _snap_reg.by_path(sub_path); - Vfs::Vfs_handle *handle = nullptr; - Opendir_result const res = fs.opendir(sub_path, create, &handle, alloc); - if (res != OPENDIR_OK) { - return OPENDIR_ERR_LOOKUP_FAILED; - } - *out_handle = new (alloc) Dir_snap_vfs_handle(*this, *this, - alloc, *handle); - return OPENDIR_OK; - } catch (Snapshot_registry::Invalid_path) { } - } - return OPENDIR_ERR_LOOKUP_FAILED; - } - - void close(Vfs_handle *handle) override - { - if (handle && (&handle->ds() == this)) - destroy(handle->alloc(), handle); - } - - Stat_result stat(char const *path, Stat &out_stat) override - { - out_stat = Stat { }; - path = _sub_path(path); - - /* path does not match directory name */ - if (!path) { - return STAT_ERR_NO_ENTRY; - } - - /* - * If path equals directory name, return information about the - * current directory. - */ - if (strlen(path) == 0 || _top_dir(path)) { - - out_stat.type = Node_type::DIRECTORY; - out_stat.inode = 1; - out_stat.device = (Genode::addr_t)this; - return STAT_OK; - } - - if (!path || path[0] != '/') { - return STAT_ERR_NO_ENTRY; - } - - try { - Snapshot_file_system &fs = _snap_reg.by_path(path); - Stat_result const res = fs.stat(path, out_stat); - return res; - } catch (Snapshot_registry::Invalid_path) { } - - return STAT_ERR_NO_ENTRY; - } - - Unlink_result unlink(char const * /* path */) override - { - return UNLINK_ERR_NO_PERM; - } - - Rename_result rename(char const * /* from */, char const * /* to */) override - { - return RENAME_ERR_NO_PERM; - } - - file_size num_dirent(char const *path) override - { - if (_top_dir(path)) { - return 1; - } - if (_root_dir(path)) { - _snap_reg.update(_vfs_env); - file_size const num = _snap_reg.number_of_snapshots(); - return num; - } - _snap_reg.update(_vfs_env); - - path = _sub_path(path); - if (!path) { - return 0; - } - try { - Snapshot_file_system &fs = _snap_reg.by_path(path); - file_size const num = fs.num_dirent(path); - return num; - } catch (Snapshot_registry::Invalid_path) { - return 0; - } - } - - bool directory(char const *path) override - { - if (_root_dir(path)) { - return true; - } - - path = _sub_path(path); - if (!path) { - return false; - } - try { - Snapshot_file_system &fs = _snap_reg.by_path(path); - return fs.directory(path); - } catch (Snapshot_registry::Invalid_path) { } - - return false; - } - - char const *leaf_path(char const *path) override - { - path = _sub_path(path); - if (!path) { - return nullptr; - } - - if (strlen(path) == 0 || strcmp(path, "") == 0) { - return path; - } - - try { - Snapshot_file_system &fs = _snap_reg.by_path(path); - char const *leaf_path = fs.leaf_path(path); - if (leaf_path) { - return leaf_path; - } - } catch (Snapshot_registry::Invalid_path) { } + if (node.has_type(Extend_file_system::type_name())) + return &_extend_fs; return nullptr; } - - - /******************************** - ** File I/O service interface ** - ********************************/ - - Write_result write(Vfs::Vfs_handle * /* vfs_handle */, - Const_byte_range_ptr const &, size_t & /* out_count */) override - { - return WRITE_ERR_IO; - } - - bool queue_read(Vfs::Vfs_handle *vfs_handle, size_t size) override - { - Dir_snap_vfs_handle *dh = - dynamic_cast(vfs_handle); - if (dh) { - return dh->vfs_handle.fs().queue_read(&dh->vfs_handle, size); - } - - return true; - } - - Read_result complete_read(Vfs::Vfs_handle *vfs_handle, - Byte_range_ptr const &dst, - size_t & out_count) override - { - Snap_vfs_handle *sh = - dynamic_cast(vfs_handle); - if (sh) { - Read_result const res = sh->read(dst, out_count); - return res; - } - - Dir_snap_vfs_handle *dh = - dynamic_cast(vfs_handle); - if (dh) { - return dh->vfs_handle.fs().complete_read(&dh->vfs_handle, - dst, out_count); - } - - return READ_ERR_IO; - } - - bool read_ready(Vfs::Vfs_handle const &) const override { - return true; } - - bool write_ready(Vfs::Vfs_handle const &) const override { - return false; } - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } }; -struct Vfs_tresor::Control_local_factory : File_system_factory -{ - Wrapper &_wrapper; - Rekey_file_system _rekeying_fs; - Rekey_progress_file_system _rekeying_progress_fs; - Deinitialize_file_system _deinitialize_fs; - Create_snapshot_file_system _create_snapshot_fs; - Discard_snapshot_file_system _discard_snapshot_fs; - Extend_file_system _extend_fs; - Extend_progress_file_system _extend_progress_fs; - - Control_local_factory(Vfs::Env & /* env */, - Xml_node /* config */, - Wrapper & wrapper) - : - _wrapper(wrapper), - _rekeying_fs(wrapper), - _rekeying_progress_fs(wrapper), - _deinitialize_fs(wrapper), - _create_snapshot_fs(wrapper), - _discard_snapshot_fs(wrapper), - _extend_fs(wrapper), - _extend_progress_fs(wrapper) - { } - - ~Control_local_factory() - { - _wrapper.dissolve_rekey_file_system(_rekeying_fs); - _wrapper.dissolve_rekey_progress_file_system(_rekeying_progress_fs); - _wrapper.dissolve_deinit_file_system(_deinitialize_fs); - _wrapper.dissolve_extend_file_system(_extend_fs); - _wrapper.dissolve_extend_progress_file_system(_extend_progress_fs); - } - - Vfs::File_system *create(Vfs::Env&, Xml_node node) override - { - if (node.has_type(Rekey_file_system::type_name())) { - return &_rekeying_fs; - } - - if (node.has_type(Rekey_progress_file_system::type_name())) { - return &_rekeying_progress_fs; - } - - if (node.has_type(Deinitialize_file_system::type_name())) { - return &_deinitialize_fs; - } - - if (node.has_type(Create_snapshot_file_system::type_name())) { - return &_create_snapshot_fs; - } - - if (node.has_type(Discard_snapshot_file_system::type_name())) { - return &_discard_snapshot_fs; - } - - if (node.has_type(Extend_file_system::type_name())) { - return &_extend_fs; - } - - if (node.has_type(Extend_progress_file_system::type_name())) { - return &_extend_progress_fs; - } - - return nullptr; - } -}; - - -class Vfs_tresor::Control_file_system : private Control_local_factory, - public Vfs::Dir_file_system +class Vfs_tresor::Control_file_system : private Control_local_factory, public Dir_file_system { private: - typedef String<256> Config; + using Config = String<256>; - static Config _config(Xml_node /* node */) + static Config _config() { char buf[Config::capacity()] { }; - Xml_generator xml(buf, sizeof(buf), "dir", [&] () { xml.attribute("name", "control"); xml.node("rekey", [&] () { }); - xml.node("rekey_progress", [&] () { }); xml.node("extend", [&] () { }); - xml.node("extend_progress", [&] () { }); - xml.node("create_snapshot", [&] () { }); - xml.node("discard_snapshot", [&] () { }); xml.node("deinitialize", [&] () { }); }); - return Config(Cstring(buf)); } public: - Control_file_system(Vfs::Env &vfs_env, - Genode::Xml_node node, - Wrapper &tresor) + Control_file_system(Vfs::Env &vfs_env, Xml_node node, Plugin &plugin) : - Control_local_factory(vfs_env, node, tresor), - Vfs::Dir_file_system(vfs_env, Xml_node(_config(node).string()), - *this) + Control_local_factory(vfs_env, node, plugin), + Dir_file_system(vfs_env, Xml_node(_config().string()), *this) { } static char const *type_name() { return "control"; } + /********************* + ** Dir_file_system ** + *********************/ + char const *type() override { return type_name(); } }; -struct Vfs_tresor::Local_factory : File_system_factory -{ - Wrapper &_wrapper; - Snapshot_file_system _current_snapshot_fs; - Snapshots_file_system _snapshots_fs; - Control_file_system _control_fs; - - Local_factory(Vfs::Env &env, Xml_node config, - Wrapper &wrapper) - : - _wrapper(wrapper), - _current_snapshot_fs(env, wrapper, 0, false), - _snapshots_fs(env, config, wrapper), - _control_fs(env, config, wrapper) - { } - - ~Local_factory() - { - _wrapper.dissolve_snapshots_file_system(_snapshots_fs); - } - - Vfs::File_system *create(Vfs::Env&, Xml_node node) override - { - using Name = String<64>; - if (node.has_type(Snapshot_file_system::type_name()) - && node.attribute_value("name", Name()) == "current") - return &_current_snapshot_fs; - - if (node.has_type(Control_file_system::type_name())) - return &_control_fs; - - if (node.has_type(Snapshots_file_system::type_name())) - return &_snapshots_fs; - - return nullptr; - } -}; - - -class Vfs_tresor::File_system : private Local_factory, - public Vfs::Dir_file_system +class Vfs_tresor::Local_factory : private Noncopyable, public File_system_factory { private: - Wrapper &_wrapper; + Plugin &_plugin; + Current_file_system _current_fs; + Control_file_system _control_fs; - typedef String<256> Config; + public: + + Local_factory(Vfs::Env &vfs_env, Xml_node config, Plugin &plugin) + : + _plugin(plugin), _current_fs(vfs_env, plugin), _control_fs(vfs_env, config, plugin) + { } + + /************************* + ** File_system_factory ** + *************************/ + + Vfs::File_system *create(Vfs::Env&, Xml_node node) override + { + if (node.has_type(Current_file_system::type_name())) + return &_current_fs; + + if (node.has_type(Control_file_system::type_name())) + return &_control_fs; + + return nullptr; + } +}; + + +class Vfs_tresor::File_system : private Local_factory, public Dir_file_system +{ + private: + + using Config = String<256>; + + Plugin &_plugin; static Config _config(Xml_node node) { char buf[Config::capacity()] { }; - - Xml_generator xml(buf, sizeof(buf), "dir", [&] () { - typedef String<64> Name; - - xml.attribute("name", - node.attribute_value("name", - Name("tresor"))); - + Xml_generator xml(buf, sizeof(buf), "dir", [&] () + { + xml.attribute("name", node.attribute_value("name", String<64>("tresor"))); xml.node("control", [&] () { }); - - xml.node("snapshot", [&] () { - xml.attribute("name", "current"); - }); - - xml.node("snapshots", [&] () { }); + xml.node("current", [&] () { }); }); - return Config(Cstring(buf)); } public: - File_system(Vfs::Env &vfs_env, Genode::Xml_node node, - Wrapper &wrapper) + File_system(Vfs::Env &vfs_env, Xml_node node, Plugin &plugin) : - Local_factory(vfs_env, node, wrapper), - Vfs::Dir_file_system(vfs_env, Xml_node(_config(node).string()), - *this), - _wrapper(wrapper) + Local_factory(vfs_env, node, plugin), + Dir_file_system(vfs_env, Xml_node(_config(node).string()), *this), + _plugin(plugin) { } - - ~File_system() - { - // XXX rather then destroying the wrapper here, it should be - // done on the out-side where it was allocated in the first - // place but the factory interface does not support that yet - // destroy(vfs_env.alloc().alloc()), &_wrapper); - } }; -/************************** - ** VFS plugin interface ** - **************************/ - -extern "C" Vfs::File_system_factory *vfs_file_system_factory(void) +bool Vfs_tresor::Rekey_operation::execute(Execute_attr const &attr) { - struct Factory : Vfs::File_system_factory - { - Vfs::File_system *create(Vfs::Env &vfs_env, - Genode::Xml_node node) override - { - try { - /* XXX wrapper is not managed and will leak */ - Vfs_tresor::Wrapper *wrapper = - new (vfs_env.alloc()) Vfs_tresor::Wrapper { vfs_env, node }; - return new (vfs_env.alloc()) - Vfs_tresor::File_system(vfs_env, node, *wrapper); - } catch (...) { - Genode::error("could not create 'tresor_fs' "); + bool progress = false; + switch (_state) { + case STARTED: + + _rekey.construct(Superblock_control::Rekey::Attr{_complete}); + _state = REKEY; + progress = true; + if (_verbose) + log("rekey started"); + break; + + case REKEY: + + progress |= attr.sb_control.execute( + *_rekey, attr.vbd, attr.free_tree, attr.meta_tree, attr.block_io, attr.crypto, attr.trust_anchor); + + if (_rekey->complete()) { + if (_rekey->success()) { + if (_complete) { + _success = true; + _state = COMPLETE; + if (attr.rekey_fs_ptr) + attr.rekey_fs_ptr->trigger_watch_response(); + if (_verbose) + log("rekey succeeded"); + } else + _state = PAUSED; + } else { + _success = false; + _state = COMPLETE; + if (attr.rekey_fs_ptr) + attr.rekey_fs_ptr->trigger_watch_response(); + if (_verbose) + log("rekey failed"); } - return nullptr; + _rekey.destruct(); + progress = true; } + break; + + case RESUMED: + + _rekey.construct(Superblock_control::Rekey::Attr{_complete}); + _state = REKEY; + progress = true; + break; + + default: break; + } + return progress; +} + + +bool Vfs_tresor::Extend_operation::execute(Execute_attr const &attr) +{ + bool progress = false; + switch (_state) { + case EXTEND_FT_STARTED: + + _extend_ft.construct(Superblock_control::Extend_free_tree::Attr{_num_blocks, _complete}); + _state = EXTEND_FT; + progress = true; + if (_verbose) + log("extend free tree started"); + break; + + case EXTEND_FT: + + progress |= attr.sb_control.execute( + *_extend_ft, attr.free_tree, attr.meta_tree, attr.block_io, attr.trust_anchor); + + if (_extend_ft->complete()) { + if (_extend_ft->success()) { + if (_complete) { + _success = true; + _state = COMPLETE; + if (attr.extend_fs_ptr) + attr.extend_fs_ptr->trigger_watch_response(); + if (_verbose) + log("extend free tree succeeded"); + } else + _state = EXTEND_FT_PAUSED; + } else { + _success = false; + _state = COMPLETE; + if (attr.extend_fs_ptr) + attr.extend_fs_ptr->trigger_watch_response(); + if (_verbose) + log("extend free tree failed"); + } + _extend_ft.destruct(); + progress = true; + } + break; + + case EXTEND_FT_RESUMED: + + _extend_ft.construct(Superblock_control::Extend_free_tree::Attr{_num_blocks, _complete}); + _state = EXTEND_FT; + progress = true; + break; + + case EXTEND_VBD_STARTED: + + _extend_vbd.construct(Superblock_control::Extend_vbd::Attr{_num_blocks, _complete}); + _state = EXTEND_VBD; + progress = true; + if (_verbose) + log("extend virtual block device started"); + break; + + case EXTEND_VBD: + + progress |= attr.sb_control.execute( + *_extend_vbd, attr.vbd, attr.free_tree, attr.meta_tree, attr.block_io, attr.trust_anchor); + + if (_extend_vbd->complete()) { + if (_extend_vbd->success()) { + if (_complete) { + _success = true; + _state = COMPLETE; + if (attr.extend_fs_ptr) + attr.extend_fs_ptr->trigger_watch_response(); + if (_verbose) + log("extend virtual block device succeeded"); + } else + _state = EXTEND_VBD_PAUSED; + } else { + _success = false; + _state = COMPLETE; + if (attr.extend_fs_ptr) + attr.extend_fs_ptr->trigger_watch_response(); + if (_verbose) + log("extend virtual block device failed"); + } + _extend_vbd.destruct(); + progress = true; + } + break; + + case EXTEND_VBD_RESUMED: + + _extend_vbd.construct(Superblock_control::Extend_vbd::Attr{_num_blocks, _complete}); + _state = EXTEND_VBD; + progress = true; + break; + + default: break; + } + return progress; +} + + +bool Vfs_tresor::Deinitialize_operation::execute(Execute_attr const &attr) +{ + bool progress = false; + switch (_state) { + case STARTED: + + _deinit_sb_control.construct(Superblock_control::Deinitialize::Attr{}); + _state = DEINIT_SB_CONTROL; + progress = true; + if (_verbose) + log("deinitialize started"); + break; + + case DEINIT_SB_CONTROL: + + progress |= attr.sb_control.execute( + *_deinit_sb_control, attr.block_io, attr.crypto, attr.trust_anchor); + + if (_deinit_sb_control->complete()) { + if (_deinit_sb_control->success()) { + _success = true; + _state = COMPLETE; + if (_verbose) + log("deinitialize succeeded"); + } else { + _success = false; + _state = DEINIT_SB_CONTROL; + if (_verbose) + log("deinitialize failed"); + } + _deinit_sb_control.destruct(); + if (attr.deinit_fs_ptr) + attr.deinit_fs_ptr->trigger_watch_response(); + progress = true; + } + break; + + default: break; + } + return progress; +} + + +extern "C" File_system_factory *vfs_file_system_factory(void) +{ + class Factory : public File_system_factory + { + private: + + Allocator *_plugin_alloc_ptr { }; + Vfs_tresor::Plugin *_plugin_ptr { }; + + public: + + ~Factory() + { + if (_plugin_ptr) + destroy(_plugin_alloc_ptr, _plugin_ptr); + } + + /************************* + ** File_system_factory ** + *************************/ + + Vfs::File_system *create(Vfs::Env &vfs_env, Xml_node node) override + { + try { + if (!_plugin_ptr) { + _plugin_alloc_ptr = &vfs_env.alloc(); + _plugin_ptr = new (_plugin_alloc_ptr) Vfs_tresor::Plugin { vfs_env, node }; + } + return new (vfs_env.alloc()) Vfs_tresor::File_system(vfs_env, node, *_plugin_ptr); + + } catch (...) { error("could not create 'tresor_fs' "); } + return nullptr; + } }; - static Factory factory; + static Factory factory { }; return &factory; } - - -/********************** - ** Vfs_tresor::Wrapper ** - **********************/ - -void Vfs_tresor::Wrapper::_snapshots_fs_update_snapshot_registry() -{ - if (_snapshots_fs.valid()) { - _snapshots_fs.obj().update_snapshot_registry(); - } -} - - -void Vfs_tresor::Wrapper::_extend_fs_trigger_watch_response() -{ - if (_extend_fs.valid()) { - _extend_fs.obj().trigger_watch_response(); - } -} - - -void Vfs_tresor::Wrapper::_extend_progress_fs_trigger_watch_response() -{ - if (_extend_progress_fs.valid()) { - _extend_progress_fs.obj().trigger_watch_response(); - } -} - - -void Vfs_tresor::Wrapper::_rekey_fs_trigger_watch_response() -{ - if (_rekey_fs.valid()) { - _rekey_fs.obj().trigger_watch_response(); - } -} - - -void Vfs_tresor::Wrapper::_rekey_progress_fs_trigger_watch_response() -{ - if (_rekey_progress_fs.valid()) { - _rekey_progress_fs.obj().trigger_watch_response(); - } -} - - -void Vfs_tresor::Wrapper::_deinit_fs_trigger_watch_response() -{ - if (_deinit_fs.valid()) { - _deinit_fs.obj().trigger_watch_response(); - } -} - - -/******************************************************* - ** Vfs_tresor::Snapshots_file_system::Snapshot_registry ** - *******************************************************/ - -void Vfs_tresor::Snapshots_file_system::Snapshot_registry::update(Vfs::Env &vfs_env) -{ - 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 = snap_info.generations[i]; - if (snap_gen == INVALID_GENERATION) - continue; - - bool is_old = false; - auto find_old = [&] (Snapshot_file_system const &fs) { - is_old |= (fs.snap_gen() == snap_gen); - }; - _registry.for_each(find_old); - - if (!is_old) { - - new (_alloc) - Genode::Registered { - _registry, vfs_env, _wrapper, snap_gen, true }; - - ++_number_of_snapshots; - trigger_watch_response = true; - } - } - - /* destroy old */ - auto find_stale = [&] (Snapshot_file_system const &fs) - { - bool is_stale = true; - for (size_t i = 0; i < MAX_NR_OF_SNAPSHOTS; i++) { - Generation const snap_gen = snap_info.generations[i]; - if (snap_gen == INVALID_GENERATION) - continue; - - if (fs.snap_gen() == snap_gen) { - is_stale = false; - break; - } - } - - if (is_stale) { - destroy(&_alloc, &const_cast(fs)); - --_number_of_snapshots; - trigger_watch_response = true; - } - }; - _registry.for_each(find_stale); - if (trigger_watch_response) { - _snapshots_fs.trigger_watch_response(); - } -} diff --git a/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc b/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc index 6c82931dc8..053fd27b0f 100644 --- a/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc +++ b/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc @@ -65,10 +65,7 @@ class Vfs_tresor_crypto::Encrypt_file_system : public Vfs::Single_file_system Tresor_crypto::Interface &crypto, uint32_t key_id) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _crypto { crypto }, - _key_id { key_id }, - _state { State::NONE } + Single_vfs_handle(ds, fs, alloc, 0), _crypto(crypto), _key_id(key_id), _state(State::NONE) { } Read_result read(Byte_range_ptr const &dst, size_t &out_count) override @@ -130,10 +127,8 @@ class Vfs_tresor_crypto::Encrypt_file_system : public Vfs::Single_file_system Encrypt_file_system(Tresor_crypto::Interface &crypto, uint32_t key_id) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("") }, - _crypto { crypto }, - _key_id { key_id } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _crypto(crypto), _key_id(key_id) { } static char const *type_name() { return "encrypt"; } @@ -199,10 +194,7 @@ class Vfs_tresor_crypto::Decrypt_file_system : public Vfs::Single_file_system Tresor_crypto::Interface &crypto, uint32_t key_id) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _crypto { crypto }, - _key_id { key_id }, - _state { State::NONE } + Single_vfs_handle(ds, fs, alloc, 0), _crypto(crypto), _key_id(key_id), _state(State::NONE) { } Read_result read(Byte_range_ptr const &dst, size_t &out_count) override @@ -261,10 +253,8 @@ class Vfs_tresor_crypto::Decrypt_file_system : public Vfs::Single_file_system Decrypt_file_system(Tresor_crypto::Interface &crypto, uint32_t key_id) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("") }, - _crypto { crypto }, - _key_id { key_id } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _crypto(crypto), _key_id(key_id) { } static char const *type_name() { return "decrypt"; } @@ -317,8 +307,7 @@ struct Vfs_tresor_crypto::Key_local_factory : File_system_factory Key_local_factory(Tresor_crypto::Interface &crypto, uint32_t key_id) : - _encrypt_fs { crypto, key_id }, - _decrypt_fs { crypto, key_id } + _encrypt_fs(crypto, key_id), _decrypt_fs(crypto, key_id) { } Vfs::File_system *create(Vfs::Env&, Xml_node node) override @@ -364,11 +353,8 @@ class Vfs_tresor_crypto::Key_file_system : private Key_local_factory, Tresor_crypto::Interface &crypto, uint32_t key_id) : - Key_local_factory { crypto, key_id }, - Vfs::Dir_file_system { vfs_env, - Xml_node(_config(key_id).string()), - *this }, - _key_id { key_id } + Key_local_factory(crypto, key_id), + Vfs::Dir_file_system(vfs_env, Xml_node(_config(key_id).string()), *this), _key_id(key_id) { } static char const *type_name() { return "keys"; } @@ -405,8 +391,7 @@ class Vfs_tresor_crypto::Keys_file_system : public Vfs::File_system Key_registry(Genode::Allocator &alloc, Tresor_crypto::Interface &crypto) : - _alloc { alloc }, - _crypto { crypto } + _alloc(alloc), _crypto(crypto) { } void update(Vfs::Env &vfs_env) @@ -652,8 +637,7 @@ class Vfs_tresor_crypto::Keys_file_system : public Vfs::File_system Keys_file_system(Vfs::Env &vfs_env, Tresor_crypto::Interface &crypto) : - _vfs_env { vfs_env }, - _key_reg { vfs_env.alloc(), crypto } + _vfs_env(vfs_env), _key_reg(vfs_env.alloc(), crypto) { } static char const *type_name() { return "keys"; } @@ -940,9 +924,7 @@ class Vfs_tresor_crypto::Management_file_system : public Vfs::Single_file_system Type type, Tresor_crypto::Interface &crypto) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _type { type }, - _crypto { crypto } + Single_vfs_handle(ds, fs, alloc, 0), _type(type), _crypto(crypto) { } Read_result read(Byte_range_ptr const &, size_t &) override @@ -1010,11 +992,8 @@ class Vfs_tresor_crypto::Management_file_system : public Vfs::Single_file_system Management_file_system(Tresor_crypto::Interface &crypto, Type type, char const *type_name) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name, - Node_rwx::wo(), Xml_node("") }, - _type { type }, - _crypto { crypto }, - _type_name { type_name } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name, Node_rwx::wo(), Xml_node("")), + _type(type), _crypto(crypto), _type_name(type_name) { } char const *type() override { return _type_name; } @@ -1090,9 +1069,7 @@ struct Vfs_tresor_crypto::Local_factory : File_system_factory Local_factory(Vfs::Env &env, Tresor_crypto::Interface &crypto) : - _keys_fs { env, crypto }, - _add_key_fs { crypto }, - _remove_key_fs { crypto } + _keys_fs(env, crypto), _add_key_fs(crypto), _remove_key_fs(crypto) { } Vfs::File_system *create(Vfs::Env&, Xml_node node) override @@ -1142,9 +1119,8 @@ class Vfs_tresor_crypto::File_system : private Local_factory, File_system(Vfs::Env &vfs_env, Genode::Xml_node node) : - Local_factory { vfs_env, Tresor_crypto::get_interface() }, - Vfs::Dir_file_system { vfs_env, Xml_node(_config(node).string()), - *this } + Local_factory(vfs_env, Tresor_crypto::get_interface()), + Vfs::Dir_file_system(vfs_env, Xml_node(_config(node).string()), *this) { } ~File_system() { } diff --git a/repos/gems/src/lib/vfs/tresor_trust_anchor/io_job.h b/repos/gems/src/lib/vfs/tresor_trust_anchor/io_job.h index a04a53354d..5e87ebb3fa 100644 --- a/repos/gems/src/lib/vfs/tresor_trust_anchor/io_job.h +++ b/repos/gems/src/lib/vfs/tresor_trust_anchor/io_job.h @@ -257,16 +257,10 @@ namespace Util { Vfs::file_offset base_offset, Partial_result partial_result = Partial_result::DENY) : - _handle { handle }, - _op { op }, - _state { _initial_state(op) }, - _data { buffer.base }, - _base_offset { base_offset }, - _current_offset { 0 }, - _current_count { buffer.size }, - _allow_partial { partial_result == Partial_result::ALLOW }, - _success { false }, - _complete { false } + _handle(handle), _op(op), _state(_initial_state(op)), _data(buffer.base), + _base_offset(base_offset), _current_offset(0), _current_count(buffer.size), + _allow_partial(partial_result == Partial_result::ALLOW), _success(false), + _complete(false) { } bool completed() const { return _complete; } 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 ba36c540b5..08151c9c75 100644 --- a/repos/gems/src/lib/vfs/tresor_trust_anchor/vfs.cc +++ b/repos/gems/src/lib/vfs/tresor_trust_anchor/vfs.cc @@ -712,7 +712,7 @@ class Trust_anchor return true; } - // XXX trigger sync + /* XXX trigger sync */ bool const progress = _private_key_io_job->execute(); bool const completed = _private_key_io_job->completed(); @@ -731,7 +731,7 @@ class Trust_anchor return true; } - // XXX trigger sync + /* XXX trigger sync */ bool const progress = _jitterentropy_io_job->execute(); bool const completed = _jitterentropy_io_job->completed(); @@ -750,7 +750,7 @@ class Trust_anchor return true; } - // XXX trigger sync + /* XXX trigger sync */ bool const progress = _key_io_job->execute(); bool const completed = _key_io_job->completed(); @@ -960,10 +960,7 @@ class Trust_anchor public: - Trust_anchor(Vfs::Env &vfs_env, Path const &path) - : - _vfs_env { vfs_env }, - _base_path { path } + Trust_anchor(Vfs::Env &vfs_env, Path const &path) : _vfs_env(vfs_env), _base_path(path) { if (_check_key_file(_base_path)) { @@ -1275,8 +1272,7 @@ class Vfs_tresor_trust_anchor::Hashsum_file_system : public Vfs::Single_file_sys Genode::Allocator &alloc, Trust_anchor &ta) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _trust_anchor { ta } + Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta) { } Read_result read(Byte_range_ptr const &src, size_t &out_count) override @@ -1367,12 +1363,11 @@ class Vfs_tresor_trust_anchor::Hashsum_file_system : public Vfs::Single_file_sys Hashsum_file_system(Trust_anchor &ta) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::ro(), Xml_node("") }, - _trust_anchor { ta } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::ro(), Xml_node("")), + _trust_anchor(ta) { } - static char const *type_name() { return "hashsum"; } + static char const *type_name() { return "hash"; } char const *type() override { return type_name(); } @@ -1433,8 +1428,7 @@ class Vfs_tresor_trust_anchor::Generate_key_file_system : public Vfs::Single_fil Genode::Allocator &alloc, Trust_anchor &ta) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _trust_anchor { ta } + Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta) { } Read_result read(Byte_range_ptr const &dst, size_t &out_count) override @@ -1473,9 +1467,8 @@ class Vfs_tresor_trust_anchor::Generate_key_file_system : public Vfs::Single_fil Generate_key_file_system(Trust_anchor &ta) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::ro(), Xml_node("") }, - _trust_anchor { ta } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::ro(), Xml_node("")), + _trust_anchor(ta) { } static char const *type_name() { return "generate_key"; } @@ -1539,9 +1532,7 @@ class Vfs_tresor_trust_anchor::Encrypt_file_system : public Vfs::Single_file_sys Genode::Allocator &alloc, Trust_anchor &ta) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _trust_anchor { ta }, - _state { State::NONE } + Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta), _state(State::NONE) { } Read_result read(Byte_range_ptr const &dst, size_t &out_count) override @@ -1600,9 +1591,8 @@ class Vfs_tresor_trust_anchor::Encrypt_file_system : public Vfs::Single_file_sys Encrypt_file_system(Trust_anchor &ta) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("") }, - _trust_anchor { ta } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _trust_anchor(ta) { } static char const *type_name() { return "encrypt"; } @@ -1665,9 +1655,7 @@ class Vfs_tresor_trust_anchor::Decrypt_file_system : public Vfs::Single_file_sys Genode::Allocator &alloc, Trust_anchor &ta) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _trust_anchor { ta }, - _state { State::NONE } + Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta), _state(State::NONE) { } Read_result read(Byte_range_ptr const &dst, size_t &out_count) override @@ -1726,9 +1714,8 @@ class Vfs_tresor_trust_anchor::Decrypt_file_system : public Vfs::Single_file_sys Decrypt_file_system(Trust_anchor &ta) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("") }, - _trust_anchor { ta } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _trust_anchor(ta) { } static char const *type_name() { return "decrypt"; } @@ -1793,8 +1780,7 @@ class Vfs_tresor_trust_anchor::Initialize_file_system : public Vfs::Single_file_ Genode::Allocator &alloc, Trust_anchor &ta) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _trust_anchor { ta } + Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta) { } Read_result read(Byte_range_ptr const &buf, @@ -1867,9 +1853,8 @@ class Vfs_tresor_trust_anchor::Initialize_file_system : public Vfs::Single_file_ Initialize_file_system(Trust_anchor &ta) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("") }, - _trust_anchor { ta } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _trust_anchor(ta) { } static char const *type_name() { return "initialize"; } @@ -1938,12 +1923,9 @@ struct Vfs_tresor_trust_anchor::Local_factory : File_system_factory Local_factory(Vfs::Env &vfs_env, Xml_node config) : - _trust_anchor { vfs_env, _storage_path(config).string() }, - _decrypt_fs { _trust_anchor }, - _encrypt_fs { _trust_anchor }, - _gen_key_fs { _trust_anchor }, - _hash_fs { _trust_anchor }, - _init_fs { _trust_anchor } + _trust_anchor(vfs_env, _storage_path(config).string()), + _decrypt_fs(_trust_anchor), _encrypt_fs(_trust_anchor), + _gen_key_fs(_trust_anchor), _hash_fs(_trust_anchor), _init_fs(_trust_anchor) { } Vfs::File_system *create(Vfs::Env&, Xml_node node) override @@ -1990,7 +1972,7 @@ class Vfs_tresor_trust_anchor::File_system : private Local_factory, xml.node("decrypt", [&] () { }); xml.node("encrypt", [&] () { }); xml.node("generate_key", [&] () { }); - xml.node("hashsum", [&] () { }); + xml.node("hash", [&] () { }); xml.node("initialize", [&] () { }); }); @@ -2001,8 +1983,7 @@ class Vfs_tresor_trust_anchor::File_system : private Local_factory, File_system(Vfs::Env &vfs_env, Genode::Xml_node node) : - Local_factory { vfs_env, node }, - Vfs::Dir_file_system { vfs_env, Xml_node(_config(node).string()), *this } + Local_factory(vfs_env, node), Vfs::Dir_file_system(vfs_env, Xml_node(_config(node).string()), *this) { } ~File_system() { } diff --git a/tool/autopilot.list b/tool/autopilot.list index 8223345fdd..2e463eb8fd 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -97,6 +97,7 @@ vbox5_win7_64_share verify vfs_cfg vfs_import +vfs_tresor vm_stress_seoul-debian32 vm_stress_vbox5-debian32 vm_stress_vbox5-debian64