From ac691eb2292edc85eab82124a6a7022480ac1d7d Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 26 Jan 2022 17:39:49 +0100 Subject: [PATCH] file_system/util.h: remove packet-stream helpers The 'read' and 'write' utilities are from a time before the VFS API as os/vfs.h was available. They rely on the (now removed) blocking semantics of the packet-stream interface. The only remaining legitimate use case of the direct interaction with the file-system session without VFS is the back end of gcov, which needs a way to exfiltrate the statistical data using a channel that is independent from the libc or the VFS. Issue #4390 --- repos/libports/src/lib/gcov/libc/libc.cc | 222 ++++++++++++++++++----- repos/os/include/file_system/util.h | 119 ------------ 2 files changed, 174 insertions(+), 167 deletions(-) diff --git a/repos/libports/src/lib/gcov/libc/libc.cc b/repos/libports/src/lib/gcov/libc/libc.cc index d87c128ed3..2dcbb1769e 100644 --- a/repos/libports/src/lib/gcov/libc/libc.cc +++ b/repos/libports/src/lib/gcov/libc/libc.cc @@ -27,7 +27,9 @@ extern "C" { #include "stdio.h" } -typedef Genode::Path Absolute_path; +using namespace Genode; + +typedef Path Absolute_path; struct FILE { }; @@ -37,25 +39,153 @@ FILE *stderr = &stderr_file; struct Gcov_env { - Genode::Env &env; - Genode::Attached_rom_dataspace config { env, "config" }; - Genode::Heap heap { env.ram(), env.rm() }; - Genode::Allocator_avl fs_alloc { &heap }; - File_system::Connection fs { env, fs_alloc, "gcov_data" }; - unsigned long seek_offset { 0 }; + using seek_off_t = File_system::seek_off_t; + + Env &env; + Attached_rom_dataspace config { env, "config" }; + Heap heap { env.ram(), env.rm() }; + Allocator_avl fs_alloc { &heap }; + + /* + * We use a file-system session directly to exfiltrate the gcov data from + * the component without any interplay with the libc or the component's + * VFS. + */ + + File_system::Connection fs { env, fs_alloc, "gcov_data" }; + seek_off_t seek_offset { 0 }; + + Io_signal_handler _fs_signal_handler { + env.ep(), *this, &Gcov_env::_handle_fs_signal }; + + void _handle_fs_signal() { } /* only one file is open at a time */ - Genode::Constructible file_handle; - FILE file; + Constructible file_handle; + FILE file; - Gcov_env(Genode::Env &env) : env(env) { } + void _block_for_ack() + { + while (!fs.tx()->ack_avail()) + env.ep().wait_and_dispatch_one_io_signal(); + } + + Gcov_env(Env &env) + : + env(env) + { + fs.sigh(_fs_signal_handler); + } + + size_t read (File_system::Node_handle const &, void *, size_t, seek_off_t); + size_t write(File_system::Node_handle const &, void const *, size_t, seek_off_t); }; -static Genode::Constructible gcov_env; +size_t Gcov_env::read(File_system::Node_handle const &node_handle, + void *dst, size_t count, seek_off_t seek_offset) +{ + bool success = true; + File_system::Session::Tx::Source &source = *fs.tx(); + + size_t const max_packet_size = source.bulk_buffer_size() / 2; + + size_t remaining_count = count; + + while (remaining_count && success) { + + size_t const curr_packet_size = + min(remaining_count, max_packet_size); + + File_system::Packet_descriptor + packet(source.alloc_packet(curr_packet_size), + node_handle, + File_system::Packet_descriptor::READ, + curr_packet_size, + seek_offset); + + /* pass packet to server side */ + source.submit_packet(packet); + + _block_for_ack(); + + packet = source.get_acked_packet(); + success = packet.succeeded(); + + size_t const read_num_bytes = + min(packet.length(), curr_packet_size); + + /* copy-out payload into destination buffer */ + memcpy(dst, source.packet_content(packet), read_num_bytes); + + source.release_packet(packet); + + /* prepare next iteration */ + seek_offset += read_num_bytes; + dst = (void *)((addr_t)dst + read_num_bytes); + remaining_count -= read_num_bytes; + + /* + * If we received less bytes than requested, we reached the end + * of the file. + */ + if (read_num_bytes < curr_packet_size) + break; + } + + return count - remaining_count; +} -void gcov_init(Genode::Env &env) +size_t Gcov_env::write(File_system::Node_handle const &node_handle, + void const *src, size_t count, + seek_off_t seek_offset) +{ + bool success = true; + File_system::Session::Tx::Source &source = *fs.tx(); + + size_t const max_packet_size = source.bulk_buffer_size() / 2; + + size_t remaining_count = count; + + while (remaining_count && success) { + + size_t const curr_packet_size = + min(remaining_count, max_packet_size); + + File_system::Packet_descriptor + packet(source.alloc_packet(curr_packet_size), + node_handle, + File_system::Packet_descriptor::WRITE, + curr_packet_size, + seek_offset); + + /* copy-out source buffer into payload */ + memcpy(source.packet_content(packet), src, curr_packet_size); + + /* pass packet to server side */ + source.submit_packet(packet); + + _block_for_ack(); + + packet = source.get_acked_packet();; + success = packet.succeeded(); + source.release_packet(packet); + + /* prepare next iteration */ + seek_offset += curr_packet_size; + src = (void *)((addr_t)src + curr_packet_size); + remaining_count -= curr_packet_size; + } + + return count - remaining_count; +} + + +static Constructible gcov_env; + + +void gcov_init(Env &env) { gcov_env.construct(env); } @@ -63,14 +193,14 @@ void gcov_init(Genode::Env &env) extern "C" void abort() { - Genode::error("abort() called: not implemented"); - Genode::sleep_forever(); + error("abort() called: not implemented"); + sleep_forever(); } extern "C" int atoi(const char *nptr) { - Genode::error("atoi() called: not implemented"); + error("atoi() called: not implemented"); return 0; } @@ -78,7 +208,7 @@ extern "C" int atoi(const char *nptr) extern "C" void exit(int status) { gcov_env->env.parent().exit(status); - Genode::sleep_forever(); + sleep_forever(); } @@ -105,12 +235,12 @@ extern "C" FILE *fopen(const char *path, const char *mode) file_name.base() + 1, File_system::READ_WRITE, false)); - if (Genode::strcmp(mode, "w+b", 3) == 0) + if (strcmp(mode, "w+b", 3) == 0) gcov_env->fs.truncate(*(gcov_env->file_handle), 0); } catch (File_system::Lookup_failed) { - if (Genode::strcmp(mode, "w+b", 3) == 0) + if (strcmp(mode, "w+b", 3) == 0) gcov_env->file_handle.construct(gcov_env->fs.file(dir, file_name.base() + 1, File_system::READ_WRITE, @@ -128,10 +258,10 @@ extern "C" FILE *fopen(const char *path, const char *mode) try { - Genode::Xml_node config(gcov_env->config.local_addr(), - gcov_env->config.size()); + Xml_node config(gcov_env->config.local_addr(), + gcov_env->config.size()); - Genode::Xml_node libgcov_node = config.sub_node("libgcov"); + Xml_node libgcov_node = config.sub_node("libgcov"); Absolute_path annotate_file_name { file_name }; annotate_file_name.remove_trailing('a'); @@ -144,29 +274,26 @@ extern "C" FILE *fopen(const char *path, const char *mode) File_system::seek_off_t seek_offset = 0; - libgcov_node.for_each_sub_node("annotate", - [&] (Genode::Xml_node annotate_node) { + libgcov_node.for_each_sub_node("annotate", [&] (Xml_node annotate_node) { - typedef Genode::String Source; + typedef String Source; Source const source = annotate_node.attribute_value("source", Source()); - seek_offset += File_system::write(gcov_env->fs, - annotate_file_handle, - source.string(), - Genode::strlen(source.string()), - seek_offset); + seek_offset += gcov_env->write(annotate_file_handle, + source.string(), + strlen(source.string()), + seek_offset); - seek_offset += File_system::write(gcov_env->fs, - annotate_file_handle, - "\n", - 1, - seek_offset); + seek_offset += gcov_env->write(annotate_file_handle, + "\n", + 1, + seek_offset); }); gcov_env->fs.close(annotate_file_handle); } - catch (Genode::Xml_node::Nonexistent_sub_node) { } - catch (Genode::Xml_attribute::Nonexistent_attribute) { } + catch (Xml_node::Nonexistent_sub_node) { } + catch (Xml_attribute::Nonexistent_attribute) { } return &gcov_env->file; } @@ -175,7 +302,7 @@ extern "C" FILE *fopen(const char *path, const char *mode) extern "C" int fprintf(FILE *stream, const char *format, ...) { if (stream != stderr) { - Genode::error("fprintf() called: not implemented"); + error("fprintf() called: not implemented"); return 0; } @@ -190,9 +317,9 @@ extern "C" int fprintf(FILE *stream, const char *format, ...) extern "C" size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) { - size_t bytes_read = File_system::read(gcov_env->fs, *(gcov_env->file_handle), - ptr, size * nmemb, - gcov_env->seek_offset); + size_t bytes_read = gcov_env->read(*(gcov_env->file_handle), + ptr, size * nmemb, + gcov_env->seek_offset); gcov_env->seek_offset += bytes_read; @@ -212,7 +339,7 @@ extern "C" void free(void *ptr) extern "C" int fseek(FILE *stream, long offset, int whence) { if (whence != 0) - Genode::error("fseek(): unsupported 'whence'"); + error("fseek(): unsupported 'whence'"); gcov_env->seek_offset = offset; @@ -229,14 +356,13 @@ extern "C" long ftell(FILE *stream) extern "C" size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) { if (stream == stderr) { - Genode::log(Genode::Cstring((const char*)ptr, size*nmemb)); + log(Cstring((const char*)ptr, size*nmemb)); return 0; } - size_t bytes_written = File_system::write(gcov_env->fs, - *(gcov_env->file_handle), - ptr, size * nmemb, - gcov_env->seek_offset); + size_t bytes_written = gcov_env->write(*(gcov_env->file_handle), + ptr, size * nmemb, + gcov_env->seek_offset); gcov_env->seek_offset += bytes_written; @@ -263,7 +389,7 @@ extern "C" void *malloc(size_t size) { return gcov_env->heap.try_alloc(size).convert( [&] (void *ptr) { return ptr; }, - [&] (Genode::Allocator::Alloc_error) -> void * { return nullptr; }); + [&] (Allocator::Alloc_error) -> void * { return nullptr; }); } @@ -316,7 +442,7 @@ extern "C" char *strchr(const char *s, int c) extern "C" char *strcpy(char *dest, const char *src) { - Genode::copy_cstring(dest, src, Genode::strlen(src) + 1); + copy_cstring(dest, src, strlen(src) + 1); return dest; } diff --git a/repos/os/include/file_system/util.h b/repos/os/include/file_system/util.h index 2561bac715..8230da40b7 100644 --- a/repos/os/include/file_system/util.h +++ b/repos/os/include/file_system/util.h @@ -92,125 +92,6 @@ namespace File_system { } - /** - * Collect pending packet acknowledgements, freeing the space occupied - * by the packet in the bulk buffer - * - * This function should be called prior enqueing new packets into the - * packet stream to free up space in the bulk buffer. - */ - static void collect_acknowledgements(Session::Tx::Source &source) - { - while (source.ack_avail()) - source.release_packet(source.get_acked_packet()); - } - - - /** - * Read file content - */ - static inline size_t read(Session &fs, Node_handle const &node_handle, - void *dst, size_t count, seek_off_t seek_offset = 0) - { - bool success = true; - Session::Tx::Source &source = *fs.tx(); - - size_t const max_packet_size = source.bulk_buffer_size() / 2; - - size_t remaining_count = count; - - while (remaining_count && success) { - - collect_acknowledgements(source); - - size_t const curr_packet_size = - Genode::min(remaining_count, max_packet_size); - - Packet_descriptor - packet(source.alloc_packet(curr_packet_size), - node_handle, - File_system::Packet_descriptor::READ, - curr_packet_size, - seek_offset); - - /* pass packet to server side */ - source.submit_packet(packet); - - packet = source.get_acked_packet(); - success = packet.succeeded(); - - size_t const read_num_bytes = - Genode::min(packet.length(), curr_packet_size); - - /* copy-out payload into destination buffer */ - Genode::memcpy(dst, source.packet_content(packet), read_num_bytes); - - source.release_packet(packet); - - /* prepare next iteration */ - seek_offset += read_num_bytes; - dst = (void *)((Genode::addr_t)dst + read_num_bytes); - remaining_count -= read_num_bytes; - - /* - * If we received less bytes than requested, we reached the end - * of the file. - */ - if (read_num_bytes < curr_packet_size) - break; - } - - return count - remaining_count; - } - - - /** - * Write file content - */ - static inline size_t write(Session &fs, Node_handle const &node_handle, - void const *src, size_t count, seek_off_t seek_offset = 0) - { - bool success = true; - Session::Tx::Source &source = *fs.tx(); - - size_t const max_packet_size = source.bulk_buffer_size() / 2; - - size_t remaining_count = count; - - while (remaining_count && success) { - - collect_acknowledgements(source); - - size_t const curr_packet_size = - Genode::min(remaining_count, max_packet_size); - - Packet_descriptor - packet(source.alloc_packet(curr_packet_size), - node_handle, - File_system::Packet_descriptor::WRITE, - curr_packet_size, - seek_offset); - - /* copy-out source buffer into payload */ - Genode::memcpy(source.packet_content(packet), src, curr_packet_size); - - /* pass packet to server side */ - source.submit_packet(packet); - - packet = source.get_acked_packet();; - success = packet.succeeded(); - source.release_packet(packet); - - /* prepare next iteration */ - seek_offset += curr_packet_size; - src = (void *)((Genode::addr_t)src + curr_packet_size); - remaining_count -= curr_packet_size; - } - - return count - remaining_count; - } - - class Handle_guard { private: