[FS] VFS and mountpoints

This commit is contained in:
Thomas Lovén 2017-03-10 23:25:25 +01:00
parent e3e661e7e5
commit 2fe66e4f80
6 changed files with 255 additions and 20 deletions

View File

@ -7,26 +7,6 @@ int main(int argc, char **argv)
(void) argc;
(void) argv;
if(!fork())
{
if(!fork())
return 200;
return 100;
}
for(int j=0; j <= 10; j++)
{
if(!fork())
return j;
}
while(1)
{
int retval;
int pid = wait(&retval);
printf("Pid: %d exited with %d\n", pid, retval);
}
for(;;);
return 0;
}

View File

@ -11,6 +11,7 @@
#include <elf.h>
#include <syscall.h>
#include <cpuid.h>
#include <vfs.h>
int kernel_execve(process_t *p, void *image, char *argv[], char *envp[]);
int kmain(uint64_t multiboot_magic, void *multiboot_data)
@ -36,6 +37,16 @@ int kmain(uint64_t multiboot_magic, void *multiboot_data)
scheduler_insert(th);
procmm_print_map(p1->mmap);
fs_mount(0, "/");
fs_mount(0, "/dev");
fs_mount(0, "/home/user/mnt/photos");
fs_namef("/");
fs_namef("/usr/local/bin/python");
fs_namef("/dev/tty0");
fs_namef("/home/thomas");
fs_namef("/home/user/mnt/photos/2016/june");
asm("sti");
debug_info("BOOT COMPLETE\n");

161
kernel/fs/vfs.c Normal file
View File

@ -0,0 +1,161 @@
#include <vfs.h>
#include <stdint.h>
#include <stddef.h>
#include <mem.h>
#include <string.h>
#include <debug.h>
file_t *fs_get(file_t *file)
{
if(!file)
file = kcalloc(1, sizeof(file_t));
file->refs += 1;
return file;
}
file_t *fs_put(file_t *file)
{
if(!file)
return file;
file->refs -= 1;
if(!file->refs)
{
kfree(file);
file = 0;
}
return file;
}
int fs_open(file_t *file, uint64_t flags)
{
if(file && file->driver && file->driver->open)
return file->driver->open(file, flags);
return -1;
}
int fs_close(file_t *file)
{
if(file && file->driver && file->driver->close)
return file->driver->close(file);
return -1;
}
size_t fs_read(file_t *file, void *buffer, size_t nbyte, size_t offset)
{
if(file && file->driver && file->driver->read)
return file->driver->read(file, buffer, nbyte, offset);
return -1;
}
size_t fs_write(file_t *file, void *buffer, size_t nbyte, size_t offset)
{
if(file && file->driver && file->driver->write)
return file->driver->write(file, buffer, nbyte, offset);
return -1;
}
int fs_readdir(file_t *dir, dirent_t *entry, uint64_t offset)
{
if(dir && dir->driver && dir->driver->readdir)
return dir->driver->readdir(dir, entry, offset);
return 0;
}
file_t *fs_finddir(file_t *dir, char *name)
{
dirent_t entry;
int offset = 0;
while(1)
{
int retval = fs_readdir(dir, &entry, offset++);
if(!retval)
break;
if(strcmp((&entry)->name, name))
{
fs_put(entry.file);
continue;
}
return entry.file;
}
return 0;
}
void fs_mount(file_t *root, const char *path)
{
struct mountpoint *mp = kcalloc(1, sizeof(struct mountpoint) + strlen(path) + 1);
mp->root = fs_get(root);
mp->path_len = strlen(path);
memcpy(mp->path, path, mp->path_len);
mp->path[mp->path_len] = '\0';
LIST_APPEND(mountpoints, mp, mountpoints);
}
void fs_umount(const char *path)
{
LIST_FOREACH(mountpoints, struct mountpoint, mp, mountpoints)
{
if(!strcmp(mp->path, path))
{
LIST_REMOVE(mountpoints, mp, mountpoints);
fs_put(mp->root);
kfree(mp);
return;
}
}
}
struct mountpoint *fs_closest_mp(const char *path)
{
uint64_t best_len = 0;
struct mountpoint *best = 0;
LIST_FOREACH(mountpoints, struct mountpoint, mp, mountpoints)
{
uint64_t len = mp->path_len;
if((!strncmp(mp->path, path, len-1)) && (len > best_len))
{
best = mp;
best_len = len;
}
}
return best;
}
char *pathtok(char **p)
{
char sep = '/';
if(!**p) return 0;
while(**p && **p == sep) (*p)++;
char *ret = *p;
while(**p && **p != sep) (*p)++;
if(**p) **p = '\0', (*p)++;
return ret;
}
file_t *fs_namef(const char *path)
{
char *name;
char *p = strdup(path);
char *q = p;
struct mountpoint *mp = fs_closest_mp(path);
file_t *root = mp->root;
p += mp->path_len;
file_t *dir = fs_get(root);
while((name = pathtok(&p)))
{
file_t *next = fs_finddir(dir, name);
if(!next)
{
dir = 0;
goto end;
}
fs_put(dir);
dir = next;
}
end:
kfree(q);
return dir;
}

