diff --git a/repos/os/include/vfs/dir_file_system.h b/repos/os/include/vfs/dir_file_system.h index 53904d041b..a7ca42de58 100644 --- a/repos/os/include/vfs/dir_file_system.h +++ b/repos/os/include/vfs/dir_file_system.h @@ -94,6 +94,47 @@ class Vfs::Dir_file_system : public File_system Dir_vfs_handle &operator = (Dir_vfs_handle const &); }; + struct Dir_watch_handle : Vfs_watch_handle + { + struct Watch_handle_element; + + typedef Genode::Registry Watch_handle_registry; + + struct Watch_handle_element : Watch_handle_registry::Element + { + Vfs_watch_handle &watch_handle; + Watch_handle_element(Watch_handle_registry ®istry, + Vfs_watch_handle &handle) + : Watch_handle_registry::Element(registry, *this), + watch_handle(handle) { } + }; + + Watch_handle_registry handle_registry { }; + + Dir_watch_handle(File_system &fs, Genode::Allocator &alloc) + : Vfs_watch_handle(fs, alloc) { } + + ~Dir_watch_handle() + { + /* close all sub-handles */ + auto f = [&] (Watch_handle_element &e) { + e.watch_handle.fs().close(&e.watch_handle); + destroy(alloc(), &e); + }; + handle_registry.for_each(f); + } + + /** + * Propagate the handle context to each sub-handle + */ + void context(Context *ctx) override + { + handle_registry.for_each( [&] (Watch_handle_element &elem) { + elem.watch_handle.context(ctx); } ); + } + }; + + /* pointer to first child file system */ File_system *_first_file_system = nullptr; @@ -733,6 +774,41 @@ class Vfs::Dir_file_system : public File_system destroy(handle->alloc(), handle); } + Watch_result watch(char const *path, + Vfs_watch_handle **handle, + Allocator &alloc) override + { + /* static by default, no allocations */ + Watch_result r = WATCH_ERR_STATIC; + Dir_watch_handle *meta_handle = nullptr; + + for (File_system *fs = _first_file_system; fs; fs = fs->next) { + Vfs_watch_handle *sub_handle; + + if (fs->watch(path, &sub_handle, alloc) == WATCH_OK) { + if (meta_handle == nullptr) { + /* at least one non-static FS, allocate handle */ + meta_handle = new (alloc) Dir_watch_handle(*this, alloc); + *handle = meta_handle; + r = WATCH_OK; + } + + /* attach child FS handle to returned handle */ + new (alloc) + Dir_watch_handle::Watch_handle_element( + meta_handle->handle_registry, *sub_handle); + } + } + + return r; + } + + void close(Vfs_watch_handle *handle) override + { + if (handle && (&handle->fs() == this)) + destroy(handle->alloc(), handle); + } + Unlink_result unlink(char const *path) override { auto unlink_fn = [] (File_system &fs, char const *path) diff --git a/repos/os/include/vfs/directory_service.h b/repos/os/include/vfs/directory_service.h index 5a59c57d41..40b6550f15 100644 --- a/repos/os/include/vfs/directory_service.h +++ b/repos/os/include/vfs/directory_service.h @@ -18,6 +18,7 @@ namespace Vfs { class Vfs_handle; + class Vfs_watch_handle; struct Directory_service; using Genode::Allocator; @@ -110,6 +111,32 @@ struct Vfs::Directory_service : Interface */ virtual void close(Vfs_handle *handle) = 0; + enum Watch_result + { + WATCH_ERR_UNACCESSIBLE, + WATCH_ERR_STATIC, + WATCH_ERR_OUT_OF_RAM, + WATCH_ERR_OUT_OF_CAPS, + WATCH_OK + }; + + /** + * Watch a file-system node for changes. + */ + virtual Watch_result watch(char const *path, + Vfs_watch_handle**, + Allocator&) + { + /* default implementation for static file-systems */ + Genode::warning("'", path, "' is static and cannot be watched"); + return WATCH_ERR_STATIC; + } + + virtual void close(Vfs_watch_handle *) + { + Genode::error("watch handle closed at invalid file-system"); + throw ~0; + }; /********** ** Stat ** diff --git a/repos/os/include/vfs/file_io_service.h b/repos/os/include/vfs/file_io_service.h index 7f9cc60d0d..201cc97774 100644 --- a/repos/os/include/vfs/file_io_service.h +++ b/repos/os/include/vfs/file_io_service.h @@ -27,7 +27,9 @@ namespace Vfs { struct Vfs::Io_response_handler : Interface { - virtual void handle_io_response(Vfs::Vfs_handle::Context *context) = 0; + virtual void handle_io_response(Vfs_handle::Context *context) = 0; + virtual void handle_watch_response(Vfs_watch_handle::Context*) { + Genode::warning(__func__, " discarding event"); }; }; diff --git a/repos/os/include/vfs/vfs_handle.h b/repos/os/include/vfs/vfs_handle.h index e949f2896f..c1a5976f51 100644 --- a/repos/os/include/vfs/vfs_handle.h +++ b/repos/os/include/vfs/vfs_handle.h @@ -19,6 +19,8 @@ namespace Vfs{ class Vfs_handle; class File_io_service; + class File_system; + class Vfs_watch_handle; } @@ -109,4 +111,41 @@ class Vfs::Vfs_handle }; +class Vfs::Vfs_watch_handle +{ + public: + + /** + * Opaque handle context + */ + struct Context : List::Element { }; + + private: + + File_system &_fs; + Genode::Allocator &_alloc; + Context *_context = nullptr; + + /* + * Noncopyable + */ + Vfs_watch_handle(Vfs_watch_handle const &); + Vfs_watch_handle &operator = (Vfs_watch_handle const &); + + public: + + Vfs_watch_handle(File_system &fs, + Genode::Allocator &alloc) + : + _fs(fs), _alloc(alloc) + { } + + virtual ~Vfs_watch_handle() { } + + File_system &fs() { return _fs; } + Allocator &alloc() { return _alloc; } + virtual void context(Context *context) { _context = context; } + Context *context() const { return _context; } +}; + #endif /* _INCLUDE__VFS__VFS_HANDLE_H_ */ diff --git a/repos/os/run/fs_rom_update_fs.run b/repos/os/run/fs_rom_update_fs.run new file mode 100644 index 0000000000..378149e41d --- /dev/null +++ b/repos/os/run/fs_rom_update_fs.run @@ -0,0 +1,138 @@ +# +# Build +# +set build_components { + core init + app/rom_logger + app/rom_to_file + drivers/timer + server/dynamic_rom + server/fs_rom + server/vfs +} + +build $build_components + +create_boot_directory + +# +# Generate config +# +append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +install_config $config + +# +# Boot modules +# + +# generic modules +set boot_modules { + core ld.lib.so init + dynamic_rom + fs_rom + vfs + rom_logger + rom_to_file + timer +} + +build_boot_image $boot_modules + +append qemu_args " -nographic" + +run_genode_until {.*.*} 60 diff --git a/repos/os/run/fs_rom_update_ram.run b/repos/os/run/fs_rom_update_ram.run new file mode 100644 index 0000000000..d34bc033fc --- /dev/null +++ b/repos/os/run/fs_rom_update_ram.run @@ -0,0 +1,123 @@ +# +# Build +# +set build_components { + core init + app/rom_logger + app/rom_to_file + drivers/timer + server/dynamic_rom + server/fs_rom + server/vfs +} + +build $build_components + +create_boot_directory + +# +# Generate config +# +append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +install_config $config + +# +# Boot modules +# + +# generic modules +set boot_modules { + core ld.lib.so init + dynamic_rom + fs_rom + vfs + rom_logger + rom_to_file + timer +} + +build_boot_image $boot_modules + +append qemu_args " -nographic" + +run_genode_until {.*.*} 60 diff --git a/repos/os/src/lib/vfs/fs_file_system.h b/repos/os/src/lib/vfs/fs_file_system.h index bece8499b1..a44a6e8fc9 100644 --- a/repos/os/src/lib/vfs/fs_file_system.h +++ b/repos/os/src/lib/vfs/fs_file_system.h @@ -29,7 +29,6 @@ class Vfs::Fs_file_system : public File_system { private: - /* * Lock used to serialize the interaction with the packet stream of the * file-system session. @@ -41,7 +40,7 @@ class Vfs::Fs_file_system : public File_system Genode::Env &_env; Genode::Allocator_avl _fs_packet_alloc; - Io_response_handler &_io_handler; + Io_response_handler &_event_handler; typedef Genode::String<64> Label_string; Label_string _label; @@ -54,6 +53,7 @@ class Vfs::Fs_file_system : public File_system typedef Genode::Id_space<::File_system::Node> Handle_space; Handle_space _handle_space { }; + Handle_space _watch_handle_space { }; struct Handle_state { @@ -82,7 +82,7 @@ class Vfs::Fs_file_system : public File_system friend class Genode::Id_space<::File_system::Node>; ::File_system::Connection &_fs; - Io_response_handler &_io_handler; + Io_response_handler &_event_handler; bool _queue_read(file_size count, file_size const seek_offset) { @@ -145,7 +145,7 @@ class Vfs::Fs_file_system : public File_system * Notify anyone who might have failed on * 'alloc_packet()' or 'submit_packet()' */ - _io_handler.handle_io_response(nullptr); + _event_handler.handle_io_response(nullptr); return READ_OK; } @@ -158,7 +158,7 @@ class Vfs::Fs_file_system : public File_system : Vfs_handle(fs, fs, alloc, status_flags), Handle_space::Element(*this, space, node_handle), - _fs(fs_connection), _io_handler(io_handler) + _fs(fs_connection), _event_handler(io_handler) { } ::File_system::File_handle file_handle() const @@ -227,7 +227,7 @@ class Vfs::Fs_file_system : public File_system * Notify anyone who might have failed on * 'alloc_packet()' or 'submit_packet()' */ - _io_handler.handle_io_response(nullptr); + _event_handler.handle_io_response(nullptr); return SYNC_OK; } @@ -355,19 +355,40 @@ class Vfs::Fs_file_system : public File_system } }; + struct Fs_vfs_watch_handle : Vfs_watch_handle, + private ::File_system::Node, + private Handle_space::Element + { + friend class Genode::Id_space<::File_system::Node>; + + ::File_system::Watch_handle const fs_handle; + + Fs_vfs_watch_handle(Vfs::File_system &fs, + Allocator &alloc, + Handle_space &space, + ::File_system::Watch_handle handle) + : + Vfs_watch_handle(fs, alloc), + Handle_space::Element(*this, space, handle), + fs_handle(handle) + { } + }; + struct Post_signal_hook : Genode::Entrypoint::Post_signal_hook { Genode::Entrypoint &_ep; - Io_response_handler &_io_handler; + Io_response_handler &_event_handler; List _context_list { }; + List + _watch_context_list { }; Lock _list_lock { }; bool _notify_all { false }; Post_signal_hook(Genode::Entrypoint &ep, Io_response_handler &io_handler) - : _ep(ep), _io_handler(io_handler) { } + : _ep(ep), _event_handler(io_handler) { } - void arm(Vfs_handle::Context *context) + void arm_io_event(Vfs_handle::Context *context) { if (!context) { Lock::Guard list_guard(_list_lock); @@ -391,6 +412,27 @@ class Vfs::Fs_file_system : public File_system _ep.schedule_post_signal_hook(this); } + void arm_watch_event(Vfs_watch_handle::Context &context) + { + { + Lock::Guard list_guard(_list_lock); + + for (Vfs_watch_handle::Context *list_context = _watch_context_list.first(); + list_context; + list_context = list_context->next()) + { + if (list_context == &context) { + /* already in list */ + return; + } + } + + _watch_context_list.insert(&context); + } + + _ep.schedule_post_signal_hook(this); + } + void function() override { Vfs_handle::Context *context = nullptr; @@ -411,14 +453,26 @@ class Vfs::Fs_file_system : public File_system } if (context || notify_all) - _io_handler.handle_io_response(context); + _event_handler.handle_io_response(context); /* done if no contexts and all notified */ } while (context); + + for (;;) { + Vfs_watch_handle::Context *context = nullptr; + { + Lock::Guard list_guard(_list_lock); + + context = _watch_context_list.first(); + if (!context) break; + _watch_context_list.remove(context); + _event_handler.handle_watch_response(context); + } + } } }; - Post_signal_hook _post_signal_hook { _env.ep(), _io_handler }; + Post_signal_hook _post_signal_hook { _env.ep(), _event_handler }; file_size _read(Fs_vfs_handle &handle, void *buf, file_size const count, file_size const seek_offset) @@ -504,7 +558,7 @@ class Vfs::Fs_file_system : public File_system void _ready_to_submit() { /* notify anyone who might have failed on write() ready_to_submit */ - _post_signal_hook.arm(nullptr); + _post_signal_hook.arm_io_event(nullptr); } void _handle_ack() @@ -519,7 +573,13 @@ class Vfs::Fs_file_system : public File_system Handle_space::Id const id(packet.handle()); try { - _handle_space.apply(id, [&] (Fs_vfs_handle &handle) + if (packet.operation() == Packet_descriptor::CONTENT_CHANGED) { + _watch_handle_space.apply(id, [&] (Fs_vfs_watch_handle &handle) { + + if (auto *ctx = handle.context()) + _post_signal_hook.arm_watch_event(*ctx); + }); + } else _handle_space.apply(id, [&] (Fs_vfs_handle &handle) { if (!packet.succeeded()) Genode::error("packet operation=", (int)packet.operation(), " failed"); @@ -527,13 +587,13 @@ class Vfs::Fs_file_system : public File_system switch (packet.operation()) { case Packet_descriptor::READ_READY: handle.read_ready_state = Handle_state::Read_ready_state::READY; - _post_signal_hook.arm(handle.context); + _post_signal_hook.arm_io_event(handle.context); break; case Packet_descriptor::READ: handle.queued_read_packet = packet; handle.queued_read_state = Handle_state::Queued_state::ACK; - _post_signal_hook.arm(handle.context); + _post_signal_hook.arm_io_event(handle.context); break; case Packet_descriptor::WRITE: @@ -541,18 +601,18 @@ class Vfs::Fs_file_system : public File_system * Notify anyone who might have failed on * 'alloc_packet()' */ - _post_signal_hook.arm(nullptr); + _post_signal_hook.arm_io_event(nullptr); break; - case Packet_descriptor::CONTENT_CHANGED: - _post_signal_hook.arm(handle.context); - break; - case Packet_descriptor::SYNC: handle.queued_sync_packet = packet; handle.queued_sync_state = Handle_state::Queued_state::ACK; - _post_signal_hook.arm(handle.context); + _post_signal_hook.arm_io_event(handle.context); + break; + + case Packet_descriptor::CONTENT_CHANGED: + /* previously handled */ break; } }); @@ -577,12 +637,12 @@ class Vfs::Fs_file_system : public File_system Fs_file_system(Genode::Env &env, Genode::Allocator &alloc, Genode::Xml_node config, - Io_response_handler &io_handler, + Io_response_handler &event_handler, File_system &) : _env(env), _fs_packet_alloc(&alloc), - _io_handler(io_handler), + _event_handler(event_handler), _label(config.attribute_value("label", Label_string())), _root( config.attribute_value("root", Root_string())), _fs(env, _fs_packet_alloc, @@ -613,7 +673,7 @@ class Vfs::Fs_file_system : public File_system try { ::File_system::Node_handle node = _fs.node(path); Fs_handle_guard node_guard(*this, _fs, node, _handle_space, - _fs, _io_handler); + _fs, _event_handler); status = _fs.status(node); } catch (::File_system::Lookup_failed) { return STAT_ERR_NO_ENTRY; } @@ -649,7 +709,7 @@ class Vfs::Fs_file_system : public File_system try { ::File_system::Dir_handle dir = _fs.dir(dir_path.base(), false); Fs_handle_guard dir_guard(*this, _fs, dir, _handle_space, _fs, - _io_handler); + _event_handler); _fs.unlink(dir, file_name.base() + 1); } @@ -685,12 +745,12 @@ class Vfs::Fs_file_system : public File_system _fs.dir(from_dir_path.base(), false); Fs_handle_guard from_dir_guard(*this, _fs, from_dir, - _handle_space, _fs, _io_handler); + _handle_space, _fs, _event_handler); ::File_system::Dir_handle to_dir = _fs.dir(to_dir_path.base(), false); Fs_handle_guard to_dir_guard(*this, _fs, to_dir, _handle_space, - _fs, _io_handler); + _fs, _event_handler); _fs.move(from_dir, from_file_name.base() + 1, to_dir, to_file_name.base() + 1); @@ -709,7 +769,7 @@ class Vfs::Fs_file_system : public File_system ::File_system::Node_handle node; try { node = _fs.node(path); } catch (...) { return 0; } Fs_handle_guard node_guard(*this, _fs, node, _handle_space, _fs, - _io_handler); + _event_handler); ::File_system::Status status = _fs.status(node); @@ -721,7 +781,7 @@ class Vfs::Fs_file_system : public File_system try { ::File_system::Node_handle node = _fs.node(path); Fs_handle_guard node_guard(*this, _fs, node, _handle_space, - _fs, _io_handler); + _fs, _event_handler); ::File_system::Status status = _fs.status(node); @@ -767,7 +827,7 @@ class Vfs::Fs_file_system : public File_system try { ::File_system::Dir_handle dir = _fs.dir(dir_path.base(), false); Fs_handle_guard dir_guard(*this, _fs, dir, _handle_space, _fs, - _io_handler); + _event_handler); ::File_system::File_handle file = _fs.file(dir, file_name.base() + 1, @@ -775,7 +835,7 @@ class Vfs::Fs_file_system : public File_system *out_handle = new (alloc) Fs_vfs_file_handle(*this, alloc, vfs_mode, _handle_space, - file, _fs, _io_handler); + file, _fs, _event_handler); } catch (::File_system::Lookup_failed) { return OPEN_ERR_UNACCESSIBLE; } catch (::File_system::Permission_denied) { return OPEN_ERR_NO_PERM; } @@ -803,7 +863,7 @@ class Vfs::Fs_file_system : public File_system *out_handle = new (alloc) Fs_vfs_dir_handle(*this, alloc, ::File_system::READ_ONLY, - _handle_space, dir, _fs, _io_handler); + _handle_space, dir, _fs, _event_handler); } catch (::File_system::Lookup_failed) { return OPENDIR_ERR_LOOKUP_FAILED; } catch (::File_system::Name_too_long) { return OPENDIR_ERR_NAME_TOO_LONG; } @@ -835,7 +895,7 @@ class Vfs::Fs_file_system : public File_system false); Fs_handle_guard from_dir_guard(*this, _fs, dir_handle, - _handle_space, _fs, _io_handler); + _handle_space, _fs, _event_handler); ::File_system::Symlink_handle symlink_handle = _fs.symlink(dir_handle, symlink_name.base() + 1, create); @@ -844,7 +904,7 @@ class Vfs::Fs_file_system : public File_system Fs_vfs_symlink_handle(*this, alloc, ::File_system::READ_ONLY, _handle_space, symlink_handle, _fs, - _io_handler); + _event_handler); return OPENLINK_OK; } @@ -871,6 +931,41 @@ class Vfs::Fs_file_system : public File_system destroy(fs_handle->alloc(), fs_handle); } + Watch_result watch(char const *path, + Vfs_watch_handle **handle, + Allocator &alloc) + { + using namespace ::File_system; + + Watch_result res = WATCH_ERR_UNACCESSIBLE; + ::File_system::Watch_handle fs_handle { -1U }; + + try { fs_handle = _fs.watch(path); } + catch (Lookup_failed) { return WATCH_ERR_UNACCESSIBLE; } + catch (Permission_denied) { return WATCH_ERR_STATIC; } + catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } + catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } + + try { + *handle = new (alloc) + Fs_vfs_watch_handle( + *this, alloc, _watch_handle_space, fs_handle); + return WATCH_OK; + } + catch (Out_of_ram) { res = WATCH_ERR_OUT_OF_RAM; } + catch (Out_of_caps) { res = WATCH_ERR_OUT_OF_CAPS; } + _fs.close(fs_handle); + return res; + } + + void close(Vfs_watch_handle *vfs_handle) override + { + Fs_vfs_watch_handle *handle = + static_cast(vfs_handle); + _fs.close(handle->fs_handle); + destroy(handle->alloc(), handle); + }; + /*************************** ** File_system interface ** diff --git a/repos/os/src/lib/vfs/ram_file_system.h b/repos/os/src/lib/vfs/ram_file_system.h index f125d89469..cd4880cbf7 100644 --- a/repos/os/src/lib/vfs/ram_file_system.h +++ b/repos/os/src/lib/vfs/ram_file_system.h @@ -19,11 +19,16 @@ #include #include +namespace Vfs { class Ram_file_system; } + namespace Vfs_ram { using namespace Genode; using namespace Vfs; + struct Io_handle; + struct Watch_handle; + class Node; class File; class Symlink; @@ -49,7 +54,39 @@ namespace Vfs_ram { } -namespace Vfs { class Ram_file_system; } + +struct Vfs_ram::Io_handle final : public Vfs_handle, + private Genode::List::Element +{ + friend Genode::List; + + Vfs_ram::Node &node; + + /* Track if this handle has modified its node */ + bool modifying = false; + + Io_handle(Vfs::File_system &fs, + Allocator &alloc, + int status_flags, + Vfs_ram::Node &node) + : Vfs_handle(fs, fs, alloc, status_flags), node(node) + { } +}; + + +struct Vfs_ram::Watch_handle final : public Vfs_watch_handle, + private Genode::List::Element +{ + friend Genode::List; + using Genode::List::Element::next; + + Vfs_ram::Node &node; + + Watch_handle(Vfs::File_system &fs, + Allocator &alloc, + Node &node) + : Vfs_watch_handle(fs, alloc), node(node) { } +}; class Vfs_ram::Node : private Genode::Avl_node, private Genode::Lock @@ -58,10 +95,16 @@ class Vfs_ram::Node : private Genode::Avl_node, private Genode::Lock friend class Genode::Avl_node; friend class Genode::Avl_tree; + friend class Genode::List; + friend class Genode::List::Element; + friend class Genode::List; + friend class Genode::List::Element; + friend class Watch_handle; friend class Directory; char _name[MAX_NAME_LEN]; - int _open_handles = 0; + Genode::List _io_handles { }; + Genode::List _watch_handles { }; /** * Generate unique inode number @@ -89,37 +132,45 @@ class Vfs_ram::Node : private Genode::Avl_node, private Genode::Lock virtual Vfs::file_size length() = 0; - /** - * Increment reference counter - */ - void open() { ++_open_handles; } + void open(Io_handle &handle) { _io_handles.insert(&handle); } + void open(Watch_handle &handle) { _watch_handles.insert(&handle); } - bool close_but_keep() + bool opened() const { - if (--_open_handles < 0) { - inode = 0; - return false; - } - return true; + return _io_handles.first() != nullptr; } - virtual size_t read(char * /* dst */, size_t /* len */, file_size /* seek_offset */) + void close(Io_handle &handle) { _io_handles.remove(&handle); } + void close(Watch_handle &handle) { _watch_handles.remove(&handle); } + + void notify(Io_response_handler &handler) + { + for (Watch_handle *h = _watch_handles.first(); h; h = h->next()) { + if (auto *ctx = h->context()) { + handler.handle_watch_response(ctx); + } + } + } + + void unlink() { inode = 0; } + bool unlinked() const { return inode == 0; } + + virtual size_t read(char*, size_t, file_size) { Genode::error("Vfs_ram::Node::read() called"); return 0; } - virtual Vfs::File_io_service::Read_result complete_read(char * /* dst */, - file_size /* count */, - file_size /* seek_offset */, - file_size & /* out_count */) + virtual Vfs::File_io_service::Read_result complete_read(char *, + file_size, + file_size, + file_size &) { Genode::error("Vfs_ram::Node::complete_read() called"); return Vfs::File_io_service::READ_ERR_INVALID; } - virtual size_t write(char const * /* src */, size_t /* len */, - file_size /* seek_offset */) + virtual size_t write(char const *, size_t, file_size) { Genode::error("Vfs_ram::Node::write() called"); return 0; @@ -308,8 +359,8 @@ class Vfs_ram::Symlink : public Vfs_ram::Node Vfs::File_io_service::Read_result complete_read(char *dst, file_size count, - file_size /* seek_offset */, - file_size &out_count) override + file_size, + file_size &out_count) override { out_count = get(dst, count); return Vfs::File_io_service::READ_OK; @@ -344,7 +395,7 @@ class Vfs_ram::Directory : public Vfs_ram::Node while (Node *node = _entries.first()) { _entries.remove(node); if (File *file = dynamic_cast(node)) { - if (file->close_but_keep()) + if (file->opened()) continue; } else if (Directory *dir = dynamic_cast(node)) { dir->empty(alloc); @@ -426,23 +477,12 @@ class Vfs::Ram_file_system : public Vfs::File_system { private: - struct Ram_vfs_handle : Vfs_handle - { - Vfs_ram::Node &node; + friend class Genode::List; - Ram_vfs_handle(Ram_file_system &fs, - Allocator &alloc, - int status_flags, - Vfs_ram::Node &node) - : Vfs_handle(fs, fs, alloc, status_flags), node(node) - { - node.open(); - } - }; - - Genode::Env &_env; - Genode::Allocator &_alloc; - Vfs_ram::Directory _root = { "" }; + Genode::Env &_env; + Genode::Allocator &_alloc; + Io_response_handler &_io_handler; + Vfs_ram::Directory _root = { "" }; Vfs_ram::Node *lookup(char const *path, bool return_parent = false) { @@ -493,8 +533,10 @@ class Vfs::Ram_file_system : public Vfs::File_system using namespace Vfs_ram; if (File *file = dynamic_cast(node)) { - if (file->close_but_keep()) + if (file->opened()) { + file->unlink(); return; + } } else if (Directory *dir = dynamic_cast(node)) { dir->empty(_alloc); } @@ -507,8 +549,9 @@ class Vfs::Ram_file_system : public Vfs::File_system Ram_file_system(Genode::Env &env, Genode::Allocator &alloc, Genode::Xml_node, - Io_response_handler &, File_system &) - : _env(env), _alloc(alloc) { } + Io_response_handler &io_handler, + File_system &) + : _env(env), _alloc(alloc), _io_handler(io_handler) { } ~Ram_file_system() { _root.empty(_alloc); } @@ -566,6 +609,7 @@ class Vfs::Ram_file_system : public Vfs::File_system try { file = new (_alloc) File(name, _alloc); } catch (Out_of_memory) { return OPEN_ERR_NO_SPACE; } parent->adopt(file); + parent->notify(_io_handler); } else { Node *node = lookup(path); if (!node) return OPEN_ERR_UNACCESSIBLE; @@ -575,7 +619,7 @@ class Vfs::Ram_file_system : public Vfs::File_system } try { - *handle = new (alloc) Ram_vfs_handle(*this, alloc, mode, *file); + *handle = new (alloc) Io_handle(*this, alloc, mode, *file); return OPEN_OK; } catch (Genode::Out_of_ram) { if (create) { @@ -607,6 +651,8 @@ class Vfs::Ram_file_system : public Vfs::File_system Directory *dir; if (create) { + if (*name == '\0') + return OPENDIR_ERR_NODE_ALREADY_EXISTS; if (strlen(name) >= MAX_NAME_LEN) return OPENDIR_ERR_NAME_TOO_LONG; @@ -618,7 +664,7 @@ class Vfs::Ram_file_system : public Vfs::File_system catch (Out_of_memory) { return OPENDIR_ERR_NO_SPACE; } parent->adopt(dir); - + parent->notify(_io_handler); } else { Node *node = lookup(path); @@ -629,9 +675,8 @@ class Vfs::Ram_file_system : public Vfs::File_system } try { - *handle = new (alloc) Ram_vfs_handle(*this, alloc, - Ram_vfs_handle::STATUS_RDONLY, - *dir); + *handle = new (alloc) Io_handle( + *this, alloc, Io_handle::STATUS_RDONLY, *dir); return OPENDIR_OK; } catch (Genode::Out_of_ram) { if (create) { @@ -677,7 +722,7 @@ class Vfs::Ram_file_system : public Vfs::File_system link->lock(); parent->adopt(link); link->unlock(); - + parent->notify(_io_handler); } else { if (!node) return OPENLINK_ERR_LOOKUP_FAILED; @@ -688,9 +733,8 @@ class Vfs::Ram_file_system : public Vfs::File_system } try { - *handle = new (alloc) Ram_vfs_handle(*this, alloc, - Ram_vfs_handle::STATUS_RDWR, - *link); + *handle = new (alloc) + Io_handle(*this, alloc, Io_handle::STATUS_RDWR, *link); return OPENLINK_OK; } catch (Genode::Out_of_ram) { if (create) { @@ -709,13 +753,19 @@ class Vfs::Ram_file_system : public Vfs::File_system void close(Vfs_handle *vfs_handle) override { - Ram_vfs_handle *ram_handle = - static_cast(vfs_handle); + Vfs_ram::Io_handle *ram_handle = + static_cast(vfs_handle); - if (ram_handle) { - if (!ram_handle->node.close_but_keep()) - destroy(_alloc, &ram_handle->node); - destroy(vfs_handle->alloc(), ram_handle); + Vfs_ram::Node &node = ram_handle->node; + bool node_modified = ram_handle->modifying; + + ram_handle->node.close(*ram_handle); + destroy(vfs_handle->alloc(), ram_handle); + + if (ram_handle->node.unlinked() && !ram_handle->node.opened()) { + destroy(_alloc, &ram_handle->node); + } else if (node_modified) { + node.notify(_io_handler); } } @@ -797,6 +847,9 @@ class Vfs::Ram_file_system : public Vfs::File_system from_node->name(new_name); to_dir->adopt(from_node); + from_dir->notify(_io_handler); + to_dir->notify(_io_handler); + return RENAME_OK; } @@ -813,6 +866,7 @@ class Vfs::Ram_file_system : public Vfs::File_system node->lock(); parent->release(node); + parent->notify(_io_handler); remove(node); return UNLINK_OK; } @@ -853,6 +907,35 @@ class Vfs::Ram_file_system : public Vfs::File_system static_cap_cast(ds_cap)); } + Watch_result watch(char const *path, + Vfs_watch_handle **handle, + Allocator &alloc) override + { + using namespace Vfs_ram; + + Node *node = lookup(path); + if (!node) return WATCH_ERR_UNACCESSIBLE; + Node::Guard guard(node); + + try { + Vfs_ram::Watch_handle *watch_handle = new(alloc) + Vfs_ram::Watch_handle(*this, alloc, *node); + node->open(*watch_handle); + *handle = watch_handle; + return WATCH_OK; + } + catch (Genode::Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } + catch (Genode::Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } + } + + void close(Vfs_watch_handle *vfs_handle) override + { + Vfs_ram::Watch_handle *watch_handle = + static_cast(vfs_handle); + watch_handle->node.close(*watch_handle); + destroy(watch_handle->alloc(), watch_handle); + }; + /************************ ** File I/O interface ** ************************/ @@ -864,11 +947,12 @@ class Vfs::Ram_file_system : public Vfs::File_system if ((vfs_handle->status_flags() & OPEN_MODE_ACCMODE) == OPEN_MODE_RDONLY) return WRITE_ERR_INVALID; - Ram_vfs_handle const *handle = - static_cast(vfs_handle); + Vfs_ram::Io_handle *handle = + static_cast(vfs_handle); Vfs_ram::Node::Guard guard(&handle->node); out = handle->node.write(buf, len, handle->seek()); + handle->modifying = true; return WRITE_OK; } @@ -878,8 +962,8 @@ class Vfs::Ram_file_system : public Vfs::File_system { out_count = 0; - Ram_vfs_handle const *handle = - static_cast(vfs_handle); + Vfs_ram::Io_handle const *handle = + static_cast(vfs_handle); Vfs_ram::Node::Guard guard(&handle->node); @@ -893,8 +977,8 @@ class Vfs::Ram_file_system : public Vfs::File_system if ((vfs_handle->status_flags() & OPEN_MODE_ACCMODE) == OPEN_MODE_RDONLY) return FTRUNCATE_ERR_NO_PERM; - Ram_vfs_handle const *handle = - static_cast(vfs_handle); + Vfs_ram::Io_handle const *handle = + static_cast(vfs_handle); Vfs_ram::Node::Guard guard(&handle->node); @@ -903,6 +987,21 @@ class Vfs::Ram_file_system : public Vfs::File_system return FTRUNCATE_OK; } + /** + * Notify other handles if this handle has modified the node + */ + Sync_result complete_sync(Vfs_handle *vfs_handle) override + { + Vfs_ram::Io_handle *handle = + static_cast(vfs_handle); + if (handle->modifying) { + handle->modifying = false; + handle->node.close(*handle); + handle->node.notify(_io_handler); + handle->node.open(*handle); + } + return SYNC_OK; + } /*************************** ** File_system interface ** diff --git a/repos/os/src/server/vfs/main.cc b/repos/os/src/server/vfs/main.cc index 23223f2bdc..426f267f00 100644 --- a/repos/os/src/server/vfs/main.cc +++ b/repos/os/src/server/vfs/main.cc @@ -35,7 +35,7 @@ namespace Vfs_server { class Session_component; class Root; - class Io_response_handler; + class Event_response_handler; typedef Genode::Registered Registered_session; typedef Genode::Registry Session_registry; @@ -53,7 +53,7 @@ namespace Vfs_server { class Vfs_server::Session_component : public File_system::Session_rpc_object, - public Node_io_handler + public Session_io_handler { private: @@ -74,6 +74,8 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, */ Path const _root_path; + Genode::Session_label const _label; + bool const _writable; /* @@ -92,11 +94,11 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, * \throw Invalid_handle */ template - void _apply(Node_handle handle, FUNC const &fn) + void _apply_node(Node_handle handle, FUNC const &fn) { Node_space::Id id { handle.value }; - try { _node_space.apply(id, fn); } + try { return _node_space.apply(id, fn); } catch (Node_space::Unknown_id) { throw Invalid_handle(); } } @@ -155,7 +157,7 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, case Packet_descriptor::READ: try { - _apply(packet.handle(), [&] (Node &node) { + _apply(packet.handle(), [&] (Io_node &node) { if (!node.read_ready()) { node.notify_read_ready(true); throw Not_ready(); @@ -178,7 +180,7 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, case Packet_descriptor::WRITE: try { - _apply(packet.handle(), [&] (Node &node) { + _apply(packet.handle(), [&] (Io_node &node) { if (node.mode() & WRITE_ONLY) { res_length = node.write((char const *)content, length, seek); @@ -213,7 +215,7 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, break; case Packet_descriptor::CONTENT_CHANGED: - /* The VFS does not track file changes yet */ + Genode::warning("ignoring CONTENT_CHANGED packet from client"); throw Dont_ack(); case Packet_descriptor::SYNC: @@ -222,7 +224,7 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, * Sync the VFS and send any pending signals on the node. */ try { - _apply(packet.handle(), [&] (Node &node) { + _apply(packet.handle(), [&] (Io_node &node) { node.sync(); succeeded = true; }); @@ -356,6 +358,8 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, destroy(_alloc, dir); else if (Symlink *link = dynamic_cast(&node)) destroy(_alloc, link); + else if (Watch_node *watch = dynamic_cast(&node)) + destroy(_alloc, watch); else destroy(_alloc, &node); } @@ -372,6 +376,7 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, */ Session_component(Genode::Env &env, + char const *label, Genode::Ram_quota ram_quota, Genode::Cap_quota cap_quota, size_t tx_buf_size, @@ -387,6 +392,7 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, _process_packet_handler(env.ep(), *this, &Session_component::_process_packets), _vfs(vfs), _root_path(root_path), + _label(label), _writable(writable) { /* @@ -419,14 +425,20 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, * node-specific, for example after 'release_packet()' to signal * that a previously failed 'alloc_packet()' may succeed now. */ - void handle_general_io() - { - _process_packets(); - } + void handle_general_io() { + _process_packets(); } - /* Node_io_handler interface */ - void handle_node_io(Node &node) override + + /******************************** + ** Node_io_handler interface ** + ********************************/ + + void handle_node_io(Io_node &node) override { + if (!tx_sink()->ready_to_ack()) + Genode::error( + "dropping I/O notfication, congested packet buffer to '", _label, "'"); + if (node.notify_read_ready() && node.read_ready() && tx_sink()->ready_to_ack()) { Packet_descriptor packet(Packet_descriptor(), @@ -440,6 +452,22 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, _process_packets(); } + void handle_node_watch(Watch_node &node) override + { + if (!tx_sink()->ready_to_ack()) + Genode::error( + "dropping watch notfication, congested packet buffer to '", _label, "'"); + + if (tx_sink()->ready_to_ack()) { + Packet_descriptor packet(Packet_descriptor(), + Node_handle { node.id().value }, + Packet_descriptor::CONTENT_CHANGED, + 0, 0); + tx_sink()->acknowledge_packet(packet); + } + _process_packets(); + } + /*************************** ** File_system interface ** ***************************/ @@ -482,7 +510,7 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, _assert_valid_name(name_str); return File_handle { - dir.file(_node_space, _vfs, _alloc, *this, name_str, fs_mode, create).value + dir.file(_node_space, _vfs, _alloc, name_str, fs_mode, create).value }; }); } @@ -516,16 +544,47 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, Node *node; - try { node = new (_alloc) Node(_node_space, path_str, STAT_ONLY, - *this); } + try { node = new (_alloc) Node(_node_space, path_str, *this); } catch (Out_of_memory) { throw Out_of_ram(); } return Node_handle { node->id().value }; } + Watch_handle watch(File_system::Path const &path) override + { + char const *path_str = path.string(); + + _assert_valid_path(path_str); + + /* re-root the path */ + Path sub_path(path_str+1, _root_path.base()); + path_str = sub_path.base(); + + Vfs::Vfs_watch_handle *vfs_handle = nullptr; + typedef Directory_service::Watch_result Result; + switch (_vfs.watch(path_str, &vfs_handle, _alloc)) { + case Result::WATCH_OK: break; + case Result::WATCH_ERR_UNACCESSIBLE: + throw Lookup_failed(); + case Result::WATCH_ERR_STATIC: + throw Unavailable(); + case Result::WATCH_ERR_OUT_OF_RAM: + throw Out_of_ram(); + case Result::WATCH_ERR_OUT_OF_CAPS: + throw Out_of_caps(); + } + + Node *node; + try { node = new (_alloc) + Watch_node(_node_space, path_str, *vfs_handle, *this); } + catch (Out_of_memory) { throw Out_of_ram(); } + + return Watch_handle { node->id().value }; + } + void close(Node_handle handle) override { - try { _apply(handle, [&] (Node &node) { + try { _apply_node(handle, [&] (Node &node) { _close(node); }); } catch (File_system::Invalid_handle) { } } @@ -534,7 +593,7 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, { File_system::Status fs_stat; - _apply(node_handle, [&] (Node &node) { + _apply_node(node_handle, [&] (Node &node) { Directory_service::Stat vfs_stat; if (_vfs.stat(node.path(), vfs_stat) != Directory_service::STAT_OK) @@ -615,15 +674,17 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object, void control(Node_handle, Control) override { } }; - -struct Vfs_server::Io_response_handler : Vfs::Io_response_handler +/** + * Global vfs event handler + */ +struct Vfs_server::Event_response_handler : Vfs::Io_response_handler { Session_registry &_session_registry; bool _in_progress { false }; bool _handle_general_io { false }; - Io_response_handler(Session_registry &session_registry) + Event_response_handler(Session_registry &session_registry) : _session_registry(session_registry) { } void handle_io_response(Vfs::Vfs_handle::Context *context) override @@ -637,7 +698,7 @@ struct Vfs_server::Io_response_handler : Vfs::Io_response_handler _in_progress = true; if (context) - Node::node_by_context(*context).handle_io_response(); + Io_node::node_by_context(*context).handle_io_response(); else _handle_general_io = true; @@ -650,6 +711,12 @@ struct Vfs_server::Io_response_handler : Vfs::Io_response_handler _in_progress = false; } + + void handle_watch_response(Vfs::Vfs_watch_handle::Context *context) override + { + if (context) + Watch_node::node_by_context(*context).handle_watch_response(); + } }; @@ -676,12 +743,12 @@ class Vfs_server::Root : public Genode::Root_component Session_registry _session_registry { }; - Io_response_handler _io_response_handler { _session_registry }; + Event_response_handler _response_handler { _session_registry }; Vfs::Global_file_system_factory _global_file_system_factory { _vfs_heap }; Vfs::Dir_file_system _vfs { - _env, _vfs_heap, vfs_config(), _io_response_handler, + _env, _vfs_heap, vfs_config(), _response_handler, _global_file_system_factory }; Genode::Signal_handler _config_handler { @@ -774,7 +841,7 @@ class Vfs_server::Root : public Genode::Root_component } Session_component *session = new (md_alloc()) - Registered_session(_session_registry, _env, + Registered_session(_session_registry, _env, label.string(), Genode::Ram_quota{ram_quota}, Genode::Cap_quota{cap_quota}, tx_buf_size, _vfs, diff --git a/repos/os/src/server/vfs/node.h b/repos/os/src/server/vfs/node.h index 0b25ffbecf..b367492e29 100644 --- a/repos/os/src/server/vfs/node.h +++ b/repos/os/src/server/vfs/node.h @@ -29,16 +29,19 @@ namespace Vfs_server { using namespace File_system; using namespace Vfs; - struct Node; - struct Directory; - struct File; - struct Symlink; + class Node; + class Io_node; + class Watch_node; + class Directory; + class File; + class Symlink; typedef Genode::Id_space Node_space; - struct Node_io_handler : Interface + struct Session_io_handler : Interface { - virtual void handle_node_io(Node &node) = 0; + virtual void handle_node_io(Io_node &node) = 0; + virtual void handle_node_watch(Watch_node &node) = 0; }; /** @@ -59,20 +62,21 @@ namespace Vfs_server { * Type trait for determining the node type for a given handle type */ template struct Node_type; - template<> struct Node_type { typedef Node Type; }; - template<> struct Node_type { typedef Directory Type; }; - template<> struct Node_type { typedef File Type; }; - template<> struct Node_type { typedef Symlink Type; }; - + template<> struct Node_type { typedef Io_node Type; }; + template<> struct Node_type { typedef Directory Type; }; + template<> struct Node_type { typedef File Type; }; + template<> struct Node_type { typedef Symlink Type; }; + template<> struct Node_type { typedef Watch_node Type; }; /** * Type trait for determining the handle type for a given node type */ template struct Handle_type; - template<> struct Handle_type { typedef Node_handle Type; }; + template<> struct Handle_type { typedef Node_handle Type; }; template<> struct Handle_type { typedef Dir_handle Type; }; template<> struct Handle_type { typedef File_handle Type; }; template<> struct Handle_type { typedef Symlink_handle Type; }; + template<> struct Handle_type { typedef Watch_handle Type; }; /* * Note that the file objects are created at the @@ -82,10 +86,8 @@ namespace Vfs_server { */ } - class Vfs_server::Node : public File_system::Node_base, - private Node_space::Element, - private Vfs::Vfs_handle::Context + private Node_space::Element { public: @@ -100,6 +102,52 @@ class Vfs_server::Node : public File_system::Node_base, Node &operator = (Node const &); Path const _path; + + protected: + + /** + * I/O handler for session context + */ + Session_io_handler &_session_io_handler; + + public: + + Node(Node_space &space, char const *node_path, + Session_io_handler &io_handler) + : + Node_space::Element(*this, space), + _path(node_path), + _session_io_handler(io_handler) + { } + + virtual ~Node() { } + + using Node_space::Element::id; + + char const *path() const { return _path.base(); } + + /** + * Print for debugging + */ + void print(Genode::Output &out) const { + out.out_string(_path.base()); } +}; + +class Vfs_server::Io_node : public Vfs_server::Node, + private Vfs::Vfs_handle::Context +{ + public: + + enum Op_state { IDLE, READ_QUEUED, SYNC_QUEUED }; + + private: + + /* + * Noncopyable + */ + Io_node(Io_node const &); + Io_node &operator = (Io_node const &); + Mode const _mode; bool _notify_read_ready = false; @@ -108,7 +156,6 @@ class Vfs_server::Node : public File_system::Node_base, Vfs::Vfs_handle::Context &context() { return *this; } - Node_io_handler &_node_io_handler; Vfs::Vfs_handle *_handle { nullptr }; Op_state op_state { Op_state::IDLE }; @@ -183,24 +230,19 @@ class Vfs_server::Node : public File_system::Node_base, public: - Node(Node_space &space, char const *node_path, Mode node_mode, - Node_io_handler &node_io_handler) - : - Node_space::Element(*this, space), - _path(node_path), _mode(node_mode), - _node_io_handler(node_io_handler) - { } + Io_node(Node_space &space, char const *node_path, Mode node_mode, + Session_io_handler &io_handler) + : Node(space, node_path, io_handler), _mode(node_mode) { } - virtual ~Node() { } + virtual ~Io_node() { } using Node_space::Element::id; - static Node &node_by_context(Vfs::Vfs_handle::Context &context) + static Io_node &node_by_context(Vfs::Vfs_handle::Context &context) { - return static_cast(context); + return static_cast(context); } - char const *path() { return _path.base(); } Mode mode() const { return _mode; } virtual size_t read(char * /* dst */, size_t /* len */, seek_off_t) @@ -211,10 +253,13 @@ class Vfs_server::Node : public File_system::Node_base, bool read_ready() { return _handle->fs().read_ready(_handle); } - void handle_io_response() - { - _node_io_handler.handle_node_io(*this); - } + /** + * The global handler has drawn an association from an I/O + * context and this open node, now process the event at the + * session for this node. + */ + void handle_io_response() { + _session_io_handler.handle_node_io(*this); } void notify_read_ready(bool requested) { @@ -257,16 +302,67 @@ class Vfs_server::Node : public File_system::Node_base, } }; -struct Vfs_server::Symlink : Node + +class Vfs_server::Watch_node final : public Vfs_server::Node, + private Vfs::Vfs_watch_handle::Context { - Symlink(Node_space &space, - Vfs::File_system &vfs, - Genode::Allocator &alloc, - Node_io_handler &node_io_handler, - char const *link_path, - Mode mode, - bool create) - : Node(space, link_path, mode, node_io_handler) + private: + + /* + * Noncopyable + */ + Watch_node(Watch_node const &); + Watch_node &operator = (Watch_node const &); + + Vfs::Vfs_watch_handle &_watch_handle; + + public: + + Watch_node(Node_space &space, char const *path, + Vfs::Vfs_watch_handle &handle, + Session_io_handler &io_handler) + : + Node(space, path, io_handler), + _watch_handle(handle) + { + /* + * set the context so this Watch object + * is passed back thru the Io_handler + */ + _watch_handle.context(this); + } + + ~Watch_node() + { + _watch_handle.context((Vfs::Vfs_watch_handle::Context*)~0ULL); + _watch_handle.fs().close(&_watch_handle); + } + + static Watch_node &node_by_context(Vfs::Vfs_watch_handle::Context &context) + { + return static_cast(context); + } + + /** + * The global handler has drawn an association from a watch + * context and this open node, now process the event at the + * session for this node. + */ + void handle_watch_response() { + _session_io_handler.handle_node_watch(*this); } +}; + + +struct Vfs_server::Symlink : Io_node +{ + Symlink(Node_space &space, + Vfs::File_system &vfs, + Genode::Allocator &alloc, + Session_io_handler &node_io_handler, + char const *link_path, + Mode mode, + bool create) + : Io_node(space, link_path, mode, node_io_handler) { assert_openlink(vfs.openlink(link_path, create, &_handle, alloc)); _handle->context = &context(); @@ -316,7 +412,7 @@ struct Vfs_server::Symlink : Node }; -class Vfs_server::File : public Node +class Vfs_server::File : public Io_node { private: @@ -330,15 +426,15 @@ class Vfs_server::File : public Node public: - File(Node_space &space, - Vfs::File_system &vfs, - Genode::Allocator &alloc, - Node_io_handler &node_io_handler, - char const *file_path, - Mode fs_mode, - bool create) + File(Node_space &space, + Vfs::File_system &vfs, + Genode::Allocator &alloc, + Session_io_handler &node_io_handler, + char const *file_path, + Mode fs_mode, + bool create) : - Node(space, file_path, fs_mode, node_io_handler) + Io_node(space, file_path, fs_mode, node_io_handler) { unsigned vfs_mode = (fs_mode-1) | (create ? Vfs::Directory_service::OPEN_MODE_CREATE : 0); @@ -387,15 +483,15 @@ class Vfs_server::File : public Node }; -struct Vfs_server::Directory : Node +struct Vfs_server::Directory : Io_node { - Directory(Node_space &space, - Vfs::File_system &vfs, - Genode::Allocator &alloc, - Node_io_handler &node_io_handler, - char const *dir_path, - bool create) - : Node(space, dir_path, READ_ONLY, node_io_handler) + Directory(Node_space &space, + Vfs::File_system &vfs, + Genode::Allocator &alloc, + Session_io_handler &node_io_handler, + char const *dir_path, + bool create) + : Io_node(space, dir_path, READ_ONLY, node_io_handler) { assert_opendir(vfs.opendir(dir_path, create, &_handle, alloc)); _handle->context = &context(); @@ -406,7 +502,6 @@ struct Vfs_server::Directory : Node Node_space::Id file(Node_space &space, Vfs::File_system &vfs, Genode::Allocator &alloc, - Node_io_handler &node_io_handler, char const *file_path, Mode mode, bool create) @@ -416,8 +511,9 @@ struct Vfs_server::Directory : Node File *file; try { - file = new (alloc) - File(space, vfs, alloc, node_io_handler, path_str, mode, create); + file = new (alloc) File(space, vfs, alloc, + _session_io_handler, + path_str, mode, create); } catch (Out_of_memory) { throw Out_of_ram(); } if (create) @@ -436,7 +532,8 @@ struct Vfs_server::Directory : Node char const *path_str = subpath.base(); Symlink *link; - try { link = new (alloc) Symlink(space, vfs, alloc, _node_io_handler, + try { link = new (alloc) Symlink(space, vfs, alloc, + _session_io_handler, path_str, mode, create); } catch (Out_of_memory) { throw Out_of_ram(); } if (create)