diff --git a/repos/libports/src/lib/libc/task.cc b/repos/libports/src/lib/libc/task.cc index 7fefd8a659..5065f05f6f 100644 --- a/repos/libports/src/lib/libc/task.cc +++ b/repos/libports/src/lib/libc/task.cc @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -75,7 +76,8 @@ class Libc::Env_implementation : public Libc::Env return Genode::Xml_node(""); } - Vfs::Dir_file_system _vfs; + Vfs::Global_file_system_factory _file_system_factory; + Vfs::Dir_file_system _vfs; Genode::Xml_node _config_xml() const override { return _config.xml(); }; @@ -85,9 +87,9 @@ class Libc::Env_implementation : public Libc::Env Env_implementation(Genode::Env &env, Genode::Allocator &alloc, Vfs::Io_response_handler &io_response_handler) : - _env(env), + _env(env), _file_system_factory(alloc), _vfs(_env, alloc, _vfs_config(), io_response_handler, - Vfs::global_file_system_factory()) + _file_system_factory) { } diff --git a/repos/os/include/vfs/file_system_factory.h b/repos/os/include/vfs/file_system_factory.h index c8f5b28f2f..e801ddde70 100644 --- a/repos/os/include/vfs/file_system_factory.h +++ b/repos/os/include/vfs/file_system_factory.h @@ -20,11 +20,6 @@ namespace Vfs { struct File_system_factory; struct Global_file_system_factory; - - /** - * Return singleton instance of a file-system factory - */ - Global_file_system_factory &global_file_system_factory(); } @@ -36,6 +31,7 @@ struct Vfs::File_system_factory * \param env Env for service connections * \param alloc internal file-system allocator * \param config file-system configuration + * \param io_handler callback handler */ virtual File_system *create(Genode::Env &env, Genode::Allocator &alloc, @@ -44,16 +40,97 @@ struct Vfs::File_system_factory }; -struct Vfs::Global_file_system_factory : File_system_factory +class Vfs::Global_file_system_factory : public Vfs::File_system_factory { - /** - * Register an additional factory for new file-system type - * - * \name name of file-system type - * \factory factory to create instances of this file-system type - */ - virtual void extend(char const *name, File_system_factory &factory) = 0; + private: + + Genode::Allocator &_md_alloc; + + public: + + typedef Genode::String<128> Fs_type_name; + typedef Genode::String<128> Node_name; + typedef Genode::String<128> Library_name; + + struct Entry_base; + + private: + + Genode::List _list; + + /** + * Add builtin File_system type + */ + template + void _add_builtin_fs(); + + Vfs::File_system *_try_create(Genode::Env &env, + Genode::Allocator &alloc, + Genode::Xml_node node, + Io_response_handler &io_handler); + + /** + * Return name of factory provided by the shared library + */ + static char const *_factory_symbol() + { + return "vfs_file_system_factory"; + } + + /** + * Return name of VFS node + */ + Node_name _node_name(Genode::Xml_node node); + + /** + * Return matching library name for a given vfs node name + */ + Library_name _library_name(Node_name const &node_name); + + class Factory_not_available { }; + + /** + * \throw Factory_not_available + */ + Vfs::File_system_factory &_load_factory(Genode::Env &env, + Genode::Allocator &alloc, + Library_name const &lib_name); + + /** + * Try to load external File_system_factory provider + */ + bool _probe_external_factory(Genode::Env &env, Genode::Allocator &alloc, + Genode::Xml_node node); + + public: + + /** + * Constructor + * + * \param alloc internal factory allocator + */ + Global_file_system_factory(Genode::Allocator &md_alloc); + + /** + * Create and return a new file-system + * + * \param env Env for service connections + * \param alloc internal file-system allocator + * \param config file-system configuration + * \param io_handler callback handler + */ + Vfs::File_system *create(Genode::Env &env, + Genode::Allocator &alloc, + Genode::Xml_node node, + Io_response_handler &io_handler) override; + + /** + * Register an additional factory for new file-system type + * + * \name name of file-system type + * \factory factory to create instances of this file-system type + */ + void extend(char const *name, File_system_factory &factory); }; - #endif /* _INCLUDE__VFS__FILE_SYSTEM_FACTORY_H_ */ diff --git a/repos/os/lib/mk/vfs.mk b/repos/os/lib/mk/vfs.mk index 75702f9201..435e11ca5e 100644 --- a/repos/os/lib/mk/vfs.mk +++ b/repos/os/lib/mk/vfs.mk @@ -1,4 +1,5 @@ -SRC_CC += file_system_factory.cc +SRC_CC += file_system_factory.cc +INC_DIR += $(REP_DIR)/src/lib/vfs LIBS = ld diff --git a/repos/os/src/app/cli_monitor/main.cc b/repos/os/src/app/cli_monitor/main.cc index 6bd2375f80..60d208a913 100644 --- a/repos/os/src/app/cli_monitor/main.cc +++ b/repos/os/src/app/cli_monitor/main.cc @@ -154,9 +154,11 @@ struct Cli_monitor::Main void handle_io_response(Vfs::Vfs_handle::Context *) override { } } io_response_handler; + Vfs::Global_file_system_factory _global_file_system_factory { _heap }; + /* initialize virtual file system */ Vfs::Dir_file_system _root_dir { _env, _heap, _vfs_config(), io_response_handler, - Vfs::global_file_system_factory() }; + _global_file_system_factory }; Subsystem_config_registry _subsystem_config_registry { _root_dir, _heap }; diff --git a/repos/os/src/lib/vfs/file_system_factory.cc b/repos/os/src/lib/vfs/file_system_factory.cc index 58a1f5712a..ce1369207e 100644 --- a/repos/os/src/lib/vfs/file_system_factory.cc +++ b/repos/os/src/lib/vfs/file_system_factory.cc @@ -11,234 +11,246 @@ * under the terms of the GNU General Public License version 2. */ + /* Genode includes */ #include #include /* supported builtin file systems */ -#include "block_file_system.h" -#include "fs_file_system.h" -#include "inline_file_system.h" -#include "log_file_system.h" -#include "null_file_system.h" -#include "ram_file_system.h" -#include "rom_file_system.h" -#include "rtc_file_system.h" -#include "symlink_file_system.h" -#include "tar_file_system.h" -#include "terminal_file_system.h" -#include "zero_file_system.h" - - -using Vfs::Io_response_handler; - - -class Default_file_system_factory : public Vfs::Global_file_system_factory -{ - private: - - typedef Genode::String<128> Fs_type_name; - typedef Genode::String<128> Node_name; - typedef Genode::String<128> Library_name; - - struct Entry_base : Vfs::File_system_factory, - Genode::List::Element - { - Fs_type_name name; - - Entry_base(Fs_type_name const &name) : name(name) { } - - bool matches(Genode::Xml_node node) const { - return node.has_type(name.string()); } - }; - - - template - struct Builtin_entry : Entry_base - { - Builtin_entry() : Entry_base(FILE_SYSTEM::name()) { } - - Vfs::File_system *create(Genode::Env &env, - Genode::Allocator &alloc, - Genode::Xml_node node, - Io_response_handler &io_handler) override - { - return new (alloc) FILE_SYSTEM(env, alloc, node, io_handler); - } - }; - - struct External_entry : Entry_base - { - File_system_factory &_fs_factory; - - External_entry(Fs_type_name const &name, - Vfs::File_system_factory &fs_factory) - : - Entry_base(name), _fs_factory(fs_factory) { } - - Vfs::File_system *create(Genode::Env &env, - Genode::Allocator &alloc, - Genode::Xml_node node, - Io_response_handler &io_handler) override { - return _fs_factory.create(env, alloc, node, io_handler); } - }; - - Genode::List _list; - - template - void _add_builtin_fs() - { - _list.insert(new (Genode::env()->heap()) Builtin_entry()); - } - - Vfs::File_system *_try_create(Genode::Env &env, - Genode::Allocator &alloc, - Genode::Xml_node node, - Io_response_handler &io_handler) - { - for (Entry_base *e = _list.first(); e; e = e->next()) - if (e->matches(node)) - return e->create(env, alloc, node, io_handler); - - return 0; - } - - /** - * Return name of factory provided by the shared library - */ - static char const *_factory_symbol() - { - return "vfs_file_system_factory"; - } - - /** - * Return name of VFS node - */ - Node_name _node_name(Genode::Xml_node node) - { - char node_name [Node_name::capacity()]; - node.type_name(node_name, sizeof(node_name)); - return Node_name(node_name); - } - - /** - * Return matching library name for a given vfs node name - */ - Library_name _library_name(Node_name const &node_name) - { - char lib_name [Library_name::capacity()]; - Genode::snprintf(lib_name, sizeof(lib_name), "vfs_%s.lib.so", - node_name.string()); - - return Library_name(lib_name); - } - - class Factory_not_available { }; - - /** - * \throw Factory_not_available - */ - Vfs::File_system_factory &_load_factory(Genode::Env &env, - Genode::Allocator &alloc, - Library_name const &lib_name) - { - Genode::Shared_object *shared_object = nullptr; - - try { - shared_object = new (alloc) - Genode::Shared_object(env, alloc, lib_name.string(), - Genode::Shared_object::BIND_LAZY, - Genode::Shared_object::DONT_KEEP); - - typedef Vfs::File_system_factory *(*Query_fn)(); - - Query_fn query_fn = shared_object->lookup(_factory_symbol()); - - return *query_fn(); - - } catch (Genode::Shared_object::Invalid_rom_module) { - Genode::warning("could not open '", lib_name, "'"); - throw Factory_not_available(); - - } catch (Genode::Shared_object::Invalid_symbol) { - Genode::warning("could not find symbol '", - Genode::Cstring(_factory_symbol()), - "' in '", lib_name, "'"); - - Genode::destroy(alloc, shared_object); - throw Factory_not_available(); - } - } - - bool _probe_external_factory(Genode::Env &env, Genode::Allocator &alloc, - Genode::Xml_node node) - { - Library_name const lib_name = _library_name(_node_name(node)); - - try { - _list.insert(new (alloc) - External_entry(_node_name(node).string(), - _load_factory(env, alloc, lib_name))); - return true; - - } catch (Factory_not_available) { return false; } - } - - public: - - Vfs::File_system *create(Genode::Env &env, - Genode::Allocator &alloc, - Genode::Xml_node node, - Io_response_handler &io_handler) override - { - try { - /* try if type is handled by the currently registered fs types */ - if (Vfs::File_system *fs = _try_create(env, alloc, node, io_handler)) - return fs; - /* if the builtin fails, do not try loading an external */ - } catch (...) { return 0; } - - try { - /* probe for file system implementation available as shared lib */ - if (_probe_external_factory(env, alloc, node)) { - /* try again with the new file system type loaded */ - if (Vfs::File_system *fs = _try_create(env, alloc, node, io_handler)) - return fs; - } - } catch (...) { } - - return 0; - } - - void extend(char const *name, File_system_factory &factory) override - { - _list.insert(new (Genode::env()->heap()) - External_entry(name, factory)); - } - - Default_file_system_factory() - { - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - _add_builtin_fs(); - } -}; +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace Vfs { - Global_file_system_factory &global_file_system_factory() + using Vfs::Io_response_handler; + + template struct Builtin_entry; + struct External_entry; +} + + +using Fs_type_name = Vfs::Global_file_system_factory::Fs_type_name; +using Node_name = Vfs::Global_file_system_factory::Node_name; +using Library_name = Vfs::Global_file_system_factory::Library_name; + + +struct Vfs::Global_file_system_factory::Entry_base : Vfs::File_system_factory, + Genode::List::Element +{ + Fs_type_name name; + + Entry_base(Fs_type_name const &name) : name(name) { } + + bool matches(Genode::Xml_node node) const { + return node.has_type(name.string()); } +}; + + +template +struct Vfs::Builtin_entry : Vfs::Global_file_system_factory::Entry_base +{ + Builtin_entry() : Entry_base(FILE_SYSTEM::name()) { } + + Vfs::File_system *create(Genode::Env &env, + Genode::Allocator &alloc, + Genode::Xml_node node, + Vfs::Io_response_handler &io_handler) override { - static Default_file_system_factory inst; - return inst; + return new (alloc) FILE_SYSTEM(env, alloc, node, io_handler); + } +}; + + +struct Vfs::External_entry : Vfs::Global_file_system_factory::Entry_base +{ + File_system_factory &_fs_factory; + + External_entry(Fs_type_name const &name, + Vfs::File_system_factory &fs_factory) + : + Entry_base(name), _fs_factory(fs_factory) { } + + Vfs::File_system *create(Genode::Env &env, + Genode::Allocator &alloc, + Genode::Xml_node node, + Vfs::Io_response_handler &io_handler) override { + return _fs_factory.create(env, alloc, node, io_handler); } +}; + + +/** + * Add builtin File_system type + */ +template +void Vfs::Global_file_system_factory::_add_builtin_fs() +{ + _list.insert(new (&_md_alloc) Builtin_entry()); +} + + +/** + * Lookup and create File_system instance + */ +Vfs::File_system *Vfs::Global_file_system_factory::_try_create(Genode::Env &env, + Genode::Allocator &alloc, + Genode::Xml_node node, + Io_response_handler &io_handler) +{ + for (Entry_base *e = _list.first(); e; e = e->next()) { + if (e->matches(node)) { + return e->create(env, alloc, node, io_handler); + } + } + + return 0; +} + + +/** + * Return name of VFS node + */ +Node_name Vfs::Global_file_system_factory::_node_name(Genode::Xml_node node) +{ + char node_name [Node_name::capacity()]; + node.type_name(node_name, sizeof(node_name)); + return Node_name(node_name); +} + + +/** + * Return matching library name for a given vfs node name + */ +Library_name Vfs::Global_file_system_factory::_library_name(Node_name const &node_name) +{ + char lib_name [Library_name::capacity()]; + Genode::snprintf(lib_name, sizeof(lib_name), "vfs_%s.lib.so", + node_name.string()); + + return Library_name(lib_name); +} + + +/** + * \throw Factory_not_available + */ +Vfs::File_system_factory &Vfs::Global_file_system_factory::_load_factory(Genode::Env &env, + Genode::Allocator &alloc, + Library_name const &lib_name) +{ + Genode::Shared_object *shared_object = nullptr; + + try { + shared_object = new (alloc) + Genode::Shared_object(env, alloc, lib_name.string(), + Genode::Shared_object::BIND_LAZY, + Genode::Shared_object::DONT_KEEP); + + typedef Vfs::File_system_factory *(*Query_fn)(); + + Query_fn query_fn = shared_object->lookup(_factory_symbol()); + + return *query_fn(); + + } catch (Genode::Shared_object::Invalid_rom_module) { + Genode::warning("could not open '", lib_name, "'"); + throw Factory_not_available(); + + } catch (Genode::Shared_object::Invalid_symbol) { + Genode::warning("could not find symbol '", + Genode::Cstring(_factory_symbol()), + "' in '", lib_name, "'"); + + Genode::destroy(alloc, shared_object); + throw Factory_not_available(); } } + + +/** + * Try to load external File_system_factory provider + */ +bool Vfs::Global_file_system_factory::_probe_external_factory(Genode::Env &env, + Genode::Allocator &alloc, + Genode::Xml_node node) +{ + Library_name const lib_name = _library_name(_node_name(node)); + + try { + _list.insert(new (alloc) + External_entry(_node_name(node).string(), + _load_factory(env, alloc, lib_name))); + return true; + + } catch (Factory_not_available) { return false; } +} + + +/** + * Create and return a new file-system + */ +Vfs::File_system *Vfs::Global_file_system_factory::create(Genode::Env &env, + Genode::Allocator &alloc, + Genode::Xml_node node, + Io_response_handler &io_handler) +{ + try { + /* try if type is handled by the currently registered fs types */ + if (Vfs::File_system *fs = _try_create(env, alloc, node, io_handler)) + return fs; + /* if the builtin fails, do not try loading an external */ + } catch (...) { return 0; } + + try { + /* probe for file system implementation available as shared lib */ + if (_probe_external_factory(env, alloc, node)) { + /* try again with the new file system type loaded */ + if (Vfs::File_system *fs = _try_create(env, alloc, node, io_handler)) + return fs; + } + } catch (...) { } + + return 0; +} + + +/** + * Register an additional factory for new file-system type + */ +void Vfs::Global_file_system_factory::extend(char const *name, File_system_factory &factory) +{ + _list.insert(new (&_md_alloc) + External_entry(name, factory)); +} + + +/** + * Constructor + */ +Vfs::Global_file_system_factory::Global_file_system_factory(Genode::Allocator &alloc) +: + _md_alloc(alloc) +{ + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); + _add_builtin_fs(); +} diff --git a/repos/os/src/server/vfs/main.cc b/repos/os/src/server/vfs/main.cc index b5a1413749..eb38941525 100644 --- a/repos/os/src/server/vfs/main.cc +++ b/repos/os/src/server/vfs/main.cc @@ -625,9 +625,11 @@ class Vfs_server::Root : Io_response_handler _io_response_handler { _session_registry }; + Vfs::Global_file_system_factory _global_file_system_factory { _heap }; + Vfs::Dir_file_system _vfs { _env, _heap, vfs_config(), _io_response_handler, - Vfs::global_file_system_factory() }; + _global_file_system_factory }; Genode::Signal_handler _config_dispatcher { _env.ep(), *this, &Root::_config_update }; diff --git a/repos/os/src/test/vfs_stress/main.cc b/repos/os/src/test/vfs_stress/main.cc index adc5e821ca..1b2ad4933c 100644 --- a/repos/os/src/test/vfs_stress/main.cc +++ b/repos/os/src/test/vfs_stress/main.cc @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2015 Genode Labs GmbH + * Copyright (C) 2015-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU General Public License version 2. @@ -480,9 +480,11 @@ void Component::construct(Genode::Env &env) } } io_response_handler; + Vfs::Global_file_system_factory global_file_system_factory(heap); + Vfs::Dir_file_system vfs_root(env, heap, config_xml.sub_node("vfs"), io_response_handler, - Vfs::global_file_system_factory()); + global_file_system_factory); char path[Vfs::MAX_PATH_LEN]; MAX_DEPTH = config_xml.attribute_value("depth", 16U); diff --git a/repos/ports/src/noux/main.cc b/repos/ports/src/noux/main.cc index 1aa6f317ac..1f8fe49938 100644 --- a/repos/ports/src/noux/main.cc +++ b/repos/ports/src/noux/main.cc @@ -210,7 +210,7 @@ struct Noux::Main } /* initialize virtual file system */ - Vfs::Global_file_system_factory &_fs_factory = Vfs::global_file_system_factory(); + Vfs::Global_file_system_factory _global_file_system_factory { _heap }; struct Io_response_handler : Vfs::Io_response_handler { @@ -219,7 +219,7 @@ struct Noux::Main Vfs::Dir_file_system _root_dir { _env, _heap, _config.xml().sub_node("fstab"), _io_response_handler, - _fs_factory }; + _global_file_system_factory }; Pid_allocator _pid_allocator;