aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2015-03-09 17:04:04 +0100
committerAlex Auvolat <alex@adnab.me>2015-03-09 17:04:04 +0100
commit3341e7a3a184b5bea17f0f678b40bc51c92d72a4 (patch)
treec77a940a371148b256676f7b59caaecc725a1f1d
parent436418e575b68fd7e85f7fdaf039e03874ec1cb9 (diff)
downloadkogata-3341e7a3a184b5bea17f0f678b40bc51c92d72a4.tar.gz
kogata-3341e7a3a184b5bea17f0f678b40bc51c92d72a4.zip
Partial implement VFS pager (enough for ISO9660!)
Also add some debugging facilities (especially stack trace).
-rw-r--r--src/kernel/core/idt.c14
-rw-r--r--src/kernel/core/kmalloc.c2
-rw-r--r--src/kernel/core/paging.c3
-rw-r--r--src/kernel/core/thread.c2
-rw-r--r--src/kernel/dev/pciide.c40
-rw-r--r--src/kernel/fs/iso9660.c152
-rw-r--r--src/kernel/include/pager.h4
-rw-r--r--src/kernel/include/region.h4
-rw-r--r--src/kernel/include/vfs.h4
-rw-r--r--src/kernel/user/ipc.c6
-rw-r--r--src/kernel/user/nullfs.c14
-rw-r--r--src/kernel/user/pager.c129
-rw-r--r--src/kernel/user/process.c8
-rw-r--r--src/kernel/user/vfs.c10
14 files changed, 261 insertions, 131 deletions
diff --git a/src/kernel/core/idt.c b/src/kernel/core/idt.c
index 6bfe8b5..eef3ca6 100644
--- a/src/kernel/core/idt.c
+++ b/src/kernel/core/idt.c
@@ -275,7 +275,19 @@ void dbg_dump_registers(registers_t *regs) {
dbg_printf("| EAX: 0x%p EBX: 0x%p ECX: 0x%p EDX: 0x%p\n", regs->eax, regs->ebx, regs->ecx, regs->edx);
dbg_printf("| EDI: 0x%p ESI: 0x%p ESP: 0x%p EBP: 0x%p\n", regs->edi, regs->esi, regs->esp, regs->ebp);
dbg_printf("| EIP: 0x%p CS : 0x%p DS : 0x%p SS : 0x%p\n", regs->eip, regs->cs, regs->ds, regs->ss);
- dbg_printf("\\ EFl: 0x%p I# : 0x%p Err: 0x%p\n", regs->eflags, regs->int_no, regs->err_code);
+ dbg_printf("| EFl: 0x%p I# : 0x%p Err: 0x%p\n", regs->eflags, regs->int_no, regs->err_code);
+ dbg_printf("- Stack trace:\n");
+
+ uint32_t ebp = regs->ebp, eip = regs->eip;
+ int i = 0;
+ while (ebp >= K_HIGHHALF_ADDR && eip >= K_HIGHHALF_ADDR && i++ < 10) {
+ dbg_printf("| 0x%p EIP: 0x%p\n", ebp, eip);
+ uint32_t *d = (uint32_t*)ebp;
+ ebp = d[0];
+ eip = d[1];
+ }
+
+ dbg_printf("\\\n");
}
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/kernel/core/kmalloc.c b/src/kernel/core/kmalloc.c
index a8b115b..85e6173 100644
--- a/src/kernel/core/kmalloc.c
+++ b/src/kernel/core/kmalloc.c
@@ -9,7 +9,7 @@
#include <freemem.h>
static void* page_alloc_fun_for_kmalloc(size_t bytes) {
- void* addr = region_alloc(bytes, "Core kernel heap", pf_handler_unexpected);
+ void* addr = region_alloc(bytes, "Core kernel heap", 0);
if (addr == 0) return 0;
// Map physical memory
diff --git a/src/kernel/core/paging.c b/src/kernel/core/paging.c
index 38e8407..f2289bd 100644
--- a/src/kernel/core/paging.c
+++ b/src/kernel/core/paging.c
@@ -66,6 +66,7 @@ void page_fault_handler(registers_t *regs) {
if ((size_t)vaddr < PAGE_SIZE) {
dbg_printf("Null pointer dereference in kernel code (0x%p)\n", vaddr);
dbg_dump_registers(regs);
+ dbg_print_region_info();
PANIC("Null pointer dereference in kernel code.");
} else if ((size_t)vaddr < K_HIGHHALF_ADDR) {
if (pd->user_pfh == 0) {
@@ -108,7 +109,7 @@ void page_fault_handler(registers_t *regs) {
PANIC("Unhandled kernel space page fault");
}
if (i->pf == 0) {
- dbg_printf("Kernel pagefault in region with no handler at 0x%p\n", vaddr);
+ dbg_printf("Kernel pagefault in region with no handler at 0x%p (%s region)\n", vaddr, i->type);
dbg_dump_registers(regs);
dbg_print_region_info();
PANIC("Unhandled kernel space page fault");
diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c
index 58c92d3..74e5a30 100644
--- a/src/kernel/core/thread.c
+++ b/src/kernel/core/thread.c
@@ -157,7 +157,7 @@ thread_t *new_thread(entry_t entry, void* data) {
thread_t *t = (thread_t*)malloc(sizeof(thread_t));
if (t == 0) return 0;
- void* stack = region_alloc(KPROC_STACK_SIZE + PAGE_SIZE, "Stack", pf_handler_stackoverflow);
+ void* stack = region_alloc(KPROC_STACK_SIZE + PAGE_SIZE, "Stack", 0);
if (stack == 0) {
free(t);
return 0;
diff --git a/src/kernel/dev/pciide.c b/src/kernel/dev/pciide.c
index 7f321a7..600f08f 100644
--- a/src/kernel/dev/pciide.c
+++ b/src/kernel/dev/pciide.c
@@ -7,13 +7,13 @@
#include <dev/pci.h>
#include <dev/pciide.h>
-static void ide_register_device(ide_controller_t *c, uint8_t device, fs_t *iofs);
+void ide_register_device(ide_controller_t *c, uint8_t device, fs_t *iofs);
// ================================ //
// HELPER FUNCTIONS FOR PCI IDE I/O //
// ================================ //
-static void ide_write(ide_controller_t *c, uint8_t channel, uint8_t reg, uint8_t data) {
+void ide_write(ide_controller_t *c, uint8_t channel, uint8_t reg, uint8_t data) {
if (reg > 0x07 && reg < 0x0C) {
ide_write(c, channel, ATA_REG_CONTROL, 0x80 | c->channels[channel].nIEN);
}
@@ -31,7 +31,7 @@ static void ide_write(ide_controller_t *c, uint8_t channel, uint8_t reg, uint8_t
}
}
-static uint8_t ide_read(ide_controller_t *c, uint8_t channel, uint8_t reg) {
+uint8_t ide_read(ide_controller_t *c, uint8_t channel, uint8_t reg) {
uint8_t result = 0;
if (reg > 0x07 && reg < 0x0C) {
ide_write(c, channel, ATA_REG_CONTROL, 0x80 | c->channels[channel].nIEN);
@@ -51,7 +51,7 @@ static uint8_t ide_read(ide_controller_t *c, uint8_t channel, uint8_t reg) {
return result;
}
-static void ide_read_buffer(ide_controller_t *c, uint8_t channel, uint8_t reg, void* buffer, size_t quads) {
+void ide_read_buffer(ide_controller_t *c, uint8_t channel, uint8_t reg, void* buffer, size_t quads) {
if (reg > 0x07 && reg < 0x0C) {
ide_write(c, channel, ATA_REG_CONTROL, 0x80 | c->channels[channel].nIEN);
}
@@ -69,7 +69,7 @@ static void ide_read_buffer(ide_controller_t *c, uint8_t channel, uint8_t reg, v
}
}
-static int ide_polling(ide_controller_t *c, uint8_t channel, bool advanced_check) {
+int ide_polling(ide_controller_t *c, uint8_t channel, bool advanced_check) {
// (I) Delay 400 nanosecond for BSY to be set:
for(int i = 0; i < 4; i++)
ide_read(c, channel, ATA_REG_ALTSTATUS); // Reading the Alternate Status port wastes 100ns; loop four times.
@@ -96,7 +96,7 @@ static int ide_polling(ide_controller_t *c, uint8_t channel, bool advanced_check
return 0; // ok
}
-static uint8_t ide_print_error(ide_controller_t *c, int drive, uint8_t err) {
+uint8_t ide_print_error(ide_controller_t *c, int drive, uint8_t err) {
if (err == 0)
return err;
@@ -189,7 +189,7 @@ void pciirq_handler(int pci_id) {
}
}
-static void ide_prewait_irq(ide_controller_t *c, int channel) {
+void ide_prewait_irq(ide_controller_t *c, int channel) {
int irq = c->channels[channel].irq;
if (irq == 14) {
mutex_lock(&on_irq14);
@@ -203,7 +203,7 @@ static void ide_prewait_irq(ide_controller_t *c, int channel) {
}
}
-static bool ide_wait_irq(ide_controller_t *c, int channel) {
+bool ide_wait_irq(ide_controller_t *c, int channel) {
bool ret = true;
int st = enter_critical(CL_NOINT);
@@ -229,7 +229,7 @@ static bool ide_wait_irq(ide_controller_t *c, int channel) {
// ACTUAL READING AND WRITING OF SECTORS //
// ===================================== //
-static uint8_t ide_ata_access(ide_controller_t *c, int direction,
+uint8_t ide_ata_access(ide_controller_t *c, int direction,
uint8_t drive, uint32_t lba, uint8_t numsects, void* ptr)
{
uint32_t channel = c->devices[drive].channel; // Read the Channel.
@@ -362,7 +362,7 @@ static uint8_t ide_ata_access(ide_controller_t *c, int direction,
}
-static uint8_t ide_atapi_read(ide_controller_t *c, uint8_t drive, uint32_t lba,
+uint8_t ide_atapi_read(ide_controller_t *c, uint8_t drive, uint32_t lba,
uint8_t numsects, void* ptr)
{
uint32_t channel = c->devices[drive].channel;
@@ -442,7 +442,7 @@ must_terminate:
return 5;
}
-static uint8_t ide_read_sectors(ide_controller_t *c, uint8_t drive,
+uint8_t ide_read_sectors(ide_controller_t *c, uint8_t drive,
uint32_t lba, uint8_t numsects, void* ptr)
{
// 1: Check if the drive presents:
@@ -467,7 +467,7 @@ static uint8_t ide_read_sectors(ide_controller_t *c, uint8_t drive,
}
}
-static uint8_t ide_write_sectors(ide_controller_t *c, uint8_t drive,
+uint8_t ide_write_sectors(ide_controller_t *c, uint8_t drive,
uint8_t numsects, uint32_t lba, void* ptr)
{
// 1: Check if the drive presents:
@@ -493,7 +493,7 @@ static uint8_t ide_write_sectors(ide_controller_t *c, uint8_t drive,
// SETUP ROUTINES //
// ============== //
-static void ide_init(int pci_id, ide_controller_t *c, fs_t *iofs) {
+void ide_init(int pci_id, ide_controller_t *c, fs_t *iofs) {
pci_devices[pci_id].data = c;
c->pci_id = pci_id;
@@ -656,15 +656,15 @@ typedef struct {
uint8_t type;
} ide_vfs_dev_t;
-static bool ide_vfs_open(fs_node_ptr n, int mode);
-static bool ide_vfs_stat(fs_node_ptr n, stat_t *st);
+bool ide_vfs_open(fs_node_ptr n, int mode);
+bool ide_vfs_stat(fs_node_ptr n, stat_t *st);
-static size_t ide_vfs_read(fs_handle_t *f, size_t offset, size_t len, char* buf);
-static size_t ide_vfs_write(fs_handle_t *f, size_t offset, size_t len, const char* buf);
-static int ide_vfs_ioctl(fs_node_ptr f, int command, void* data);
-static void ide_vfs_close(fs_handle_t *f);
+size_t ide_vfs_read(fs_handle_t *f, size_t offset, size_t len, char* buf);
+size_t ide_vfs_write(fs_handle_t *f, size_t offset, size_t len, const char* buf);
+int ide_vfs_ioctl(fs_node_ptr f, int command, void* data);
+void ide_vfs_close(fs_handle_t *f);
-static fs_node_ops_t ide_vfs_node_ops = {
+fs_node_ops_t ide_vfs_node_ops = {
.open = ide_vfs_open,
.stat = ide_vfs_stat,
.walk = 0,
diff --git a/src/kernel/fs/iso9660.c b/src/kernel/fs/iso9660.c
index 9c9d31a..9fd8d0b 100644
--- a/src/kernel/fs/iso9660.c
+++ b/src/kernel/fs/iso9660.c
@@ -3,30 +3,31 @@
#include <fs/iso9660.h>
-static bool iso9660_make(fs_handle_t *source, const char* opts, fs_t *t);
-static void iso9660_fs_shutdown(fs_ptr f);
+bool iso9660_make(fs_handle_t *source, const char* opts, fs_t *t);
+void iso9660_fs_shutdown(fs_ptr f);
-static bool iso9660_node_stat(fs_node_ptr n, stat_t *st);
-static void iso9660_node_dispose(fs_node_ptr n);
-static void iso9660_node_close(fs_handle_t *h);
+bool iso9660_node_stat(fs_node_ptr n, stat_t *st);
+void iso9660_node_dispose(fs_node_t *n);
+void iso9660_node_close(fs_handle_t *h);
-static bool iso9660_dir_open(fs_node_ptr n, int mode);
-static bool iso9660_dir_walk(fs_node_ptr n, const char* file, struct fs_node *node_d);
-static bool iso9660_dir_readdir(fs_handle_t *h, size_t ent_no, dirent_t *d);
+bool iso9660_dir_open(fs_node_ptr n, int mode);
+bool iso9660_dir_walk(fs_node_t* n, const char* file, struct fs_node *node_d);
+bool iso9660_dir_readdir(fs_handle_t *h, size_t ent_no, dirent_t *d);
-static bool iso9660_file_open(fs_node_ptr n, int mode);
-static size_t iso9660_file_read(fs_handle_t *h, size_t offset, size_t len, char* buf);
+bool iso9660_file_open(fs_node_ptr n, int mode);
-static fs_driver_ops_t iso9660_driver_ops = {
+size_t iso9660_node_read(fs_node_t *n, size_t offset, size_t len, char* buf);
+
+fs_driver_ops_t iso9660_driver_ops = {
.make = iso9660_make,
};
-static fs_ops_t iso9660_fs_ops = {
+fs_ops_t iso9660_fs_ops = {
.add_source = 0,
.shutdown = iso9660_fs_shutdown
};
-static fs_node_ops_t iso9660_dir_ops = {
+fs_node_ops_t iso9660_dir_ops = {
.open = iso9660_dir_open,
.stat = iso9660_node_stat,
.walk = iso9660_dir_walk,
@@ -42,7 +43,7 @@ static fs_node_ops_t iso9660_dir_ops = {
.poll = 0,
};
-static fs_node_ops_t iso9660_file_ops = {
+fs_node_ops_t iso9660_file_ops = {
.open = iso9660_file_open,
.stat = iso9660_node_stat,
.dispose = iso9660_node_dispose,
@@ -52,12 +53,18 @@ static fs_node_ops_t iso9660_file_ops = {
.create = 0,
.readdir = 0,
.close = iso9660_node_close,
- .read = iso9660_file_read,
+ .read = fs_read_from_pager,
.write = 0,
.ioctl = 0,
.poll = 0,
};
+vfs_pager_ops_t iso9660_pager_ops = {
+ .read = iso9660_node_read,
+ .write = 0,
+ .resize = 0,
+};
+
void register_iso9660_driver() {
ASSERT(sizeof(iso9660_dr_date_t) == 7);
ASSERT(sizeof(iso9660_dr_t) == 34);
@@ -93,10 +100,7 @@ bool iso9660_make(fs_handle_t *source, const char* opts, fs_t *t) {
if (fs == 0) return false;
iso9660_node_t *root = (iso9660_node_t*)malloc(sizeof(iso9660_node_t));
- if (root == 0) {
- free(fs);
- return false;
- }
+ if (root == 0) goto error;
memcpy(&fs->vol_descr, &ent.prim, sizeof(iso9660_pvd_t));
fs->disk = source;
@@ -110,8 +114,14 @@ bool iso9660_make(fs_handle_t *source, const char* opts, fs_t *t) {
t->root->data = root;
t->root->ops = &iso9660_dir_ops;
+ t->root->pager = new_vfs_pager(root->dr.size.lsb, t->root, &iso9660_pager_ops);
+
+ return true;
- return true; // TODO
+error:
+ if (root) free(root);
+ if (fs) free(fs);
+ return false;
}
void iso9660_fs_shutdown(fs_ptr f) {
@@ -139,7 +149,7 @@ static void dr_stat(iso9660_dr_t *dr, stat_t *st) {
st->size = dr->size.lsb; // TODO: precise item count ?
} else {
st->type = FT_REGULAR;
- st->access = FM_READ;
+ st->access = FM_READ | FM_MMAP;
st->size = dr->size.lsb;
}
}
@@ -153,8 +163,11 @@ bool iso9660_node_stat(fs_node_ptr n, stat_t *st) {
return true;
}
-void iso9660_node_dispose(fs_node_ptr n) {
- iso9660_node_t *node = (iso9660_node_t*)n;
+void iso9660_node_dispose(fs_node_t *n) {
+ ASSERT(n->pager != 0);
+ delete_pager(n->pager);
+
+ iso9660_node_t *node = (iso9660_node_t*)n->data;
free(node);
}
@@ -168,22 +181,25 @@ bool iso9660_dir_open(fs_node_ptr n, int mode) {
return true;
}
-bool iso9660_dir_walk(fs_node_ptr n, const char* search_for, struct fs_node *node_d) {
- iso9660_node_t *node = (iso9660_node_t*)n;
+bool iso9660_dir_walk(fs_node_t *n, const char* search_for, struct fs_node *node_d) {
+ iso9660_node_t *node = (iso9660_node_t*)n->data;
size_t filename_len = strlen(search_for);
dbg_printf("Looking up %s...\n", search_for);
- char buffer[2048];
size_t dr_len = 0;
for (size_t pos = 0; pos < node->dr.size.lsb; pos += dr_len) {
- if (pos % 2048 == 0) {
- if (file_read(node->fs->disk, node->dr.lba_loc.lsb * 2048 + pos, 2048, buffer) != 2048)
- return false;
- }
+ union {
+ iso9660_dr_t dr;
+ char buf[256];
+ } data;
+
+ size_t rs = pager_read(n->pager, pos, 256, data.buf);
+ if (rs < sizeof(iso9660_dr_t)) return false;
+
+ iso9660_dr_t *dr = &data.dr;
- iso9660_dr_t *dr = (iso9660_dr_t*)(buffer + (pos % 2048));
dr_len = dr->len;
if (dr_len == 0) return false;
@@ -210,6 +226,12 @@ bool iso9660_dir_walk(fs_node_ptr n, const char* search_for, struct fs_node *nod
node_d->ops = &iso9660_file_ops;
}
+ node_d->pager = new_vfs_pager(dr->size.lsb, node_d, &iso9660_pager_ops);
+ if (node_d->pager == 0) {
+ free(n);
+ return false;
+ }
+
return true;
}
}
@@ -217,44 +239,45 @@ bool iso9660_dir_walk(fs_node_ptr n, const char* search_for, struct fs_node *nod
}
bool iso9660_file_open(fs_node_ptr n, int mode) {
- if (mode != FM_READ) return false;
+ int ok_modes = FM_READ | FM_MMAP;
+
+ if (mode & ~ok_modes) return false;
return true;
}
-size_t iso9660_file_read(fs_handle_t *h, size_t offset, size_t len, char* buf) {
- iso9660_node_t *node = (iso9660_node_t*)h->node->data;
+size_t iso9660_node_read(fs_node_t *n, size_t offset, size_t len, char* buf) {
+ iso9660_node_t *node = (iso9660_node_t*)n->data;
if (offset >= node->dr.size.lsb) return 0;
- if (offset + len > node->dr.size.lsb) len = node->dr.size.lsb - offset;
+ if (offset + len > node->dr.size.lsb) len = node->dr.size.lsb - offset;
- size_t ret = 0;
+ ASSERT(offset % 2048 == 0);
- const size_t off0 = offset % 2048;
- const size_t first_block = offset - off0;
+ size_t ret = 0;
- char buffer[2048];
+ for (size_t i = offset; i < offset + len; i += 2048) {
+ size_t stor_pos = node->dr.lba_loc.lsb * 2048 + i;
- for (size_t i = first_block; i < offset + len; i += 2048) {
- if (file_read(node->fs->disk, node->dr.lba_loc.lsb * 2048 + i, 2048, buffer) != 2048) {
- dbg_printf("Could not read data at %d\n", i);
- break;
- }
+ size_t blk_len = 2048;
+ if (i + blk_len > offset + len) blk_len = offset + len - i;
- size_t block_pos;
- size_t block_buf_ofs;
- if (i <= offset) {
- block_pos = 0;
- block_buf_ofs = off0;
+ if (blk_len == 2048) {
+ if (file_read(node->fs->disk, stor_pos, 2048, buf + i - offset) != 2048) break;
+ ret += 2048;
} else {
- block_pos = i - offset - off0;
- block_buf_ofs = 0;
- }
- size_t block_buf_end = (i + 2048 > offset + len ? offset + len - i : 2048);
- size_t block_len = block_buf_end - block_buf_ofs;
+ char *block_buf = (void*)malloc(2048);
+ if (block_buf == 0) break;
+
+ size_t read = file_read(node->fs->disk, stor_pos, 2048, block_buf);
+
+ if (read == 2048) {
+ memcpy(buf + i - offset, block_buf, blk_len);
+ ret += blk_len;
+ }
- memcpy(buf + block_pos, buffer + block_buf_ofs, block_len);
- ret += block_len;
+ free(block_buf);
+ }
}
return ret;
@@ -265,20 +288,21 @@ void iso9660_file_close(fs_node_ptr f) {
}
bool iso9660_dir_readdir(fs_handle_t *h, size_t ent_no, dirent_t *d) {
- // TODO : Very nonefficient !!
-
iso9660_node_t *node = (iso9660_node_t*)h->node->data;
- char buffer[2048];
size_t dr_len = 0;
size_t idx = 0;
for (size_t pos = 0; pos < node->dr.size.lsb; pos += dr_len) {
- if (pos % 2048 == 0) {
- if (file_read(node->fs->disk, node->dr.lba_loc.lsb * 2048 + pos, 2048, buffer) != 2048)
- return false;
- }
+ union {
+ iso9660_dr_t dr;
+ char buf[256];
+ } data;
+
+ size_t rs = pager_read(h->node->pager, pos, 256, data.buf);
+ if (rs < sizeof(iso9660_dr_t)) return false;
+
+ iso9660_dr_t *dr = &data.dr;
- iso9660_dr_t *dr = (iso9660_dr_t*)(buffer + (pos % 2048));
dr_len = dr->len;
if (dr_len == 0) return false;
diff --git a/src/kernel/include/pager.h b/src/kernel/include/pager.h
index 7ef8b6c..7f93b8c 100644
--- a/src/kernel/include/pager.h
+++ b/src/kernel/include/pager.h
@@ -33,8 +33,8 @@ typedef struct pager {
union {
struct {
- fs_node_t* vfs_data;
- vfs_pager_ops_t *vfs_ops;
+ fs_node_t* node;
+ vfs_pager_ops_t *ops;
} vfs_pager;
struct {
size_t phys_offset;
diff --git a/src/kernel/include/region.h b/src/kernel/include/region.h
index d5cba2d..eb6f7e8 100644
--- a/src/kernel/include/region.h
+++ b/src/kernel/include/region.h
@@ -24,8 +24,8 @@ region_info_t *find_region(void* addr);
void region_free(void* addr);
// some usefull PF handlers
-void pf_handler_unexpected(pagedir_t *pd, struct region_info *r, void* addr); // Expects never to be called
-void pf_handler_stackoverflow(pagedir_t *pd, struct region_info *r, void* addr); // Stack overflow detected
+// void pf_handler_unexpected(pagedir_t *pd, struct region_info *r, void* addr); // Expects never to be called
+// void pf_handler_stackoverflow(pagedir_t *pd, struct region_info *r, void* addr); // Stack overflow detected
// some functions for freeing regions and frames
// region_free_unmap_free : deletes a region and frees all frames that were mapped in it
diff --git a/src/kernel/include/vfs.h b/src/kernel/include/vfs.h
index cdd9e8d..2d50c9a 100644
--- a/src/kernel/include/vfs.h
+++ b/src/kernel/include/vfs.h
@@ -90,11 +90,11 @@ typedef struct fs_node_ops {
bool (*stat)(fs_node_ptr n, stat_t *st);
int (*ioctl)(fs_node_ptr f, int command, void* data);
- bool (*walk)(fs_node_ptr n, const char* file, struct fs_node *node_d);
+ bool (*walk)(fs_node_t *n, const char* file, struct fs_node *node_d);
bool (*delete)(fs_node_ptr n, const char* file);
bool (*move)(fs_node_ptr dir, const char* old_name, struct fs_node *new_parent, const char *new_name);
bool (*create)(fs_node_ptr n, const char* name, int type); // create sub-node in directory
- void (*dispose)(fs_node_ptr n);
+ void (*dispose)(fs_node_t *n);
} fs_node_ops_t;
typedef struct fs_node {
diff --git a/src/kernel/user/ipc.c b/src/kernel/user/ipc.c
index ff4d5c8..a8362ea 100644
--- a/src/kernel/user/ipc.c
+++ b/src/kernel/user/ipc.c
@@ -15,7 +15,7 @@ static int channel_poll(fs_handle_t *c, void** out_wait_obj);
static bool channel_open(fs_node_ptr c, int mode);
static bool channel_stat(fs_node_ptr c, stat_t *st);
static void channel_close(fs_handle_t *c);
-static void channel_dispose(fs_node_ptr c);
+static void channel_dispose(fs_node_t *c);
static fs_node_ops_t channel_ops = {
.read = channel_read,
@@ -214,8 +214,8 @@ void channel_close(fs_handle_t *ch) {
// do nothing
}
-void channel_dispose(fs_node_ptr ch) {
- channel_t *c = (channel_t*)ch;
+void channel_dispose(fs_node_t *n) {
+ channel_t *c = (channel_t*)n->data;
mutex_lock(&c->lock);
diff --git a/src/kernel/user/nullfs.c b/src/kernel/user/nullfs.c
index fa6a088..d4f345f 100644
--- a/src/kernel/user/nullfs.c
+++ b/src/kernel/user/nullfs.c
@@ -15,18 +15,18 @@ static void nullfs_fs_shutdown(fs_ptr fs);
// nullfs directory node
static bool nullfs_d_open(fs_node_ptr n, int mode);
static bool nullfs_d_stat(fs_node_ptr n, stat_t *st);
-static bool nullfs_d_walk(fs_node_ptr n, const char* file, struct fs_node *node_d);
+static bool nullfs_d_walk(fs_node_t *n, const char* file, struct fs_node *node_d);
static bool nullfs_d_delete(fs_node_ptr n, const char* file);
static bool nullfs_d_move(fs_node_ptr n, const char* old_name, fs_node_t *new_parent, const char *new_name);
static bool nullfs_d_create(fs_node_ptr n, const char* file, int type);
-static void nullfs_d_dispose(fs_node_ptr n);
+static void nullfs_d_dispose(fs_node_t *n);
static bool nullfs_d_readdir(fs_handle_t *f, size_t ent_no, dirent_t *d);
static void nullfs_d_close(fs_handle_t *f);
// nullfs ram file node
static bool nullfs_f_open(fs_node_ptr n, int mode);
static bool nullfs_f_stat(fs_node_ptr n, stat_t *st);
-static void nullfs_f_dispose(fs_node_ptr n);
+static void nullfs_f_dispose(fs_node_t *n);
static size_t nullfs_f_read(fs_handle_t *f, size_t offset, size_t len, char* buf);
static size_t nullfs_f_write(fs_handle_t *f, size_t offset, size_t len, const char* buf);
static void nullfs_f_close(fs_handle_t *f);
@@ -250,8 +250,8 @@ bool nullfs_d_stat(fs_node_ptr n, stat_t *st) {
return true;
}
-bool nullfs_d_walk(fs_node_ptr n, const char* file, struct fs_node *node_d) {
- nullfs_dir_t* d = (nullfs_dir_t*)n;
+bool nullfs_d_walk(fs_node_t *n, const char* file, struct fs_node *node_d) {
+ nullfs_dir_t* d = (nullfs_dir_t*)n->data;
mutex_lock(&d->lock);
@@ -415,7 +415,7 @@ bool nullfs_d_create(fs_node_ptr n, const char* file, int type) {
}
}
-void nullfs_d_dispose(fs_node_ptr n) {
+void nullfs_d_dispose(fs_node_t *n) {
// nothing to do
}
@@ -486,7 +486,7 @@ bool nullfs_f_stat(fs_node_ptr n, stat_t *st) {
return true;
}
-void nullfs_f_dispose(fs_node_ptr n) {
+void nullfs_f_dispose(fs_node_t *n) {
// nothing to do
}
diff --git a/src/kernel/user/pager.c b/src/kernel/user/pager.c
index f03e45b..b1ce9c3 100644
--- a/src/kernel/user/pager.c
+++ b/src/kernel/user/pager.c
@@ -12,17 +12,17 @@
// SWAP PAGER //
// ========== //
-static void swap_page_in(pager_t *p, size_t offset, size_t len);
-static void swap_page_out(pager_t *p, size_t offset, size_t len);
-static void swap_page_release(pager_t *p, size_t offset, size_t len);
-static bool swap_resize(pager_t *p, size_t new_size);
+void swap_page_in(pager_t *p, size_t offset, size_t len);
+void swap_page_out(pager_t *p, size_t offset, size_t len);
+void swap_page_release(pager_t *p, size_t offset, size_t len);
+bool swap_pager_resize(pager_t *p, size_t new_size);
-static pager_ops_t swap_pager_ops = {
+pager_ops_t swap_pager_ops = {
.page_in = swap_page_in,
.page_commit = 0,
.page_out = swap_page_out,
.page_release = swap_page_release,
- .resize = swap_resize,
+ .resize = swap_pager_resize,
};
pager_t *new_swap_pager(size_t size) {
@@ -53,14 +53,15 @@ void swap_page_in(pager_t *p, size_t offset, size_t len) {
for (size_t page = offset; page < offset + len; page += PAGE_SIZE) {
if (hashtbl_find(p->pages, (void*)page) == 0) {
uint32_t frame = frame_alloc(1);
- if (frame != 0) {
- if (!pd_map_page(region, frame, true)) PANIC("TODO");;
- memset(region, 0, PAGE_SIZE);
- pd_unmap_page(region);
- }
- if (!hashtbl_add(p->pages, (void*)page, (void*)(frame << ENT_FRAME_SHIFT))) {
- frame_free(frame, 1);
- }
+
+ if (frame == 0) continue;
+ if (!pd_map_page(region, frame, true)) continue;
+
+ memset(region, 0, PAGE_SIZE);
+ pd_unmap_page(region);
+
+ bool ok = hashtbl_add(p->pages, (void*)page, (void*)(frame << ENT_FRAME_SHIFT));
+ if (!ok) frame_free(frame, 1);
}
}
@@ -83,7 +84,7 @@ void swap_page_release(pager_t *p, size_t offset, size_t len) {
}
}
-bool swap_resize(pager_t *p, size_t new_size) {
+bool swap_pager_resize(pager_t *p, size_t new_size) {
// later : remove unused pages in swap file
swap_page_release(p, PAGE_ALIGN_UP(new_size), p->size - PAGE_ALIGN_UP(new_size));
@@ -110,13 +111,105 @@ bool swap_resize(pager_t *p, size_t new_size) {
return true;
}
+// ========= //
+// VFS PAGER //
+// ========= //
+
+void vfs_page_in(pager_t *p, size_t offset, size_t len);
+void vfs_page_commit(pager_t *p, size_t offset, size_t len);
+void vfs_page_out(pager_t *p, size_t offset, size_t len);
+void vfs_page_release(pager_t *p, size_t offset, size_t len);
+bool vfs_pager_resize(pager_t *p, size_t new_size);
+
+pager_ops_t vfs_pager_ops = {
+ .page_in = vfs_page_in,
+ .page_commit = vfs_page_commit,
+ .page_out = vfs_page_out,
+ .page_release = vfs_page_release,
+ .resize = vfs_pager_resize,
+};
+
+pager_t *new_vfs_pager(size_t size, fs_node_t *vfs_node, vfs_pager_ops_t *vfs_ops) {
+ pager_t *p = (pager_t*)malloc(sizeof(pager_t));
+ if (p == 0) return 0;
+
+ p->pages = create_hashtbl(id_key_eq_fun, id_hash_fun, 0);
+ if (p->pages == 0) goto error;
+
+ p->ops = &vfs_pager_ops;
+ p->size = size;
+ p->lock = MUTEX_UNLOCKED;
+ p->maps = 0;
+ p->vfs_pager.node = vfs_node;
+ p->vfs_pager.ops = vfs_ops;
+
+ return p;
+
+error:
+ if (p) free(p);
+ return 0;
+}
+
+void vfs_page_in(pager_t *p, size_t offset, size_t len) {
+ ASSERT(PAGE_ALIGNED(offset));
+ ASSERT(p->vfs_pager.ops->read != 0);
+
+ void *region = region_alloc(PAGE_SIZE, "Page loading area", 0);
+ if (region == 0) return;
+
+ for (size_t page = offset; page < offset + len; page += PAGE_SIZE) {
+ if (hashtbl_find(p->pages, (void*)page) == 0) {
+ bool ok = false;
+ uint32_t frame = frame_alloc(1);
+
+ if (frame == 0) continue;
+ if (!pd_map_page(region, frame, true)) goto end;
+
+ size_t expect_len = PAGE_SIZE;
+ if (page + expect_len > p->size) {
+ expect_len = p->size - page;
+ memset(region + expect_len, 0, PAGE_SIZE - expect_len);
+ }
+
+ size_t read_len = p->vfs_pager.ops->read(p->vfs_pager.node, page, expect_len, (char*)region);
+ pd_unmap_page(region);
+
+ if (read_len != expect_len) goto end;
+
+ ok = hashtbl_add(p->pages, (void*)page, (void*)(frame << ENT_FRAME_SHIFT));
+
+ end:
+ if (!ok) frame_free(frame, 1);
+ }
+ }
+
+ region_free(region);
+}
+
+void vfs_page_commit(pager_t *p, size_t offset, size_t len) {
+ // TODO
+}
+
+void vfs_page_out(pager_t *p, size_t offset, size_t len) {
+ // TODO
+}
+
+void vfs_page_release(pager_t *p, size_t offset, size_t len) {
+ // TODO
+}
+
+bool vfs_pager_resize(pager_t *p, size_t new_size) {
+ // TODO
+ return false;
+}
+
// ============ //
// DEVICE PAGER //
// ============ //
-static void device_page_in(pager_t *p, size_t offset, size_t len);
+void device_page_in(pager_t *p, size_t offset, size_t len);
-static pager_ops_t device_pager_ops = {
+pager_ops_t device_pager_ops = {
.page_in = device_page_in,
.page_commit = 0,
.page_out = 0,
@@ -227,7 +320,7 @@ int pager_get_frame(pager_t *p, size_t offset) {
return ret;
}
-static size_t pager_do_rw(pager_t *p, size_t offset, size_t len, char* buf, bool write) {
+size_t pager_do_rw(pager_t *p, size_t offset, size_t len, char* buf, bool write) {
size_t ret = 0;
void* region = 0;
diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c
index 7433517..d8f1eed 100644
--- a/src/kernel/user/process.c
+++ b/src/kernel/user/process.c
@@ -9,8 +9,8 @@
static int next_pid = 1;
-static void proc_user_exception(registers_t *regs);
-static void proc_usermem_pf(void* proc, registers_t *regs, void* addr);
+void proc_user_exception(registers_t *regs);
+void proc_usermem_pf(void* proc, registers_t *regs, void* addr);
process_t *current_process() {
if (current_thread) return current_thread->proc;
@@ -661,12 +661,12 @@ void dbg_dump_proc_memmap(process_t *proc) {
// USER MEMORY PAGE FAULT HANDLERS //
// =============================== //
-static void proc_user_exception(registers_t *regs) {
+void proc_user_exception(registers_t *regs) {
dbg_printf("Usermode exception in user process : exiting.\n");
dbg_dump_registers(regs);
current_process_exit(PS_FAILURE, FAIL_EXCEPTION);
}
-static void proc_usermem_pf(void* p, registers_t *regs, void* addr) {
+void proc_usermem_pf(void* p, registers_t *regs, void* addr) {
process_t *proc = (process_t*)p;
user_region_t *r = find_user_region(proc, addr);
diff --git a/src/kernel/user/vfs.c b/src/kernel/user/vfs.c
index 1fa1cc2..66ede94 100644
--- a/src/kernel/user/vfs.c
+++ b/src/kernel/user/vfs.c
@@ -101,7 +101,7 @@ void unref_fs(fs_t *fs) {
unref_fs_node(fs->root);
} else {
ASSERT(fs->root->refs == 1);
- if (fs->root->ops->dispose) fs->root->ops->dispose(fs->root->data);
+ if (fs->root->ops->dispose) fs->root->ops->dispose(fs->root);
}
if (fs->ops->shutdown) fs->ops->shutdown(fs->data);
free(fs);
@@ -130,7 +130,7 @@ void unref_fs_node(fs_node_t *n) {
mutex_lock(&n->parent->lock);
hashtbl_remove(n->parent->children, n->name);
- if (n->ops->dispose) n->ops->dispose(n->data);
+ if (n->ops->dispose) n->ops->dispose(n);
mutex_unlock(&n->parent->lock);
unref_fs_node(n->parent);
@@ -144,7 +144,7 @@ void unref_fs_node(fs_node_t *n) {
// stand-alone IPC/SHM object
ASSERT(n->parent == 0 && n->children == 0);
- if (n->ops->dispose) n->ops->dispose(n->data);
+ if (n->ops->dispose) n->ops->dispose(n);
}
if (n->name) free(n->name);
free(n);
@@ -178,7 +178,7 @@ fs_node_t* fs_walk_one(fs_node_t* from, const char* file) {
n->name = strdup(file);
if (n->name == 0) goto error;
- walk_ok = from->ops->walk && from->ops->walk(from->data, file, n);
+ walk_ok = from->ops->walk && from->ops->walk(from, file, n);
if (!walk_ok) goto error;
if (from->children == 0) {
@@ -197,7 +197,7 @@ fs_node_t* fs_walk_one(fs_node_t* from, const char* file) {
return n;
error:
- if (walk_ok) n->ops->dispose(n->data);
+ if (walk_ok) n->ops->dispose(n);
if (n != 0 && n->name != 0) free(n->name);
if (n != 0) free(n);
mutex_unlock(&from->lock);