diff options
author | Alex Auvolat <alex.auvolat@ens.fr> | 2015-02-09 19:24:42 +0100 |
---|---|---|
committer | Alex Auvolat <alex.auvolat@ens.fr> | 2015-02-09 19:24:42 +0100 |
commit | 440d9dc470703d20a55365b3a560196e71d450d4 (patch) | |
tree | bcc864c7aeb0af7a81c4fcd7430fa8c3001f8383 /src | |
parent | caf842864bdc0794e387f9580af96ab1036996f4 (diff) | |
download | kogata-440d9dc470703d20a55365b3a560196e71d450d4.tar.gz kogata-440d9dc470703d20a55365b3a560196e71d450d4.zip |
Start work on filesystems.
Diffstat (limited to 'src')
-rw-r--r-- | src/common/string.c | 5 | ||||
-rw-r--r-- | src/kernel/Makefile | 3 | ||||
-rw-r--r-- | src/kernel/core/kmain.c | 49 | ||||
-rw-r--r-- | src/kernel/include/devfs.h | 8 | ||||
-rw-r--r-- | src/kernel/include/nullfs.h | 25 | ||||
-rw-r--r-- | src/kernel/include/process.h | 32 | ||||
-rw-r--r-- | src/kernel/include/vfs.h | 86 | ||||
-rw-r--r-- | src/kernel/user/nullfs.c | 30 | ||||
-rw-r--r-- | src/kernel/user/process.c | 23 | ||||
-rw-r--r-- | src/kernel/user/vfs.c | 126 |
10 files changed, 320 insertions, 67 deletions
diff --git a/src/common/string.c b/src/common/string.c index 2c73900..027bf03 100644 --- a/src/common/string.c +++ b/src/common/string.c @@ -10,10 +10,9 @@ size_t strlen(const char* str) { } char *strchr(const char *str, char c) { - while (*str) { + do { if (*str == c) return (char*)str; - str++; - } + } while (*(str++)); return NULL; } diff --git a/src/kernel/Makefile b/src/kernel/Makefile index 3fc7e9c..e847827 100644 --- a/src/kernel/Makefile +++ b/src/kernel/Makefile @@ -1,7 +1,8 @@ OBJ = core/loader.o core/kmain.o core/dbglog.o core/sys.o \ core/gdt.o core/idt.o core/interrupt.o core/context_switch.o core/thread.o \ - core/frame.o core/paging.o core/region.o core/kmalloc.o + core/frame.o core/paging.o core/region.o core/kmalloc.o \ + user/vfs.o user/nullfs.o LIB = ../common/common.lib diff --git a/src/kernel/core/kmain.c b/src/kernel/core/kmain.c index 6024b77..2782cc1 100644 --- a/src/kernel/core/kmain.c +++ b/src/kernel/core/kmain.c @@ -13,6 +13,9 @@ #include <thread.h> +#include <vfs.h> +#include <nullfs.h> + #include <slab_alloc.h> #include <hashtbl.h> @@ -150,23 +153,8 @@ void test_thread(void* a) { if (i % 8 == 0) yield(); } } -void kernel_init_stage2(void* data) { - dbg_print_region_info(); - dbg_print_frame_stats(); - - test_hashtbl_1(); - test_hashtbl_2(); - - thread_t *tb = new_thread(test_thread, 0); - resume_thread(tb, false); - for (int i = 0; i < 120; i++) { - dbg_printf("a"); - for (int x = 0; x < 100000; x++) asm volatile("xor %%ebx, %%ebx":::"%ebx"); - } - PANIC("Reached kmain end! Falling off the edge."); -} - +void kernel_init_stage2(void* data); void kmain(struct multiboot_info_t *mbd, int32_t mb_magic) { dbglog_setup(); @@ -212,4 +200,33 @@ void kmain(struct multiboot_info_t *mbd, int32_t mb_magic) { PANIC("Should never come here."); } +void kernel_init_stage2(void* data) { + dbg_print_region_info(); + dbg_print_frame_stats(); + + test_hashtbl_1(); + test_hashtbl_2(); + + thread_t *tb = new_thread(test_thread, 0); + resume_thread(tb, false); + + for (int i = 0; i < 120; i++) { + dbg_printf("a"); + for (int x = 0; x < 100000; x++) asm volatile("xor %%ebx, %%ebx":::"%ebx"); + } + + register_nullfs_driver(); + fs_t *devfs = make_fs("nullfs", 0, ""); + ASSERT(devfs != 0); + + //TODO : + // - populate devfs with information regarding kernel command line & modules + // - create user process with init module provided on command line + // - give it rights to devfs + // - launch it + // - just return, this thread is done + + PANIC("Reached kmain end! Falling off the edge."); +} + /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/devfs.h b/src/kernel/include/devfs.h new file mode 100644 index 0000000..0dee246 --- /dev/null +++ b/src/kernel/include/devfs.h @@ -0,0 +1,8 @@ +#pragma once + +#include <vfs.h> + +fs_t* init_devfs(); + + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/nullfs.h b/src/kernel/include/nullfs.h new file mode 100644 index 0000000..16fff87 --- /dev/null +++ b/src/kernel/include/nullfs.h @@ -0,0 +1,25 @@ +#pragma once + +#include <vfs.h> + +#define NULLFS_OPT_CREATE_EN 1 +#define NULLFS_OPT_DELETE_EN 2 + +typedef struct nullfs nullfs_t; + +typedef struct { + void* (*open)(void* f, int mode, fs_handle_t *h); + size_t (*read)(void* f, size_t offset, size_t len, char* buf); + size_t (*write)(void* f, size_t offset, size_t len, const char* buf); + void (*close)(void* f); + void (*delete)(void* f); +} nullfs_node_ops_t; + +void register_nullfs_driver(); + +nullfs_t* as_nullfs(fs_t *fs); + +bool nullfs_add(nullfs_t *f, const char* name, void* data, nullfs_node_ops_t* ops); +bool nullfs_add_ram_file(nullfs_t *f, const char* name, void* data, size_t init_sz, int ok_modes); + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 00ed1d7..a6ca1e9 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -3,41 +3,19 @@ // Things described in this file are essentially a public interface // All implementation details are hidden in process.c +// A process is a recipient for user code, as well as for mounting File Systems, +// which allow access to features of the system. + #include <thread.h> #include <hashtbl.h> -#include <buffer.h> - -#define PW_NOT_WAITING 0 -#define PW_WAIT_ANY_MSG 1 -#define PW_WAIT_MSG_ON_CHAN 2 - -#define PROCESS_MAILBOX_SIZE 42 - -typedef int chan_id_t; -typedef struct chan_pair { - chan_id_t fst, snd; -} chan_pair_t; - -typedef struct message { - buffer_t *data; - chan_id_t chan_id; -} message_t; struct process; typedef struct process process_t; -process_t *new_process(entry_t entry, void* data, chan_pair_t *give_chans); - -chan_pair_t new_chan(); // not used very often, but still usefull -chan_id_t unbox_chan(chan_id_t chan, chan_id_t subchan); -void detach_chan(chan_id_t chan); // chan ID is freed - -int send_message(chan_id_t chan, buffer_t *msg); // nonnull on error (recipient queue is full) +process_t *new_process(entry_t entry, void* data); -size_t await_message(); // returns the size of the first message to come -size_t await_message_on_chan(chan_id_t chan); // returns the size of the first message to come -message_t get_message(); // gets the first message in the queue (or nothing when queue is empty) +bool mmap(process_t *proc, void* addr, size_t size, int type); /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/vfs.h b/src/kernel/include/vfs.h new file mode 100644 index 0000000..5f7a0d8 --- /dev/null +++ b/src/kernel/include/vfs.h @@ -0,0 +1,86 @@ +#pragma once + +#include <stdbool.h> +#include <malloc.h> + +typedef struct { + // TODO + // (should also be moved to a user-visible header) +} stat_t; + +#define FM_READ (0x01) +#define FM_WRITE (0x02) +#define FM_MMAP (0x04) +#define FM_CREATE (0x10) +#define FM_TRUNC (0x20) +#define FM_APPEND (0x40) + +// How to use : +// - when using a filesystem : never call the operations in fs_*_ops_t directly, use +// the functions defined bellow +// - when programming a filesystem : don't worry about allocating the fs_handle_t and fs_t, +// it is done automatically + + +// Structure defining a handle to an open file + +typedef struct { + size_t (*read)(void* f, size_t offset, size_t len, char* buf); + size_t (*write)(void* f, size_t offset, size_t len, const char* buf); + void (*close)(void* f); +} fs_handle_ops_t; + +typedef struct fs_handle { + int refs; + fs_handle_ops_t *ops; + void* data; + int mode; +} fs_handle_t; + +// Structure defining a filesystem + +typedef struct { + bool (*open)(void *fs, const char* file, int mode, fs_handle_t *s); + bool (*delete)(void *fs, const char* file); + bool (*rename)(void *fs, const char* from, const char* to); + bool (*stat)(void *fs, const char* file, stat_t *st); + int (*ioctl)(void *fs, const char* file, int command, void* data); + bool (*add_source)(void* fs, fs_handle_t* source); + void (*shutdown)(void *fs); +} fs_ops_t; + +typedef struct fs { + int refs; + fs_ops_t *ops; + void* data; +} fs_t; + +// Structure defining a filesystem driver + +typedef struct { + bool (*make)(fs_handle_t *source, char* opts, fs_t *d); + bool (*detect)(fs_handle_t *source); +} fs_driver_ops_t; + +// Common functions + +void register_fs_driver(const char* name, fs_driver_ops_t *ops); + +fs_t* make_fs(const char* driver, fs_handle_t *source, char* opts); +bool fs_add_source(fs_t *fs, fs_handle_t *source); +void ref_fs(fs_t *fs); +void unref_fs(fs_t *fs); + +bool fs_delete(fs_t *fs, const char* file); +bool fs_rename(fs_t *fs, const char* from, const char* to); +bool fs_stat(fs_t *fs, const char* file, stat_t *st); +int fs_ioctl(fs_t *fs, const char* file, int command, void* data); + +fs_handle_t* fs_open(fs_t *fs, const char* file, int mode); +void ref_file(fs_handle_t *file); +void unref_file(fs_handle_t *file); +size_t file_read(fs_handle_t *f, size_t offset, size_t len, char* buf); +size_t file_write(fs_handle_t *f, size_t offset, size_t len, const char* buf); +int file_get_mode(fs_handle_t *f); + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/user/nullfs.c b/src/kernel/user/nullfs.c new file mode 100644 index 0000000..3c11198 --- /dev/null +++ b/src/kernel/user/nullfs.c @@ -0,0 +1,30 @@ +#include <nullfs.h> + +bool nullfs_i_make(fs_handle_t *source, char* opts, fs_t *d); + +fs_driver_ops_t nullfs_driver_ops = { + .make = nullfs_i_make, + .detect = 0, +}; + +fs_ops_t nullfs_ops = { + 0 //TODO +}; + +void register_nullfs_driver() { + register_fs_driver("nullfs", &nullfs_driver_ops); +} + +nullfs_t *make_nullfs(char* options) { + fs_t *it = make_fs("nullfs", 0, options); + if (it == 0) return 0; + if (it->ops != &nullfs_ops) return 0; + return (nullfs_t*)it->data; +} + +bool nullfs_i_make(fs_handle_t *source, char* opts, fs_t *d) { + // TODO + return false; +} + +/* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c index 7519dae..22295ef 100644 --- a/src/kernel/user/process.c +++ b/src/kernel/user/process.c @@ -2,29 +2,12 @@ #include <process.h> typedef struct process { - thread_t *thread; - int pid; - - mutex_t com_mutex; + pagedir_t *pd; - hashtbl_t *chans; - chan_id_t next_chan_id; - - message_t mbox[PROCESS_MAILBOX_SIZE]; - int mbox_size; // number of messages in queue - int mbox_first; // first message in queue (circular buffer) + thread_t *thread; - // a process can be in several waiting states : - // - wait for any message - // - wait for a message on a particular channel - // in this case, if a message is pushed on this particular channel, - // then it is put in front of the queue, so that it is the next message read - // (it is guaranteed that doing await_message_on_chan() immediately followed by get_message() - // gets the message whose size was returned by await_...) - int wait_state; - chan_id_t wait_chan_id; // when waiting for a message on a particular channel + int pid, ppid; } process_t; -int push_message(process_t *proc, message_t msg); // nonnull on error (process queue is full) /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/user/vfs.c b/src/kernel/user/vfs.c new file mode 100644 index 0000000..ebd5808 --- /dev/null +++ b/src/kernel/user/vfs.c @@ -0,0 +1,126 @@ +#include <debug.h> +#include <vfs.h> +#include <string.h> + +// ============================= // +// FILESYSTEM DRIVER REGISTERING // +// ============================= // + +typedef struct fs_driver { + const char* name; + fs_driver_ops_t *ops; + struct fs_driver *next; +} fs_driver_t; + +fs_driver_t *drivers = 0; + +void register_fs_driver(const char* name, fs_driver_ops_t *ops) { + fs_driver_t *d = (fs_driver_t*)malloc(sizeof(fs_driver_t)); + ASSERT(d != 0); // should we fail in a more graceful manner ? + + d->name = name; + d->ops = ops; + d->next = drivers; + drivers = d; +} + +// ================================== // +// CREATING AND DELETINF FILE SYSTEMS // +// ================================== // + +fs_t *make_fs(const char* drv_name, fs_handle_t *source, char* opts) { + // Look for driver + fs_driver_t *d = 0; + for(fs_driver_t *i = drivers; i != 0; i = i->next) { + if (drv_name != 0 && strcmp(i->name, drv_name) == 0) d = i; + if (drv_name == 0 && source != 0 && i->ops->detect && i->ops->detect(source)) d = i; + if (d != 0) break; + } + + // Open file system + fs_t *fs = (fs_t*)malloc(sizeof(fs_t)); + if (fs == 0) return 0; + + if (d->ops->make(source, opts, fs)) { + return fs; + } else { + free(fs); + return 0; + } +} + +bool fs_add_source(fs_t *fs, fs_handle_t *source) { + return fs->ops->add_source && fs->ops->add_source(fs->data, source); +} + +void ref_fs(fs_t *fs) { + fs->refs++; +} + +void unref_fs(fs_t *fs) { + fs->refs--; + if (fs->refs == 0) { + fs->ops->shutdown(fs->data); + free(fs); + } +} + +// DOING THINGS IN FLESYSTEMS // + +bool fs_delete(fs_t *fs, const char* file) { + return fs->ops->delete && fs->ops->delete(fs->data, file); +} + +bool fs_rename(fs_t *fs, const char* from, const char* to) { + return fs->ops->rename && fs->ops->rename(fs->data, from, to); +} + +bool fs_stat(fs_t *fs, const char* name, stat_t *st) { + return fs->ops->stat && fs->ops->stat(fs->data, name, st); +} + +int fs_ioctl(fs_t *fs, const char* file, int command, void* data) { + return fs->ops->ioctl && fs->ops->ioctl(fs->data, file, command, data); +} + +// =================== // +// OPERATIONS ON FILES // +// =================== // + +fs_handle_t* fs_open(fs_t *fs, const char* file, int mode) { + fs_handle_t *h = (fs_handle_t*)malloc(sizeof(fs_handle_t)); + if (h == 0) return 0; + + if (fs->ops->open(fs->data, file, mode, h)) { + return h; + } else { + free(h); + return 0; + } +} + +void ref_file(fs_handle_t *file) { + file->refs++; +} + +void unrefe_file(fs_handle_t *file) { + file->refs--; + if (file->refs == 0) { + file->ops->close(file->data); + free(file); + } +} + +size_t file_read(fs_handle_t *f, size_t offset, size_t len, char* buf) { + return f->ops->read && f->ops->read(f->data, offset, len, buf); +} + +size_t file_write(fs_handle_t *f, size_t offset, size_t len, const char* buf) { + return f->ops->write && f->ops->write(f->data, offset, len, buf); +} + +int file_get_mode(fs_handle_t *f) { + return f->mode; +} + +/* vim: set ts=4 sw=4 tw=0 noet :*/ |