VFS: less crazy design

with actual inodes now
This commit is contained in:
2024-05-03 21:13:15 +02:00
parent d7631577c7
commit d31bba399b
10 changed files with 199 additions and 78 deletions

View File

@@ -43,6 +43,7 @@ void templates_tester() {
void vfs_tester() { void vfs_tester() {
VFSTester vfsTester; VFSTester vfsTester;
vfsTester.test(); vfsTester.test();
GlobalTtyManager.all_tty_putstr("Testing vfs OK\n");
} }
void ktask_main() { void ktask_main() {
@@ -54,7 +55,7 @@ void ktask_main() {
(new Task(Task::TaskMode::TASKMODE_KERN, templates_tester, "templates_tester2"))->start(); (new Task(Task::TaskMode::TASKMODE_KERN, templates_tester, "templates_tester2"))->start();
VFSGlobals::mounts.add_mount(new MemFs(&VFSGlobals::root)); VFSGlobals::mounts.add_mount(new MemFs(&VFSGlobals::root));
(new Task(Task::TaskMode::TASKMODE_KERN, vfs_tester, "vfs_tester"))->start(); (new Task(Task::TaskMode::TASKMODE_KERN, vfs_tester, "vfs_tester"))->start();
Task *init;
for (int i = 0; i < saved_modules_size; i++) { for (int i = 0; i < saved_modules_size; i++) {
auto &mod = saved_modules[i]; auto &mod = saved_modules[i];
@@ -64,23 +65,20 @@ void ktask_main() {
f->write(static_cast<const char *>(mod.address), mod.size); f->write(static_cast<const char *>(mod.address), mod.size);
if (strcmp(saved_modules_names[i], "/init") == 0) { 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<char> read_data(mod.size); Vector<char> read_data(mod.size);
memcpy(read_data.begin(), mod.address, mod.size); memcpy(read_data.begin(), mod.address, mod.size);
ElfParser elfParser(std::move(read_data)); ElfParser elfParser(std::move(read_data));
Task *utask = new Task(Task::TaskMode::TASKMODE_USER, (void (*)()) elfParser.get_entrypoint(), saved_modules_names[i]); init = new Task(Task::TaskMode::TASKMODE_USER, (void (*)()) elfParser.get_entrypoint(), saved_modules_names[i]);
if (elfParser.copy_to(utask)) if (!elfParser.copy_to(init))
utask->start();
else
assert2(false, "Init couldn't be loaded!"); assert2(false, "Init couldn't be loaded!");
} }
VFSApi::close(fd); VFSApi::close(fd);
} }
GlobalTtyManager.all_tty_putstr("Setup finished \n");
GlobalTtyManager.all_tty_putstr("Starting init \n");
init->start();
} }
void dummy_task() { void dummy_task() {

View File

@@ -269,11 +269,13 @@ int64_t syscall_getdents(int fd, struct dirent *dp, int count) {
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
auto &child = children[i + f->pos()]; auto &child = children[i + f->pos()];
dp[i].d_fileno = i + f->pos() + 1; dp[i].d_fileno = i + f->pos() + 1;
strncpy(dp[i].d_name, child->name().c_str(), 255); strncpy(dp[i].d_name, child.name.c_str(), 255);
dp[i].d_name[child->name().length() + 1] = '\0'; dp[i].d_name[child.name.length() + 1] = '\0';
dp[i].d_namlen = child->name().length(); dp[i].d_namlen = child.name.length();
dp[i].d_reclen = sizeof(dirent); dp[i].d_reclen = sizeof(dirent);
dp[i].d_type = child->type() == Node::DIR ? 4 : 8; // FIXME:
// dp[i].d_type = child.type() == Node::DIR ? 4 : 8;
dp[i].d_type = 4;
} }
f->seek(count + f->pos()); f->seek(count + f->pos());
return count * sizeof(dirent); return count * sizeof(dirent);

View File

@@ -7,12 +7,15 @@
#include "Node.hpp" #include "Node.hpp"
#include "PointersCollection.hpp"
class Filesystem { class Filesystem {
public: public:
Filesystem(NodeDir *mounted_on); Filesystem(NodeDir *mounted_on);
virtual ~Filesystem() = 0;
virtual NodeDir *root() = 0; virtual SharedPtr<NodeDir> root() = 0;
virtual ~Filesystem() = 0; virtual SharedPtr<Node> get_node(ino_t inode) = 0;
NodeDir *_mounted_on; NodeDir *_mounted_on;
}; };

View File

@@ -7,45 +7,110 @@
#include <algorithm> #include <algorithm>
Vector<SharedPtr<Node>> MemFs::MemFsNodeDir::children() { Vector<DirEntry> MemFs::MemFsNodeDir::children() {
LockGuard l(_lock); LockGuard l(_lock);
LockGuard l2(_fs_node->lock);
Vector<SharedPtr<Node>> out; Vector<DirEntry> out;
for (auto c: _children) { for (auto c: _fs_node->entries) {
out.emplace_back(c.second); out.emplace_back(c.first, c.second);
} }
return out; return out;
} }
SharedPtr<NodeDir> MemFs::MemFsNodeDir::mkdir(const String &name) { ino_t MemFs::MemFsNodeDir::mkdir(const String &name) {
LockGuard l(_lock); LockGuard l(_lock);
auto newnode = MemFsNodeDir::create(name);
_children.emplace(name, static_ptr_cast<Node>(newnode)); MemFs *mem_fs = static_cast<MemFs *>(_fs);
return static_ptr_cast<NodeDir>(newnode); ino_t res;
{
LockGuard l3(mem_fs->_files_lock);
SharedPtr<DirInode> new_inode = SharedPtr<DirInode>(new DirInode{++mem_fs->_top_inode});
mem_fs->_files.emplace(new_inode->id, static_ptr_cast<Inode>(new_inode));
res = new_inode->id;
}
{
LockGuard l2(_fs_node->lock);
_fs_node->entries.emplace(name, res);
}
return res;
} }
SharedPtr<NodeFile> MemFs::MemFsNodeDir::mkfile(const String &name) { ino_t MemFs::MemFsNodeDir::mkfile(const String &name) {
LockGuard l(_lock); LockGuard l(_lock);
auto newfile = MemFsNodeFile::create(name);
_children.emplace(name, static_ptr_cast<Node>(newfile)); MemFs *mem_fs = static_cast<MemFs *>(_fs);
return static_ptr_cast<NodeFile>(newfile); ino_t res;
{
LockGuard l3(mem_fs->_files_lock);
SharedPtr<FileInode> new_inode = SharedPtr<FileInode>(new FileInode{++mem_fs->_top_inode});
mem_fs->_files.emplace(new_inode->id, static_ptr_cast<Inode>(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) { int64_t MemFs::MemFsNodeFile::read(char *buf, size_t start, size_t num) {
LockGuard l(_lock); 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++) { for (size_t i = 0; i < num; i++) {
buf[i] = _bytes[start + i]; buf[i] = _fs_node->data[start + i];
} }
return num; return num;
} }
int64_t MemFs::MemFsNodeFile::write(const char *buf, size_t start, size_t num) { int64_t MemFs::MemFsNodeFile::write(const char *buf, size_t start, size_t num) {
LockGuard l(_lock); 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++) { for (size_t i = 0; i < num; i++) {
_bytes[start + i] = buf[i]; _fs_node->data[start + i] = buf[i];
} }
return num; return num;
} }
size_t MemFs::MemFsNodeFile::size() { size_t MemFs::MemFsNodeFile::size() {
LockGuard l(_lock); 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<NodeDir> MemFs::root() {
SharedPtr<Inode> root;
{
LockGuard l(_files_lock);
root = _files.find(1)->second;
}
assert(root.get() != nullptr);
{
LockGuard l(root->lock);
return static_ptr_cast<NodeDir>(MemFsNodeDir::create(this, static_ptr_cast<DirInode>(root)));
}
}
SharedPtr<Node> 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<Node>(MemFsNodeDir::create(this, static_ptr_cast<DirInode>(found->second)));
} else if (found->second->type == InodeType::File) {
return static_ptr_cast<Node>(MemFsNodeFile::create(this, static_ptr_cast<FileInode>(found->second)));
}
assert(false);
}
MemFs::Inode::~Inode() = default;

View File

@@ -5,6 +5,8 @@
#ifndef FICUS_MEMFS_HPP #ifndef FICUS_MEMFS_HPP
#define FICUS_MEMFS_HPP #define FICUS_MEMFS_HPP
#include <utility>
#include "Filesystem.hpp" #include "Filesystem.hpp"
#include "Node.hpp" #include "Node.hpp"
@@ -12,48 +14,92 @@
#include "Vector.hpp" #include "Vector.hpp"
class MemFs : public Filesystem { 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<uint8_t> data;
};
struct DirInode final : public Inode {
explicit DirInode(ino_t id)
: Inode(InodeType::Dir, id) {}
~DirInode() override = default;
SkipListMap<String, ino_t> entries;
};
struct MemFsNodeDir : public NodeDir { struct MemFsNodeDir : public NodeDir {
public: public:
Vector<SharedPtr<Node>> children() override; ~MemFsNodeDir() override = default;
SharedPtr<NodeDir> mkdir(const String &name) override;
SharedPtr<NodeFile> mkfile(const String &name) override;
static SharedPtr<MemFsNodeDir> create(const String &name) { Vector<DirEntry> children() override;
auto shared = SharedPtr(new MemFsNodeDir(name)); ino_t mkdir(const String &name) override;
ino_t mkfile(const String &name) override;
static SharedPtr<MemFsNodeDir> create(Filesystem *fs, SharedPtr<DirInode> fs_node) {
auto shared = SharedPtr(new MemFsNodeDir(fs, std::move(fs_node)));
shared->_self_weak = static_ptr_cast<Node>(shared); shared->_self_weak = static_ptr_cast<Node>(shared);
return shared; return shared;
} }
private: private:
MemFsNodeDir(const String &name) { _name = name; } MemFsNodeDir(Filesystem *fs, SharedPtr<DirInode> fs_node) : NodeDir(fs, fs_node->id), _fs_node(std::move(fs_node)) {}
SkipListMap<String, SharedPtr<Node>> _children;
SharedPtr<DirInode> _fs_node;
}; };
struct MemFsNodeFile : public NodeFile { struct MemFsNodeFile : public NodeFile {
public: public:
~MemFsNodeFile() override = default;
int64_t read(char *buf, size_t start, size_t num) override; 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; int64_t write(const char *buf, size_t start, size_t num) override;
size_t size() override; size_t size() override;
bool is_tty() override { return false; } bool is_tty() override { return false; }
static SharedPtr<MemFsNodeFile> create(const String &name) { static SharedPtr<MemFsNodeFile> create(Filesystem *fs, SharedPtr<FileInode> fs_node) {
auto shared = SharedPtr(new MemFsNodeFile(name)); auto shared = SharedPtr(new MemFsNodeFile(fs, std::move(fs_node)));
shared->_self_weak = static_ptr_cast<Node>(shared); shared->_self_weak = static_ptr_cast<Node>(shared);
return shared; return shared;
} }
private: private:
MemFsNodeFile(const String &name) { _name = name; } MemFsNodeFile(Filesystem *fs, SharedPtr<FileInode> fs_node) : NodeFile(fs, fs_node->id), _fs_node(std::move(fs_node)) {}
Vector<uint8_t> _bytes;
SharedPtr<FileInode> _fs_node;
}; };
public: public:
MemFs(NodeDir *mounted_on) : Filesystem(mounted_on) {} MemFs(NodeDir *mounted_on);
NodeDir *root() override { return _rootNode.get(); } SharedPtr<NodeDir> root() override;
SharedPtr<Node> get_node(ino_t inode) override;
private: private:
SharedPtr<MemFsNodeDir> _rootNode = MemFsNodeDir::create(""); ino_t _top_inode;
SkipListMap<ino_t, SharedPtr<Inode>> _files;
Mutex _files_lock;
}; };

View File

@@ -7,7 +7,7 @@
#include "Filesystem.hpp" #include "Filesystem.hpp"
Node::~Node() = default; Node::~ Node() = default;
SharedPtr<Node> Node::traverse(const Path &path) { SharedPtr<Node> Node::traverse(const Path &path) {
Filesystem *mnt; Filesystem *mnt;
@@ -23,13 +23,12 @@ SharedPtr<Node> Node::traverse(const Path &path) {
return *ret; return *ret;
} }
if (type() == DIR) { if (type() == DIR) {
// Horribly inefficient // Horribly inefficient
auto children = static_cast<NodeDir *>(this)->children(); auto children = static_cast<NodeDir *>(this)->children();
for (size_t i = 0; i < children.size(); i++) { for (size_t i = 0; i < children.size(); i++) {
if (children[i]->name() == path[0]) { if (children[i].name == path[0]) {
return children[i]->traverse(path.subvector(1, path.size())); return _fs->get_node(children[i].inode)->traverse(path.subvector(1, path.size()));
} }
} }
return nullptr; return nullptr;

View File

@@ -25,37 +25,41 @@ public:
}; };
virtual ~Node() = 0; virtual ~Node() = 0;
Type type() const { return _type; } Type type() const { return _type; }
const String &name() const {
LockGuard l(_lock);
return _name;
}
virtual SharedPtr<Node> traverse(const Path &path); virtual SharedPtr<Node> traverse(const Path &path);
protected: 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; const Type _type = Type::INVALID;
// This is uuugly
mutable Mutex _lock; 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<Node> _self_weak = nullptr; WeakPtr<Node> _self_weak = nullptr;
}; };
class NodeFile; class NodeFile;
struct DirEntry {
String name;
ino_t inode;
};
class NodeDir : public Node { class NodeDir : public Node {
public: public:
virtual Vector<SharedPtr<Node>> children() = 0; virtual Vector<DirEntry> children() = 0;
virtual SharedPtr<NodeDir> mkdir(const String &name) = 0; virtual ino_t mkdir(const String &name) = 0;
virtual SharedPtr<NodeFile> mkfile(const String &name) = 0; virtual ino_t mkfile(const String &name) = 0;
virtual void set_mounted(Filesystem *mount); virtual void set_mounted(Filesystem *mount);
protected: protected:
NodeDir() : Node(Type::DIR) {} NodeDir(Filesystem *fs, ino_t ino) : Node(Type::DIR, fs, ino) {}
}; };
class NodeFile : public Node { class NodeFile : public Node {
@@ -66,7 +70,7 @@ public:
virtual bool is_tty() = 0; virtual bool is_tty() = 0;
protected: protected:
NodeFile() : Node(Type::FILE) {} NodeFile(Filesystem *fs, ino_t ino) : Node(Type::FILE, fs, ino) {}
}; };

View File

@@ -15,13 +15,14 @@ public:
bool is_tty() override { return true; } bool is_tty() override { return true; }
static SharedPtr<TtyPipe> create() { static SharedPtr<TtyPipe> create() {
auto shared = SharedPtr(new TtyPipe()); auto shared = SharedPtr(new TtyPipe(nullptr, -1));
shared->_self_weak = static_ptr_cast<Node>(shared); shared->_self_weak = static_ptr_cast<Node>(shared);
return shared; return shared;
} }
private: private:
TtyPipe() = default; TtyPipe(Filesystem *fs, ino_t ino)
: NodeFile(fs, ino) {}
}; };

