From 2419b2e9e0c30b73054a86535fa8c930eb5fd069 Mon Sep 17 00:00:00 2001 From: Matheus Date: Tue, 2 Aug 2022 22:14:32 -0300 Subject: [PATCH] vfs filesystem mounting --- src/arch/x86_64/main.c | 5 ++ src/fs/tmpfs.c | 31 ++++++++++ src/fs/vfs.c | 116 +++++++++++++++++++++++++++++++------ src/include/errno.h | 3 + src/include/kernel/tmpfs.h | 8 +++ src/include/kernel/vfs.h | 21 +++---- 6 files changed, 155 insertions(+), 29 deletions(-) create mode 100644 src/fs/tmpfs.c create mode 100644 src/include/kernel/tmpfs.h diff --git a/src/arch/x86_64/main.c b/src/arch/x86_64/main.c index 14d7825d..026ca129 100644 --- a/src/arch/x86_64/main.c +++ b/src/arch/x86_64/main.c @@ -49,6 +49,11 @@ void kmain(){ alloc_init(); vfs_init(); + + printf("Mounting tmpfs in /\n"); + + if(vfs_mount(vfs_root(), NULL, "", "tmpfs", 0, NULL)) + _panic("Failed to mount tmpfs", 0); _panic("End of kmain()", 0); diff --git a/src/fs/tmpfs.c b/src/fs/tmpfs.c new file mode 100644 index 00000000..73c2845a --- /dev/null +++ b/src/fs/tmpfs.c @@ -0,0 +1,31 @@ +#include +#include +#include + +static int tmpfs_mount(dirnode_t** rootptr, vnode_t* device, int mountflags, void* fsinfo){ + + fs_t* desc = alloc(sizeof(fs_t)); + + if(!desc) + return ENOMEM; + + dirnode_t* root = vfs_newdirnode(desc, NULL); + + if(!root){ + free(desc); + return ENOMEM; + } + + *rootptr = root; + + return 0; +} + +static fscalls_t funcs = { + tmpfs_mount +}; + + +fscalls_t* tmpfs_getfuncs(){ + return &funcs; +} diff --git a/src/fs/vfs.c b/src/fs/vfs.c index bef8a939..b61b9939 100644 --- a/src/fs/vfs.c +++ b/src/fs/vfs.c @@ -5,24 +5,88 @@ #include dirnode_t* vfsroot; +hashtable fsfuncs; -vnode_t* vfs_newnode(fs_t* fs, void* fsdata){ +static inline dirnode_t* mountpoint(dirnode_t* node){ + dirnode_t* ret = node; + while(ret->mount) + ret = ret->mount; + return ret; +} + +int vfs_mount(dirnode_t* ref, char* device, char* mountpoint, char* fs, int mountflags, void* fsinfo){ + + fscalls_t* fscalls = hashtable_get(&fsfuncs, fs); + + if(!fscalls) + return ENODEV; + + vnode_t* dev = NULL; + dirnode_t* mountdir = ref; + + if(device){ + dev = ref; + if(*device){ + int result = vfs_resolvepath(&dev, ref, device); + + if(result) + return result; + } + } + + + int result = vfs_resolvepath(&mountdir, ref, mountpoint); + + if(result) + return result; + + if(GETTYPE(mountdir->vnode.st.st_mode) != TYPE_DIR) + return ENOTDIR; + + dirnode_t* mount; + + result = fscalls->mount(&mount, dev, mountflags, fsinfo); + + if(result) + return result; + + mountdir->mount = mount; + + return 0; +} + +vnode_t* vfs_newnode(char* name, fs_t* fs, void* fsdata){ vnode_t* node = alloc(sizeof(vnode_t)); if(!node) return NULL; + node->name = alloc(strlen(name)+1); + if(!name){ + free(node); + return NULL; + } + node->fs = fs; node->fsdata = fsdata; - + strcpy(node->name, name); + return node; } -dirnode_t* vfs_newdirnode(fs_t* fs, void* fsdata){ +dirnode_t* vfs_newdirnode(char* name, fs_t* fs, void* fsdata){ dirnode_t* node = alloc(sizeof(dirnode_t)); if(!node) return NULL; vnode_t* vnode = (vnode_t*)node; + + vnode->name = alloc(strlen(name)+1); + + if(!vnode->name){ + free(node); + return NULL; + } if(!hashtable_init(&node->children, 10)){ // add more here later + free(vnode->name); free(node); return NULL; } @@ -30,6 +94,10 @@ dirnode_t* vfs_newdirnode(fs_t* fs, void* fsdata){ vnode->st.st_mode = MAKETYPE(TYPE_DIR); vnode->fs = fs; vnode->fsdata = fsdata; + strcpy(vnode->name, name); + + return node; + } int vfs_resolvepath(vnode_t** result, dirnode_t* ref, char *path){ @@ -38,25 +106,33 @@ int vfs_resolvepath(vnode_t** result, dirnode_t* ref, char *path){ char name[512]; off_t nameoffset = 0; - while(nameoffset <= strlen(path)){ + memset(name, 0, 512); + + iterator = mountpoint(iterator); + + while(nameoffset < strlen(path)){ size_t offset = 0; - while(path[nameoffset]) + while(path[nameoffset] && path[nameoffset] != '/') name[offset++] = path[nameoffset++]; + if(path[nameoffset] == '/') + ++nameoffset; + name[offset] = 0; // make sure we're a directory if(!GETTYPE(iterator->vnode.st.st_mode) == TYPE_DIR) return ENOTDIR; - - // find correct node if mountmoint - while(iterator->mountednode) - iterator = iterator->mountednode; + // get the right vnode for this point + iterator = mountpoint(iterator); + + // now try to get the right child + vnode_t* child = hashtable_get(&iterator->children, name); if(!child){ @@ -72,7 +148,7 @@ int vfs_resolvepath(vnode_t** result, dirnode_t* ref, char *path){ iterator = (dirnode_t*)child; } - + *result = (vnode_t*)iterator; return 0; @@ -93,21 +169,23 @@ dirnode_t* vfs_root(){ } void vfs_acquirenode(vnode_t* node){ - while(node){ - ++node->refcount; - node = (vnode_t*)node->parent; - } + ++node->refcount; } void vfs_releasenode(vnode_t* node){ - while(node){ - --node->refcount; - node = (vnode_t*)node->parent; - } + --node->refcount; } +#include + void vfs_init(){ printf("Creating a fake root for the VFS\n"); - vfsroot = vfs_newdirnode(NULL, NULL); + vfsroot = vfs_newdirnode("/", NULL, NULL); + + hashtable_init(&fsfuncs, 10); + + hashtable_insert(&fsfuncs, "tmpfs", (void*)tmpfs_getfuncs()); + + } diff --git a/src/include/errno.h b/src/include/errno.h index b10d1df7..42312ea5 100644 --- a/src/include/errno.h +++ b/src/include/errno.h @@ -2,5 +2,8 @@ #define _ERRNO_H_INCLUDE #define ENOTDIR 1 +#define ENODEV 2 +#define ENOMEM 3 +#define EINVAL 4 #endif diff --git a/src/include/kernel/tmpfs.h b/src/include/kernel/tmpfs.h new file mode 100644 index 00000000..d2b135d9 --- /dev/null +++ b/src/include/kernel/tmpfs.h @@ -0,0 +1,8 @@ +#ifndef _TMPFS_H_INCLUDE +#define _TMPFS_H_INCLUDE + +#include + +fscalls_t* tmpfs_getfuncs(); + +#endif diff --git a/src/include/kernel/vfs.h b/src/include/kernel/vfs.h index 20145340..a5449a25 100644 --- a/src/include/kernel/vfs.h +++ b/src/include/kernel/vfs.h @@ -18,6 +18,7 @@ typedef struct { typedef struct _vnode_t { stat st; + char* name; fs_t* fs; void* fsdata; size_t refcount; @@ -28,23 +29,23 @@ typedef struct _vnode_t { typedef struct _dirnode_t{ vnode_t vnode; - struct _dirnode_t* mountednode; + struct _dirnode_t* mount; hashtable children; } dirnode_t; // fs specific calls called by the vfs on filesystems typedef struct _fscalls_t { - // prepares the filesystem using a filesystem data pointer and returns the root node - dirnode_t* (*mount)(void*); + // prepares the filesystem using a filesystem data pointer and device, returning the root node in rootptr + int (*mount)(dirnode_t** rootptr, vnode_t* device, int mountflags, void* fsinfo); // cleanup of the filesystem - int (*umount)(); + int (*umount)(fs_t* fs); // opens a file under a dirnode // args: parent, name - int (*open)(dirnode_t*, char*); - // cleans up a vfsnode + int (*open)(dirnode_t* parent, char* name); + // cleans up a node // args: the node to clean - int (*close)(vnode_t*); + int (*close)(vnode_t* node); // creates a new directory with the right mode // args: parent, name, mode int (*mkdir)(dirnode_t* parent, char* name, mode_t mode); @@ -54,7 +55,7 @@ typedef struct _fscalls_t { } fscalls_t; -int vfs_mount(dirnode_t* ref, char* device, char* mountpoint, char* fs); +int vfs_mount(dirnode_t* ref, char* device, char* mountpoint, char* fs, int mountflags, void* fsinfo); int vfs_umount(dirnode_t* ref, char* mountpoint); int vfs_open(vnode_t* buf, dirnode_t* ref, char* path, int flags, mode_t mode); int vfs_close(vnode_t* node); @@ -66,8 +67,8 @@ void vfs_init(); dirnode_t* vfs_root(); void vfs_acquirenode(vnode_t* node); void vfs_releasenode(vnode_t* node); -vnode_t* vfs_newnode(fs_t* fs, void* fsdata); -dirnode_t* vfs_newdirnode(fs_t* fs, void* fsdata); +vnode_t* vfs_newnode(char* name, fs_t* fs, void* fsdata); +dirnode_t* vfs_newdirnode(char* name, fs_t* fs, void* fsdata); void vfs_destroynode(vnode_t* node); int vfs_resolvepath(vnode_t** result, dirnode_t* ref, char* path);