Asynchronous mess of a VFS..
Posted: Tue Apr 24, 2007 7:24 am
So it seems my quest for the ultimate asynchronous is about to cause Voix VFS to get rewritten again (that'd be VFSv3 then) and since the design is getting pretty nasty, I thought I'd subject it to comments here. Basicly, idea is to make all I/O and filesystem operations asynchronous. I'm going to start by making reads/writes asynchronous first, because that's required for the rest anyway.
Since this is going to result in rather ugly code with callbacks, I'm trying to abstract the stuff as much as possible, such that I don't need to special-case any more than I have to. So I've basicly come up with the following ideas so far:
1. Any I/O is done on abstract files, which are represented by block-lists.
2. It is FS specific issue how to come up with a block-list. VFS (or the FS itself) just asks for a list of N blocks starting from block M. This will allow either proper inodes or FAT style linked lists, but also handling free-space bitmaps and other special filesystem areas as "abstract files" (block lists).
3. To do I/O on a device, one tells what block one wants, what function to call with the block, and what additional data to pass to the function.
4. To do I/O on an abstract file (well, vnode mostly) one asks the relevant filesystem for a blocklist, and gives it a function to call, and additional data to pass to that function. Coming up with a blocklist might require FS to do some other I/O, but it can do so, as long as it keeps the original callback-data as part of the "additional info" of it's own callback.
5. We don't actually call any of the callbacks directly, but magically cause them to be called just before exit from the kernel (as delayed procedure invocations as they are sometimes called). This avoids stack growth (recursion) when the blocks are already in cache.
6. Magically the user process gets informed when the operation either completes or fails.
6b. Even more magically the user process might cancel the operation before it has completed.
Does this sound general enough?
Since this is going to result in rather ugly code with callbacks, I'm trying to abstract the stuff as much as possible, such that I don't need to special-case any more than I have to. So I've basicly come up with the following ideas so far:
1. Any I/O is done on abstract files, which are represented by block-lists.
2. It is FS specific issue how to come up with a block-list. VFS (or the FS itself) just asks for a list of N blocks starting from block M. This will allow either proper inodes or FAT style linked lists, but also handling free-space bitmaps and other special filesystem areas as "abstract files" (block lists).
3. To do I/O on a device, one tells what block one wants, what function to call with the block, and what additional data to pass to the function.
4. To do I/O on an abstract file (well, vnode mostly) one asks the relevant filesystem for a blocklist, and gives it a function to call, and additional data to pass to that function. Coming up with a blocklist might require FS to do some other I/O, but it can do so, as long as it keeps the original callback-data as part of the "additional info" of it's own callback.
5. We don't actually call any of the callbacks directly, but magically cause them to be called just before exit from the kernel (as delayed procedure invocations as they are sometimes called). This avoids stack growth (recursion) when the blocks are already in cache.
6. Magically the user process gets informed when the operation either completes or fails.
6b. Even more magically the user process might cancel the operation before it has completed.
Does this sound general enough?