diff --git a/src/arch/x86/kmain.cpp b/src/arch/x86/kmain.cpp index 7befffba7..70c534af8 100644 --- a/src/arch/x86/kmain.cpp +++ b/src/arch/x86/kmain.cpp @@ -43,6 +43,7 @@ void templates_tester() { void vfs_tester() { VFSTester vfsTester; vfsTester.test(); + GlobalTtyManager.all_tty_putstr("Testing vfs OK\n"); } void ktask_main() { @@ -54,7 +55,7 @@ void ktask_main() { (new Task(Task::TaskMode::TASKMODE_KERN, templates_tester, "templates_tester2"))->start(); VFSGlobals::mounts.add_mount(new MemFs(&VFSGlobals::root)); (new Task(Task::TaskMode::TASKMODE_KERN, vfs_tester, "vfs_tester"))->start(); - + Task *init; for (int i = 0; i < saved_modules_size; i++) { auto &mod = saved_modules[i]; @@ -64,23 +65,20 @@ void ktask_main() { f->write(static_cast(mod.address), mod.size); if (strcmp(saved_modules_names[i], "/init") == 0) { - GlobalTtyManager.all_tty_putstr("Starting "); - GlobalTtyManager.all_tty_putstr(saved_modules_names[i]); - GlobalTtyManager.all_tty_putchar('\n'); - Vector read_data(mod.size); memcpy(read_data.begin(), mod.address, mod.size); ElfParser elfParser(std::move(read_data)); - Task *utask = new Task(Task::TaskMode::TASKMODE_USER, (void (*)()) elfParser.get_entrypoint(), saved_modules_names[i]); - if (elfParser.copy_to(utask)) - utask->start(); - else + init = new Task(Task::TaskMode::TASKMODE_USER, (void (*)()) elfParser.get_entrypoint(), saved_modules_names[i]); + if (!elfParser.copy_to(init)) assert2(false, "Init couldn't be loaded!"); } VFSApi::close(fd); } + GlobalTtyManager.all_tty_putstr("Setup finished \n"); + GlobalTtyManager.all_tty_putstr("Starting init \n"); + init->start(); } void dummy_task() { diff --git a/src/arch/x86/syscalls.cpp b/src/arch/x86/syscalls.cpp index 87d68605e..21c484b5d 100644 --- a/src/arch/x86/syscalls.cpp +++ b/src/arch/x86/syscalls.cpp @@ -269,11 +269,13 @@ int64_t syscall_getdents(int fd, struct dirent *dp, int count) { for (int i = 0; i < count; i++) { auto &child = children[i + f->pos()]; dp[i].d_fileno = i + f->pos() + 1; - strncpy(dp[i].d_name, child->name().c_str(), 255); - dp[i].d_name[child->name().length() + 1] = '\0'; - dp[i].d_namlen = child->name().length(); - dp[i].d_reclen = sizeof(dirent); - dp[i].d_type = child->type() == Node::DIR ? 4 : 8; + strncpy(dp[i].d_name, child.name.c_str(), 255); + dp[i].d_name[child.name.length() + 1] = '\0'; + dp[i].d_namlen = child.name.length(); + dp[i].d_reclen = sizeof(dirent); + // FIXME: + // dp[i].d_type = child.type() == Node::DIR ? 4 : 8; + dp[i].d_type = 4; } f->seek(count + f->pos()); return count * sizeof(dirent); diff --git a/src/kernel/vfs/Filesystem.hpp b/src/kernel/vfs/Filesystem.hpp index e2fd19974..ec0e3919f 100644 --- a/src/kernel/vfs/Filesystem.hpp +++ b/src/kernel/vfs/Filesystem.hpp @@ -7,12 +7,15 @@ #include "Node.hpp" +#include "PointersCollection.hpp" + class Filesystem { public: - Filesystem(NodeDir *mounted_on); + Filesystem(NodeDir *mounted_on); + virtual ~Filesystem() = 0; - virtual NodeDir *root() = 0; - virtual ~Filesystem() = 0; + virtual SharedPtr root() = 0; + virtual SharedPtr get_node(ino_t inode) = 0; NodeDir *_mounted_on; }; diff --git a/src/kernel/vfs/MemFs.cpp b/src/kernel/vfs/MemFs.cpp index c6504ca29..883c50c75 100644 --- a/src/kernel/vfs/MemFs.cpp +++ b/src/kernel/vfs/MemFs.cpp @@ -7,45 +7,110 @@ #include -Vector> MemFs::MemFsNodeDir::children() { +Vector MemFs::MemFsNodeDir::children() { LockGuard l(_lock); + LockGuard l2(_fs_node->lock); - Vector> out; - for (auto c: _children) { - out.emplace_back(c.second); + Vector out; + for (auto c: _fs_node->entries) { + out.emplace_back(c.first, c.second); } + return out; } -SharedPtr MemFs::MemFsNodeDir::mkdir(const String &name) { +ino_t MemFs::MemFsNodeDir::mkdir(const String &name) { LockGuard l(_lock); - auto newnode = MemFsNodeDir::create(name); - _children.emplace(name, static_ptr_cast(newnode)); - return static_ptr_cast(newnode); + + MemFs *mem_fs = static_cast(_fs); + ino_t res; + { + LockGuard l3(mem_fs->_files_lock); + + SharedPtr new_inode = SharedPtr(new DirInode{++mem_fs->_top_inode}); + mem_fs->_files.emplace(new_inode->id, static_ptr_cast(new_inode)); + res = new_inode->id; + } + + { + LockGuard l2(_fs_node->lock); + + _fs_node->entries.emplace(name, res); + } + + return res; } -SharedPtr MemFs::MemFsNodeDir::mkfile(const String &name) { +ino_t MemFs::MemFsNodeDir::mkfile(const String &name) { LockGuard l(_lock); - auto newfile = MemFsNodeFile::create(name); - _children.emplace(name, static_ptr_cast(newfile)); - return static_ptr_cast(newfile); + + MemFs *mem_fs = static_cast(_fs); + ino_t res; + { + LockGuard l3(mem_fs->_files_lock); + + SharedPtr new_inode = SharedPtr(new FileInode{++mem_fs->_top_inode}); + mem_fs->_files.emplace(new_inode->id, static_ptr_cast(new_inode)); + res = new_inode->id; + } + + { + LockGuard l2(_fs_node->lock); + + _fs_node->entries.emplace(name, res); + } + + return res; } int64_t MemFs::MemFsNodeFile::read(char *buf, size_t start, size_t num) { LockGuard l(_lock); - num = std::min(num, _bytes.size() - start); + LockGuard l2(_fs_node->lock); + num = std::min(num, _fs_node->data.size() - start); for (size_t i = 0; i < num; i++) { - buf[i] = _bytes[start + i]; + buf[i] = _fs_node->data[start + i]; } return num; } int64_t MemFs::MemFsNodeFile::write(const char *buf, size_t start, size_t num) { LockGuard l(_lock); - while (_bytes.size() <= start + num) _bytes.emplace_back(0); + LockGuard l2(_fs_node->lock); + while (_fs_node->data.size() <= start + num) _fs_node->data.emplace_back(0); for (size_t i = 0; i < num; i++) { - _bytes[start + i] = buf[i]; + _fs_node->data[start + i] = buf[i]; } return num; } size_t MemFs::MemFsNodeFile::size() { LockGuard l(_lock); - return _bytes.size(); + LockGuard l2(_fs_node->lock); + return _fs_node->data.size(); } +MemFs::MemFs(NodeDir *mounted_on) : Filesystem(mounted_on) { + _files.emplace(1, new DirInode{1}); + _top_inode = 2; +} +SharedPtr MemFs::root() { + SharedPtr root; + { + LockGuard l(_files_lock); + root = _files.find(1)->second; + } + assert(root.get() != nullptr); + { + LockGuard l(root->lock); + return static_ptr_cast(MemFsNodeDir::create(this, static_ptr_cast(root))); + } +} +SharedPtr MemFs::get_node(ino_t inode) { + LockGuard l(_files_lock); + auto found = _files.find(inode); + if (found == _files.end()) return nullptr; + if (found->second->type == InodeType::Dir) { + return static_ptr_cast(MemFsNodeDir::create(this, static_ptr_cast(found->second))); + } else if (found->second->type == InodeType::File) { + return static_ptr_cast(MemFsNodeFile::create(this, static_ptr_cast(found->second))); + } + assert(false); +} + + +MemFs::Inode::~Inode() = default; \ No newline at end of file diff --git a/src/kernel/vfs/MemFs.hpp b/src/kernel/vfs/MemFs.hpp index dbf37dfef..f4f4f20ab 100644 --- a/src/kernel/vfs/MemFs.hpp +++ b/src/kernel/vfs/MemFs.hpp @@ -5,6 +5,8 @@ #ifndef FICUS_MEMFS_HPP #define FICUS_MEMFS_HPP +#include + #include "Filesystem.hpp" #include "Node.hpp" @@ -12,48 +14,92 @@ #include "Vector.hpp" class MemFs : public Filesystem { +private: + enum class InodeType { + File, + Dir + }; + + // FIXME: refcount + struct Inode { + explicit Inode(InodeType type, ino_t id) + : type(type), id(id) {} + virtual ~Inode() = 0; + + ino_t id; + InodeType type; + mutable Mutex lock; + }; + + struct FileInode final : public Inode { + explicit FileInode(ino_t id) + : Inode(InodeType::File, id) {} + + ~FileInode() override = default; + + Vector data; + }; + + struct DirInode final : public Inode { + explicit DirInode(ino_t id) + : Inode(InodeType::Dir, id) {} + + ~DirInode() override = default; + + SkipListMap entries; + }; + struct MemFsNodeDir : public NodeDir { public: - Vector> children() override; - SharedPtr mkdir(const String &name) override; - SharedPtr mkfile(const String &name) override; + ~MemFsNodeDir() override = default; - static SharedPtr create(const String &name) { - auto shared = SharedPtr(new MemFsNodeDir(name)); + Vector children() override; + ino_t mkdir(const String &name) override; + ino_t mkfile(const String &name) override; + + static SharedPtr create(Filesystem *fs, SharedPtr fs_node) { + auto shared = SharedPtr(new MemFsNodeDir(fs, std::move(fs_node))); shared->_self_weak = static_ptr_cast(shared); return shared; } private: - MemFsNodeDir(const String &name) { _name = name; } - SkipListMap> _children; + MemFsNodeDir(Filesystem *fs, SharedPtr fs_node) : NodeDir(fs, fs_node->id), _fs_node(std::move(fs_node)) {} + + SharedPtr _fs_node; }; struct MemFsNodeFile : public NodeFile { public: + ~MemFsNodeFile() override = default; + int64_t read(char *buf, size_t start, size_t num) override; int64_t write(const char *buf, size_t start, size_t num) override; size_t size() override; bool is_tty() override { return false; } - static SharedPtr create(const String &name) { - auto shared = SharedPtr(new MemFsNodeFile(name)); + static SharedPtr create(Filesystem *fs, SharedPtr fs_node) { + auto shared = SharedPtr(new MemFsNodeFile(fs, std::move(fs_node))); shared->_self_weak = static_ptr_cast(shared); return shared; } private: - MemFsNodeFile(const String &name) { _name = name; } - Vector _bytes; + MemFsNodeFile(Filesystem *fs, SharedPtr fs_node) : NodeFile(fs, fs_node->id), _fs_node(std::move(fs_node)) {} + + SharedPtr _fs_node; }; public: - MemFs(NodeDir *mounted_on) : Filesystem(mounted_on) {} + MemFs(NodeDir *mounted_on); - NodeDir *root() override { return _rootNode.get(); } + SharedPtr root() override; + SharedPtr get_node(ino_t inode) override; private: - SharedPtr _rootNode = MemFsNodeDir::create(""); + ino_t _top_inode; + SkipListMap> _files; + Mutex _files_lock; }; diff --git a/src/kernel/vfs/Node.cpp b/src/kernel/vfs/Node.cpp index 9ac695586..d1ffc5720 100644 --- a/src/kernel/vfs/Node.cpp +++ b/src/kernel/vfs/Node.cpp @@ -7,7 +7,7 @@ #include "Filesystem.hpp" -Node::~Node() = default; +Node::~ Node() = default; SharedPtr Node::traverse(const Path &path) { Filesystem *mnt; @@ -23,13 +23,12 @@ SharedPtr Node::traverse(const Path &path) { return *ret; } - if (type() == DIR) { // Horribly inefficient auto children = static_cast(this)->children(); for (size_t i = 0; i < children.size(); i++) { - if (children[i]->name() == path[0]) { - return children[i]->traverse(path.subvector(1, path.size())); + if (children[i].name == path[0]) { + return _fs->get_node(children[i].inode)->traverse(path.subvector(1, path.size())); } } return nullptr; diff --git a/src/kernel/vfs/Node.hpp b/src/kernel/vfs/Node.hpp index 9d18e61d1..e9ec3567d 100644 --- a/src/kernel/vfs/Node.hpp +++ b/src/kernel/vfs/Node.hpp @@ -25,37 +25,41 @@ public: }; virtual ~Node() = 0; - Type type() const { return _type; } - const String &name() const { - LockGuard l(_lock); - return _name; - } + Type type() const { return _type; } virtual SharedPtr traverse(const Path &path); protected: - Node(Type type) : _type(type) {} + Node(Type type, Filesystem *fs, ino_t ino) : _type(type), _fs(fs), _ino(ino) {} const Type _type = Type::INVALID; - // This is uuugly mutable Mutex _lock; - String _name; - Filesystem *_mount = nullptr; + Filesystem *_mount = nullptr; + Filesystem *_fs = nullptr; + + ino_t _ino; + + // TODO: enable_shared_from_this or something prettier WeakPtr _self_weak = nullptr; }; class NodeFile; +struct DirEntry { + String name; + ino_t inode; +}; + class NodeDir : public Node { public: - virtual Vector> children() = 0; - virtual SharedPtr mkdir(const String &name) = 0; - virtual SharedPtr mkfile(const String &name) = 0; - virtual void set_mounted(Filesystem *mount); + virtual Vector children() = 0; + virtual ino_t mkdir(const String &name) = 0; + virtual ino_t mkfile(const String &name) = 0; + virtual void set_mounted(Filesystem *mount); protected: - NodeDir() : Node(Type::DIR) {} + NodeDir(Filesystem *fs, ino_t ino) : Node(Type::DIR, fs, ino) {} }; class NodeFile : public Node { @@ -66,7 +70,7 @@ public: virtual bool is_tty() = 0; protected: - NodeFile() : Node(Type::FILE) {} + NodeFile(Filesystem *fs, ino_t ino) : Node(Type::FILE, fs, ino) {} }; diff --git a/src/kernel/vfs/TtyPipe.hpp b/src/kernel/vfs/TtyPipe.hpp index b39298f06..92cc45dcc 100644 --- a/src/kernel/vfs/TtyPipe.hpp +++ b/src/kernel/vfs/TtyPipe.hpp @@ -15,13 +15,14 @@ public: bool is_tty() override { return true; } static SharedPtr create() { - auto shared = SharedPtr(new TtyPipe()); + auto shared = SharedPtr(new TtyPipe(nullptr, -1)); shared->_self_weak = static_ptr_cast(shared); return shared; } private: - TtyPipe() = default; + TtyPipe(Filesystem *fs, ino_t ino) + : NodeFile(fs, ino) {} }; diff --git a/src/kernel/vfs/VFSGlobals.cpp b/src/kernel/vfs/VFSGlobals.cpp index 8353b0ee6..b894b47df 100644 --- a/src/kernel/vfs/VFSGlobals.cpp +++ b/src/kernel/vfs/VFSGlobals.cpp @@ -3,17 +3,17 @@ // #include "VFSGlobals.hpp" -Vector> RootNode::children() { +Vector RootNode::children() { assert(false); return {}; } -SharedPtr RootNode::mkdir(const String &name) { +ino_t RootNode::mkdir(const String &name) { assert(false); - return nullptr; + return -1; } -SharedPtr RootNode::mkfile(const String &name) { +ino_t RootNode::mkfile(const String &name) { assert(false); - return nullptr; + return -1; } diff --git a/src/kernel/vfs/VFSGlobals.hpp b/src/kernel/vfs/VFSGlobals.hpp index a6e68bc4b..714697ded 100644 --- a/src/kernel/vfs/VFSGlobals.hpp +++ b/src/kernel/vfs/VFSGlobals.hpp @@ -10,15 +10,18 @@ class RootNode : public NodeDir { public: - Vector> children() override; - SharedPtr mkdir(const String &name) override; - SharedPtr mkfile(const String &name) override; + RootNode() + : NodeDir(nullptr, -1) {} + + Vector children() override; + ino_t mkdir(const String &name) override; + ino_t mkfile(const String &name) override; }; namespace VFSGlobals { extern RootNode root; extern MountTable mounts; -}; // namespace VFSGlobals +}; // namespace VFSGlobals #endif //FICUS_VFSGLOBALS_HPP