View File

@ -11,3 +11,6 @@ void *memmove(void *dest, const void *src, size_t n);
int memcmp(const void *s1, const void *s2, size_t n);
size_t strlen(const char *s);
int strncmp(const char *s1, const char *s2, size_t n);
int strcmp(const char *s1, const char *s2);
char *strdup(const char *s);

58
kernel/include/vfs.h Normal file
View File

@ -0,0 +1,58 @@
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <list.h>
typedef struct vfs_node_st * INODE;
typedef struct file_st
{
uint64_t refs;
uint64_t type;
struct fs_driver_st *driver;
void *data;
} file_t;
typedef struct dirent_st
{
char name[256];
file_t *file;
} dirent_t;
#define FS_FILE 0x1
#define FS_DIR 0x2
#define FS_PIPE 0x3
typedef struct fs_driver_st
{
int (*open)(file_t *file, uint64_t flags);
int (*close)(file_t *file);
size_t (*read)(file_t *file, void *buffer, size_t nbyte, size_t offset);
size_t (*write)(file_t *file, void *buffer, size_t nbyte, size_t offset);
int (*readdir)(file_t *dir, dirent_t *entry, uint64_t offset);
} fs_driver_t;
int fs_open(file_t *file, uint64_t flags);
int fs_close(file_t *file);
size_t fs_read(file_t *file, void *buffer, size_t nbyte, size_t offset);
size_t fs_write(file_t *file, void *buffer, size_t nbyte, size_t offset);
int fs_readdir(file_t *dir, dirent_t *entry, uint64_t offset);
struct mountpoint
{
LIST(struct mountpoint, mountpoints);
file_t *root;
uint64_t path_len;
char path[];
};
file_t *fs_get(file_t *file);
file_t *fs_put(file_t *file);
LIST(struct mountpoint, mountpoints);
void fs_mount(file_t *root, const char *path);
void fs_umount(const char *path);
file_t *fs_namef(const char *path);

View File

@ -1,6 +1,7 @@
#include <string.h>
#include <stdint.h>
#include <stddef.h>
#include <mem.h>
// Standard function required by gcc
// Just the naíve implementations for now
@ -44,3 +45,24 @@ size_t strlen(const char *s)
while(*s++) len++;
return len;
}
int strncmp(const char *s1, const char *s2, size_t n)
{
while(n && *s1 && (*s1==*s2))
s1++, s2++, n--;
return *(const unsigned char*)s1-*(const unsigned char*)s2;
}
int strcmp(const char *s1, const char *s2)
{
while(*s1 && (*s1==*s2))
s1++, s2++;
return *(const unsigned char*)s1-*(const unsigned char*)s2;
}
char *strdup(const char *s)
{
char *ret = kmalloc(strlen(s)+1);
memcpy(ret, s, strlen(s)+1);
return ret;
}