From 3451d50a37d6d97ac1abf09c1f15dd23411b818e Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 12 Nov 2022 18:13:41 +0100 Subject: [PATCH] Try building a tmpfs, but weird stuff happens --- initrd/make-folders.sh | 61 ++++++++++++ kernel/include/fs/TmpFS.h | 16 ++++ kernel/include/utils/Dynamic.h | 167 +++++++++++++++++++++++++++++++++ kernel/src/fs/TmpFS.cpp | 94 +++++++++++++++++++ kernel/src/main.cpp | 3 + 5 files changed, 341 insertions(+) create mode 100644 initrd/make-folders.sh create mode 100644 kernel/include/fs/TmpFS.h create mode 100644 kernel/include/utils/Dynamic.h create mode 100644 kernel/src/fs/TmpFS.cpp diff --git a/initrd/make-folders.sh b/initrd/make-folders.sh new file mode 100644 index 00000000..c149ffd8 --- /dev/null +++ b/initrd/make-folders.sh @@ -0,0 +1,61 @@ +mkdir /tmp/folder0 +sleep 1 +mkdir /tmp/folder1 +sleep 1 +mkdir /tmp/folder2 +sleep 1 +mkdir /tmp/folder3 +sleep 1 +mkdir /tmp/folder4 +sleep 1 +mkdir /tmp/folder5 +sleep 1 +mkdir /tmp/folder6 +sleep 1 +mkdir /tmp/folder7 +sleep 1 +mkdir /tmp/folder8 +sleep 1 +mkdir /tmp/folder9 +sleep 1 +mkdir /tmp/folder10 +sleep 1 +mkdir /tmp/folder11 +sleep 1 +mkdir /tmp/folder12 +sleep 1 +mkdir /tmp/folder13 +sleep 1 +mkdir /tmp/folder14 +sleep 1 +mkdir /tmp/folder15 +sleep 1 +mkdir /tmp/folder16 +sleep 1 +mkdir /tmp/folder17 +sleep 1 +mkdir /tmp/folder18 +sleep 1 +mkdir /tmp/folder19 +sleep 1 +mkdir /tmp/folder20 +sleep 1 +mkdir /tmp/folder21 +sleep 1 +mkdir /tmp/folder22 +sleep 1 +mkdir /tmp/folder23 +sleep 1 +mkdir /tmp/folder24 +sleep 1 +mkdir /tmp/folder25 +sleep 1 +mkdir /tmp/folder26 +sleep 1 +mkdir /tmp/folder27 +sleep 1 +mkdir /tmp/folder28 +sleep 1 +mkdir /tmp/folder29 +sleep 1 +mkdir /tmp/folder30 \ No newline at end of file diff --git a/kernel/include/fs/TmpFS.h b/kernel/include/fs/TmpFS.h new file mode 100644 index 00000000..159b406c --- /dev/null +++ b/kernel/include/fs/TmpFS.h @@ -0,0 +1,16 @@ +#pragma once + +#include "fs/VFS.h" + +namespace TmpFS +{ + VFS::Node* get(); + + VFS::Node* finddir(VFS::Node* node, const char* filename); + VFS::Node* readdir(VFS::Node* node, long offset); + + int mkdir(VFS::Node* node, const char* name, mode_t mode); + + ssize_t read(VFS::Node* node, size_t offset, size_t length, char* buffer); + ssize_t write(VFS::Node* node, size_t offset, size_t length, char* buffer); +} \ No newline at end of file diff --git a/kernel/include/utils/Dynamic.h b/kernel/include/utils/Dynamic.h new file mode 100644 index 00000000..6a2fd496 --- /dev/null +++ b/kernel/include/utils/Dynamic.h @@ -0,0 +1,167 @@ +#pragma once +#include "log/Log.h" +#include "std/ensure.h" +#include "std/stdlib.h" +#include "std/string.h" +#include "utils/new.h" + +#define __noinline __attribute__((noinline)) + +template struct Dynamic +{ + Dynamic() + { + set_expand_rate(16); + ensure(expand_fixed()); + } + + Dynamic(size_t capacity) + { + set_expand_rate(16); + ensure(expand_fixed()); + } + + Dynamic(const Dynamic& other) + { + set_expand_rate(other.m_expand_rate); + ensure_capacity(other.capacity()); + m_size = other.size(); + memcpy(m_buf, other.data(), m_capacity * sizeof(T)); + } + + Dynamic(Dynamic&& other) + { + set_expand_rate(other.m_expand_rate); + m_buf = other.release_data(); + m_capacity = other.capacity(); + m_size = other.size(); + } + + Dynamic& operator=(const Dynamic& other) + { + if (this == &other) return *this; + + if (m_buf) + { + while (m_size) pop(); // destroy all objects + kfree(m_buf); + } + + set_expand_rate(other.m_expand_rate); + ensure_capacity(other.capacity()); + m_size = other.size(); + memcpy(m_buf, other.data(), m_capacity * sizeof(T)); + + return *this; + } + + ~Dynamic() + { + if (m_buf) + { + while (m_size) pop(); // destroy all objects + kfree(m_buf); + } + } + + T& at(size_t index) + { + ensure(index < m_size); + return m_buf[index]; + } + + const T& at(size_t index) const + { + ensure(index < m_size); + return m_buf[index]; + } + + T& operator[](size_t index) + { + return at(index); + } + + const T& operator[](size_t index) const + { + return at(index); + } + + bool expand_capacity(size_t capacity) + { + return expand(capacity); + } + + void ensure_capacity(size_t capacity) + { + ensure(expand(capacity)); + } + + void set_expand_rate(size_t rate) + { + if (!rate) return; + m_expand_rate = rate; + } + + __noinline bool push(const T& item) + { + if (m_size == m_capacity) + if (!expand_fixed()) return false; + m_size++; + T* loc = ptr_at(m_size - 1); + new (loc) T(item); + return true; + } + + void pop() + { + at(m_size - 1).~T(); + m_size--; + } + + size_t capacity() const + { + return m_capacity; + } + + size_t size() const + { + return m_size; + } + + const T* data() const + { + return m_buf; + } + + T* release_data() + { + T* result = m_buf; + m_buf = nullptr; + return result; + } + + private: + T* m_buf = nullptr; + size_t m_capacity = 0; + size_t m_size = 0; + size_t m_expand_rate = 16; + + bool expand(size_t new_capacity) + { + m_buf = (T*)krealloc(m_buf, new_capacity * sizeof(T)); + if (!m_buf) return false; + m_capacity = new_capacity; + return true; + } + + bool expand_fixed() + { + ensure(m_expand_rate != 0); + return expand(m_capacity + m_expand_rate); + } + + T* ptr_at(size_t index) + { + return (T*)((char*)m_buf + index * sizeof(T)); + } +}; \ 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..a9c3a798 --- /dev/null +++ b/kernel/src/fs/TmpFS.cpp @@ -0,0 +1,94 @@ +#include "fs/TmpFS.h" +#include "std/errno.h" +#include "std/string.h" +#include "utils/Dynamic.h" +#include "utils/move.h" + +namespace TmpFS +{ + struct File + { + char* ptr; + uint64_t pages; + uint64_t length; + }; + + struct Directory + { + Dynamic files; + }; +} + +VFS::Node* tmpfs_root = nullptr; + +Dynamic tmpfs_dirs; +Dynamic tmpfs_files; + +extern uint64_t clock_now(); + +VFS::Node* TmpFS::get() +{ + if (tmpfs_root) return tmpfs_root; + tmpfs_root = new VFS::Node; + tmpfs_root->length = 0; + tmpfs_root->inode = 0; + tmpfs_root->type = VFS_DIRECTORY; + tmpfs_root->find_func = TmpFS::finddir; + tmpfs_root->readdir_func = TmpFS::readdir; + tmpfs_root->mkdir_func = TmpFS::mkdir; + tmpfs_root->mode = 0755; + tmpfs_root->uid = tmpfs_root->gid = 0; + tmpfs_root->atime = tmpfs_root->ctime = tmpfs_root->mtime = clock_now(); + strncpy(tmpfs_root->name, "tmpfs", sizeof(tmpfs_root->name)); + tmpfs_dirs.ensure_capacity(16); + tmpfs_files.ensure_capacity(16); + tmpfs_dirs.set_expand_rate(16); + tmpfs_files.set_expand_rate(16); + ensure(tmpfs_dirs.push({{}})); + return tmpfs_root; +} + +VFS::Node* TmpFS::finddir(VFS::Node* node, const char* filename) +{ + if (!node) return nullptr; + if (node->inode >= tmpfs_dirs.size()) return nullptr; + auto& dir = tmpfs_dirs[node->inode]; + for (size_t i = 0; i < dir.files.size(); i++) + { + if (!strncmp(dir.files[i]->name, filename, sizeof(dir.files[i]->name))) return dir.files[i]; + } + return nullptr; +} + +VFS::Node* TmpFS::readdir(VFS::Node* node, long offset) +{ + if (!node) return nullptr; + if (node->inode >= tmpfs_dirs.size()) return nullptr; + auto& dir = tmpfs_dirs[node->inode]; + if (offset < 0) return nullptr; + if ((size_t)offset >= dir.files.size()) return nullptr; + return dir.files[offset]; +} + +int TmpFS::mkdir(VFS::Node* node, const char* name, mode_t mode) +{ + if (node->inode >= tmpfs_dirs.size()) return -EINVAL; + if (!(node->type & VFS_DIRECTORY)) return -ENOTDIR; + auto& parent = tmpfs_dirs[node->inode]; + uint64_t inode = tmpfs_dirs.size(); + VFS::Node* new_node = new VFS::Node; + new_node->inode = inode; + new_node->find_func = TmpFS::finddir; + new_node->readdir_func = TmpFS::readdir; + new_node->mkdir_func = TmpFS::mkdir; + new_node->length = 0; + new_node->type = VFS_DIRECTORY; + new_node->mode = mode; + new_node->uid = new_node->gid = 0; + new_node->atime = new_node->ctime = new_node->mtime = clock_now(); + strncpy(new_node->name, name, sizeof(new_node->name)); + ensure(tmpfs_dirs.push({{}})); + node->length++; + ensure(parent.files.push(new_node)); + return 0; +} \ No newline at end of file diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index ec781c93..f12e9e7c 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" @@ -58,7 +59,9 @@ extern "C" void _start() }); ensure(VFS::mkdir("/dev") == 0); + ensure(VFS::mkdir("/tmp") == 0); VFS::mount("/dev", DeviceFS::get()); + VFS::mount("/tmp", TmpFS::get()); Init::finish_kernel_boot();