Hi Martin, hi Norman,
Thanks for your answers, I we will try to implement as you suggest.
Best regards Stefan
On 23.09.21 14:19, Martin Stein wrote:
Hi Stefan,
I'm sorry for the delayed response of mine, somehow I missed your initial mail.
On 23.09.21 12:37, Norman Feske wrote:
The control flow is always driven by the client of the VFS, e.g., the libc or the VFS server. Whenever the client detects that I/O happened (an I/O signal occurred), it checks each outstanding VFS request for possible progress. In the case of the CBE, there is a chain. For example, the CBE client requests the reading of a block. The CBE, in turn, requests the 'Cbe_crypto' to decrypt data as a prerequisite of finishing the block-read request.
Each time, some I/O happened, the client (e.g., the libc's 'read') asks the VFS for possible progress of the read request (by calling 'complete_read'). This call eventually reaches the CBE. The CBE, in turn, checks the progress of its outstanding crypto operation ('complete_read'). This is what I meant with polling. It is not busy polling but checking for progress each time after I/O happened. This checking is done transitively (libc checks the VFS, VFS checks the CBE, CBE checks crypto).
For this to work, one has to make sure that the I/O backends of the VFS plugins use 'Io_signal_handler' not mere 'Signal_handler' for the reception of asynchronous events like your device interrupt. Otherwise the VFS client won't notice that I/O happened. You may follow the use of the 'Io_progress_handler' interface in base/entrypoint.h to connect the dots.
Hence, there is no special feature in the 'Cbe_crypto::Interface' needed to support asynchronous operation. The pair of 'request' (submit work) and 'complete' (check the state of the submitted work) functions suffices.
I can confirm all of this and have little to add. The Crypto (as any other module in the CBE) is polled for progress, but only driven by external events - kind of "conditional polling". In the request chains that Norman mentioned that span over the different internal modules of the program, the last module before the Crypto talks to the Crypto only by the means of "add request" and "poll if request finished".
As soon as the Crypto wants to communicate that there was some progress, it signals the user of the CBE (See _io_handler respectively _backend_io_response_handler in repos/gems/src/lib/vfs/cbe/vfs.cc (or, for a less vfs-ish context _sigh in repos/gems/src/app/cbe_tester/main.cc)), which polls the CBE and the CBE polls each of its modules for progress again, including the one that talks to the Crypto. The latter then polls Crypto and reacts to the progress. This avoids that different external events have different entry points into the program which causes execution flow to remain plain and simple.
Note that there are modules internal to the CBE (block cache, tree walks, request scheduling, etc.) and modules that must be considered external, like crypto, block back-end, or trust anchor. Pending progress of internal modules is always resolved in the course of one "root poll" of the CBE to the point where each internal module either waits for progress of an external module again or is idle (no requests). Thus, the signal feedback (towards the CBE user) is only applied for modules that must be considered external.
I hope this helped. Don't hesitate to ask if you have further questions.
Cheers, Martin