VFS: Add basic mount(), unmount() and mkdir() functions (not accessible to userspace yet)
This commit is contained in:
parent
1278cec065
commit
4aa3da8c12
@ -7,12 +7,15 @@ typedef long ssize_t;
|
||||
#define VFS_FILE 0x0
|
||||
#define VFS_DIRECTORY 0x1
|
||||
|
||||
#define VFS_MOUNTPOINT 0x1
|
||||
|
||||
namespace VFS
|
||||
{
|
||||
struct Node;
|
||||
|
||||
typedef ssize_t (*node_read)(Node*, size_t, size_t, char*);
|
||||
typedef Node* (*node_finddir)(Node*, const char*);
|
||||
typedef int (*node_mkdir)(Node*, const char*);
|
||||
|
||||
struct Node
|
||||
{
|
||||
@ -20,15 +23,23 @@ namespace VFS
|
||||
uint64_t inode;
|
||||
uint64_t length;
|
||||
int type;
|
||||
int flags;
|
||||
node_read read_func;
|
||||
node_finddir find_func;
|
||||
node_mkdir mkdir_func;
|
||||
Node* link;
|
||||
};
|
||||
|
||||
ssize_t read(Node* node, size_t offset, size_t length, char* buffer);
|
||||
int mkdir(const char* path, const char* name);
|
||||
|
||||
void mount_root(Node* root);
|
||||
|
||||
Node* resolve_path(const char* filename, Node* root = nullptr);
|
||||
|
||||
void mount(Node* mountpoint, Node* mounted);
|
||||
|
||||
void unmount(Node* mountpoint);
|
||||
|
||||
Node* root();
|
||||
}
|
@ -90,10 +90,53 @@ VFS::Node* VFS::resolve_path(const char* filename, Node* root)
|
||||
kwarnln("Current node did not find our target node");
|
||||
return 0;
|
||||
}
|
||||
if (child->flags & VFS_MOUNTPOINT)
|
||||
{
|
||||
kdbgln("Current node (%s, inode=%ld) is a mountpoint, resolving actual node", child->name,
|
||||
child->inode);
|
||||
if (!child->link)
|
||||
{
|
||||
kwarnln("Current node's link is null");
|
||||
return 0;
|
||||
}
|
||||
child = child->link;
|
||||
kdbgln("Resolved to %s (inode %ld)", child->name, child->inode);
|
||||
}
|
||||
current_node = child;
|
||||
kfree(buffer);
|
||||
}
|
||||
|
||||
filename += path_section_size;
|
||||
}
|
||||
}
|
||||
|
||||
int VFS::mkdir(const char* path, const char* name)
|
||||
{
|
||||
Node* node = resolve_path(path, vfs_root);
|
||||
if (!node)
|
||||
{
|
||||
kwarnln("Attempting to mkdir in %s, which does not exist", path);
|
||||
return -1;
|
||||
}
|
||||
if (!node->mkdir_func)
|
||||
{
|
||||
kwarnln("Chosen node does not support mkdir()");
|
||||
return -1;
|
||||
}
|
||||
return node->mkdir_func(node, name);
|
||||
}
|
||||
|
||||
void VFS::mount(Node* mountpoint, Node* mounted)
|
||||
{
|
||||
if (!mountpoint || !mounted) return;
|
||||
if (mountpoint->flags & VFS_MOUNTPOINT || mounted->flags & VFS_MOUNTPOINT) return;
|
||||
mountpoint->link = mounted;
|
||||
mountpoint->flags |= VFS_MOUNTPOINT;
|
||||
}
|
||||
|
||||
void VFS::unmount(Node* mountpoint)
|
||||
{
|
||||
if (!mountpoint) return;
|
||||
if (!(mountpoint->flags & VFS_MOUNTPOINT)) return;
|
||||
mountpoint->flags &= ~VFS_MOUNTPOINT;
|
||||
}
|
@ -185,6 +185,46 @@ VFS::Node* initrd_scan_dir(VFS::Node* node, const char* filename)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int initrd_mkdir(VFS::Node* node, const char* name) // FIXME: Return proper error numbers.
|
||||
{
|
||||
if (total_dirs >= 32)
|
||||
{
|
||||
kwarnln("mkdir() failed: too many directories");
|
||||
return -1;
|
||||
}
|
||||
if (node->inode > total_dirs)
|
||||
{
|
||||
kwarnln("mkdir() failed: invalid node");
|
||||
return -1;
|
||||
}
|
||||
if (!(node->type & VFS_DIRECTORY))
|
||||
{
|
||||
kwarnln("mkdir() failed: not a directory");
|
||||
return -1;
|
||||
}
|
||||
InitRD::Directory& parent = dirs[node->inode];
|
||||
if (parent.entries == INITRD_MAX_FILES_IN_DIR)
|
||||
{
|
||||
kwarnln("mkdir() failed: parent is null");
|
||||
return -1;
|
||||
}
|
||||
uint64_t inode = total_dirs;
|
||||
VFS::Node& new_node = nodes[total_nodes++];
|
||||
new_node.inode = inode;
|
||||
new_node.find_func = initrd_scan_dir;
|
||||
new_node.mkdir_func = initrd_mkdir;
|
||||
new_node.length = 0;
|
||||
new_node.type = VFS_DIRECTORY;
|
||||
strncpy(new_node.name, name, sizeof(new_node.name));
|
||||
InitRD::Directory dir;
|
||||
strncpy(dir.name, name, sizeof(dir.name));
|
||||
dir.entries = 0;
|
||||
dirs[total_dirs++] = dir; // FIXME: Right now this isn't of worry, but there is a possibility for a TOCTOU bug here.
|
||||
// Should use a spinlock or something.
|
||||
parent.files[parent.entries++] = &new_node;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool initrd_register_dir(InitRD::Directory& dir, uint64_t inode)
|
||||
{
|
||||
const char* filename = dir.name;
|
||||
@ -318,11 +358,13 @@ static void initrd_initialize_root()
|
||||
{
|
||||
initrd_root.length = 0;
|
||||
initrd_root.inode = 0;
|
||||
initrd_root.type |= VFS_DIRECTORY;
|
||||
InitRD::Directory& root = dirs[0];
|
||||
total_dirs++;
|
||||
strncpy(initrd_root.name, "initrd", sizeof(initrd_root.name));
|
||||
strncpy(root.name, "initrd", sizeof(root.name));
|
||||
initrd_root.find_func = initrd_scan_dir;
|
||||
initrd_root.mkdir_func = initrd_mkdir;
|
||||
}
|
||||
|
||||
void InitRD::init()
|
||||
|
@ -164,12 +164,11 @@ extern "C" void _start()
|
||||
|
||||
kinfoln("Trying VFS");
|
||||
|
||||
VFS::Node* node = VFS::resolve_path("/sys/");
|
||||
if (!node) { kerrorln("Unable to find /sys in VFS"); }
|
||||
if (VFS::mkdir("/", "rootfs") < 0) { kerrorln("Unable to create directory rootfs"); }
|
||||
else
|
||||
{
|
||||
kinfoln("Found '%s'", node->name);
|
||||
node = VFS::resolve_path("config", node);
|
||||
VFS::mount(VFS::resolve_path("/rootfs"), VFS::root());
|
||||
VFS::Node* node = VFS::resolve_path("/rootfs/sys/config");
|
||||
if (!node) kerrorln("unable to find /sys/config in VFS");
|
||||
else
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user