Hey all, I'm back with another question
I have working disk drivers, and a mono-tasking fs/vfs design (which I've scrapd completely since it crashed or froze 50% of the time).
Anyway, my disk drivers are functioning. They inherit from my C++ interface that provides functions such as Read(unsigned long long offset, void *buffer, unsigned int size). I've removed all FS and VFS drivers from my OS. My kernel stores a linked list of disk device instances with common functions such as GetSize, GetName, Read, Write, etc..
How my disk drives work is each driver has a background thread. This thread is sleeping when there is no request on the queue. When a thread calls Read or Write on the device, the disk driver adds a request to the driver's queue, wakes the driver's thread, and places the thread that called Read or Write to sleep. The driver's thread completes the first request on the queue. When the request is completed (or failed), the calling thread is woken. A device driver can only do one request at a time, since the driver goes through each request on the queue one by one, so I am thinking of designing my VFS to split calls up into 64kb/128kb sections, so if someone is copy a 1GB file, all other requests on the device are not held up.
Anyway, on to my FS driver and VFS design. How do I design my VFS system? I know that a VFS is made up of nodes representing files/directories, but when do I update what is in the VFS with what is on the disk? And on a FAT FS driver, always storing the FAT in memory is obvious, but what about storing directories? Like, if I access the file "/a/b/c/d/e/f/g" a lot, would it have to scan through directory a, then directory b, then directory c, etc each time I wanted to access the file? Say directory c had thousands of files which took a 20 seconds to scan through (on a very slow floppy drive) and I wanted to loop through 100 files in a subfolder of c, then starting at the drive's root and going through each folder on each file request would be slow.
VFS
- AndrewAPrice
- Member
- Posts: 2309
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
VFS
My OS is Perception.
- AndrewAPrice
- Member
- Posts: 2309
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
I'm thinking about changing my device driver interface to support asynchronous transferring.
e.g. I'd pass a struct to my driver which is something like:
This struct is constructed and stored inside the driver:
I'll get this up and working now before I write any more.
e.g. I'd pass a struct to my driver which is something like:
Code: Select all
struct StorageDeviceRequest
{
unsigned char action; // type of request (0 = read, 1 = write)
unsigned long long offset; // offset on the disk of where to begin
unsigned long long size; // the amount to transfer
void *buffer; // a pointer in memory where to store/get the data
char done; // sets to 0 while still reading, 1 when successfully, -1 if failed
bool wakeThreadWhenDone; // if set to true, wake calling thread when transfer is complete
};
Code: Select all
struct InternalStorageDeviceRequest
{
StorageDeviceRequest *request; // the request
Thread *thread; // the calling thread - the thread to wake (can be null if wakeThreadWhenDone is false)
Process *process; // the calling process - needed so the driver can switch into the process's memory space to copy the data to/from, also stored here so we know which process's memory to switch to to read the other struct from
InternalStorageDeviceRequest *next; // pointer to next request on the list (forms a linked list of requested)
};
My OS is Perception.
- AndrewAPrice
- Member
- Posts: 2309
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
My floppy driver is done! It supports synchronous and asynchronous transfer, although only one transfer may be done at a time (the others are placed in a FIFO queue).
I'm thinking my VFS should sort requests via devices. Requests will be broken up into 128KB chunks, with each device processing one chunk at time. If there is more than 1 request per device, then the device will process a chunk from each request in a round-robin fashion.
I'm still not sure if this "chunking" should be done in the VFS or in the disk driver.
I'm still not sure how I should handle directories and files.
I'm thinking my VFS should sort requests via devices. Requests will be broken up into 128KB chunks, with each device processing one chunk at time. If there is more than 1 request per device, then the device will process a chunk from each request in a round-robin fashion.
I'm still not sure if this "chunking" should be done in the VFS or in the disk driver.
I'm still not sure how I should handle directories and files.
My OS is Perception.
-
- Member
- Posts: 50
- Joined: Sun Dec 02, 2007 1:24 pm
- Libera.chat IRC: elfenix
- Location: United States
- Contact:
You really want to keep the VFS and the block IO subsystem as divided as possible. Really, you'll need to queue the IO if you are doing any serious work, so the best way (IMO) is to use the queue to separate requests.
I'd suggest letting queue have a configurable 'maximum request size' with a global default that a block device driver can change.
I'd suggest letting queue have a configurable 'maximum request size' with a global default that a block device driver can change.
- AndrewAPrice
- Member
- Posts: 2309
- Joined: Mon Jun 05, 2006 11:00 pm
- Location: USA (and Australia)
I have a lot of code for my file system drivers!
My drivers have two classes which inherit from Device and a Driver. A driver basically gives access to functions like detecting devices and initialising the Device objects. The Device object is an instance of a running driver and represents a physical device.
e.g. My floppy device inherits from StorageDevice which inherits from Device. Any class which inherits from StorageDevice gives access to functions such as reading/writing/etc.
Anyway, I have an FSDevice representing a filesystem "device". The FSDevice provides one function:
FSInstance *DetectFileSystem(StorageDevice *storageDevice);
which detects if a storage device contains that file system (my OS has no sense of partitions yet). FSInstance represents an instance of a mounted file system, and is through FSInstance that gives you functions like OpenFile, OpenDirectory, etc.
My drivers have two classes which inherit from Device and a Driver. A driver basically gives access to functions like detecting devices and initialising the Device objects. The Device object is an instance of a running driver and represents a physical device.
e.g. My floppy device inherits from StorageDevice which inherits from Device. Any class which inherits from StorageDevice gives access to functions such as reading/writing/etc.
Anyway, I have an FSDevice representing a filesystem "device". The FSDevice provides one function:
FSInstance *DetectFileSystem(StorageDevice *storageDevice);
which detects if a storage device contains that file system (my OS has no sense of partitions yet). FSInstance represents an instance of a mounted file system, and is through FSInstance that gives you functions like OpenFile, OpenDirectory, etc.
My OS is Perception.