0f03189a | 30-Sep-2016 |
David van Moolenbroek <david@minix3.org> |
RMIB: add indirection support for sparse subtrees
Normally, each RMIB subtree consists of an array of nodes, indexed by node identifier. In a sparsely filled subtree, most of the array is empty and
RMIB: add indirection support for sparse subtrees
Normally, each RMIB subtree consists of an array of nodes, indexed by node identifier. In a sparsely filled subtree, most of the array is empty and just wasting memory. In that case, it may be beneficial to have a level of indirection, with an intermediate array containing pairs of node IDs and pointers to the actual nodes. This patch adds support for such indirection.
For the use cases that inspired this patch, net.inet and net.inet6, the indirection shaves off a little under 16KB of memory from the TCP/IP service.
Change-Id: Ic68ca3fee1a0f2032f77eef6df42728f9b9400e8
show more ...
|
27852ebe | 21-Feb-2016 |
David van Moolenbroek <david@minix3.org> |
UDS: full rewrite
This new implementation of the UDS service is built on top of the libsockevent library. It thereby inherits all the advantages that libsockevent brings. However, the fundamental
UDS: full rewrite
This new implementation of the UDS service is built on top of the libsockevent library. It thereby inherits all the advantages that libsockevent brings. However, the fundamental restructuring required for that change also paved the way for resolution of a number of other important open issues with the old UDS code. Most importantly, the rewrite brings the behavior of the service much closer to POSIX compliance and NetBSD compatibility. These are the most important changes:
- due to the use of libsockevent, UDS now supports multiple suspending calls per socket and a large number of standard socket flags and options; - socket address matching is now based on <device,inode> lookups instead of canonized path names, and socket addresses are no longer altered either due to canonization or at connect time; - the socket state machine is now well defined, most importantly resolving the erroneous reset-on-EOF semantics of the old UDS, but also allowing socket reuse; - sockets are now connected before being accepted instead of being held in connecting state, unless the LOCAL_CONNWAIT option is set on either the connecting or the listening socket; - connect(2) on datagram sockets is now supported (needed by syslog), and proper datagram socket disconnect notification is provided; - the receive queue now supports segmentation, associating ancillary data (in-flight file descriptors and credentials) with each segment instead of being kept fully separately; this is a POSIX requirement (and needed by tmux); - as part of the segmentation support, the receive queue can now hold as many packets as can fit, instead of one; - in addition to the flags supported by libsockevent, the MSG_PEEK, MSG_WAITALL, MSG_CMSG_CLOEXEC, MSG_TRUNC, and MSG_CTRUNC send and receive flags are now supported; - the SO_PASSCRED and SO_PEERCRED socket options are replaced by LOCAL_CREDS and LOCAL_PEEREID respectively, now following NetBSD semantics and allowing use of NetBSD libc's getpeereid(3); - memory usage is reduced by about 250 KB due to centralized in-flight file descriptor tracking, with a limit of OPEN_MAX total rather than of OPEN_MAX per socket; - memory usage is reduced by another ~50 KB due to removal of state redundancy, despite the fact that socket path names may now be up to 253 bytes rather than the previous 104 bytes; - compared to the old UDS, there is now very little direct indexing on the static array of sockets, thus allowing dynamic allocation of sockets more easily in the future; - the UDS service now has RMIB support for the net.local sysctl tree, implementing preliminary support for NetBSD netstat(1).
Change-Id: I4a9b6fe4aaeef0edf2547eee894e6c14403fcb32
show more ...
|
241ebcae | 30-Sep-2016 |
David van Moolenbroek <david@minix3.org> |
RMIB: expose full node path; improve restartability
A single function may be used to handle the implementation of more than one node. In some cases, the behavior of that function may depend on the
RMIB: expose full node path; improve restartability
A single function may be used to handle the implementation of more than one node. In some cases, the behavior of that function may depend on the path name used to reach the node. Therefore, provide the full path name as part of the call information.
As a result, RMIB has to save the paths for each of its remote MIB mount points. That in turn also allows it to autonomously remount its mount points after a MIB service restart, thus bringing us a step closer to proper recovery after a MIB crash without requiring the service using RMIB to perform explicit steps. As before, the missing ingredient is actual notification of MIB service restarts, and proper support for *that* will likely require changes to the DS service.
Change-Id: Ic0c79931d6f3a76c2c998047f8b47350fd0fa5b0
show more ...
|
bfa518c7 | 12-Jul-2016 |
David van Moolenbroek <david@minix3.org> |
PM/libsys: extend getepinfo, add getsockcred(3)
The service-only getepinfo(2) PM call returns information about a given endpoint. This patch extends that call so that it returns enough information
PM/libsys: extend getepinfo, add getsockcred(3)
The service-only getepinfo(2) PM call returns information about a given endpoint. This patch extends that call so that it returns enough information to allow correctly filling a sockcred structure. A new getsockcred(3) function is added to libsys to fill an actual sockcred structure with the obtained information. However, for the caller's convenience, the groups list is kept separate.
Change-Id: I9f1a6d1a221c77eabaa3498ff4ec9a5fb922e4fd
show more ...
|
46271349 | 27-Jan-2016 |
David van Moolenbroek <david@minix3.org> |
libsys: retire getnucred in favor of getepinfo
The getnucred() function was used by UDS to obtain credentials of user processes in a form used in the UDS API, namely the ucred structure. Since the N
libsys: retire getnucred in favor of getepinfo
The getnucred() function was used by UDS to obtain credentials of user processes in a form used in the UDS API, namely the ucred structure. Since the NetBSD merge, this structure has changed drastically (aside from being renamed to "uucred"), and it is no longer in UDS's best interest to use this structure internally. Therefore, getnucred() is no longer a useful API either, and instead we directly use the previously private getepinfo() function to obtain credentials.
Change-Id: I80bc809de716ec0a9b7497cb109d2f2708a629d5
show more ...
|
dd969671 | 27-Dec-2015 |
David van Moolenbroek <david@minix3.org> |
UDS: prepare for socket file creation in bind(2)
This patch prepares for moving of the creation of socket files on the file system from the libc bind(2) stub into the UDS service. This change is ne
UDS: prepare for socket file creation in bind(2)
This patch prepares for moving of the creation of socket files on the file system from the libc bind(2) stub into the UDS service. This change is necessary for the socket type agnostic libc implementation. The change is not yet activated - the code that is not yet used is enclosed in "#if NOT_YET" blocks. The activation needs to be atomic with UDS's switch to libsockdriver; otherwise, user applications may break.
As part of the change, various UDS bind(2) semantics are changed to match the POSIX standard and other operating systems. In implementation terms, the service-only VFS API checkperms(2) is renamed to socketpath(2), and extended with a new subcall which creates a new socket file. An extension to test56 checks the new bind(2) semantics of UDS, although most new tests are still disabled until activation as well.
Finally, as further preparation for a more structural redesign of the UDS service, also return the <device,inode> number pair for the created or checked file name, and make returning the canonized path name optional.
Change-Id: I892d04b3301d4b911bdc571632ddde65fb747a8a
show more ...
|
491d647a | 25-Jul-2016 |
David van Moolenbroek <david@minix3.org> |
VFS: support for suspending close(2) for sockets
This change effectively adds the VFS side of support for the SO_LINGER socket option, by allowing file descriptor close operations to be suspended (a
VFS: support for suspending close(2) for sockets
This change effectively adds the VFS side of support for the SO_LINGER socket option, by allowing file descriptor close operations to be suspended (and later resumed) by socket drivers. Currently, support is limited to the close(2) system call--in all other cases where file descriptors are closed (dup2, close-on-exec, process exit..), the close operation still completes instantly. As a general policy, the close(2) return value will always indicate that the file descriptor has been closed: either 0, or -1 with errno set to EINPROGRESS. The latter error may be thrown only when a suspended close is interrupted by a signal.
As necessary for UDS, this change also introduces a closenb(2) system call extension, allowing the caller to bypass blocking SO_LINGER close behavior. This extension allows UDS to avoid blocking on closing the last reference to an in-flight file descriptor, in an atomic fashion. The extension is currently part of libsys, but there is no reason why userland would not be allowed to make this call, so it is deliberately not protected from use by userland.
Change-Id: Iec77d6665232110346180017fc1300b1614910b7
show more ...
|
3ac58492 | 24-Sep-2016 |
David van Moolenbroek <david@minix3.org> |
Add LLVM GCOV coverage support
With this patch, it is now possible to generate coverage information for MINIX3 system services with LLVM. In particular, the system can be built with MKCOVERAGE=yes,
Add LLVM GCOV coverage support
With this patch, it is now possible to generate coverage information for MINIX3 system services with LLVM. In particular, the system can be built with MKCOVERAGE=yes, either with a native "make build" or with crosscompilation. Either way, MKCOVERAGE=yes will build the MINIX3 system services with coverage profiling support, generating a .gcno file for each source module. After a reboot it is possible to obtain runtime coverage data (.gcda files) for individual system services using gcov-pull(8). The combination of the .gcno and .gcda files can then be inspected with llvm-cov(1).
For reasons documented in minix.gcov.mk, only system service program modules are supported for now; system service libraries (libsys etc.) are not included. Userland programs are not affected by MKCOVERAGE.
The heart of this patch is the libsys code that writes data generated by the LLVM coverage hooks into a serialized format using the routines we already had for GCC GCOV. Unfortunately, the new llvm_gcov.c code is LLVM ABI dependent, and may therefore have to be updated later when we upgrade LLVM. The current implementation should support all LLVM versions 3.x with x >= 4.
The rest of this patch is mostly a light cleanup of our existing GCOV infrastructure, with as most visible change that gcov-pull(8) now takes a service label string rather than a PID number.
Change-Id: I6de055359d3d2b3f53e426f3fffb17af7877261f
show more ...
|
cfd712b4 | 21-Jul-2016 |
David van Moolenbroek <david@minix3.org> |
Various timer improvements
Now that clock_t is an unsigned value, we can also allow the system uptime to wrap. Essentially, instead of using (a <= b) to see if time a occurs no later than time b, w
Various timer improvements
Now that clock_t is an unsigned value, we can also allow the system uptime to wrap. Essentially, instead of using (a <= b) to see if time a occurs no later than time b, we use (b - a <= CLOCK_MAX / 2). The latter value does not exist, so instead we add TMRDIFF_MAX for that purpose.
We must therefore also avoid using values like 0 and LONG_MAX as special values for absolute times. This patch extends the libtimers interface so that it no longer uses 0 to indicate "no timeout". Similarly, TMR_NEVER is now used as special value only when otherwise a relative time difference would be used. A minix_timer structure is now considered in use when it has a watchdog function set, rather than when the absolute expiry time is not TMR_NEVER. A few new macros in <minix/timers.h> help with timer comparison and obtaining properties from a minix_timer structure.
This patch also eliminates the union of timer arguments, instead using the only union element that is only used (the integer). This prevents potential problems with e.g. live update. The watchdog function prototype is changed to pass in the argument value rather than a pointer to the timer structure, since obtaining the argument value was the only current use of the timer structure anyway. The result is a somewhat friendlier timers API.
The VFS select code required a few more invasive changes to restrict the timer value to the new maximum, effectively matching the timer code in PM. As a side effect, select(2) has been changed to reject invalid timeout values. That required a change to the test set, which relied on the previous, erroneous behavior.
Finally, while we're rewriting significant chunks of the timer code anyway, also covert it to KNF and add a few more explanatory comments.
Change-Id: Id43165c3fbb140b32b90be2cca7f68dd646ea72e
show more ...
|
6f3e0bcd | 23-Apr-2016 |
David van Moolenbroek <david@minix3.org> |
MIB/libsys: support for remote MIB (RMIB) subtrees
Most of the nodes in the general sysctl tree will be managed directly by the MIB service, which obtains the necessary information as needed. Howeve
MIB/libsys: support for remote MIB (RMIB) subtrees
Most of the nodes in the general sysctl tree will be managed directly by the MIB service, which obtains the necessary information as needed. However, in certain cases, it makes more sense to let another service manage a part of the sysctl tree itself, in order to avoid replicating part of that other service in the MIB service. This patch adds the basic support for such delegation: remote services may now register their own subtrees within the full sysctl tree with the MIB service, which will then forward any sysctl(2) requests on such subtrees to the remote services.
The system works much like mounting a file system, but in addition to support for shadowing an existing node, the MIB service also supports creating temporary mount point nodes. Each have their own use cases. A remote "kern.ipc" would use the former, because even when such a subtree were not mounted, userland would still expect some of its children to exist and return default values. A remote "net.inet" would use the latter, as there is no reason to precreate nodes for all possible supported networking protocols in the MIB "net" subtree.
A standard remote MIB (RMIB) implementation is provided for services that wish to make use of this functionality. It is essentially a simplified and somewhat more lightweight version of the MIB service's internals, and works more or less the same from a programmer's point of view. The most important difference is the "rmib" prefix instead of the "mib" prefix. Documentation will hopefully follow later.
Overall, the RMIB functionality should not be used lightly, for several reasons. First, despite being more lightweight than the MIB service, the RMIB module still adds substantially to the code footprint of the containing service. Second, the RMIB protocol not only adds extra IPC for sysctl(2), but has also not been optimized for performance in other ways. Third, and most importantly, the RMIB implementation also several limitations. The main limitation is that remote MIB subtrees must be fully static. Not only may the user not create or destroy nodes, the service itself may not either, as this would clash with the simplified remote node versioning system and the cached subtree root node child counts. Other limitations exist, such as the fact that the root of a remote subtree may only be a node-type node, and a stricter limit on the highest node identifier of any child in this subtree root (currently 4095).
The current implementation was born out of necessity, and therefore it leaves several improvements to future work. Most importantly, support for exit and crash notification is missing, primarily in the MIB service. This means that remote subtrees may not be cleaned up immediately, but instead only when the MIB service attempts to talk to the dead remote service. In addition, if the MIB service itself crashes, re-registration of remote subtrees is currently left up to the individual RMIB users. Finally, the MIB service uses synchronous (sendrec-based) calls to the remote services, which while convenient may cause cascading service hangs. The underlying protocol is ready for conversion to an asynchronous implementation already, though.
A new test set, testrmib.sh, tests the basic RMIB functionality. To this end it uses a test service, rmibtest, and also reuses part of the existing test87 MIB service test.
Change-Id: I3378fe04f2e090ab231705bde7e13d6289a9183e
show more ...
|
10b7016b | 30-Dec-2015 |
David van Moolenbroek <david@minix3.org> |
Fix soft faults in FSes resulting in partial I/O
In order to resolve page faults on file-mapped pages, VM may need to communicate (through VFS) with a file system. The file system must therefore no
Fix soft faults in FSes resulting in partial I/O
In order to resolve page faults on file-mapped pages, VM may need to communicate (through VFS) with a file system. The file system must therefore not be the one to cause, and thus end up being blocked on, such page faults. To resolve this potential deadlock, the safecopy system was previously extended with the CPF_TRY flag, which causes the kernel to return EFAULT to the caller of a safecopy function upon getting a pagefault, bypassing VM and thus avoiding the loop. VFS was extended to repeat relevant file system calls that returned EFAULT, after resolving the page fault, to keep these soft faults from being exposed to applications.
However, general UNIX I/O semantics dictate that if an I/O transfer partially succeeded before running into a failure, the partial result is to be returned. Proper file system implementations may therefore end up returning partial success rather than the EFAULT code resulting from a soft fault. Since VFS does not get the EFAULT code in this case, it does not know that a soft fault occurred, and thus does not repeat the call either. The end result is that an application may get partial I/O results (e.g., a short read(2)) even on regular files. Applications cannot reasonably be expected to deal with this.
Due to the fact that most of the current file system implementations do not implement proper partial-failure semantics, this problem is not yet widespread. In fact, it has only occurred on direct block device I/O so far. However, the next generation of file system services will be implementing proper I/O semantics, thus exacerbating the problem.
To remedy this situation, this patch changes the CPF_TRY semantics: whenever the kernel experiences a soft fault during a safecopy call, in addition to returning FAULT, the kernel also stores a mark in the grant created with CPF_TRY. Instead of testing on EFAULT, VFS checks whether the grant was marked, as part of revoking the grant. If the grant was indeed marked by the kernel, VFS repeats the file system operation, regardless of its initial return value. Thus, the EFAULT code now only serves to make the file system fail the call faster.
The approach is currently supported for both direct and magic grants, but is used only with magic grants - arguably the only case where it makes sense. Indirect grants should not have CPF_TRY set; in a chain of indirect grants, the original grant is marked, as it should be. In order to avoid potential SMP issues, the mark stored in the grant is its grant identifier, so as to discard outdated kernel writes. Whether this is necessary or effective remains to be evaluated.
This patch also cleans up the grant structure a bit, removing reserved space and thus making the structure slightly smaller. The structure is used internally between system services only, so there is no need for binary compatibility.
Change-Id: I6bb3990dce67a80146d954546075ceda4d6567f8
show more ...
|
efc775b4 | 29-Dec-2015 |
David van Moolenbroek <david@minix3.org> |
libsys: use linked list for free grants
With this change, obtaining an existing free grant is no longer an operation of O(n) complexity. As a result, the now-deprecated getgrant/setgrant part of th
libsys: use linked list for free grants
With this change, obtaining an existing free grant is no longer an operation of O(n) complexity. As a result, the now-deprecated getgrant/setgrant part of the grants API also no longer has a performance advantage.
Change-Id: Ic19308a76924c6242f9784244a6b3600e561e0fe
show more ...
|