rdos wrote:
j4cobgarby wrote:
I'm implementing the filesystem in my operating system at the moment, and have been wondering what various ways people implement partitions within drives.
My filesystem implementation at the moment basically consists of several tables:
- A table of different types of physical drive, where each type contains function pointers for reading and writing sectors in that type of drive.
- A table of "filesystem descriptor" structs, which contain function pointers for manipulating a filesystem.
- A table of drives. Each drive has an index into the drive type table, and an index into the filesystem type table. Each drive also has a void pointer to store arbitrary metadata about that specific drive.
Now, I want the system to be able to handle partitioned drives, but I'm unsure of the best way to do this. What I'm thinking is that, for example if I have a physical drive called A, and it has two partitions which I'll call B and C, then I will have an entry in my drive table for A, and also one for B and one for C. For each drive I'll store a value in its metadata to represent the first sector to read from (so, and offset to add when reading or writing sectors), and for A that would be 0, to represent the whole drive. Then for each partition it would be mostly the same metadata except that the offset would be the beginning of the partition, and the sector count would be the amount of sectors in the partition.
I think this would work, but I'm interested to see how other people would go about doing this. Any ideas?
You should separate discs and drives. The disc interface has functions to read/write sector data. A drive should be connected to a range of sectors within a disc and contain functions related to filesystems.
Why should a disc (presumably by which I think you mean a physical drive) and drives (by which I think you mean a logical drive that contain a file system) be treated any differently to each other?
They both provide a block based view of sector based storage. Filesystems read and write to either in essentially in the same way, and whole discs can be used to store a single file system, and a file system can span more than a single disc (for example, RAID).
You're putting up artificial API barriers where none really exist. In fact, what you're advocating is more along the lines of the raw/buffered device model in traditional UNIX, where /dev/sd0 might be the buffered block interface to the first disc that can be used by file systems, whereas /dev/rsd0 is an unbuffered character device, which talks more directly to the underlying disc and is used by whatever the hell used to require unbuffered access to the disc (fsck?) I never understood that (false IMO) dichotomy either.
My 2c on the original question (theoretical, unimplemented as of yet.)
I intend to use a device manager in my kernel, which defines a simple device interface/properties for a device:
- Device address
- Device driver, which will be filled in once a driver claims ownership
- Device name
- Device type (disc, bus, fb etc.)
- Functions to abstractly enumerate the device contents.
The meat will be the enumeration. When used, the device will do whatever device enumeration the driver supports. For each enumerated sub-device, create a new device instance of the above, and broadcast its arrival in the kernel.
So, I'll have a bootstrap device type, which for a PC, might be an ACPI root device. Enumerating that will result in devices being created for each device described in the device tree in ACPI. That tree will likely include an (S)ATA disc, and when that is created, partition device drivers will probe it to see whether it contains an appropriate partition table (MBR, GPT), and once the appropriate partition driver has attached, the device is enumerated, and the partition table is read and a device for each partition created.
The same device interface will be used for whatever type of device is being enumerated. For a PCI bus, it'll enumerate PCI devices. For a USB controller, it'll enumerate USB devices connected to the root hub. For a USB hub, it'll do the same as for the root hub, but just under this USB hub.
Drivers will register interest in new device attachments using device attributes that can be matched. For a PCI driver, we'll have probes for PCI device class/subclass/function or PCI vendor information. For USB devices, we'll have similar USB device information available. For SATA block devices, we just mark devices attached to a SATA controller as a block device. For USB storage devices, the USB UMS driver will enumerate block devices contained in the USB device.
This all sounds a bit like BSD auto configuration. I'll have to look into the details to see how closely the above models the BSD model.
This recursive device discovery using enumeration allows partition drivers to simply probe newly attached block devices, and create the relevant partitions on the fly, which can themselves also contain partitions (and more devices). Once we get to the level of devices with file systems on it, the file system driver can attach, and read the file system parameters (such as disk label/UUID, status) and make the corresponding device manager file system entries to make the newly attached device mountable via whatever identification mechanism required (mount by device address, or UUID, or volume label) the user level code decides.