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() {
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<const char *>(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<char> 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() {

View File

@@ -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);

View File

@@ -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<NodeDir> root() = 0;
virtual SharedPtr<Node> get_node(ino_t inode) = 0;
NodeDir *_mounted_on;
};

View File

@@ -7,45 +7,110 @@
#include <algorithm>
Vector<SharedPtr<Node>> MemFs::MemFsNodeDir::children() {
Vector<DirEntry> MemFs::MemFsNodeDir::children() {
LockGuard l(_lock);
LockGuard l2(_fs_node->lock);
Vector<SharedPtr<Node>> out;
for (auto c: _children) {
out.emplace_back(c.second);
Vector<DirEntry> out;
for (auto c: _fs_node->entries) {
out.emplace_back(c.first, c.second);
}
return out;
}
SharedPtr<NodeDir> 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<Node>(newnode));
return static_ptr_cast<NodeDir>(newnode);
MemFs *mem_fs = static_cast<MemFs *>(_fs);
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);
auto newfile = MemFsNodeFile::create(name);
_children.emplace(name, static_ptr_cast<Node>(newfile));
return static_ptr_cast<NodeFile>(newfile);
MemFs *mem_fs = static_cast<MemFs *>(_fs);
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) {
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<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
#define FICUS_MEMFS_HPP
#include <utility>
#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<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 {
public:
Vector<SharedPtr<Node>> children() override;
SharedPtr<NodeDir> mkdir(const String &name) override;
SharedPtr<NodeFile> mkfile(const String &name) override;
~MemFsNodeDir() override = default;
static SharedPtr<MemFsNodeDir> create(const String &name) {
auto shared = SharedPtr(new MemFsNodeDir(name));
Vector<DirEntry> children() override;
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);
return shared;
}
private:
MemFsNodeDir(const String &name) { _name = name; }
SkipListMap<String, SharedPtr<Node>> _children;
MemFsNodeDir(Filesystem *fs, SharedPtr<DirInode> fs_node) : NodeDir(fs, fs_node->id), _fs_node(std::move(fs_node)) {}
SharedPtr<DirInode> _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<MemFsNodeFile> create(const String &name) {
auto shared = SharedPtr(new MemFsNodeFile(name));
static SharedPtr<MemFsNodeFile> create(Filesystem *fs, SharedPtr<FileInode> fs_node) {
auto shared = SharedPtr(new MemFsNodeFile(fs, std::move(fs_node)));
shared->_self_weak = static_ptr_cast<Node>(shared);
return shared;
}
private:
MemFsNodeFile(const String &name) { _name = name; }
Vector<uint8_t> _bytes;
MemFsNodeFile(Filesystem *fs, SharedPtr<FileInode> fs_node) : NodeFile(fs, fs_node->id), _fs_node(std::move(fs_node)) {}
SharedPtr<FileInode> _fs_node;
};
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:
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"
Node::~Node() = default;
Node::~ Node() = default;
SharedPtr<Node> Node::traverse(const Path &path) {
Filesystem *mnt;
@@ -23,13 +23,12 @@ SharedPtr<Node> Node::traverse(const Path &path) {
return *ret;
}
if (type() == DIR) {
// Horribly inefficient
auto children = static_cast<NodeDir *>(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;

View File

@@ -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<Node> 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<Node> _self_weak = nullptr;
};
class NodeFile;
struct DirEntry {
String name;
ino_t inode;
};
class NodeDir : public Node {
public:
virtual Vector<SharedPtr<Node>> children() = 0;
virtual SharedPtr<NodeDir> mkdir(const String &name) = 0;
virtual SharedPtr<NodeFile> mkfile(const String &name) = 0;
virtual void set_mounted(Filesystem *mount);
virtual Vector<DirEntry> 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) {}
};

View File

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

View File

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

View File

@@ -10,15 +10,18 @@
class RootNode : public NodeDir {
public:
Vector<SharedPtr<Node>> children() override;
SharedPtr<NodeDir> mkdir(const String &name) override;
SharedPtr<NodeFile> mkfile(const String &name) override;
RootNode()
: NodeDir(nullptr, -1) {}
Vector<DirEntry> 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