diff options
| author | Jake Mannens <jakem_5@hotmail.com> | 2020-03-07 17:37:49 +1100 |
|---|---|---|
| committer | Jake Mannens <jakem_5@hotmail.com> | 2020-03-07 17:37:49 +1100 |
| commit | b808d33c6bf30691b8cdb6cc0fd65f49e7db29f8 (patch) | |
| tree | f8a0a9b1b2328089fa1f72edea7be05d306d653b /kernel/fs | |
| parent | 07c004bf3cf7fcb6e875bddb1a7fb0793377ebfb (diff) | |
Makefile now correctly calls i386 QEMU instead of x86_64
Changed the type for block addresses from size_t to uint16_t.
Added the '%c' conversion specifier to vsprintf(), so that it can now
output individual characters passed as arguments.
Added a an errno.h header containing a list of commonly used error
codes, as well as a basic strerror() routine to fetch corresponding
human-readable strings from a table.
Implemented barebones floppy driver. Currently lacking many (essential)
features, see TODO notes in floppy.c for more details.
Buffer structs now have a b_present flag to indicate whether or not the
data section is populated, as well as a b_wait element, as a queue for
any tasks waiting on the buffer. All tasks waiting on a block wait in
this queue, however, the task that originally called the driver to read,
may wait in a separate queue maintained by the driver. This system may
change in the future, and will likely depend on how head scheduling is
implemented in the driver.
The buffer_get_block() routine is now publically available in
kernel/fs.h. It can be called to retrieve a block from the buffer cache
(if readily available), or from the specified block device otherwise.
This routine returns a pointer to the buffer containing the cache.
The block_read() function now passes arguments and return values to the
floppy driver regardless of the device specified. The block_write()
function now indicates an error condition by setting b_device to zero in
the allocated buffer structure, as no devices with write functionality
currently exist. This behaviour will be updated in future, as more block
devices are added.
The mount_root() function has been modified to call buffer_get_block(),
instead of calling block_read() directly. As of now, nothing should call
block_read() or block_write() directly, as those functions are intended
for use by the buffer subsystem only.
Diffstat (limited to 'kernel/fs')
| -rw-r--r-- | kernel/fs/block.c | 22 | ||||
| -rw-r--r-- | kernel/fs/buffer.c | 102 | ||||
| -rw-r--r-- | kernel/fs/fs.c | 2 | ||||
| -rw-r--r-- | kernel/fs/mount.c | 12 |
4 files changed, 88 insertions, 50 deletions
diff --git a/kernel/fs/block.c b/kernel/fs/block.c index caf97d2..8f9d907 100644 --- a/kernel/fs/block.c +++ b/kernel/fs/block.c @@ -1,9 +1,23 @@ +#include <kernel/fd.h> +#include <kernel/fs.h> #include <sys/types.h> -int block_read(void *buf, size_t block) { - return -1; +/* + * Minix Major Numbers: + * + * [0] NULL + * [1] /dev/mem + * [2] /dev/fdX + * [3] /dev/hdX + * [4] /dev/ttyX + * [5] /dev/tty + * [6] /dev/lpX + */ + +void block_read(struct buffer *b) { + fd_block_read(b); } -int block_write(void *buf, size_t block) { - return -1; +void block_write(struct buffer *b) { + b->b_device = 0; } diff --git a/kernel/fs/buffer.c b/kernel/fs/buffer.c index 7405738..99c3161 100644 --- a/kernel/fs/buffer.c +++ b/kernel/fs/buffer.c @@ -1,16 +1,76 @@ +#include <asm/interrupt.h> +#include <errno.h> #include <kernel/con.h> #include <kernel/fs.h> #include <stdint.h> #include <string.h> /* memory dedicated to the block cache */ +/* TODO: start buffers at kernel end not 512K */ #define BSTART 0x80000 #define BEND 0xA0000 static struct buffer *lru; static struct buffer *mru; -struct buffer *buffer_get_block(uint16_t device, uint16_t block); +struct buffer *buffer_get_block(uint16_t device, uint16_t block) { + struct buffer **p = &mru; + struct buffer *b; + + if(!device) + return NULL; + + /* check if the requested block is already in the cache */ + while(b = *p) { + if(b->b_device != device || b->b_block != block) + goto next; + /* remove the buffer from the list */ + if(lru == b && b->b_next) lru = b->b_next; + if(b->b_next) b->b_next->b_prev = b->b_prev; + if(b->b_prev) b->b_prev->b_next = b->b_next; + /* put the buffer back at the MRU end of the list */ + b->b_next = NULL; + b->b_prev = mru; + if(mru != b) + mru->b_next = b; + mru = b; + cli(); + /* if the buffer exists but isn't populated. wait on it */ + if(!b->b_present) { + sleep_on(&b->b_wait); + printk("[buf] Waiting for buffer %04x:%04x to be populated...\n", b->b_device, b->b_block); + } + sti(); + printk("[buf] Fetched block %04x:%04x from cache\n", b->b_device, b->b_block); + return b->b_device ? b : NULL; +next: + p = &b->b_prev; + } + + /* + * otherwise, iterate through the least recently used + * buffers, to find a buffer that isn't pending an + * I/O operation, and read into it. + */ + + p = &lru; + while(b = *p) { + if(b->b_present || !b->b_device) + break; + p = &(*p)->b_next; + } + + if(!b) + return NULL; + + b->b_device = device; + b->b_block = block; + b->b_present = 0; + block_read(b); + wake_up(&b->b_wait); + printk("[buf] Called driver to read block %04x:%04x\n", b->b_device, b->b_block); + return b->b_device ? b : NULL; +} void buffer_init(void) { int c = 0; @@ -40,43 +100,3 @@ void buffer_init(void) { printk("[buf] Buffers initialized (0x%x buffers in pool)\n", c); } - -struct buffer *buffer_get_block(uint16_t device, uint16_t block) { - int ret; - struct buffer **p = &mru; - struct buffer *b; - - /* check if the requested block is already in the cache */ - while(*p) { - if((*p)->b_device == device && (*p)->b_block == block) { - /* put the buffer back at the MRU end of the list */ - (*p)->b_next = NULL; - (*p)->b_prev = mru; - mru = *p; - return *p; - } - p = &(*p)->b_prev; - } - - /* find a buffer at the end of the LRU list */ - b = lru; - lru = lru->b_next; - lru->b_prev = NULL; - ret = block_read(b->b_data, block); - /* abort if we failed to read in the block */ - if(ret < 0) { - /* release the allocated buffer to the pool */ - lru->b_prev = b; - b->b_next = lru; - b->b_prev = NULL; - lru = b; - return NULL; - } - b->b_device = device; - b->b_block = block; - /* put the buffer back at the MRU end of the list */ - b->b_next = NULL; - b->b_prev = mru; - mru = b; - return b; -} diff --git a/kernel/fs/fs.c b/kernel/fs/fs.c index 381f20a..e460a4a 100644 --- a/kernel/fs/fs.c +++ b/kernel/fs/fs.c @@ -1,5 +1,6 @@ #include <errno.h> #include <kernel/con.h> +#include <kernel/fd.h> #include <kernel/fs.h> #include <kernel/kernel.h> #include <kernel/sched.h> @@ -32,6 +33,7 @@ void fs_init(void) { buffer_init(); /* hd_init(); */ + fd_init(); mount_root(); } diff --git a/kernel/fs/mount.c b/kernel/fs/mount.c index 9cdf49b..e4d3636 100644 --- a/kernel/fs/mount.c +++ b/kernel/fs/mount.c @@ -7,15 +7,17 @@ struct super_block sblocks[NRSUPER]; void mount_root(void) { int ret; - char buf[BLOCK_SIZE]; - struct super_block *s = (void*) buf; + struct buffer *b; + struct super_block *s; - ret = block_read(buf, 1); - if(ret < 0) { + b = buffer_get_block(1, 1); + if(!b) { printk("[fs] Failed to read super block\n"); return; } + s = b->b_data; + if(s->s_magic != SUPER_MAGIC) { printk("[fs] Invalid magic number in super block!\n"); return; @@ -31,5 +33,5 @@ void mount_root(void) { printk(" Max file size: 0x%01x\n", s->s_max_size); /* copy the super block into the table */ - memcpy(sblocks, buf, ((unsigned) &s->s_imap - (unsigned) s)); + memcpy(sblocks, s, ((unsigned) &s->s_imap - (unsigned) s)); } |
