diff --git a/repos/os/src/lib/vfs/block_file_system.h b/repos/os/src/lib/vfs/block_file_system.h index 9469831b0a..2aa4697f22 100644 --- a/repos/os/src/lib/vfs/block_file_system.h +++ b/repos/os/src/lib/vfs/block_file_system.h @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2013-2017 Genode Labs GmbH + * Copyright (C) 2013-2020 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. @@ -15,21 +15,39 @@ #ifndef _INCLUDE__VFS__BLOCK_FILE_SYSTEM_H_ #define _INCLUDE__VFS__BLOCK_FILE_SYSTEM_H_ +/* Genode includes */ #include #include +#include +#include +#include #include + namespace Vfs { class Block_file_system; } -class Vfs::Block_file_system : public Single_file_system +struct Vfs::Block_file_system +{ + typedef String<64> Name; + + struct Local_factory; + struct Data_file_system; + struct Compound_file_system; +}; + + +class Vfs::Block_file_system::Data_file_system : public Single_file_system { private: - Vfs::Env &_env; + /* + * Noncopyable + */ + Data_file_system(Data_file_system const &); + Data_file_system &operator = (Data_file_system const &); - typedef Genode::String<64> Label; - Label _label; + Vfs::Env &_env; /* * Serialize access to packet stream of the block session @@ -39,37 +57,26 @@ class Vfs::Block_file_system : public Single_file_system char *_block_buffer; unsigned _block_buffer_count; - Genode::Allocator_avl _tx_block_alloc { &_env.alloc() }; + Block::Connection<> &_block; + Block::Session::Info const &_info; - Block::Connection<> _block { - _env.env(), &_tx_block_alloc, 128*1024, _label.string() }; - - Block::Session::Info const _info { _block.info() }; Block::Session::Tx::Source *_tx_source; - bool _writeable; + bool const _writeable; Genode::Signal_receiver _signal_receiver { }; Genode::Signal_context _signal_context { }; Genode::Signal_context_capability _source_submit_cap; - /* - * Noncopyable - */ - Block_file_system(Block_file_system const &); - Block_file_system &operator = (Block_file_system const &); - class Block_vfs_handle : public Single_vfs_handle { private: Genode::Allocator &_alloc; - Label &_label; Mutex &_mutex; char *_block_buffer; unsigned &_block_buffer_count; - Genode::Allocator_avl &_tx_block_alloc; Block::Connection<> &_block; Genode::size_t const _block_size; Block::sector_t const _block_count; @@ -147,11 +154,9 @@ class Vfs::Block_file_system : public Single_file_system Block_vfs_handle(Directory_service &ds, File_io_service &fs, Genode::Allocator &alloc, - Label &label, Mutex &mutex, char *block_buffer, unsigned &block_buffer_count, - Genode::Allocator_avl &tx_block_alloc, Block::Connection<> &block, Genode::size_t block_size, Block::sector_t block_count, @@ -162,11 +167,9 @@ class Vfs::Block_file_system : public Single_file_system Genode::Signal_context_capability &source_submit_cap) : Single_vfs_handle(ds, fs, alloc, 0), _alloc(alloc), - _label(label), _mutex(mutex), _block_buffer(block_buffer), _block_buffer_count(block_buffer_count), - _tx_block_alloc(tx_block_alloc), _block(block), _block_size(block_size), _block_count(block_count), @@ -352,14 +355,20 @@ class Vfs::Block_file_system : public Single_file_system public: - Block_file_system(Vfs::Env &env, Genode::Xml_node config) + Data_file_system(Vfs::Env &env, + Block::Connection<> &block, + Block::Session::Info const &info, + Name const &name, + unsigned block_buffer_count) : - Single_file_system(Node_type::CONTINUOUS_FILE, name(), - Node_rwx::rw(), config), + Single_file_system { Node_type::CONTINUOUS_FILE, name.string(), + info.writeable ? Node_rwx::rw() : Node_rwx::ro(), + Genode::Xml_node("") }, _env(env), - _label(config.attribute_value("label", Label())), _block_buffer(0), - _block_buffer_count(config.attribute_value("block_buffer_count", 1UL)), + _block_buffer_count(block_buffer_count), + _block(block), + _info(info), _tx_source(_block.tx()), _writeable(_info.writeable), _source_submit_cap(_signal_receiver.manage(&_signal_context)) @@ -370,15 +379,15 @@ class Vfs::Block_file_system : public Single_file_system _block.tx_channel()->sigh_ready_to_submit(_source_submit_cap); } - ~Block_file_system() + ~Data_file_system() { _signal_receiver.dissolve(&_signal_context); destroy(_env.alloc(), _block_buffer); } - static char const *name() { return "block"; } - char const *type() override { return "block"; } + static char const *name() { return "data"; } + char const *type() override { return "data"; } /********************************* ** Directory service interface ** @@ -393,10 +402,9 @@ class Vfs::Block_file_system : public Single_file_system try { *out_handle = new (alloc) Block_vfs_handle(*this, *this, alloc, - _label, _mutex, + _mutex, _block_buffer, _block_buffer_count, - _tx_block_alloc, _block, _info.block_size, _info.block_count, @@ -427,25 +435,135 @@ class Vfs::Block_file_system : public Single_file_system { return FTRUNCATE_OK; } +}; - Ioctl_result ioctl(Vfs_handle *, Ioctl_opcode opcode, Ioctl_arg, - Ioctl_out &out) override + +struct Vfs::Block_file_system::Local_factory : File_system_factory +{ + typedef Genode::String<64> Label; + Label const _label; + + Name const _name; + + Vfs::Env &_env; + + Genode::Allocator_avl _tx_block_alloc { &_env.alloc() }; + + Block::Connection<> _block { + _env.env(), &_tx_block_alloc, 128*1024, _label.string() }; + + Block::Session::Info const _info { _block.info() }; + + Data_file_system _data_fs; + + struct Info : Block::Session::Info + { + void print(Genode::Output &out) const { - switch (opcode) { - case IOCTL_OP_DIOCGMEDIASIZE: - - out.diocgmediasize.size = _info.block_count * _info.block_size; - return IOCTL_OK; - - default: - - Genode::warning("invalid ioctl request ", (int)opcode); - break; - } - - /* never reached */ - return IOCTL_ERR_INVALID; + char buf[128] { }; + Genode::Xml_generator xml(buf, sizeof(buf), "block", [&] () { + xml.attribute("count", Block::Session::Info::block_count); + xml.attribute("size", Block::Session::Info::block_size); + }); + Genode::print(out, Genode::Cstring(buf)); } + }; + + Readonly_value_file_system _info_fs { "info", Info { } }; + Readonly_value_file_system _block_count_fs { "block_count", 0 }; + Readonly_value_file_system _block_size_fs { "block_size", 0 }; + + static Name name(Xml_node config) + { + return config.attribute_value("name", Name("block")); + } + + static unsigned buffer_count(Xml_node config) + { + return config.attribute_value("block_buffer_count", 1UL); + } + + Local_factory(Vfs::Env &env, Xml_node config) + : + _label { config.attribute_value("label", Label("")) }, + _name { name(config) }, + _env { env }, + _data_fs { _env, _block, _info, name(config), buffer_count(config) } + { + _info_fs .value(Info { _info }); + _block_count_fs.value(_info.block_count); + _block_size_fs .value(_info.block_size); + } + + Vfs::File_system *create(Vfs::Env&, Xml_node node) override + { + if (node.has_type("data")) { + return &_data_fs; + } + + if (node.has_type("info")) { + return &_info_fs; + } + + if (node.has_type("block_count")) { + return &_block_count_fs; + } + + if (node.has_type("block_size")) { + return &_block_size_fs; + } + + return nullptr; + } +}; + + +class Vfs::Block_file_system::Compound_file_system : private Local_factory, + public Vfs::Dir_file_system +{ + private: + + using Name = Block_file_system::Name; + + using Config = String<200>; + static Config _config(Name const &name) + { + char buf[Config::capacity()] { }; + + /* + * By not using the node type "dir", we operate the + * 'Dir_file_system' in root mode, allowing multiple sibling nodes + * to be present at the mount point. + */ + Genode::Xml_generator xml(buf, sizeof(buf), "compound", [&] () { + + xml.node("data", [&] () { + xml.attribute("name", name); }); + + xml.node("dir", [&] () { + xml.attribute("name", Name(".", name)); + xml.node("info", [&] () {}); + xml.node("block_count", [&] () {}); + xml.node("block_size", [&] () {}); + }); + }); + + return Config(Genode::Cstring(buf)); + } + + public: + + Compound_file_system(Vfs::Env &vfs_env, Genode::Xml_node node) + : + Local_factory { vfs_env, node }, + Vfs::Dir_file_system { vfs_env, + Xml_node(_config(Local_factory::name(node)).string()), + *this } + { } + + static const char *name() { return "block"; } + + char const *type() override { return name(); } }; #endif /* _INCLUDE__VFS__BLOCK_FILE_SYSTEM_H_ */ diff --git a/repos/os/src/lib/vfs/file_system_factory.cc b/repos/os/src/lib/vfs/file_system_factory.cc index 48069d3fb8..5cdf20e8e3 100644 --- a/repos/os/src/lib/vfs/file_system_factory.cc +++ b/repos/os/src/lib/vfs/file_system_factory.cc @@ -224,7 +224,7 @@ Vfs::Global_file_system_factory::Global_file_system_factory(Genode::Allocator &a _add_builtin_fs(); _add_builtin_fs(); _add_builtin_fs(); - _add_builtin_fs(); + _add_builtin_fs(); _add_builtin_fs(); _add_builtin_fs(); _add_builtin_fs();