From 70b3d70133936c2a61c1360882ccbd9396243e66 Mon Sep 17 00:00:00 2001 From: apio Date: Sun, 30 Oct 2022 21:30:49 +0100 Subject: [PATCH 1/3] Initial TmpFS work --- kernel/include/fs/TmpFS.h | 51 ++++++++++++++++++++ kernel/src/fs/TmpFS.cpp | 99 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 kernel/include/fs/TmpFS.h create mode 100644 kernel/src/fs/TmpFS.cpp diff --git a/kernel/include/fs/TmpFS.h b/kernel/include/fs/TmpFS.h new file mode 100644 index 00000000..2a4bea96 --- /dev/null +++ b/kernel/include/fs/TmpFS.h @@ -0,0 +1,51 @@ +#pragma once +#include "fs/VFS.h" + +namespace TmpFSImpl +{ + ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer); + ssize_t write(VFS::Node* node, size_t offset, size_t size, char* buffer); +} + +class TmpFS +{ + public: + VFS::Node* root() + { + return m_root; + } + + static TmpFS* create(const char* name); + static void release(TmpFS* fs); + + ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer); + ssize_t write(VFS::Node* node, size_t offset, size_t size, char* buffer); + + void purge(); + + private: + struct File + { + char* buf; + size_t len; + int valid; + }; + + struct Directory + { + VFS::Node* buf; + size_t len; + int valid; + }; + + template struct Array + { + T* buf; + size_t len; + }; + + TmpFS(const char* name); + Array m_files; + Array m_dirs; + VFS::Node* m_root; +}; \ No newline at end of file diff --git a/kernel/src/fs/TmpFS.cpp b/kernel/src/fs/TmpFS.cpp new file mode 100644 index 00000000..2ad64036 --- /dev/null +++ b/kernel/src/fs/TmpFS.cpp @@ -0,0 +1,99 @@ +#include "fs/TmpFS.h" +#include "std/stdlib.h" +#include "std/string.h" + +ssize_t TmpFSImpl::read(VFS::Node* node, size_t offset, size_t size, char* buffer) +{ + if (!node) return -1; + if (!node->impl) return -1; + return ((TmpFS*)node->impl)->read(node, offset, size, buffer); +} + +ssize_t TmpFSImpl::write(VFS::Node* node, size_t offset, size_t size, char* buffer) +{ + if (!node) return -1; + if (!node->impl) return -1; + return ((TmpFS*)node->impl)->write(node, offset, size, buffer); +} + +TmpFS* TmpFS::create(const char* name) +{ + return new TmpFS(name); +} + +void TmpFS::release(TmpFS* fs) +{ + fs->purge(); + kfree(fs->m_dirs.buf); + delete fs->root(); + delete fs; +} + +extern uint64_t clock_now(); + +TmpFS::TmpFS(const char* name) +{ + m_root = new VFS::Node; + m_root->atime = m_root->ctime = m_root->mtime = clock_now(); + m_root->impl = (uint64_t)this; + m_root->inode = 0; + m_root->gid = m_root->uid = 0; + m_root->mode = 0755; + m_root->length = 0; + m_root->type = VFS_DIRECTORY; + m_root->tty = 0; + strlcpy(m_root->name, name, sizeof(m_root->name)); + m_dirs.buf = (Directory*)krealloc(nullptr, sizeof(Directory)); + m_dirs.len = 1; + m_dirs.buf[0] = {nullptr, 0, 1}; +} + +void TmpFS::purge() +{ + for (size_t i = 0; i < m_dirs.len; i++) + { + if (m_dirs.buf[i].valid && m_dirs.buf[i].len) kfree(m_dirs.buf[i].buf); + } + + m_dirs.buf = (Directory*)krealloc(m_dirs.buf, sizeof(Directory)); // leave space for the root directory + + for (size_t i = 0; i < m_files.len; i++) + { + if (m_files.buf[i].valid && m_files.buf[i].len) kfree(m_files.buf[i].buf); + } + + kfree(m_files.buf); +} + +ssize_t TmpFS::read(VFS::Node* node, size_t offset, size_t size, char* buffer) +{ + if (!node) return -1; + if (node->inode >= m_files.len) return -1; + File& file = m_files.buf[node->inode]; + if (!file.valid) return -1; + if (offset > file.len) return 0; + if (offset + size > file.len) { size = file.len - offset; } + memcpy(buffer, (void*)(file.buf + offset), size); + return size; +} + +ssize_t TmpFS::write(VFS::Node* node, size_t offset, size_t size, char* buffer) +{ + if (!node) return -1; + if (node->inode >= m_files.len) return -1; + File& file = m_files.buf[node->inode]; + if (!file.valid) return -1; + if (offset + size > file.len) + { + char* newbuf = (char*)krealloc(file.buf, offset + size); + if (!newbuf) { size = file.len - offset; } + else + { + file.buf = newbuf; + file.len = offset + size; + node->length = file.len; + } + } + memcpy((void*)(file.buf + offset), buffer, size); + return size; +} \ No newline at end of file -- 2.34.1 From bc48b64ec66ec0afd62407300e32308a229905eb Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 31 Oct 2022 09:53:37 +0100 Subject: [PATCH 2/3] More tmpfs stuff but mkdir corrupts the system --- kernel/include/fs/TmpFS.h | 8 +++ kernel/src/fs/TmpFS.cpp | 108 ++++++++++++++++++++++++++++++++ kernel/src/fs/VFS.cpp | 22 ++++--- kernel/src/main.cpp | 3 + kernel/src/thread/Scheduler.cpp | 1 + 5 files changed, 135 insertions(+), 7 deletions(-) diff --git a/kernel/include/fs/TmpFS.h b/kernel/include/fs/TmpFS.h index 2a4bea96..4411389e 100644 --- a/kernel/include/fs/TmpFS.h +++ b/kernel/include/fs/TmpFS.h @@ -5,6 +5,9 @@ namespace TmpFSImpl { ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer); ssize_t write(VFS::Node* node, size_t offset, size_t size, char* buffer); + VFS::Node* find(VFS::Node* node, const char* filename); + VFS::Node* readdir(VFS::Node* node, long index); + int mkdir(VFS::Node* node, const char* filename, mode_t mode); } class TmpFS @@ -21,6 +24,11 @@ class TmpFS ssize_t read(VFS::Node* node, size_t offset, size_t size, char* buffer); ssize_t write(VFS::Node* node, size_t offset, size_t size, char* buffer); + VFS::Node* find(VFS::Node* node, const char* filename); + VFS::Node* readdir(VFS::Node* node, long index); + + int mkdir(VFS::Node* node, const char* filename, mode_t mode); + void purge(); private: diff --git a/kernel/src/fs/TmpFS.cpp b/kernel/src/fs/TmpFS.cpp index 2ad64036..e6567d02 100644 --- a/kernel/src/fs/TmpFS.cpp +++ b/kernel/src/fs/TmpFS.cpp @@ -1,4 +1,8 @@ +#define MODULE "tmpfs" + #include "fs/TmpFS.h" +#include "log/Log.h" +#include "std/errno.h" #include "std/stdlib.h" #include "std/string.h" @@ -16,6 +20,27 @@ ssize_t TmpFSImpl::write(VFS::Node* node, size_t offset, size_t size, char* buff return ((TmpFS*)node->impl)->write(node, offset, size, buffer); } +VFS::Node* TmpFSImpl::find(VFS::Node* node, const char* filename) +{ + if (!node) return 0; + if (!node->impl) return 0; + return ((TmpFS*)node->impl)->find(node, filename); +} + +VFS::Node* TmpFSImpl::readdir(VFS::Node* node, long index) +{ + if (!node) return 0; + if (!node->impl) return 0; + return ((TmpFS*)node->impl)->readdir(node, index); +} + +int TmpFSImpl::mkdir(VFS::Node* node, const char* filename, mode_t mode) +{ + if (!node) return -1; + if (!node->impl) return -1; + return ((TmpFS*)node->impl)->mkdir(node, filename, mode); +} + TmpFS* TmpFS::create(const char* name) { return new TmpFS(name); @@ -42,6 +67,10 @@ TmpFS::TmpFS(const char* name) m_root->length = 0; m_root->type = VFS_DIRECTORY; m_root->tty = 0; + m_root->readdir_func = TmpFSImpl::readdir; + m_root->find_func = TmpFSImpl::find; + m_root->mkdir_func = TmpFSImpl::mkdir; + m_root->flags = 0; strlcpy(m_root->name, name, sizeof(m_root->name)); m_dirs.buf = (Directory*)krealloc(nullptr, sizeof(Directory)); m_dirs.len = 1; @@ -96,4 +125,83 @@ ssize_t TmpFS::write(VFS::Node* node, size_t offset, size_t size, char* buffer) } memcpy((void*)(file.buf + offset), buffer, size); return size; +} + +VFS::Node* TmpFS::find(VFS::Node* node, const char* filename) +{ + if (!node) return 0; + if (node->inode >= m_dirs.len) return 0; + Directory& dir = m_dirs.buf[node->inode]; + if (!dir.valid) return 0; + for (size_t i = 0; i < dir.len; i++) + { + if (!strncmp(dir.buf[i].name, filename, sizeof(dir.buf[i].name))) { return &dir.buf[i]; } + } + return 0; +} + +VFS::Node* TmpFS::readdir(VFS::Node* node, long index) +{ + if (!node) return 0; + if (node->inode >= m_dirs.len) return 0; + Directory& dir = m_dirs.buf[node->inode]; + if (!dir.valid) return 0; + if (index >= (long)dir.len) return 0; + return &dir.buf[index]; +} + +int TmpFS::mkdir(VFS::Node* node, const char* filename, mode_t mode) +{ + kinfoln("starting to create directory %s in %s", filename, node->name); + + if (!node) return 0; + if (node->inode >= m_dirs.len) return 0; + Directory& dir = m_dirs.buf[node->inode]; + if (!dir.valid) return 0; + + kinfoln("creating directory %s in %s", filename, node->name); + + size_t new_len = m_dirs.len + 1; + Directory* new_buf = (Directory*)krealloc(m_dirs.buf, new_len); + if (!new_buf) return -ENOMEM; + + m_dirs.len = new_len; + m_dirs.buf = new_buf; + + uint64_t new_inode = m_dirs.len - 1; + + m_dirs.buf[new_inode].valid = 0; + + size_t new_dir_len = dir.len + 1; + VFS::Node* new_dir_buf = (VFS::Node*)krealloc(dir.buf, new_dir_len); + if (!new_dir_buf) return -ENOMEM; + + m_dirs.buf[new_inode].valid = 1; + m_dirs.buf[new_inode].len = 0; + m_dirs.buf[new_inode].buf = nullptr; + + dir.buf = new_dir_buf; + dir.len = new_dir_len; + + node->mtime = clock_now(); + node->ctime = clock_now(); + node->length++; + + VFS::Node* new_node = &dir.buf[dir.len - 1]; + + new_node->inode = new_inode; + new_node->atime = new_node->ctime = new_node->mtime = clock_now(); + new_node->impl = (uint64_t)this; + new_node->gid = new_node->uid = 0; + new_node->mode = mode; + new_node->length = 0; + new_node->type = VFS_DIRECTORY; + new_node->tty = 0; + new_node->readdir_func = TmpFSImpl::readdir; + new_node->find_func = TmpFSImpl::find; + new_node->mkdir_func = TmpFSImpl::mkdir; + new_node->flags = 0; + strlcpy(new_node->name, filename, sizeof(new_node->name)); + + return 0; } \ No newline at end of file diff --git a/kernel/src/fs/VFS.cpp b/kernel/src/fs/VFS.cpp index ef0deae2..0a61980a 100644 --- a/kernel/src/fs/VFS.cpp +++ b/kernel/src/fs/VFS.cpp @@ -25,12 +25,12 @@ ssize_t VFS::read(Node* node, size_t offset, size_t length, char* buffer) } if (node->type == VFS_DIRECTORY) { - kwarnln("read() failed: is a directory"); + kwarnln("read() failed for %s: is a directory", node->name); return -EISDIR; } if (!node->read_func) { - kwarnln("read() failed: the chosen node doesn't support reading"); + kwarnln("read() failed for %s: the chosen node doesn't support reading", node->name); return -1; } @@ -46,12 +46,12 @@ ssize_t VFS::write(Node* node, size_t offset, size_t length, const char* buffer) } if (node->type == VFS_DIRECTORY) { - kwarnln("write() failed: is a directory"); + kwarnln("write() failed for %s: is a directory", node->name); return -EISDIR; } if (!node->write_func) { - kwarnln("write() failed: the chosen node doesn't support writing"); + kwarnln("write() failed for %s: the chosen node doesn't support writing", node->name); return -1; } @@ -107,7 +107,7 @@ VFS::Node* VFS::resolve_path(const char* filename, Node* root) buffer[path_section_size] = 0; if (!current_node->find_func) { - kwarnln("Current node has no way to find child nodes"); + kwarnln("Current node %s has no way to find child nodes", current_node->name); return 0; } Node* child = current_node->find_func(current_node, buffer); @@ -239,8 +239,16 @@ bool VFS::exists(const char* pathname) void VFS::mount(Node* mountpoint, Node* mounted) { - if (!mountpoint || !mounted) return; - if (mountpoint->flags & VFS_MOUNTPOINT || mounted->flags & VFS_MOUNTPOINT) return; + if (!mountpoint || !mounted) + { + kinfoln("mount failed: invalid pointers"); + return; + } + if (mountpoint->flags & VFS_MOUNTPOINT || mounted->flags & VFS_MOUNTPOINT) + { + kinfoln("mount failed: already a mountpoint"); + return; + } mountpoint->link = mounted; mountpoint->flags |= VFS_MOUNTPOINT; } diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index ab5c3751..131b7ab8 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -2,6 +2,7 @@ #include "config.h" #include "cpu/CPU.h" +#include "fs/TmpFS.h" #include "fs/devices/DeviceFS.h" #include "gdt/GDT.h" #include "init/Init.h" @@ -69,6 +70,8 @@ extern "C" void _start() ASSERT(VFS::mkdir("/dev") == 0); VFS::mount("/dev", DeviceFS::get()); + ASSERT(VFS::mkdir("/tmp") == 0); + VFS::mount("/tmp", TmpFS::create("tmp")->root()); Init::finish_kernel_boot(); diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 8248095d..11365c22 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -43,6 +43,7 @@ template void sched_for_each_task(Callback callback) bool will_continue = callback(task); if (!will_continue) break; task = task->next_task; + if (!task) break; } while (task != base_task); } -- 2.34.1 From 26ee79fe17523e3b21f710c941a947971c80b547 Mon Sep 17 00:00:00 2001 From: apio Date: Mon, 31 Oct 2022 10:23:54 +0100 Subject: [PATCH 3/3] why does it not work --- kernel/src/fs/TmpFS.cpp | 5 +++-- kernel/src/thread/Scheduler.cpp | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/src/fs/TmpFS.cpp b/kernel/src/fs/TmpFS.cpp index e6567d02..f1ff2802 100644 --- a/kernel/src/fs/TmpFS.cpp +++ b/kernel/src/fs/TmpFS.cpp @@ -59,6 +59,7 @@ extern uint64_t clock_now(); TmpFS::TmpFS(const char* name) { m_root = new VFS::Node; + memset(m_root, 0, sizeof(VFS::Node)); m_root->atime = m_root->ctime = m_root->mtime = clock_now(); m_root->impl = (uint64_t)this; m_root->inode = 0; @@ -152,8 +153,6 @@ VFS::Node* TmpFS::readdir(VFS::Node* node, long index) int TmpFS::mkdir(VFS::Node* node, const char* filename, mode_t mode) { - kinfoln("starting to create directory %s in %s", filename, node->name); - if (!node) return 0; if (node->inode >= m_dirs.len) return 0; Directory& dir = m_dirs.buf[node->inode]; @@ -189,6 +188,8 @@ int TmpFS::mkdir(VFS::Node* node, const char* filename, mode_t mode) VFS::Node* new_node = &dir.buf[dir.len - 1]; + memset(new_node, 0, sizeof(VFS::Node)); + new_node->inode = new_inode; new_node->atime = new_node->ctime = new_node->mtime = clock_now(); new_node->impl = (uint64_t)this; diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 11365c22..edcce627 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -370,6 +370,7 @@ void Scheduler::reap_tasks() static void sched_decrement_sleep_times() { sched_for_each_task([](Task* task) { + if (!task) return false; if (task->task_sleep > 0) { task->task_sleep -= frequency; -- 2.34.1