Dear Genode developers,
Following Martijn's mail at the end of last year, which stated:
As a way to support detachment / reattachment of USB storage I’m thinking about placing the rump_fs and part_blk components in a child subtree of the CLI component that is spawned on demand and cleaned-up after use. But this seems a bit like overkill.
That's exactly the right solution. I don't think that it's overkill either. Spawning up rump_fs and part_blk dynamically is certainly quick enough. Memory-wise, it does not take more resources that a static scenario either. By letting your CLI component implement the protocol outlined above, you have full control over chain of events. Also the aborting rump_fs is nothing fatal anymore but can be gracefully handled by the CLI component. As another benefit, the solution does not need us to supplement the notion of hot-plugging to the file-system and block session interfaces, which would otherwise inflate the complexity of these interfaces (and thereby all the clients that rely on them).
Martijn and I have been thinking of a way to implement this, and came to the conclusion that instead of spawning the stack as children of the CLI component, it might be better to use a new management component in-between. As Josef said earlier:
A custom runtime/management component could monitor the usb_drv device report and spawn the whole stack if it detects a USB storage device. The usb_drv's device report does not contain the device class so far though but adding that to the report is easy.
This is exactly what we're trying to do now. We want to create a custom component called "media" that monitors usb devices by reading the report. It provides a service to other components through which they can request a filesystem session in order to read-write from/to the usb-stick. For this, it spawns the part_blk and rump_fs components as children if the usb is plugged in, and kills them once the usb is plugged out. It roughly looks like this:
rump_fs part_blk
| |
CLI media USB_drv
| | |
init
But this raises a few questions. First, the filesystem interface needs to be presented to the client somehow. To avoid adding another layer of indirection into media, essentially duplicating rump_fs's entire API, we would like the client (in this case CLI) to be directly connected to rump_fs. The client can then ask media if the USB is connected before calling a function from rump_fs.
However, this means that rump_fs provides a service, announces it to its parent (media), and media has to decide what to do with that announce. It can implement rump_fs as a slave, but that way the entire API needs to be copied into media so media can present it as its own service to the client.
So we would like media to announce the filesystem service to its parent (in this case init), so any client can use this service. In the same way, any session request will be passed from CLI to its parent (init), init has to pass it to media, and media passes it to rump_fs. However, the current implementation and specification of genode does not allow services of any server to exist in any level above the server's parent. Services can only be provided to direct parents, and to other components in the parent's subtree. Therefore, copying the API from the child to the parent seems unavoidable.
Another problem that pops up is that media has to spawn all these subcomponents as children. In order to route block session requests from rump-fs to part-blk, media needs to implement some routing policy and effectively serves the same role for these two components as init serves for the system. So we could:
1. Copy all necessary code for routing from init to media (which is almost all code if we want to be generic).
2. Let media spawn another init child component (let's call it sub-init for now) which in turn spawns rump-fs and part-blk and does the routing.
To us, the second option seems much more clean as it involves no code-copying. However, services announced by rump-fs can not be used by other components that are not children of the new init, and are kind of useless. Their announcements can not be passed on to the parents, leaving us with the same problem as we had with rump_fs but with the additional problem that even if there would be a custom way to forward service announces and requests to the parent/child respectively, sub-init has no such policy, and this functionality has to be included in sub-init's code as well, adding a lot of complexity.
Eventually both cases bottle down to the same problem: service announcements to a parent cannot automatically be forwarded to that parent's parent, and likewise, service requests need to be able to be delegated to children of children without a lot of hassle. The only option if I'm correct is implementing this functionality manually, but this does not work if the parent is an existing component that does not support it.
Is there a reason this is never done? For init it is clear that it would never pass an announce to its parent (usually core) or receive session requests from it. But how about the general case?
And how should we solve cases such as the above scenario?
kind regards,
Boris Mulder
Cyber Security Labs B.V. | Gooimeer 6-31 | 1411 DD Naarden | The Netherlands +31 35 631 3253 (office)