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_FILE 0x0
|
||||||
#define VFS_DIRECTORY 0x1
|
#define VFS_DIRECTORY 0x1
|
||||||
|
|
||||||
|
#define VFS_MOUNTPOINT 0x1
|
||||||
|
|
||||||
namespace VFS
|
namespace VFS
|
||||||
{
|
{
|
||||||
struct Node;
|
struct Node;
|
||||||
|
|
||||||
typedef ssize_t (*node_read)(Node*, size_t, size_t, char*);
|
typedef ssize_t (*node_read)(Node*, size_t, size_t, char*);
|
||||||
typedef Node* (*node_finddir)(Node*, const char*);
|
typedef Node* (*node_finddir)(Node*, const char*);
|
||||||
|
typedef int (*node_mkdir)(Node*, const char*);
|
||||||
|
|
||||||
struct Node
|
struct Node
|
||||||
{
|
{
|
||||||
@ -20,15 +23,23 @@ namespace VFS
|
|||||||
uint64_t inode;
|
uint64_t inode;
|
||||||
uint64_t length;
|
uint64_t length;
|
||||||
int type;
|
int type;
|
||||||
|
int flags;
|
||||||
node_read read_func;
|
node_read read_func;
|
||||||
node_finddir find_func;
|
node_finddir find_func;
|
||||||
|
node_mkdir mkdir_func;
|
||||||
|
Node* link;
|
||||||
};
|
};
|
||||||
|
|
||||||
ssize_t read(Node* node, size_t offset, size_t length, char* buffer);
|
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);
|
void mount_root(Node* root);
|
||||||
|
|
||||||
Node* resolve_path(const char* filename, Node* root = nullptr);
|
Node* resolve_path(const char* filename, Node* root = nullptr);
|
||||||
|
|
||||||
|
void mount(Node* mountpoint, Node* mounted);
|
||||||
|
|
||||||
|
void unmount(Node* mountpoint);
|
||||||
|
|
||||||
Node* root();
|
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");
|
kwarnln("Current node did not find our target node");
|
||||||
return 0;
|
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;
|
current_node = child;
|
||||||
kfree(buffer);
|
kfree(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
filename += path_section_size;
|
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;
|
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)
|
static bool initrd_register_dir(InitRD::Directory& dir, uint64_t inode)
|
||||||
{
|
{
|
||||||
const char* filename = dir.name;
|
const char* filename = dir.name;
|
||||||
@ -318,11 +358,13 @@ static void initrd_initialize_root()
|
|||||||
{
|
{
|
||||||
initrd_root.length = 0;
|
initrd_root.length = 0;
|
||||||
initrd_root.inode = 0;
|
initrd_root.inode = 0;
|
||||||
|
initrd_root.type |= VFS_DIRECTORY;
|
||||||
InitRD::Directory& root = dirs[0];
|
InitRD::Directory& root = dirs[0];
|
||||||
total_dirs++;
|
total_dirs++;
|
||||||
strncpy(initrd_root.name, "initrd", sizeof(initrd_root.name));
|
strncpy(initrd_root.name, "initrd", sizeof(initrd_root.name));
|
||||||
strncpy(root.name, "initrd", sizeof(root.name));
|
strncpy(root.name, "initrd", sizeof(root.name));
|
||||||
initrd_root.find_func = initrd_scan_dir;
|
initrd_root.find_func = initrd_scan_dir;
|
||||||
|
initrd_root.mkdir_func = initrd_mkdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitRD::init()
|
void InitRD::init()
|
||||||
|
@ -164,12 +164,11 @@ extern "C" void _start()
|
|||||||
|
|
||||||
kinfoln("Trying VFS");
|
kinfoln("Trying VFS");
|
||||||
|
|
||||||
VFS::Node* node = VFS::resolve_path("/sys/");
|
if (VFS::mkdir("/", "rootfs") < 0) { kerrorln("Unable to create directory rootfs"); }
|
||||||
if (!node) { kerrorln("Unable to find /sys in VFS"); }
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
kinfoln("Found '%s'", node->name);
|
VFS::mount(VFS::resolve_path("/rootfs"), VFS::root());
|
||||||
node = VFS::resolve_path("config", node);
|
VFS::Node* node = VFS::resolve_path("/rootfs/sys/config");
|
||||||
if (!node) kerrorln("unable to find /sys/config in VFS");
|
if (!node) kerrorln("unable to find /sys/config in VFS");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user