View File

@@ -3,17 +3,17 @@
// //
#include "VFSGlobals.hpp" #include "VFSGlobals.hpp"
Vector<SharedPtr<Node>> RootNode::children() { Vector<DirEntry> RootNode::children() {
assert(false); assert(false);
return {}; return {};
} }
SharedPtr<NodeDir> RootNode::mkdir(const String &name) { ino_t RootNode::mkdir(const String &name) {
assert(false); assert(false);
return nullptr; return -1;
} }
SharedPtr<NodeFile> RootNode::mkfile(const String &name) { ino_t RootNode::mkfile(const String &name) {
assert(false); assert(false);
return nullptr; return -1;
} }

View File

@@ -10,15 +10,18 @@
class RootNode : public NodeDir { class RootNode : public NodeDir {
public: public:
Vector<SharedPtr<Node>> children() override; RootNode()
SharedPtr<NodeDir> mkdir(const String &name) override; : NodeDir(nullptr, -1) {}
SharedPtr<NodeFile> mkfile(const String &name) override;
Vector<DirEntry> children() override;
ino_t mkdir(const String &name) override;
ino_t mkfile(const String &name) override;
}; };
namespace VFSGlobals { namespace VFSGlobals {
extern RootNode root; extern RootNode root;
extern MountTable mounts; extern MountTable mounts;
}; // namespace VFSGlobals }; // namespace VFSGlobals
#endif //FICUS_VFSGLOBALS_HPP #endif //FICUS_VFSGLOBALS_HPP