Really hack VFS implementation

This commit is contained in:
Kevin Lange 2013-03-15 00:20:55 -07:00
parent 22f04f137b
commit 8dd2686b40
14 changed files with 278 additions and 54 deletions

0
hdd/dev/hello Normal file
View File

0
hdd/dev/null Normal file
View File

0
hdd/dev/ttyS0 Normal file
View File

0
hdd/dev/ttyS1 Normal file
View File

0
hdd/dev/ttyS2 Normal file
View File

0
hdd/dev/ttyS3 Normal file
View File

View File

@ -1108,7 +1108,7 @@ void ext2_disk_mount(uint32_t offset_sector, uint32_t max_sector) {
debug_print(NOTICE, "Oh dear...");
}
debug_print(NOTICE, "Root file system is ready.");
fs_root = RN;
vfs_mount("/", RN);
debug_print(NOTICE, "Mounted EXT2 disk, root VFS node is at 0x%x", RN);
}

54
kernel/fs/hellodev.c Normal file
View File

@ -0,0 +1,54 @@
/* vim: tabstop=4 shiftwidth=4 noexpandtab
* A device that returns "hello world" when read from.
*/
#include <system.h>
#include <fs.h>
uint32_t read_hello(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
uint32_t write_hello(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
void open_hello(fs_node_t *node, uint8_t read, uint8_t write);
void close_hello(fs_node_t *node);
char hello[] = "hello world";
uint32_t read_hello(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
uint32_t s = 0;
int d = strlen(hello);
while (s < size) {
buffer[offset] = hello[offset % d];
offset++;
s++;
}
return size;
}
uint32_t write_hello(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer) {
return size;
}
void open_hello(fs_node_t * node, uint8_t read, uint8_t write) {
return;
}
void close_hello(fs_node_t * node) {
return;
}
fs_node_t * hello_device_create() {
fs_node_t * fnode = malloc(sizeof(fs_node_t));
memset(fnode, 0x00, sizeof(fs_node_t));
fnode->inode = 0;
strcpy(fnode->name, "hello");
fnode->uid = 0;
fnode->gid = 0;
fnode->length = strlen(hello);
fnode->flags = FS_CHARDEVICE;
fnode->read = read_hello;
fnode->write = write_hello;
fnode->open = open_hello;
fnode->close = close_hello;
fnode->readdir = NULL;
fnode->finddir = NULL;
return fnode;
}

View File

@ -32,11 +32,12 @@ void close_null(fs_node_t * node) {
fs_node_t * null_device_create() {
fs_node_t * fnode = malloc(sizeof(fs_node_t));
memset(fnode, 0x00, sizeof(fs_node_t));
fnode->inode = 0;
strcpy(fnode->name, "null");
fnode->uid = 0;
fnode->gid = 0;
fnode->flags = 0;
fnode->flags = FS_CHARDEVICE;
fnode->read = read_null;
fnode->write = write_null;
fnode->open = open_null;

View File

@ -46,6 +46,7 @@ void close_serial(fs_node_t * node) {
fs_node_t * serial_device_create(int device) {
fs_node_t * fnode = malloc(sizeof(fs_node_t));
memset(fnode, 0x00, sizeof(fs_node_t));
fnode->inode = device;
strcpy(fnode->name, "serial");
fnode->uid = 0;
@ -64,3 +65,19 @@ fs_node_t * serial_device_create(int device) {
return fnode;
}
void serial_mount_devices() {
fs_node_t * ttyS0 = serial_device_create(SERIAL_PORT_A);
vfs_mount("/dev/ttyS0", ttyS0);
fs_node_t * ttyS1 = serial_device_create(SERIAL_PORT_B);
vfs_mount("/dev/ttyS1", ttyS1);
fs_node_t * ttyS2 = serial_device_create(SERIAL_PORT_C);
vfs_mount("/dev/ttyS2", ttyS2);
fs_node_t * ttyS3 = serial_device_create(SERIAL_PORT_D);
vfs_mount("/dev/ttyS3", ttyS3);
}

View File

@ -9,7 +9,8 @@
#include <process.h>
#include <logging.h>
fs_node_t *fs_root = 0;
tree_t * fs_tree = NULL; /* File system mountpoint tree */
fs_node_t * fs_root = NULL; /* Pointer to the root mount fs_node (must be some form of filesystem, even ramdisk) */
/**
* read_fs: Read a file system node based on its underlying type.
@ -323,63 +324,191 @@ char *canonicalize_path(char *cwd, char *input) {
return output;
}
struct vfs_entry {
char * name;
fs_node_t * file; /* Or null */
};
void vfs_install() {
/* Initialize the mountpoint tree */
fs_tree = tree_create();
struct vfs_entry * root = malloc(sizeof(struct vfs_entry));
root->name = strdup("[root]");
root->file = NULL; /* Nothing mounted as root */
tree_set_root(fs_tree, root);
}
/**
* vfs_mount - Mount a file system to the specified path.
*
* For example, if we have an EXT2 filesystem with a root node
* of ext2_root and we want to mount it to /, we would run
* vfs_mount("/", ext2_root); - or, if we have a procfs node,
* we could mount that to /dev/procfs. Individual files can also
* be mounted.
*
* Paths here must be absolute.
*/
int vfs_mount(char * path, fs_node_t * local_root) {
if (!fs_tree) {
debug_print(ERROR, "VFS hasn't been initialized, you can't mount things yet!");
return 1;
}
if (!path || path[0] != '/') {
debug_print(ERROR, "Path must be absolute for mountpoint.");
return 2;
}
int ret_val = 0;
char * p = strdup(path);
char * i = p;
int path_len = strlen(p);
/* Chop the path up */
while (i < p + path_len) {
if (*i == PATH_SEPARATOR) {
*i = '\0';
}
i++;
}
/* Clean up */
p[path_len] = '\0';
i = p + 1;
/* Root */
tree_node_t * root_node = fs_tree->root;
if (*i == '\0') {
/* Special case, we're trying to set the root node */
struct vfs_entry * root = (struct vfs_entry *)root_node->value;
if (root->file) {
debug_print(WARNING, "Path %s already mounted, unmount before trying to mount something else.", path);
ret_val = 3;
goto _vfs_cleanup;
}
root->file = local_root;
/* We also keep a legacy shortcut around for that */
fs_root = local_root;
} else {
tree_node_t * node = root_node;
char * at = i;
while (1) {
if (at >= p + path_len) {
break;
}
int found = 0;
debug_print(INFO, "Searching for %s", at);
foreach(child, node->children) {
tree_node_t * tchild = (tree_node_t *)child->value;
struct vfs_entry * ent = (struct vfs_entry *)tchild->value;
if (!strcmp(ent->name, at)) {
found = 1;
node = tchild;
break;
}
}
if (!found) {
debug_print(INFO, "Did not find %s, making it.", at);
struct vfs_entry * ent = malloc(sizeof(struct vfs_entry));
ent->name = strdup(at);
ent->file = NULL;
node = tree_node_insert_child(fs_tree, node, ent);
}
at = at + strlen(at) + 1;
}
struct vfs_entry * ent = (struct vfs_entry *)node->value;
if (ent->file) {
debug_print(WARNING, "Path %s already mounted, unmount before trying to mount something else.", path);
ret_val = 3;
goto _vfs_cleanup;
}
ent->file = local_root;
}
_vfs_cleanup:
free(p);
return ret_val;
}
void debug_print_vfs_tree_node(tree_node_t * node, size_t height) {
/* End recursion on a blank entry */
if (!node) return;
/* Indent output */
for (uint32_t i = 0; i < height; ++i) { kprintf(" "); }
/* Get the current process */
struct vfs_entry * fnode = (struct vfs_entry *)node->value;
/* Print the process name */
if (fnode->file) {
kprintf("%s → 0x%x (%s)", fnode->name, fnode->file, fnode->file->name);
} else {
kprintf("%s → (empty)", fnode->name);
}
/* Linefeed */
kprintf("\n");
foreach(child, node->children) {
/* Recursively print the children */
debug_print_vfs_tree_node(child->value, height + 1);
}
}
void debug_print_vfs_tree() {
debug_print_vfs_tree_node(fs_tree->root, 0);
}
/**
* get_mount_point
*
*/
fs_node_t *get_mount_point(char * path, size_t path_depth) {
#if 0
fs_node_t *get_mount_point(char * path, size_t path_depth, char **outpath) {
size_t depth;
kprintf("[root]");
for (depth = 0; depth <= path_depth; ++depth) {
kprintf("%s%c", path, (depth == path_depth) ? '\n' : '/');
path += strlen(path) + 1;
}
#endif
#if 0
tree_node_t * tnode = from;
foreach(node, tnode->children) {
tree_node_t * _node = (tree_node_t *)node->value;
shm_node_t * snode = (shm_node_t *)_node->value;
/* Last available node */
fs_node_t * last = fs_root;
tree_node_t * node = fs_tree->root;
if (!strcmp(snode->name, pch)) {
if (*save == '\0') {
return snode;
char * at = *outpath;
while (1) {
if (at >= path) {
break;
}
int found = 0;
debug_print(INFO, "Searching for %s", at);
foreach(child, node->children) {
tree_node_t * tchild = (tree_node_t *)child->value;
struct vfs_entry * ent = (struct vfs_entry *)tchild->value;
if (!strcmp(ent->name, at)) {
found = 1;
node = tchild;
at = at + strlen(at) + 1;
if (ent->file) {
last = ent->file;
*outpath = at;
}
break;
}
return _get_node(save, create, _node);
}
if (!found) {
break;
}
}
#endif
#if 0
for (depth = 0; depth < path_depth; ++depth) {
/* Search the active directory for the requested directory */
node_next = finddir_fs(node_ptr, path_offset);
free(node_ptr);
node_ptr = node_next;
if (!node_ptr) {
/* We failed to find the requested directory */
/* XXX: This is where we should be checking other file system mappings */
free((void *)path);
return NULL;
} else if (depth == path_depth - 1) {
/* We found the file and are done, open the node */
open_fs(node_ptr, 1, 0);
free((void *)path);
return node_ptr;
}
/* We are still searching... */
path_offset += strlen(path_offset) + 1;
}
#endif
return fs_root;
return last;
}
/**
* kopen: Open a file by name.
*
@ -446,7 +575,12 @@ fs_node_t *kopen(char *filename, uint32_t flags) {
uint32_t depth;
fs_node_t *node_ptr = malloc(sizeof(fs_node_t));
/* Find the mountpoint for this file */
fs_node_t *mount_point = get_mount_point(path, path_depth);
fs_node_t *mount_point = get_mount_point(path, path_depth, &path_offset);
if (path_offset >= path+path_len) {
free(path);
return mount_point;
}
/* Set the active directory to the mountpoint */
memcpy(node_ptr, mount_point, sizeof(fs_node_t));
fs_node_t *node_next = NULL;

View File

@ -86,6 +86,9 @@ struct stat {
extern fs_node_t *fs_root;
extern fs_node_t * null_device_create();
extern fs_node_t * serial_device_create(int device);
extern void serial_mount_devices();
extern fs_node_t * hello_device_create();
uint32_t read_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
uint32_t write_fs(fs_node_t *node, uint32_t offset, uint32_t size, uint8_t *buffer);
@ -99,4 +102,10 @@ fs_node_t *kopen(char *filename, uint32_t flags);
char *canonicalize_path(char *cwd, char *input);
fs_node_t *clone_fs(fs_node_t * source);
void vfs_install();
int vfs_mount(char * path, fs_node_t * local_root);
/* Debug purposes only, please */
void debug_print_vfs_tree();
#endif

View File

@ -114,6 +114,8 @@ int main(struct multiboot *mboot, uint32_t mboot_mag, uintptr_t esp) {
paging_install(mboot_ptr->mem_upper + mboot_ptr->mem_lower); /* Paging */
heap_install(); /* Kernel heap */
vfs_install();
/* Hardware drivers */
timer_install(); /* PIC driver */
serial_install(); /* Serial console */
@ -132,6 +134,20 @@ int main(struct multiboot *mboot, uint32_t mboot_mag, uintptr_t esp) {
parse_args(cmdline);
}
/*
vfs_mount("/foo/bar/baz", fs_root);
vfs_mount("/foo/bar/loof", fs_root);
vfs_mount("/raz/daz/bar", fs_root);
*/
serial_mount_devices();
vfs_mount("/dev/null", null_device_create());
vfs_mount("/dev/hello", hello_device_create());
debug_print_vfs_tree();
//assert(0);
if (ramdisk && !fs_root) {
kprintf("---- ramdisk[0x%x:0x%x]\n", ramdisk, ramdisk_top);
for (uintptr_t i = (uintptr_t)ramdisk; i <= (uintptr_t)ramdisk_top; i += 0x1000) {

View File

@ -13,7 +13,6 @@
#include "lib/pthread.h"
#include "../kernel/include/signal.h"
DEFN_SYSCALL1(serial, 44, int);
int fd = 0;
int child_pid = 0;
@ -35,25 +34,19 @@ void *print_serial_stuff(void * garbage) {
}
int main(int argc, char ** argv) {
int device = 0x2F8;
pthread_t receive_thread;
pthread_t flush_thread;
char * device = argv[1];
if (argc > 1) {
if (!strcmp(argv[1], "com1")) {
device = 0x3F8;
} else if (!strcmp(argv[1], "com2")) {
device = 0x2F8;
} else {
fprintf(stderr, "Unrecognized com device, try com1 or com2; default is com2.\n");
return 1;
}
if (argc < 1) {
device = "/dev/ttyS0";
}
printf("\033[1560z");
fflush(stdout);
fd = syscall_serial(device);
fd = syscall_open(device, 0, 0);
pthread_create(&receive_thread, NULL, print_serial_stuff, NULL);
while (1) {