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