From 9b953e79babdd3a427979cf047ad574326f468c1 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Mon, 15 Mar 2021 16:52:48 +0100 Subject: [PATCH] vfs/cbe: support watching the snapshots fs The snapshots file system couldn't be watched. But it's of interest to watch for appearing and disappearing snapshots. Ref #4032 --- repos/gems/src/lib/vfs/cbe/vfs.cc | 234 ++++++++++++++++++++++-------- 1 file changed, 177 insertions(+), 57 deletions(-) diff --git a/repos/gems/src/lib/vfs/cbe/vfs.cc b/repos/gems/src/lib/vfs/cbe/vfs.cc index c42c73ffc9..a2a8f00b70 100644 --- a/repos/gems/src/lib/vfs/cbe/vfs.cc +++ b/repos/gems/src/lib/vfs/cbe/vfs.cc @@ -252,8 +252,9 @@ class Vfs_cbe::Wrapper .last_result = Extending::Result::NONE, }; - Pointer _extend_fs { }; - Pointer _rekey_fs { }; + Pointer _snapshots_fs { }; + Pointer _extend_fs { }; + Pointer _rekey_fs { }; /* configuration options */ bool _verbose { false }; @@ -336,6 +337,34 @@ class Vfs_cbe::Wrapper public: + void manage_snapshots_file_system(Snapshots_file_system &snapshots_fs) + { + if (_snapshots_fs.valid()) { + + class Already_managing_an_snapshots_file_system { }; + throw Already_managing_an_snapshots_file_system { }; + } + _snapshots_fs = snapshots_fs; + } + + void dissolve_snapshots_file_system(Snapshots_file_system &snapshots_fs) + { + 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 { }; + } + } + void manage_extend_file_system(Extend_file_system &extend_fs) { if (_extend_fs.valid()) { @@ -616,6 +645,8 @@ class Vfs_cbe::Wrapper return progress; } + void _snapshots_fs_update_snapshot_registry(); + void _extend_fs_trigger_watch_response(); void _rekey_fs_trigger_watch_response(); @@ -728,6 +759,7 @@ class Vfs_cbe::Wrapper log("Complete request: (", cbe_request, ")"); } _create_snapshot_request.cbe_request = Cbe::Request(); + _snapshots_fs_update_snapshot_registry(); continue; } @@ -736,6 +768,7 @@ class Vfs_cbe::Wrapper log("Complete request: (", cbe_request, ")"); } _discard_snapshot_request.cbe_request = Cbe::Request(); + _snapshots_fs_update_snapshot_registry(); continue; } @@ -2601,6 +2634,11 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system { 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; } @@ -2608,63 +2646,27 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system struct Snapshot_registry { - Genode::Allocator &_alloc; - Wrapper &_w; + 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 { }; - uint32_t _number_of_snapshots { 0 }; - Genode::Registry> _snap_fs { }; - Snapshot_registry(Genode::Allocator &alloc, Wrapper &w) - : _alloc(alloc), _w(w) + 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) - { - Cbe::Active_snapshot_ids list { }; - _w.active_snapshot_ids(list); - - /* alloc new */ - for (size_t i = 0; i < sizeof (list.values) / sizeof (list.values[0]); i++) { - uint32_t const id = list.values[i]; - if (!id) { continue; } - - bool is_old = false; - auto find_old = [&] (Snapshot_file_system const &fs) { - is_old |= (fs.snapshot_id() == id); - }; - _snap_fs.for_each(find_old); - - if (!is_old) { - new (_alloc) Genode::Registered( - _snap_fs, vfs_env, _w, id, true); - ++_number_of_snapshots; - } - } - - /* destroy old */ - auto find_stale = [&] (Snapshot_file_system const &fs) { - bool is_stale = true; - for (size_t i = 0; i < sizeof (list.values) / sizeof (list.values[0]); i++) { - uint32_t const id = list.values[i]; - if (!id) { continue; } - - if (fs.snapshot_id() == id) { - is_stale = false; - break; - } - } - - if (is_stale) { - destroy(&_alloc, &const_cast(fs)); - --_number_of_snapshots; - } - }; - _snap_fs.for_each(find_stale); - } + void update(Vfs::Env &vfs_env); uint32_t number_of_snapshots() const { return _number_of_snapshots; } @@ -2678,7 +2680,7 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system } ++i; }; - _snap_fs.for_each(lookup); + _registry.for_each(lookup); if (fsp == nullptr) { throw Invalid_index(); } @@ -2693,7 +2695,7 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system fsp = &fs; } }; - _snap_fs.for_each(lookup); + _registry.for_each(lookup); if (fsp == nullptr) { throw Invalid_path(); } @@ -2718,6 +2720,40 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system 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; @@ -2847,7 +2883,8 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system } }; - Snapshot_registry _snap_reg; + Snapshot_registry _snap_reg; + Wrapper &_wrapper; char const *_sub_path(char const *path) const { @@ -2878,9 +2915,19 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system Snapshots_file_system(Vfs::Env &vfs_env, Genode::Xml_node node, - Wrapper &w) - : _vfs_env(vfs_env), _snap_reg(vfs_env.alloc(), w) - { } + Wrapper &wrapper) + : + _vfs_env { vfs_env }, + _snap_reg { vfs_env.alloc(), wrapper, *this }, + _wrapper { wrapper } + { + _wrapper.manage_snapshots_file_system(*this); + } + + ~Snapshots_file_system() + { + _wrapper.dissolve_snapshots_file_system(*this); + } static char const *type_name() { return "snapshots"; } @@ -3339,6 +3386,18 @@ extern "C" int memcmp(const void *s1, const void *s2, Genode::size_t n) } +/********************** + ** Vfs_cbe::Wrapper ** + **********************/ + +void Vfs_cbe::Wrapper::_snapshots_fs_update_snapshot_registry() +{ + if (_snapshots_fs.valid()) { + _snapshots_fs.obj().update_snapshot_registry(); + } +} + + void Vfs_cbe::Wrapper::_extend_fs_trigger_watch_response() { if (_extend_fs.valid()) { @@ -3353,3 +3412,64 @@ void Vfs_cbe::Wrapper::_rekey_fs_trigger_watch_response() _rekey_fs.obj().trigger_watch_response(); } } + + +/******************************************************* + ** Vfs_cbe::Snapshots_file_system::Snapshot_registry ** + *******************************************************/ + +void Vfs_cbe::Snapshots_file_system::Snapshot_registry::update(Vfs::Env &vfs_env) +{ + Cbe::Active_snapshot_ids list { }; + _wrapper.active_snapshot_ids(list); + bool trigger_watch_response { false }; + + /* alloc new */ + for (size_t i = 0; i < sizeof (list.values) / sizeof (list.values[0]); i++) { + + uint32_t const id = list.values[i]; + if (!id) { + continue; + } + bool is_old = false; + auto find_old = [&] (Snapshot_file_system const &fs) { + is_old |= (fs.snapshot_id() == id); + }; + _registry.for_each(find_old); + + if (!is_old) { + + new (_alloc) + Genode::Registered { + _registry, vfs_env, _wrapper, id, 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 < sizeof (list.values) / sizeof (list.values[0]); i++) { + uint32_t const id = list.values[i]; + if (!id) { continue; } + + if (fs.snapshot_id() == id) { + 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(); + } +}