mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-14 22:47:12 +00:00
vfs/cbe: control/deinitialize file
There were no means for issuing a Deinitialize request at the CBE using the CBE VFS plugin. The new control/deinitialize file fixes this. When writing "true" to the file, a Deinitialize request is submitted at the CBE. When reading the file, the state of the operation is returned as a string of the format "[current_state] last-result: [last_result]" where [current_state] can be "idle" or "in-progress" and [last_result] can be "none", "success", or "failed". Ref #4032
This commit is contained in:
parent
88e6991083
commit
1b4a80ffae
@ -35,6 +35,7 @@ namespace Vfs_cbe {
|
||||
|
||||
class Extend_file_system;
|
||||
class Rekey_file_system;
|
||||
class Deinitialize_file_system;
|
||||
class Create_snapshot_file_system;
|
||||
class Discard_snapshot_file_system;
|
||||
|
||||
@ -205,6 +206,25 @@ class Vfs_cbe::Wrapper
|
||||
}
|
||||
};
|
||||
|
||||
struct Deinitialize
|
||||
{
|
||||
enum State { IDLE, IN_PROGRESS, };
|
||||
enum Result { NONE, SUCCESS, FAILED, };
|
||||
State state;
|
||||
Result last_result;
|
||||
uint32_t key_id;
|
||||
|
||||
static char const *state_to_cstring(State const s)
|
||||
{
|
||||
switch (s) {
|
||||
case State::IDLE: return "idle";
|
||||
case State::IN_PROGRESS: return "in-progress";
|
||||
}
|
||||
|
||||
return "-";
|
||||
}
|
||||
};
|
||||
|
||||
struct Extending
|
||||
{
|
||||
enum Type { INVALID, VBD, FT };
|
||||
@ -246,15 +266,22 @@ class Vfs_cbe::Wrapper
|
||||
.last_result = Rekeying::Result::NONE,
|
||||
.key_id = 0, };
|
||||
|
||||
Deinitialize _deinit_obj
|
||||
{
|
||||
.state = Deinitialize::State::IDLE,
|
||||
.last_result = Deinitialize::Result::NONE
|
||||
};
|
||||
|
||||
Extending _extend_obj {
|
||||
.type = Extending::Type::INVALID,
|
||||
.state = Extending::State::UNKNOWN,
|
||||
.last_result = Extending::Result::NONE,
|
||||
};
|
||||
|
||||
Pointer<Snapshots_file_system> _snapshots_fs { };
|
||||
Pointer<Extend_file_system> _extend_fs { };
|
||||
Pointer<Rekey_file_system> _rekey_fs { };
|
||||
Pointer<Snapshots_file_system> _snapshots_fs { };
|
||||
Pointer<Extend_file_system> _extend_fs { };
|
||||
Pointer<Rekey_file_system> _rekey_fs { };
|
||||
Pointer<Deinitialize_file_system> _deinit_fs { };
|
||||
|
||||
/* configuration options */
|
||||
bool _verbose { false };
|
||||
@ -421,6 +448,34 @@ class Vfs_cbe::Wrapper
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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<Deinitialize_file_system> { };
|
||||
|
||||
} else {
|
||||
|
||||
class No_deinit_file_system_managed { };
|
||||
throw No_deinit_file_system_managed { };
|
||||
}
|
||||
}
|
||||
|
||||
Wrapper(Vfs::Env &env, Xml_node config) : _env(env)
|
||||
{
|
||||
_read_config(config);
|
||||
@ -651,6 +706,8 @@ class Vfs_cbe::Wrapper
|
||||
|
||||
void _rekey_fs_trigger_watch_response();
|
||||
|
||||
void _deinit_fs_trigger_watch_response();
|
||||
|
||||
bool _handle_cbe_frontend(Cbe::Library &cbe, Frontend_request &frontend_request)
|
||||
{
|
||||
if (_helper_read_request.pending()) {
|
||||
@ -726,6 +783,19 @@ class Vfs_cbe::Wrapper
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cbe_request.operation() == Cbe::Request::Operation::DEINITIALIZE) {
|
||||
bool const req_sucess = cbe_request.success();
|
||||
if (_verbose) {
|
||||
log("Complete request: backend request (", cbe_request, ")");
|
||||
}
|
||||
_deinit_obj.state = Deinitialize::State::IDLE;
|
||||
_deinit_obj.last_result = req_sucess ? Deinitialize::Result::SUCCESS
|
||||
: Deinitialize::Result::FAILED;
|
||||
|
||||
_deinit_fs_trigger_watch_response();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cbe_request.operation() == Cbe::Request::Operation::EXTEND_VBD) {
|
||||
bool const req_sucess = cbe_request.success();
|
||||
if (_verbose) {
|
||||
@ -1619,6 +1689,38 @@ class Vfs_cbe::Wrapper
|
||||
return _rekey_obj;
|
||||
}
|
||||
|
||||
bool start_deinitialize()
|
||||
{
|
||||
if (!_cbe->client_request_acceptable()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Cbe::Request req(
|
||||
Cbe::Request::Operation::DEINITIALIZE,
|
||||
false,
|
||||
0, 0, 0,
|
||||
0,
|
||||
0);
|
||||
|
||||
if (_verbose) {
|
||||
Genode::log("Req: (background req: ", req, ")");
|
||||
}
|
||||
|
||||
_cbe->submit_client_request(req, 0);
|
||||
_deinit_obj.state = Deinitialize::State::IN_PROGRESS;
|
||||
_deinit_obj.last_result = Deinitialize::Deinitialize::FAILED;
|
||||
_deinit_fs_trigger_watch_response();
|
||||
|
||||
// XXX kick-off deinitialize
|
||||
handle_frontend_request();
|
||||
return true;
|
||||
}
|
||||
|
||||
Deinitialize const deinitialize_progress() const
|
||||
{
|
||||
return _deinit_obj;
|
||||
}
|
||||
|
||||
|
||||
bool start_extending(Extending::Type type,
|
||||
Cbe::Number_of_blocks blocks)
|
||||
@ -2363,6 +2465,189 @@ class Vfs_cbe::Rekey_file_system : public Vfs::Single_file_system
|
||||
};
|
||||
|
||||
|
||||
class Vfs_cbe::Deinitialize_file_system : public Vfs::Single_file_system
|
||||
{
|
||||
private:
|
||||
|
||||
typedef Registered<Vfs_watch_handle> Registered_watch_handle;
|
||||
typedef Registry<Registered_watch_handle> Watch_handle_registry;
|
||||
|
||||
Watch_handle_registry _handle_registry { };
|
||||
|
||||
Wrapper &_w;
|
||||
|
||||
using Content_string = String<32>;
|
||||
|
||||
static Content_string content_string(Wrapper const &wrapper)
|
||||
{
|
||||
Wrapper::Deinitialize const & deinitialize_progress {
|
||||
wrapper.deinitialize_progress() };
|
||||
|
||||
bool const in_progress {
|
||||
deinitialize_progress.state ==
|
||||
Wrapper::Deinitialize::State::IN_PROGRESS };
|
||||
|
||||
bool const last_result {
|
||||
!in_progress &&
|
||||
deinitialize_progress.last_result !=
|
||||
Wrapper::Deinitialize::Result::NONE };
|
||||
|
||||
bool const success {
|
||||
deinitialize_progress.last_result ==
|
||||
Wrapper::Deinitialize::Result::SUCCESS };
|
||||
|
||||
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(char *dst, file_size count,
|
||||
file_size &out_count) override
|
||||
{
|
||||
if (seek() != 0) {
|
||||
out_count = 0;
|
||||
return READ_OK;
|
||||
}
|
||||
Content_string const result { content_string(_w) };
|
||||
copy_cstring(dst, result.string(), count);
|
||||
size_t const length_without_nul = result.length() - 1;
|
||||
out_count = count > length_without_nul - 1 ?
|
||||
length_without_nul : count;
|
||||
|
||||
return READ_OK;
|
||||
}
|
||||
|
||||
Write_result write(char const *src, file_size count, file_size &out_count) override
|
||||
{
|
||||
using State = Wrapper::Deinitialize::State;
|
||||
if (_w.deinitialize_progress().state != State::IDLE) {
|
||||
return WRITE_ERR_IO;
|
||||
}
|
||||
|
||||
bool start_deinitialize { false };
|
||||
Genode::ascii_to(src, start_deinitialize);
|
||||
|
||||
if (!start_deinitialize) {
|
||||
return WRITE_ERR_IO;
|
||||
}
|
||||
|
||||
if (!_w.start_deinitialize()) {
|
||||
return WRITE_ERR_IO;
|
||||
}
|
||||
|
||||
out_count = count;
|
||||
return WRITE_OK;
|
||||
}
|
||||
|
||||
bool read_ready() override { return true; }
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
Deinitialize_file_system(Wrapper &w)
|
||||
:
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(),
|
||||
Node_rwx::rw(), Xml_node("<deinitialize/>")),
|
||||
_w(w)
|
||||
{
|
||||
_w.manage_deinit_file_system(*this);
|
||||
}
|
||||
|
||||
~Deinitialize_file_system()
|
||||
{
|
||||
_w.dissolve_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
|
||||
{
|
||||
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<Registered_watch_handle *>(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(_w).length() - 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/********************************
|
||||
** File I/O service interface **
|
||||
********************************/
|
||||
|
||||
Ftruncate_result ftruncate(Vfs::Vfs_handle *handle, file_size) override
|
||||
{
|
||||
return FTRUNCATE_OK;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Vfs_cbe::Create_snapshot_file_system : public Vfs::Single_file_system
|
||||
{
|
||||
private:
|
||||
@ -3178,6 +3463,7 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system
|
||||
struct Vfs_cbe::Control_local_factory : File_system_factory
|
||||
{
|
||||
Rekey_file_system _rekeying_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;
|
||||
@ -3187,6 +3473,7 @@ struct Vfs_cbe::Control_local_factory : File_system_factory
|
||||
Wrapper &cbe)
|
||||
:
|
||||
_rekeying_fs(cbe),
|
||||
_deinitialize_fs(cbe),
|
||||
_create_snapshot_fs(cbe),
|
||||
_discard_snapshot_fs(cbe),
|
||||
_extend_fs(cbe)
|
||||
@ -3197,6 +3484,9 @@ struct Vfs_cbe::Control_local_factory : File_system_factory
|
||||
if (node.has_type(Rekey_file_system::type_name())) {
|
||||
return &_rekeying_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;
|
||||
@ -3232,6 +3522,7 @@ class Vfs_cbe::Control_file_system : private Control_local_factory,
|
||||
xml.node("extend", [&] () { });
|
||||
xml.node("create_snapshot", [&] () { });
|
||||
xml.node("discard_snapshot", [&] () { });
|
||||
xml.node("deinitialize", [&] () { });
|
||||
});
|
||||
|
||||
return Config(Cstring(buf));
|
||||
@ -3414,6 +3705,14 @@ void Vfs_cbe::Wrapper::_rekey_fs_trigger_watch_response()
|
||||
}
|
||||
|
||||
|
||||
void Vfs_cbe::Wrapper::_deinit_fs_trigger_watch_response()
|
||||
{
|
||||
if (_deinit_fs.valid()) {
|
||||
_deinit_fs.obj().trigger_watch_response();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************
|
||||
** Vfs_cbe::Snapshots_file_system::Snapshot_registry **
|
||||
*******************************************************/
|
||||
|
Loading…
x
Reference in New Issue
Block a user