fix(kernel/vfs): 🎉 a complete rewrite of the vfs

This is the fourth time re-writing the VFS, hope this will be the last. Tried to make it as modular as possible so this won't be necessary in the future. 🙏

This change required the entire kernel code to be modified.
This commit is contained in:
2025-05-13 15:59:12 +00:00
parent 83a7f83f81
commit 557c7e6235
83 changed files with 3252 additions and 2487 deletions

110
Drivers/include/block.h Normal file
View File

@ -0,0 +1,110 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_BLOCK_H__
#define __FENNIX_API_BLOCK_H__
#include <types.h>
#if __has_include(<interface/fs.h>)
#include <interface/fs.h>
#else
#include <fs.h>
#endif
struct BlockDevice
{
/**
* @brief Base name of the device.
*
* This name is used to identify the device in the system. It should be unique
* across all block devices. The kernel may append a number to this name to
* create a unique device name (e.g., "ahci0", "ahci1").
*/
const char *Name;
/**
* @brief Total size of the device in bytes.
*
* This value represents the total addressable storage capacity of the device.
* It is used for bounds checking and partitioning.
*/
size_t Size;
/**
* @brief Size of a single block in bytes.
*
* All read and write operations are performed in multiples of this block size.
* Typical values are 512 or 4096 bytes.
*/
uint32_t BlockSize;
/**
* @brief Number of blocks in the device.
*
* This value is calculated as Size / BlockSize. It represents the total number
* of addressable blocks on the device.
*/
size_t BlockCount;
/**
* @brief Pointer to the block device operations structure.
*
* This structure contains function pointers for various operations that can
* be performed on the block device, such as read, write, and ioctl.
*
* Yea, inode operations are used for block devices too.
*/
const InodeOperations *Ops;
/**
* @brief Opaque pointer to driver-specific or hardware-specific data.
*
* This field allows the driver to associate private context or state with the
* device, such as controller registers or internal buffers.
*/
void *PrivateData;
};
#ifndef __kernel__
/**
* @brief Registers a block device with the kernel block subsystem.
*
* This function should be called by block device drivers after initializing
* a device. The kernel will take ownership of the device structure and assign
* it a unique device ID. The device will then be accessible for filesystem
* mounting and I/O operations.
*
* @param Device Pointer to a fully initialized BlockDevice structure. All required fields must be set and valid for the lifetime of the device.
* @return Device ID (dev_t) assigned by the kernel on success, or an error code on failure.
*/
dev_t RegisterBlockDevice(struct BlockDevice *Device);
/**
* @brief Unregisters a block device from the kernel block subsystem.
*
* This function should be called by drivers when a device is being removed
* or is no longer available. The kernel will release any resources associated
* with the device and invalidate its device ID.
*
* @param DeviceID The device ID (dev_t) previously returned by RegisterBlockDevice().
* @return 0 on success, or an error code.
*/
int UnregisterBlockDevice(dev_t DeviceID);
#endif // __kernel__
#endif // __FENNIX_API_BLOCK_H__

View File

@ -322,10 +322,6 @@ struct InodeOperations
int (*Stat)(struct Inode *Node, struct kstat *Stat);
} __attribute__((packed));
#define I_FLAG_ROOT 0x1
#define I_FLAG_MOUNTPOINT 0x2
#define I_FLAG_CACHE_KEEP 0x4
struct FileSystemInfo;
struct SuperBlockOperations
{
@ -337,8 +333,8 @@ struct SuperBlockOperations
*
* Write all pending changes to the disk.
*
* @param Info Inode to synchronize. If NULL, synchronize all inodes.
* @param Node Inode to synchronize.
* @param Info Inode to synchronize.
* @param Node Inode to synchronize. If NULL, synchronize all inodes.
*
* @return Zero on success, otherwise an error code.
*/
@ -354,13 +350,50 @@ struct SuperBlockOperations
* @return Zero on success, otherwise an error code.
*/
int (*Destroy)(struct FileSystemInfo *Info);
/**
* Probe the filesystem.
*
* Check if the filesystem is supported by the driver.
*
* @param Device Device to probe.
*
* @return Zero on success, otherwise an error code.
*/
int (*Probe)(void *Device);
/**
* Mount the filesystem.
*
* Mount the filesystem on the given device.
*
* @param FS Filesystem to mount.
* @param Root Pointer to the root inode.
* @param Device Device to mount.
*
* @return Zero on success, otherwise an error code.
*/
int (*Mount)(struct FileSystemInfo *FS, struct Inode **Root, void *Device);
/**
* Unmount the filesystem.
*
* Unmount the filesystem from the given device.
*
* @param FS Filesystem to unmount.
*
* @return Zero on success, otherwise an error code.
*/
int (*Unmount)(struct FileSystemInfo *FS);
} __attribute__((packed));
struct FileSystemInfo
{
const char *Name;
const char *RootName;
int Flags;
int Capabilities;
struct SuperBlockOperations SuperOps;
struct InodeOperations Ops;
@ -368,6 +401,9 @@ struct FileSystemInfo
} __attribute__((packed));
#ifndef __kernel__
dev_t RegisterMountPoint(FileSystemInfo *fsi, Inode *Root);
int UnregisterMountPoint(dev_t Device);
dev_t RegisterFileSystem(struct FileSystemInfo *Info, struct Inode *Root);
int UnregisterFileSystem(dev_t Device);
#endif // !__kernel__