summaryrefslogtreecommitdiff
path: root/kernel/fs
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/fs')
-rw-r--r--kernel/fs/block.c22
-rw-r--r--kernel/fs/buffer.c102
-rw-r--r--kernel/fs/fs.c2
-rw-r--r--kernel/fs/mount.c12
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));
}