diff options
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)); } |
