tresor: fix faults on failed free-tree requests

* fixes two places, where the free tree module used to continue to process a
  request after actually having determined that the request fails
* moves the functionality of checking the hash of a read block and decoding it
  to a dedicated method in order to improve readability

Ref #5077
This commit is contained in:
Martin Stein 2024-03-20 05:38:50 +01:00 committed by Christian Helmuth
parent 81b17ba1e4
commit 067a8a35cd
2 changed files with 45 additions and 24 deletions

View File

@ -121,6 +121,37 @@ void Free_tree::Allocate_pbas::_start_tree_traversal(bool &progress)
} }
bool Free_tree::Extend_tree::_check_and_decode_read_blk(bool &progress)
{
if (_lvl == _attr.in_out_ft.max_lvl) {
if (!check_hash(_blk, _attr.in_out_ft.hash)) {
_helper.mark_failed(progress, "hash mismatch");
return false;
}
_t1_blks[_lvl].decode_from_blk(_blk);
return true;
}
Type_1_node &node = _t1_blks[_lvl + 1].nodes[tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree)];
if (_lvl > 1) {
if (!check_hash(_blk, node.hash)) {
_helper.mark_failed(progress, "hash mismatch");
return false;
}
_t1_blks[_lvl].decode_from_blk(_blk);
return true;
}
if (_lvl == 1) {
if (!check_hash(_blk, node.hash)) {
_helper.mark_failed(progress, "hash mismatch");
return false;
}
_t2_blk.decode_from_blk(_blk);
return true;
}
ASSERT_NEVER_REACHED;
}
bool Free_tree::Allocate_pbas::execute(Block_io &block_io, Meta_tree &meta_tree) bool Free_tree::Allocate_pbas::execute(Block_io &block_io, Meta_tree &meta_tree)
{ {
bool progress = false; bool progress = false;
@ -173,12 +204,12 @@ bool Free_tree::Allocate_pbas::execute(Block_io &block_io, Meta_tree &meta_tree)
_attr.in_out_ft.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]); _attr.in_out_ft.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]);
_helper.mark_succeeded(progress); _helper.mark_succeeded(progress);
} else { } else {
if (_num_pbas < _attr.in_num_required_pbas) if (_num_pbas < _attr.in_num_required_pbas) {
_helper.mark_failed(progress, "not enough free pbas"); _helper.mark_failed(progress, "not enough free pbas");
else { break;
_apply_allocation = true;
_start_tree_traversal(progress);
} }
_apply_allocation = true;
_start_tree_traversal(progress);
} }
} }
break; break;
@ -305,21 +336,13 @@ bool Free_tree::Extend_tree::execute(Block_io &block_io, Meta_tree &meta_tree)
case READ_BLK: progress |= _read_block.execute(block_io); break; case READ_BLK: progress |= _read_block.execute(block_io); break;
case READ_BLK_SUCCEEDED: case READ_BLK_SUCCEEDED:
if (!_check_and_decode_read_blk(progress))
break;
if (_lvl > 1) { if (_lvl > 1) {
_t1_blks[_lvl].decode_from_blk(_blk);
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))
_helper.mark_failed(progress, "hash mismatch");
} else
if (!check_hash(_blk, _attr.in_out_ft.hash))
_helper.mark_failed(progress, "hash mismatch");
Tree_node_index node_idx = tree_node_index(_vba, _lvl, _attr.in_out_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]; Type_1_node &t1_node = _t1_blks[_lvl].nodes[node_idx];
if (t1_node.valid()) { if (t1_node.valid()) {
_lvl--; _lvl--;
_old_pbas.pbas [_lvl] = t1_node.pba; _old_pbas.pbas [_lvl] = t1_node.pba;
_old_generations.items[_lvl] = t1_node.gen; _old_generations.items[_lvl] = t1_node.gen;
@ -340,16 +363,12 @@ bool Free_tree::Extend_tree::execute(Block_io &block_io, Meta_tree &meta_tree)
} }
} }
} else { } else {
_t2_blk.decode_from_blk(_blk); Tree_node_index node_idx = tree_node_index(_vba, _lvl, _attr.in_out_ft.degree);
Tree_node_index t1_node_idx = tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree); if (_t2_blk.nodes[node_idx].valid()) {
if (!check_hash(_blk, _t1_blks[_lvl + 1].nodes[t1_node_idx].hash))
_helper.mark_failed(progress, "hash mismatch");
Tree_node_index t2_node_idx = tree_node_index(_vba, _lvl, _attr.in_out_ft.degree);
if (_t2_blk.nodes[t2_node_idx].valid())
_helper.mark_failed(progress, "t2 node valid"); _helper.mark_failed(progress, "t2 node valid");
break;
_add_new_branch_at(_lvl, t2_node_idx); }
_add_new_branch_at(_lvl, node_idx);
_alloc_lvl = _lvl; _alloc_lvl = _lvl;
if (VERBOSE_FT_EXTENSION) if (VERBOSE_FT_EXTENSION)
log(" alloc lvl ", _alloc_lvl); log(" alloc lvl ", _alloc_lvl);

View File

@ -152,6 +152,8 @@ class Tresor::Free_tree::Extend_tree : Noncopyable
Generatable_request<Helper, State, Block_io::Write> _write_block { }; Generatable_request<Helper, State, Block_io::Write> _write_block { };
Generatable_request<Helper, State, Meta_tree::Allocate_pba> _allocate_pba { }; Generatable_request<Helper, State, Meta_tree::Allocate_pba> _allocate_pba { };
bool _check_and_decode_read_blk(bool &);
void _add_new_branch_at(Tree_level_index, Tree_node_index); void _add_new_branch_at(Tree_level_index, Tree_node_index);
bool _add_new_root_lvl(); bool _add_new_root_lvl();