Calling 'handle_io_response()' in a regular VFS function (in contrast to a
post-signal hook) can cause problems if the caller of the VFS function holds
a lock which prevents the io response handler from returning.
With this commit, the user of the VFS becomes responsible for unblocking
threads which might be blocking after a failed 'queue_read()', 'queue_sync()'
or 'write()' call.
Fixes#2896
This new vfs_import plugin allows a VFS instance to be populated during
construction using a sub-VFS configured in an '<import>' configuration
node. This allows the ram_fs File_system server to be replaced by the
VFS server by reimplementing the ram_fs 'content' feature. At the
moment the copying of symlinks is not enabled, and the resources
obtained by the import file-system may not be freed after the import is
finished.
Fix#2906
The ram plugin to the VFS must send notifications to watch handles on
files when they are removed. This brings the VFS server to parity with
the ram_fs server for the sake of notifications.
Move run/fs_report to gems and use the vfs server and the vfs init
plugin in the test.
Ref #2902
When mounting a ROM module with binary="no", the
vfs will detect the 0-termination to calculate the
file size instead of using the dataspace size.
Fixes#2903
The Ethernet payload may be followed by padding of variable length and
the FCS (Frame Check Sequence). Thus, we should consider the value
"Ethernet-frame size minus Ethernet-header size" to be only the maximum
size of the encapsulated IP packet. But until now, we considered it to
be also the actual size of the encapsulated IP packet. This commit fixes
the problem for all affected components of the Genode base-repository.
Fixes#2775
This reduces the redundant implementations of checksum calculation to
one generic implementation, makes the checksum interface conform over
all protocols, and brings performance optimizations. For instance,
the checksum is now calculated directly in big endian which saves us
most of the previously done byte-re-ordering.
Issue #2775
The 'stat' method is called for all paths, not just the specific file
system node of the ROM module. The ROM update is needed only in the
latter case.
Otherwise, when always updating the ROM on stat, stat calls on the VFS
become very expensive in the presence of a mounted ROM module if the ROM
is obtained from fs_rom (which re-watches the file and all its
individual path elements whenever the 'update' RPC function is called).
Reduce the size and forward compatibility of VFS file-system
constructors by passing an object holding accessors for 'Genode::Env',
'Genode::Allocator', response handlers, and the root file-system.
Fix#2742
To handle all pending timeouts in the context of scheduling a timeout
was only necessary because the Timeout framework once made use of the
Alarm framework. The method Alarm_scheduler::schedule_absolute took an
absolute deadline as argument and we couldn't change this beause the
Alarm framework was also used without the Timeout framework. We had to
calculate this absolute deadline with the now time of the Timeout
framework but the Alarm framework has its own now time that is always a
bit behind the one of the Timeout framework. This lead to bad decisisons
when finding the right position for the new timeout. Now, we can call
schedule_absolute with a relative duration and thereby fix the problem.
When we schedule an absolute timeout without considering the small time
difference, the end-time for the timeout that is calculated using the
local time value is also smaller than the expected end-time. This can
also lead to directly triggering timeouts that should have triggered
with a certain delay.
As it is not trivial to update the local time value while scheduling a
timeout _without_ calling other timeout handlers, we simply raise the
duration of the new timeout by the age of the local time value.
Issue #2704
This fixes the problem that large timeouts, when rescheduled, are interpreted
to be from the last now_period instead of, what would be right, the next
now_period. This occured if there were multiple pending alarms at the head of
the queue and the reschedule of the first one was done with the other outdated
deadlines still in place.
Issue #2704
Instead of taking the absolute deadline of a timeout as argument from
outside (where it is calculated with a freshly requested now time), we
now take a relative duration as argument and calculate the deadline with
the scheduler-internal now time (which can be a little bit outdated).
This enables us to schedule timeouts without updating the internal now time
and thereby handle all pending timeouts.
Issue #2704
Integrate the code of the Alarm framework directly into the Timeout
framework. The former Alarm-framework methods are all private to the
corresponding classes of the Timeout framework and get prefixed with
'_alarm__'. The latter avoids name clashes and makes it easier to
simplify the code later.
Issue #2704
Add a new 'Vfs_watch_handle' type to the VFS interface. This handle type
will pass a handle context up through the I/O handler to the application
when a notification event occurs.
Watch support implemented for RAM and File_system plugins, all other
file-systems return WATCH_ERR_STATIC by default.
Test at run/fs_rom_update_ram and run/fs_rom_update_fs.
Fix#1934
This patch enables the use of the VFS from VFS plugins by passing a
reference of the root directory to the constructors of file-system
instances. Since it changes the signature of 'Vfs::Dir_file_system',
any code that uses the VFS directly requires an adaptation.
Fixes#2701
Catch out of RAM and capability exceptions and return error values.
Abort opening a composite directory at Dir_file_system where an
opendir call on any child file-system returns an OUT_OF_RAM or
OUT_OF_CAPS error.
Ref #2642
Building this policy was disabled by a REQUIRES = riscv_toolchain_bugfix
to prevent compiler crashes on nightly test builds. Since the latest
RISCV toolchain update, test builds for RISCV crash at much more places
which makes this single work-around senseless.
Issue #2654
According to the creator of the net-stat lib, this lib was a mere debugging
tool that is not used anymore nor worth the work of updating the it to
modern Genode coding paradigms. Also, there exist no tests for the lib.
Instead of having a method validate_size in each packet class, check
sizes in the data accessor of the surrounding packet class. This packet
accessor is the one that casts the data pointer to the desired data type
so it is sensible that it also checks whether the desired type would
exceed the available RAM before doing the cast. This also fits nicely
the fact that for the top-level packet-class of a packet, the size must
not be checked (which was previously done).
Issue #465
The patch adjust the code of the base, base-<kernel>, and os repository.
To adapt existing components to fix violations of the best practices
suggested by "Effective C++" as reported by the -Weffc++ compiler
argument. The changes follow the patterns outlined below:
* A class with virtual functions can no longer publicly inherit base
classed without a vtable. The inherited object may either be moved
to a member variable, or inherited privately. The latter would be
used for classes that inherit 'List::Element' or 'Avl_node'. In order
to enable the 'List' and 'Avl_tree' to access the meta data, the
'List' must become a friend.
* Instead of adding a virtual destructor to abstract base classes,
we inherit the new 'Interface' class, which contains a virtual
destructor. This way, single-line abstract base classes can stay
as compact as they are now. The 'Interface' utility resides in
base/include/util/interface.h.
* With the new warnings enabled, all member variables must be explicitly
initialized. Basic types may be initialized with '='. All other types
are initialized with braces '{ ... }' or as class initializers. If
basic types and non-basic types appear in a row, it is nice to only
use the brace syntax (also for basic types) and align the braces.
* If a class contains pointers as members, it must now also provide a
copy constructor and assignment operator. In the most cases, one
would make them private, effectively disallowing the objects to be
copied. Unfortunately, this warning cannot be fixed be inheriting
our existing 'Noncopyable' class (the compiler fails to detect that
the inheriting class cannot be copied and still gives the error).
For now, we have to manually add declarations for both the copy
constructor and assignment operator as private class members. Those
declarations should be prepended with a comment like this:
/*
* Noncopyable
*/
Thread(Thread const &);
Thread &operator = (Thread const &);
In the future, we should revisit these places and try to replace
the pointers with references. In the presence of at least one
reference member, the compiler would no longer implicitly generate
a copy constructor. So we could remove the manual declaration.
Issue #465
Detect loops by walking hard-links at two different speeds and checking
for lapping. Tar link walking is no longer a recursive procedure.
Caught a loop created by GNU tar 1.29.
Fix#2611
One can configure the NIC router to act as DHCP server at interfaces of a
domain by adding the <dhcp> tag to the configuration of the domain like
this:
<domain name="vbox" interface="10.0.1.1/24">
<dhcp-server ip_first="10.0.1.80"
ip_last="10.0.1.100"
ip_lease_time_sec="3600"
dns_server="10.0.0.2"/>
...
</domain>
The attributes ip_first and ip_last define the available IPv4 address
range while ip_lease_time_sec defines the lifetime of an IPv4 address
assignment in seconds. The IPv4 address range must be in the subnet
defined by the interface attribute of the domain tag and must not cover
the IPv4 address in this attribute. The dns_server attribute gives the
IPv4 address of the DNS server that might also be in another subnet.
The lifetime of an offered assignment is the configured round trip time of
the router while the ip_lease_time_sec is applied only if the offer is
requested by the client in time.
The ports/run/virtualbox_nic_router.run script is an example of how to
use the new DHCP server functionality.
Ref #2490
Apply the style rule that an accessor is named similar to the the underlying
value. Provide read and write accessors for each mandatory header attribute.
Fix some incorrect structure in the headers like with the flags field
in Ipv4_packet.
Ref #2490
Encapsulate the enum into a struct so that it is named
Ethernet_frame::Type::Enum, give it the correct storage type
uint16_t, and remove those values that are (AFAIK) not used by
now (genode, world).
Ref #2490
We did not set the correct now_period previously but it wasn't conspicuous
because the bug triggered not before a full period had passed which on most
platforms is a pretty long time.
Ref #2490
Ensure that the timer does not handle timeouts again within 1000
microseconds after the last handling of timeouts. This makes denial of
service attacks harder. This commit does not limit the rate of timeout
signals handled inside the timer but it causes the timer to do it less
often. If a client continuously installs a very small timeout at the
timer it still causes a signal to be submitted to the timer each time
and some extra CPU time to be spent in the internal handling method. But
only every 1000 microseconds this internal handling causes user timeouts
to trigger.
If we would want to limit also the call of the internal handling method
to ensure that CPU time is spent beside the RPCs only every 1000
microseconds, things would get more complex. For instance, on NOVA
Time_source::schedule_timeout(0) must be called each time a new timeout
gets installed and becomes head of the scheduling queue. We cannot
simply overwrite the already running timeout with the new one.
Ref #2490
We update the alarm-scheduler time with results of
Timer::Connection::curr_time when we schedule new timeouts but when
handling the signal from the Timer server we updated the alarm-scheduler
time with the result of Timer::Connection::elapsed_us. Mixing times
like this could cause a non-monotone time value in the alarm scheduler.
The alarm scheduler then thought that the time value wrapped and
triggered all timeouts immediately. The problem was fixed by always
using Timer::Connection::curr_time as time source.
Ref #2490
If we add an absolute timeout to the back-end alarm-scheduler we must first
call 'handle' at the scheduler to update its internal time value.
Otherwise, it might happen that we add a timeout who's deadline is so big that
it normally belongs to the next time-counter period but the scheduler thinks
that it belongs to the current period as its time is older than the one used
to calculate the deadline.
Ref #2490
When we have two time values of an unsigned integer type and we create
the difference and want to know wether it is positive or negative within
the same value we loose at least one half of the value range for casting
to signed integers. This was the case in the alarm scheduler when
checking wether an alarm already triggered. Even worse, we casted from
'unsigned long' to 'signed int' which caused further loss on at least
x86_64. Thus, big timeouts like ~0UL falsely triggered directly.
Now, we use an extra boolean value to remember in which period of the
time counter we are and to which period of the time counter the deadline
of an alarm belongs. This boolean switches its value each time the time
counter wraps. This way, we can avoid any casting by checking wether the
current time is of the same period as the deadline of the alarm that we
inspect. If so, the alarm is pending if "current time >= alarm
deadline", otherwise it is pending if "current time < alarm deadline".
Ref #2490
When synchronizing with the remote time source, we have to take care that the
measured time difference cannot become null because its real value is smaller
than the measurement granularity. Since the granularity is one microsecond, we
simply go on polling timestamp and time until the microsecond has passed.
This busy waiting should be no problem for the system for two reasons. First,
it is limited to a relatively small amount of time and second, a busy lock
does not happen because the time source that is responsible for the limiting
factor is explicitely called on each poll.
Ref #2400
The VFS library can be used in single-threaded or multi-threaded
environments and depending on that, signals are handled by the same thread
which uses the VFS library or possibly by a different thread. If a VFS
plugin needs to block to wait for a signal, there is currently no way
which works reliably in both environments.
For this reason, this commit makes the interface of the VFS library
nonblocking, similar to the File_system session interface.
The most important changes are:
- Directories are created and opened with the 'opendir()' function and the
directory entries are read with the recently introduced 'queue_read()'
and 'complete_read()' functions.
- Symbolic links are created and opened with the 'openlink()' function and
the link target is read with the 'queue_read()' and 'complete_read()'
functions and written with the 'write()' function.
- The 'write()' function does not wait for signals anymore. This can have
the effect that data written by a VFS library user has not been
processed by a file system server yet when the library user asks for the
size of the file or closes it (both done with RPC functions at the file
system server). For this reason, a user of the VFS library should
request synchronization before calling 'stat()' or 'close()'. To make
sure that a file system server has processed all write request packets
which a client submitted before the synchronization request,
synchronization is now requested at the file system server with a
synchronization packet instead of an RPC function. Because of this
change, the synchronization interface of the VFS library is now split
into 'queue_sync()' and 'complete_sync()' functions.
Fixes#2399
The calibration of the interpolation parameters was previously only done
periodically every 500 ms. Together with the fact that the parameters
had to be stable for at least 3 calibration steps to enable
interpolation, it took at least 1.5 seconds after establishing a
connection to get microseconds-precise time values.
This is a problem for some drivers that directly start to poll time.
Thus, the timer connection now does a calibration burst as soon as it
switches to the modern mode (the mode with microseconds precision).
During this phase it does several (currently 9) calibration steps
without a delay inbetween. It is assumed that this is fast enough to not
get interrupted by scheduling. Thus, despite being small, the measured
values should be very stable which is why the burst should in most cases
be sufficient to get the interpolation initialized.
Ref #2400
When in modern mode (with local time interpolation), the timer
connection used to maximize the left shifting of its
timestamp-to-microseconds factor. The higher the shift the more precise
is the translation from timestamps to microseconds. If the timestamp
values used for determining the best shift were small - i.e. the delay
between the calibration steps were small - we may got a pretty big
shift. If we then used the shift with bigger timestamp values - i.e.
called curr_time seldom or raised calibration delays - the big shift
value became a problem. The framework had to scale down all measured
timestamps and time values temporarily to stay operative until the next
calibration step.
Thus, we now raise the shift only that much that the resulting factor
fullfills a given minimum. This keeps it as low as possible according
to the precision requirement. Currently, this requirement is set to 8
meaning that the shifted factor shall be at least 2^8 = 256.
Ref #2400
As the timer session now provides a method 'elapsed_us', there is no more need
for doing any internal calculations with values of milliseconds.
Ref #2400
In the timeout framework, we maintain a translation factor value to
translate between time and timestamps. To raise precision we scale-up
the factor when we calculate it and scale-down the result of its
appliance later again. This up and down scaling is achieved through
left and right shifting. Until now, the shift width was statically
choosen. However, some platforms need a big shift width and others a
smaller one. The one static shift width couldn't cover all platforms
which caused overflows or precision problems.
Now, the shift width is choosen optimally for the actual translation
factor each time it gets re-calculated. This way, we can take care that
the shift always renders the best precision level without the risk for
overflows.
Ref #2400
We incorrectly used 'unsigned long' (which is 32 or 64 bit depending on
the CPU architecture) for a timestamp (which is always 64 bit) in the
timer-connection implementation.
Ref #2435
On ARM, we do not have a component-local hardware time-source. The ARM
performance counter has no reliable frequency as the ARM idle command
halts the counter. Thus, we do not do local time interpolation on ARM.
Except we're on the HW kernel. In this case we can read out the kernel
time instead.
Ref #2435
Previously, the Genode::Timer::curr_time always used the
Timer_session::elapsed_ms RPC as back end. Now, Genode::Timer reads
this remote time only in a periodic fashion independently from the calls
to Genode::Timer::curr_time. If now one calls Genode::Timer::curr_time,
the function takes the last read remote time value and adapts it using
the timestamp difference since the remote-time read. The conversion
factor from timestamps to time is estimated on every remote-time read
using the last read remote-time value and the timestamp difference since
the last remote time read.
This commit also re-works the timeout test. The test now has two stages.
In the first stage, it tests fast polling of the
Genode::Timer::curr_time. This stage checks the error between locally
interpolated and timer-driver time as well as wether the locally
interpolated time is monotone and sufficiently homogeneous. In the
second stage several periodic and one-shot timeouts are scheduled at
once. This stage checks if the timeouts trigger sufficiently precise.
This commit adds the new Kernel::time syscall to base-hw. The syscall is
solely used by the Genode::Timer on base-hw as substitute for the
timestamp. This is because on ARM, the timestamp function uses the ARM
performance counter that stops counting when the WFI (wait for
interrupt) instruction is active. This instruction, however is used by
the base-hw idle contexts that get active when no user thread needs to
be scheduled. Thus, the ARM performance counter is not a good choice for
time interpolation and we use the kernel internal time instead.
With this commit, the timeout library becomes a basic library. That means
that it is linked against the LDSO which then provides it to the program it
serves. Furthermore, you can't use the timeout library anymore without the
LDSO because through the kernel-dependent LDSO make-files we can achieve a
kernel-dependent timeout implementation.
This commit introduces a structured Duration type that shall successively
replace the use of Microseconds, Milliseconds, and integer types for duration
values.
Open issues:
* The timeout test fails on Raspberry PI because of precision errors in the
first stage. However, this does not render the framework unusable in general
on the RPI but merely is an issue when speaking of microseconds precision.
* If we run on ARM with another Kernel than HW the timestamp speed may
continuously vary from almost 0 up to CPU speed. The Timer, however,
only uses interpolation if the timestamp speed remained stable (12.5%
tolerance) for at least 3 observation periods. Currently, one period is
100ms, so its 300ms. As long as this is not the case,
Timer_session::elapsed_ms is called instead.
Anyway, it might happen that the CPU load was stable for some time so
interpolation becomes active and now the timestamp speed drops. In the
worst case, we would now have 100ms of slowed down time. The bad thing
about it would be, that this also affects the timeout of the period.
Thus, it might "freeze" the local time for more than 100ms.
On the other hand, if the timestamp speed suddenly raises after some
stable time, interpolated time can get too fast. This would shorten the
period but nonetheless may result in drifting away into the far future.
Now we would have the problem that we can't deliver the real time
anymore until it has caught up because the output of Timer::curr_time
shall be monotone. So, effectively local time might "freeze" again for
more than 100ms.
It would be a solution to not use the Trace::timestamp on ARM w/o HW but
a function whose return value causes the Timer to never use
interpolation because of its stability policy.
Fixes#2400
This patch reduces the number of exception types by facilitating
globally defined exceptions for common usage patterns shared by most
services. In particular, RPC functions that demand a session-resource
upgrade not longer reflect this condition via a session-specific
exception but via the 'Out_of_ram' or 'Out_of_caps' types.
Furthermore, the 'Parent::Service_denied', 'Parent::Unavailable',
'Root::Invalid_args', 'Root::Unavailable', 'Service::Invalid_args',
'Service::Unavailable', and 'Local_service::Factory::Denied' types have
been replaced by the single 'Service_denied' exception type defined in
'session/session.h'.
This consolidation eases the error handling (there are fewer exceptions
to handle), alleviates the need to convert exceptions along the
session-creation call chain, and avoids possible aliasing problems
(catching the wrong type with the same name but living in a different
scope).
Change metadata before submitting a packet. If the submitting thread is a
pthread, the metadata may be immediately change by the signal handler running
in the context of the entrypoint thread.
When a directory gets destructed it dissolves the handles of each contained file
but the acknowledgement might be still in-flight. If we finally receive it,
it leads to an Unknown_id exception on the Handles ID Space in 'handle_ack'.
Now we catch it, print a warning, and go on.
The support has two parts. First, a VFS plugin now gets passed an
I/O-response handler callback on construction, which informs users of the
VFS that an I/O event occurred. This enables, for example, the libC to
check if blocking read can be completed. Further, the VFS file I/O
interface provides now functions for suspendable reads, i.e.,
queue_read() and complete_read().
The block file system wrongly modified the seek offset during a
read-modify-write operation that is required for sub-block-size
requests. This led to problems whenever such write requests spanned
multiple blocks and thereby were handled in multiple iterations.
Fixes#2262
This commit enables compile-time warnings displayed whenever a deprecated
API header is included, and adjusts the existing #include directives
accordingly.
Issue #1987
This patch enables warnings if one of the deprecate functions that rely
in the implicit use of the global Genode::env() accessor are called.
For the time being, some places within the base framework continue
to rely on the global function while omitting the warning by calling
'env_deprecated' instead of 'env'.
Issue #1987
Both methods are now available for Ipv4_address as well as for
Ipv4_address_prefix. An IPv4 address is invalid if it contains zeros only.
An IPv4 address prefix is invalid if its address is invalid and its
prefix is 32.
Ref #2139
The log plugin can now be configured to request a log session with the
specified label like follows.
<log label="..."/>
Per default, no new log session is requested but the existing log
session of the component's environment is used.
This is a redesign of the root and parent interfaces to eliminate
blocking RPC calls.
- New session representation at the parent (base/session_state.h)
- base-internal root proxy mechanism as migration path
- Redesign of base/service.h
- Removes ancient 'Connection::KEEP_OPEN' feature
- Interface change of 'Child', 'Child_policy', 'Slave', 'Slave_policy'
- New 'Slave::Connection'
- Changed child-construction procedure to be compatible with the
non-blocking parent interface and to be easier to use
- The child's initial LOG session, its binary ROM session, and the
linker ROM session have become part of the child's envirenment.
- Session upgrading must now be performed via 'env.upgrade' instead
of performing a sole RPC call the parent. To make RAM upgrades
easier, the 'Connection' provides a new 'upgrade_ram' method.
Issue #2120
Besides adapting the components to the use of base/log.h, the patch
cleans up a few base headers, i.e., it removes unused includes from
root/component.h, specifically base/heap.h and
ram_session/ram_session.h. Hence, components that relied on the implicit
inclusion of those headers have to manually include those headers now.
While adjusting the log messages, I repeatedly stumbled over the problem
that printing char * arguments is ambiguous. It is unclear whether to
print the argument as pointer or null-terminated string. To overcome
this problem, the patch introduces a new type 'Cstring' that allows the
caller to express that the argument should be handled as null-terminated
string. As a nice side effect, with this type in place, the optional len
argument of the 'String' class could be removed. Instead of supplying a
pair of (char const *, size_t), the constructor accepts a 'Cstring'.
This, in turn, clears the way let the 'String' constructor use the new
output mechanism to assemble a string from multiple arguments (and
thereby getting rid of snprintf within Genode in the near future).
To enforce the explicit resolution of the char * ambiguity, the 'char *'
overload of the 'print' function is marked as deleted.
Issue #1987
It turns out that the name function does not have much use in practice
except for naming the thread of the component's initial entrypoint. For
dynamically linked components, this thread is created by the dynamic
linker. It is named "ep" in these cases. Considering that we will
eventually turn all regular components into dynamically linked
executables, the additional information provided by the
Component::name() function remains unused. So it is better to not bother
the component developers with adding boilerplate code.
The original 'Env' interface as returned by 'Genode::env()' has been
renamed to 'Env_deprecated' and moved to deprecated/env.h. The new version
of base/env.h contains the interface passed to modern components that
use the component API via base/component.h.
Issue #1832